Add OLSR routing support, (loosely) based on Francisco J. Ros's NS-2 code (University of Murcia).
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Thu, 26 Jul 2007 12:49:00 +0100
changeset 1716 9757633a85da
parent 1715 b51c9c412844
child 1722 7420a485aa32
Add OLSR routing support, (loosely) based on Francisco J. Ros's NS-2 code (University of Murcia).
examples/simple-p2p-olsr.cc
examples/wscript
src/routing/olsr/olsr-header.cc
src/routing/olsr/olsr-header.h
src/routing/olsr/olsr-private.h
src/routing/olsr/olsr-repositories.h
src/routing/olsr/olsr-state.cc
src/routing/olsr/olsr-state.h
src/routing/olsr/olsr.cc
src/routing/olsr/olsr.h
src/routing/olsr/routing-table.cc
src/routing/olsr/routing-table.h
src/routing/olsr/wscript
src/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/simple-p2p-olsr.cc	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,198 @@
+/* -*- 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
+ *
+ * ns-2 simple.tcl script (ported from ns-2)
+ * Originally authored by Steve McCanne, 12/19/1996
+ */
+
+// Port of ns-2/tcl/ex/simple.tcl to ns-3
+//
+// Network topology
+//
+//  n0
+//     \ 5 Mb/s, 2ms
+//      \          1.5Mb/s, 10ms
+//       n2 -------------------------n3
+//      /
+//     / 5 Mb/s, 2ms
+//   n1
+//
+// - all links are p2p links with indicated one-way BW/delay
+// - CBR/UDP flows from n0 to n3, and from n3 to n1
+// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
+// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
+//   (i.e., DataRate of 448,000 bps)
+// - DropTail queues 
+// - Tracing of queues and packet receptions to file "simple-p2p.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/p2p-channel.h"
+#include "ns3/p2p-net-device.h"
+#include "ns3/mac-address.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/p2p-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/debug.h"
+
+#include "ns3/olsr.h"
+
+using namespace ns3;
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+#if 1
+//   DebugComponentEnable("Ipv4L3Protocol");
+//   DebugComponentEnable("ArpL3Protocol");
+//  DebugComponentEnable("OlsrRoutingTable");
+//   DebugComponentEnable("Object");
+//   DebugComponentEnable("Queue");
+//   DebugComponentEnable("DropTailQueue");
+//   DebugComponentEnable("Channel");
+//   DebugComponentEnable("PointToPointChannel");
+//   DebugComponentEnable("PointToPointNetDevice");
+#endif
+
+  // Set up some default values for the simulation.  Use the Bind()
+  // technique to tell the system what subclass of Queue to use,
+  // and what the queue limit is
+
+  // The below Bind command tells the queue factory which class to
+  // instantiate, when the queue factory is invoked in the topology code
+  Bind ("Queue", "DropTailQueue");
+
+  Bind ("OnOffApplicationPacketSize", "210");
+  Bind ("OnOffApplicationDataRate", "448kb/s");
+
+  //Bind ("DropTailQueue::m_maxPackets", 30);   
+
+  // Allow the user to override any of the defaults and the above
+  // Bind()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create four nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> (); 
+  Ptr<Node> n3 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+      n0, n2, DataRate(5000000), MilliSeconds(2));
+
+  Ptr<PointToPointChannel> channel1 = 
+    PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate(5000000), MilliSeconds(2));
+  
+  Ptr<PointToPointChannel> channel2 = 
+    PointToPointTopology::AddPointToPointLink (
+      n2, n3, DataRate(1500000), MilliSeconds(10));
+  
+  // Later, we add IP addresses.  
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address("10.1.1.1"),
+      n2, Ipv4Address("10.1.1.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address("10.1.2.1"),
+      n2, Ipv4Address("10.1.2.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel2, n2, Ipv4Address("10.1.3.1"),
+      n3, Ipv4Address("10.1.3.2"));
+
+
+  // Run OLSR in each node.
+  ComponentManager::Create<Olsr, Ptr<Node> >
+    (Olsr::cid, Olsr::iid, n0)->Start ();
+
+  ComponentManager::Create<Olsr, Ptr<Node> >
+    (Olsr::cid, Olsr::iid, n1)->Start ();
+
+  ComponentManager::Create<Olsr, Ptr<Node> >
+    (Olsr::cid, Olsr::iid, n2)->Start ();
+
+  ComponentManager::Create<Olsr, Ptr<Node> >
+    (Olsr::cid, Olsr::iid, n3)->Start ();
+
+
+#if 1
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    Ipv4Address("10.1.3.2"), 
+    80, 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.0));
+  ooff->Stop (Seconds(10.0));
+
+  // Create a similar flow from n3 to n1, starting at time 1.1 seconds
+  ooff = Create<OnOffApplication> (
+    n3, 
+    Ipv4Address("10.1.2.1"), 
+    80, 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.1));
+  ooff->Stop (Seconds(10.0));
+#endif
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-p2p.tr file
+//   AsciiTrace asciitrace ("simple-p2p-olsr.tr");
+//   asciitrace.TraceAllQueues ();
+//   asciitrace.TraceAllNetDeviceRx ();
+
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named simple-p2p.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("simple-p2p-olsr.pcap");
+  pcaptrace.TraceAllIp ();
+
+  Simulator::StopAt (Seconds (10.0));
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+}
--- a/examples/wscript	Thu Jul 26 12:27:49 2007 +0100
+++ b/examples/wscript	Thu Jul 26 12:49:00 2007 +0100
@@ -10,4 +10,6 @@
         return obj
         
     obj = create_ns_prog('simple-p2p', 'simple-p2p.cc', deps=['p2p', 'internet-node'])
+    obj = create_ns_prog('simple-p2p-olsr', 'simple-p2p-olsr.cc',
+                         deps=['p2p', 'internet-node', 'olsr'])
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-header.cc	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,704 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#include "ns3/assert.h"
+
+#include "olsr-header.h"
+
+#define IPV4_ADDRESS_SIZE 4
+#define OLSR_MSG_HEADER_SIZE 12
+#define OLSR_PKT_HEADER_SIZE 4
+
+namespace ns3 {
+
+/// Scaling factor used in RFC 3626.
+#define OLSR_C 0.0625
+
+///
+/// \brief Converts a decimal number of seconds to the mantissa/exponent format.
+///
+/// \param seconds decimal number of seconds we want to convert.
+/// \return the number of seconds in mantissa/exponent format.
+///
+uint8_t
+OlsrSecondsToEmf (double seconds)
+{
+  int a, b = 0;
+  
+  // find the largest integer 'b' such that: T/C >= 2^b
+  for (b = 0; (seconds/OLSR_C) >= (1 << b); ++b)
+    ;
+  NS_ASSERT ((seconds/OLSR_C) < (1 << b));
+  b--;
+  NS_ASSERT ((seconds/OLSR_C) >= (1 << b));
+
+  // compute the expression 16*(T/(C*(2^b))-1), which may not be a integer
+  double tmp = 16*(seconds/(OLSR_C*(1<<b))-1);
+
+  // round it up.  This results in the value for 'a'
+  a = (int) ceil (tmp);
+
+  // if 'a' is equal to 16: increment 'b' by one, and set 'a' to 0
+  if (a == 16)
+    {
+      b += 1;
+      a = 0;
+    }
+
+  // now, 'a' and 'b' should be integers between 0 and 15,
+  NS_ASSERT (a >= 0 && a < 16);
+  NS_ASSERT (b >= 0 && b < 16);
+
+  // the field will be a byte holding the value a*16+b
+  return (uint8_t) ((a << 4) | b);
+}
+
+///
+/// \brief Converts a number of seconds in the mantissa/exponent format to a decimal number.
+///
+/// \param olsr_format number of seconds in mantissa/exponent format.
+/// \return the decimal number of seconds.
+///
+double
+OlsrEmfToSeconds (uint8_t olsrFormat)
+{
+  int a = (olsrFormat >> 4);
+  int b = (olsrFormat & 0xf);
+  // value = C*(1+a/16)*2^b [in seconds]
+  return OLSR_C * (1 + a/16.0) * (1 << b);
+}
+
+
+
+// ---------------- OLSR Packet -------------------------------
+
+OlsrPacketHeader::OlsrPacketHeader ()
+{}
+
+OlsrPacketHeader::~OlsrPacketHeader ()
+{}
+
+uint32_t 
+OlsrPacketHeader::GetSerializedSize (void) const
+{
+  return OLSR_PKT_HEADER_SIZE;
+}
+
+void 
+OlsrPacketHeader::PrintTo (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+OlsrPacketHeader::SerializeTo (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteHtonU16 (m_packetLength);
+  i.WriteHtonU16 (m_packetSequenceNumber);
+}
+
+uint32_t
+OlsrPacketHeader::DeserializeFrom (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  m_packetLength  = i.ReadNtohU16 ();
+  m_packetSequenceNumber = i.ReadNtohU16 ();
+  return GetSerializedSize ();
+}
+
+
+// ---------------- OLSR Message -------------------------------
+
+OlsrMessageHeader::OlsrMessageHeader ()
+{}
+
+OlsrMessageHeader::~OlsrMessageHeader ()
+{}
+
+uint32_t 
+OlsrMessageHeader::GetSerializedSize (void) const
+{
+  return OLSR_MSG_HEADER_SIZE;
+}
+
+void 
+OlsrMessageHeader::PrintTo (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+OlsrMessageHeader::SerializeTo (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (m_messageType);
+  i.WriteU8 (m_vTime);
+  i.WriteHtonU16 (m_messageSize);
+  i.WriteHtonU32 (m_originatorAddress.GetHostOrder ());
+  i.WriteU8 (m_timeToLive);
+  i.WriteU8 (m_hopCount);
+  i.WriteHtonU16 (m_messageSequenceNumber);
+}
+
+uint32_t
+OlsrMessageHeader::DeserializeFrom (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  m_messageType  = (MessageType) i.ReadU8 ();
+  NS_ASSERT (m_messageType >= HELLO_MESSAGE && m_messageType <= HNA_MESSAGE);
+  m_vTime  = i.ReadU8 ();
+  m_messageSize  = i.ReadNtohU16 ();
+  m_originatorAddress = Ipv4Address (i.ReadNtohU32 ());
+  m_timeToLive  = i.ReadU8 ();
+  m_hopCount  = i.ReadU8 ();
+  m_messageSequenceNumber = i.ReadNtohU16 ();
+  return GetSerializedSize ();
+}
+
+
+// ---------------- OLSR MID Message -------------------------------
+
+OlsrMidMessageHeader::OlsrMidMessageHeader ()
+{}
+
+OlsrMidMessageHeader::~OlsrMidMessageHeader ()
+{}
+
+uint32_t 
+OlsrMidMessageHeader::GetSerializedSize (void) const
+{
+  return m_interfaceAddresses.size () * IPV4_ADDRESS_SIZE;
+}
+
+void 
+OlsrMidMessageHeader::PrintTo (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+OlsrMidMessageHeader::SerializeTo (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  for (std::vector<Ipv4Address>::const_iterator iter = m_interfaceAddresses.begin ();
+       iter != m_interfaceAddresses.end (); iter++)
+    {
+      i.WriteHtonU32 (iter->GetHostOrder ());
+    }
+}
+
+uint32_t
+OlsrMidMessageHeader::DeserializeFrom (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  m_interfaceAddresses.clear ();
+  NS_ASSERT (m_messageSize >= 0);
+  NS_ASSERT (m_messageSize % IPV4_ADDRESS_SIZE == 0);
+  
+  int numAddresses = m_messageSize / IPV4_ADDRESS_SIZE;
+  m_interfaceAddresses.erase (m_interfaceAddresses.begin(),
+                              m_interfaceAddresses.end ());
+  for (int n = 0; n < numAddresses; ++n)
+      m_interfaceAddresses.push_back (Ipv4Address (i.ReadNtohU32 ()));
+  return GetSerializedSize ();
+}
+
+
+
+// ---------------- OLSR HELLO Message -------------------------------
+
+OlsrHelloMessageHeader::OlsrHelloMessageHeader ()
+{}
+
+OlsrHelloMessageHeader::~OlsrHelloMessageHeader ()
+{}
+
+uint32_t 
+OlsrHelloMessageHeader::GetSerializedSize (void) const
+{
+  uint32_t size = 4;
+  for (std::vector<LinkMessage>::const_iterator iter = m_linkMessages.begin ();
+       iter != m_linkMessages.end (); iter++)
+    {
+      const LinkMessage &lm = *iter;
+      size += 4;
+      size += IPV4_ADDRESS_SIZE * lm.neighborInterfaceAddresses.size ();
+    }
+  return size;
+}
+
+void 
+OlsrHelloMessageHeader::PrintTo (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+OlsrHelloMessageHeader::SerializeTo (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU16 (0); // Reserved
+  i.WriteU8 (m_hTime);
+  i.WriteU8 (m_willingness);
+  
+  for (std::vector<LinkMessage>::const_iterator iter = m_linkMessages.begin ();
+       iter != m_linkMessages.end (); iter++)
+    {
+      const LinkMessage &lm = *iter;
+
+      i.WriteU8 (lm.linkCode);
+      i.WriteU8 (0); // Reserved
+
+      // The size of the link message, counted in bytes and measured
+      // from the beginning of the "Link Code" field and until the
+      // next "Link Code" field (or - if there are no more link types
+      // - the end of the message).
+      i.WriteHtonU16 (4 + lm.neighborInterfaceAddresses.size () * IPV4_ADDRESS_SIZE);
+      
+      for (std::vector<Ipv4Address>::const_iterator neigh_iter = lm.neighborInterfaceAddresses.begin ();
+           neigh_iter != lm.neighborInterfaceAddresses.end (); neigh_iter++)
+        {
+          i.WriteHtonU32 (neigh_iter->GetHostOrder ());
+        }
+    }
+}
+
+uint32_t
+OlsrHelloMessageHeader::DeserializeFrom (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  NS_ASSERT (m_messageSize >= 4);
+
+  m_linkMessages.clear ();
+  
+  uint16_t helloSizeLeft = m_messageSize;
+  
+  i.ReadNtohU16 (); // Reserved
+  m_hTime = i.ReadU8 ();
+  m_willingness = i.ReadU8 ();
+  
+  helloSizeLeft -= 4;
+
+  while (helloSizeLeft)
+    {
+      LinkMessage lm;
+      NS_ASSERT (helloSizeLeft >= 4);
+      lm.linkCode = i.ReadU8 ();
+      i.ReadU8 (); // Reserved
+      uint16_t lmSize = i.ReadNtohU16 ();
+      NS_ASSERT ((lmSize - 4) % IPV4_ADDRESS_SIZE == 0);
+      for (int n = (lmSize - 4) / IPV4_ADDRESS_SIZE; n; --n)
+        {
+          lm.neighborInterfaceAddresses.push_back (Ipv4Address (i.ReadNtohU32 ()));
+        }
+      helloSizeLeft -= lmSize;
+      m_linkMessages.push_back (lm);
+    }
+
+  return m_messageSize;
+}
+
+
+
+// ---------------- OLSR TC Message -------------------------------
+
+OlsrTcMessageHeader::OlsrTcMessageHeader ()
+{}
+
+OlsrTcMessageHeader::~OlsrTcMessageHeader ()
+{}
+
+uint32_t 
+OlsrTcMessageHeader::GetSerializedSize (void) const
+{
+  return 4 + m_neighborAddresses.size () * IPV4_ADDRESS_SIZE;
+}
+
+void 
+OlsrTcMessageHeader::PrintTo (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+OlsrTcMessageHeader::SerializeTo (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteHtonU16 (m_ansn);
+  i.WriteHtonU16 (0); // Reserved
+
+  for (std::vector<Ipv4Address>::const_iterator iter = m_neighborAddresses.begin ();
+       iter != m_neighborAddresses.end (); iter++)
+    {
+      i.WriteHtonU32 (iter->GetHostOrder ());
+    }
+}
+
+uint32_t
+OlsrTcMessageHeader::DeserializeFrom (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  m_neighborAddresses.clear ();
+  NS_ASSERT (m_messageSize >= 4);
+
+  m_ansn = i.ReadNtohU16 ();
+  i.ReadNtohU16 (); // Reserved
+  
+  NS_ASSERT ((m_messageSize - 4) % IPV4_ADDRESS_SIZE == 0);
+  int numAddresses = (m_messageSize - 4) / IPV4_ADDRESS_SIZE;
+  m_neighborAddresses.clear ();
+  for (int n = 0; n < numAddresses; ++n)
+    m_neighborAddresses.push_back (Ipv4Address (i.ReadNtohU32 ()));
+
+  return m_messageSize;
+}
+
+
+// ---------------- OLSR HNA Message -------------------------------
+
+OlsrHnaMessageHeader::OlsrHnaMessageHeader ()
+{}
+
+OlsrHnaMessageHeader::~OlsrHnaMessageHeader ()
+{}
+
+uint32_t 
+OlsrHnaMessageHeader::GetSerializedSize (void) const
+{
+  return 2*m_associations.size () * IPV4_ADDRESS_SIZE;
+}
+
+void 
+OlsrHnaMessageHeader::PrintTo (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+OlsrHnaMessageHeader::SerializeTo (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  for (size_t n = 0; n < m_associations.size (); ++n)
+    {
+      i.WriteHtonU32 (m_associations[n].address.GetHostOrder ());
+      i.WriteHtonU32 (m_associations[n].mask.GetHostOrder ());
+    }
+}
+
+uint32_t
+OlsrHnaMessageHeader::DeserializeFrom (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  NS_ASSERT (m_messageSize % (IPV4_ADDRESS_SIZE*2) == 0);
+  int numAddresses = m_messageSize / IPV4_ADDRESS_SIZE / 2;
+  m_associations.clear ();
+  for (int n = 0; n < numAddresses; ++n)
+    {
+      Ipv4Address address (i.ReadNtohU32 ());
+      Ipv4Mask mask (i.ReadNtohU32 ());
+      m_associations.push_back ((Association) {address, mask});
+    }
+  return m_messageSize;
+}
+
+
+
+}; // namespace ns3
+
+
+#ifdef RUN_SELF_TESTS
+
+
+#include "ns3/test.h"
+#include "ns3/packet.h"
+#include <math.h>
+
+
+namespace ns3 {
+
+class OlsrHeaderTest : public ns3::Test {
+private:
+public:
+  OlsrHeaderTest ();
+  virtual bool RunTests (void);
+
+
+};
+
+OlsrHeaderTest::OlsrHeaderTest ()
+  : ns3::Test ("OlsrHeader")
+{}
+
+
+bool 
+OlsrHeaderTest::RunTests (void)
+{
+  bool result = true;
+
+  // Testing packet header + message header + MID message
+  {
+    Packet packet;
+
+    {
+      OlsrPacketHeader hdr;
+      OlsrMessageHeader msg1;
+      OlsrMidMessageHeader mid1;
+      OlsrMessageHeader msg2;
+      OlsrMidMessageHeader mid2;
+    
+      // MID message #1
+      {
+        std::vector<Ipv4Address> addresses;
+        addresses.push_back (Ipv4Address ("1.2.3.4"));
+        addresses.push_back (Ipv4Address ("1.2.3.5"));
+        mid1.SetInterfaceAddresses (addresses);
+      }
+
+      msg1.SetMessageSize (mid1.GetSize () + msg1.GetSize ());
+      msg1.SetTimeToLive (255);
+      msg1.SetOriginatorAddress (Ipv4Address ("11.22.33.44"));
+      msg1.SetVTime (Seconds (9));
+      msg1.SetMessageType (OlsrMessageHeader::MID_MESSAGE);
+      msg1.SetMessageSequenceNumber (7);
+
+      // MID message #2
+      {
+        std::vector<Ipv4Address> addresses;
+        addresses.push_back (Ipv4Address ("2.2.3.4"));
+        addresses.push_back (Ipv4Address ("2.2.3.5"));
+        mid2.SetInterfaceAddresses (addresses);
+      }
+
+      msg2.SetMessageSize (mid2.GetSize () + msg2.GetSize ());
+      msg2.SetTimeToLive (254);
+      msg2.SetOriginatorAddress (Ipv4Address ("12.22.33.44"));
+      msg2.SetVTime (Seconds (10));
+      msg2.SetMessageType (OlsrMessageHeader::MID_MESSAGE);
+      msg2.SetMessageSequenceNumber (7);
+
+      // Build an OLSR packet header
+      hdr.SetPacketLength (hdr.GetSize () + msg1.GetMessageSize () + msg2.GetMessageSize ());
+      hdr.SetPacketSequenceNumber (123);
+    
+
+      // Now add all the headers in the correct order
+      packet.AddHeader (mid2);
+      packet.AddHeader (msg2);
+      packet.AddHeader (mid1);
+      packet.AddHeader (msg1);
+      packet.AddHeader (hdr);
+    }    
+
+    {
+      OlsrPacketHeader hdr;
+      packet.RemoveHeader (hdr);
+      NS_TEST_ASSERT_EQUAL (hdr.GetPacketSequenceNumber (), 123);
+      uint32_t sizeLeft = hdr.GetPacketLength () - hdr.GetSize ();
+      {
+        OlsrMessageHeader msg1;
+        OlsrMidMessageHeader mid1;
+
+        packet.RemoveHeader (msg1);
+
+        NS_TEST_ASSERT_EQUAL (msg1.GetTimeToLive (),  255);
+        NS_TEST_ASSERT_EQUAL (msg1.GetOriginatorAddress (), Ipv4Address ("11.22.33.44"));
+        NS_TEST_ASSERT_EQUAL (msg1.GetVTime (), Seconds (9));
+        NS_TEST_ASSERT_EQUAL (msg1.GetMessageType (), OlsrMessageHeader::MID_MESSAGE);
+        NS_TEST_ASSERT_EQUAL (msg1.GetMessageSequenceNumber (), 7);
+
+        mid1.SetMessageSize (msg1.GetMessageSize () - msg1.GetSize ());
+        packet.RemoveHeader (mid1);
+        NS_TEST_ASSERT_EQUAL (mid1.GetInterfaceAddresses ().size (), 2);
+        NS_TEST_ASSERT_EQUAL (*mid1.GetInterfaceAddresses ().begin (), Ipv4Address ("1.2.3.4"));
+
+        sizeLeft -= msg1.GetMessageSize ();
+        NS_TEST_ASSERT (sizeLeft > 0);
+      }
+      {
+        // now read the second message
+        OlsrMessageHeader msg2;
+        OlsrMidMessageHeader mid2;
+
+        packet.RemoveHeader (msg2);
+
+        NS_TEST_ASSERT_EQUAL (msg2.GetTimeToLive (),  254);
+        NS_TEST_ASSERT_EQUAL (msg2.GetOriginatorAddress (), Ipv4Address ("12.22.33.44"));
+        NS_TEST_ASSERT_EQUAL (msg2.GetVTime (), Seconds (10));
+        NS_TEST_ASSERT_EQUAL (msg2.GetMessageType (), OlsrMessageHeader::MID_MESSAGE);
+        NS_TEST_ASSERT_EQUAL (msg2.GetMessageSequenceNumber (), 7);
+
+        mid2.SetMessageSize (msg2.GetMessageSize () - msg2.GetSize ());
+        packet.RemoveHeader (mid2);
+        NS_TEST_ASSERT_EQUAL (mid2.GetInterfaceAddresses ().size (), 2);
+        NS_TEST_ASSERT_EQUAL (*mid2.GetInterfaceAddresses ().begin (), Ipv4Address ("2.2.3.4"));
+
+        sizeLeft -= msg2.GetMessageSize ();
+        NS_TEST_ASSERT_EQUAL (sizeLeft, 0);
+      }
+    }
+  }
+  
+  // Test the HELLO message
+  {
+    Packet packet;
+    OlsrHelloMessageHeader helloIn;
+
+    helloIn.SetHTime (Seconds (7));
+    helloIn.SetWillingness (66);
+
+    {
+      std::vector<OlsrHelloMessageHeader::LinkMessage> vec;
+
+      OlsrHelloMessageHeader::LinkMessage lm1;
+      lm1.linkCode = 2;
+      lm1.neighborInterfaceAddresses.push_back (Ipv4Address ("1.2.3.4"));
+      lm1.neighborInterfaceAddresses.push_back (Ipv4Address ("1.2.3.5"));
+      vec.push_back (lm1);
+
+      OlsrHelloMessageHeader::LinkMessage lm2;
+      lm2.linkCode = 3;
+      lm2.neighborInterfaceAddresses.push_back (Ipv4Address ("2.2.3.4"));
+      lm2.neighborInterfaceAddresses.push_back (Ipv4Address ("2.2.3.5"));
+      vec.push_back (lm2);
+
+      helloIn.SetLinkMessages (vec);
+    }
+
+    packet.AddHeader (helloIn);
+
+    OlsrHelloMessageHeader helloOut;
+    helloOut.SetMessageSize (packet.GetSize ());
+    packet.RemoveHeader (helloOut);
+    
+    NS_TEST_ASSERT_EQUAL (helloOut.GetHTime (), Seconds (7));
+    NS_TEST_ASSERT_EQUAL (helloOut.GetWillingness (), 66);
+    NS_TEST_ASSERT_EQUAL (helloOut.GetLinkMessages ().size (), 2);
+
+    NS_TEST_ASSERT_EQUAL (helloOut.GetLinkMessages ()[0].linkCode, 2);
+    NS_TEST_ASSERT_EQUAL (helloOut.GetLinkMessages ()[0].neighborInterfaceAddresses[0],
+                          Ipv4Address ("1.2.3.4"));
+    NS_TEST_ASSERT_EQUAL (helloOut.GetLinkMessages ()[0].neighborInterfaceAddresses[1],
+                          Ipv4Address ("1.2.3.5"));
+
+    NS_TEST_ASSERT_EQUAL (helloOut.GetLinkMessages ()[1].linkCode, 3);
+    NS_TEST_ASSERT_EQUAL (helloOut.GetLinkMessages ()[1].neighborInterfaceAddresses[0],
+                          Ipv4Address ("2.2.3.4"));
+    NS_TEST_ASSERT_EQUAL (helloOut.GetLinkMessages ()[1].neighborInterfaceAddresses[1],
+                          Ipv4Address ("2.2.3.5"));
+
+    // check that all bytes of the message were read
+    NS_TEST_ASSERT_EQUAL (packet.GetSize (), 0);
+  }
+
+  // Test the TC message
+  {
+    Packet packet;
+    OlsrTcMessageHeader tcIn;
+
+    tcIn.SetAnsn (0x1234);
+    {
+      std::vector<Ipv4Address> vec;
+      vec.push_back (Ipv4Address ("1.2.3.4"));
+      vec.push_back (Ipv4Address ("1.2.3.5"));
+      tcIn.SetNeighborAddresses (vec);
+    }
+    packet.AddHeader (tcIn);
+
+    OlsrTcMessageHeader tcOut;
+    tcOut.SetMessageSize (packet.GetSize ());
+    packet.RemoveHeader (tcOut);
+    
+    NS_TEST_ASSERT_EQUAL (tcOut.GetAnsn (), 0x1234);
+    NS_TEST_ASSERT_EQUAL (tcOut.GetNeighborAddresses ().size (), 2);
+
+    NS_TEST_ASSERT_EQUAL (tcOut.GetNeighborAddresses ()[0],
+                          Ipv4Address ("1.2.3.4"));
+    NS_TEST_ASSERT_EQUAL (tcOut.GetNeighborAddresses ()[1],
+                          Ipv4Address ("1.2.3.5"));
+
+    // check that all bytes of the message were read
+    NS_TEST_ASSERT_EQUAL (packet.GetSize (), 0);
+  }
+
+  // Test the HNA message
+  {
+    Packet packet;
+    OlsrHnaMessageHeader hnaIn;
+
+    {
+      std::vector<OlsrHnaMessageHeader::Association> vec;
+      vec.push_back ((OlsrHnaMessageHeader::Association)
+                     { Ipv4Address ("1.2.3.4"), Ipv4Mask ("255.255.255.0")});
+      vec.push_back ((OlsrHnaMessageHeader::Association)
+                     {Ipv4Address ("1.2.3.5"), Ipv4Mask ("255.255.0.0")});
+      hnaIn.SetAssociations (vec);
+    }
+    packet.AddHeader (hnaIn);
+
+    OlsrHnaMessageHeader hnaOut;
+    hnaOut.SetMessageSize (packet.GetSize ());
+    packet.RemoveHeader (hnaOut);
+    
+    NS_TEST_ASSERT_EQUAL (hnaOut.GetAssociations ().size (), 2);
+
+    NS_TEST_ASSERT_EQUAL (hnaOut.GetAssociations ()[0].address,
+                          Ipv4Address ("1.2.3.4"));
+    NS_TEST_ASSERT_EQUAL (hnaOut.GetAssociations ()[0].mask,
+                          Ipv4Mask ("255.255.255.0"));
+
+    NS_TEST_ASSERT_EQUAL (hnaOut.GetAssociations ()[1].address,
+                          Ipv4Address ("1.2.3.5"));
+    NS_TEST_ASSERT_EQUAL (hnaOut.GetAssociations ()[1].mask,
+                          Ipv4Mask ("255.255.0.0"));
+
+    // check that all bytes of the message were read
+    NS_TEST_ASSERT_EQUAL (packet.GetSize (), 0);
+  }
+
+  for (int time = 1; time <= 30; time++)
+    {
+      uint8_t emf = OlsrSecondsToEmf (time);
+      double seconds = OlsrEmfToSeconds (emf);
+      if (seconds < 0 || fabs (seconds - time) > 0.1)
+        {
+          result = false;
+          Failure () << "In " << time << " out " << seconds << std::endl;
+        }
+    }
+
+  return result;
+}
+
+static OlsrHeaderTest gOlsrHeaderTest;
+
+}; // namespace
+
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-header.h	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,470 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#ifndef OLSR_HEADER_H
+#define OLSR_HEADER_H
+
+#include <stdint.h>
+#include <vector>
+#include "ns3/header.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/nstime.h"
+
+
+namespace ns3 {
+
+
+double OlsrEmfToSeconds (uint8_t emf);
+uint8_t OlsrSecondsToEmf (double seconds);
+
+// 3.3.  Packet Format
+//
+//    The basic layout of any packet in OLSR is as follows (omitting IP and
+//    UDP headers):
+//
+//        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
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |         Packet Length         |    Packet Sequence Number     |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Message Type |     Vtime     |         Message Size          |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                      Originator Address                       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Time To Live |   Hop Count   |    Message Sequence Number    |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                                                               |
+//       :                            MESSAGE                            :
+//       |                                                               |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Message Type |     Vtime     |         Message Size          |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                      Originator Address                       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Time To Live |   Hop Count   |    Message Sequence Number    |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                                                               |
+//       :                            MESSAGE                            :
+//       |                                                               |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       :                                                               :
+//                (etc.)
+class OlsrPacketHeader : public Header
+{
+public:
+  OlsrPacketHeader ();
+  virtual ~OlsrPacketHeader ();
+
+  void SetPacketLength (uint16_t length)
+  {
+    m_packetLength = length;
+  }
+  uint16_t GetPacketLength () const
+  {
+    return m_packetLength;
+  }
+
+  void SetPacketSequenceNumber (uint16_t seqnum)
+  {
+    m_packetSequenceNumber = seqnum;
+  }
+  uint16_t GetPacketSequenceNumber () const
+  {
+    return m_packetSequenceNumber;
+  }
+
+private:
+  uint16_t m_packetLength;
+  uint16_t m_packetSequenceNumber;
+  
+  virtual void PrintTo (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void SerializeTo (Buffer::Iterator start) const;
+  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
+  virtual std::string DoGetName (void) const { return "OlsrPacket"; }
+};
+
+
+//        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
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Message Type |     Vtime     |         Message Size          |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                      Originator Address                       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Time To Live |   Hop Count   |    Message Sequence Number    |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+class OlsrMessageHeader : public Header
+{
+public:
+
+  enum MessageType {
+    HELLO_MESSAGE = 1,
+    TC_MESSAGE    = 2,
+    MID_MESSAGE   = 3,
+    HNA_MESSAGE   = 4,
+  };
+
+  OlsrMessageHeader ();
+  virtual ~OlsrMessageHeader ();
+
+  void SetMessageType (MessageType messageType)
+  {
+    m_messageType = messageType;
+  }
+  MessageType GetMessageType () const
+  {
+    return m_messageType;
+  }
+
+  void SetVTime (Time time)
+  {
+    m_vTime = OlsrSecondsToEmf (time.GetSeconds ());
+  }
+  Time GetVTime () const
+  {
+    return Seconds (OlsrEmfToSeconds (m_vTime));
+  }
+
+  void SetOriginatorAddress (Ipv4Address originatorAddress)
+  {
+    m_originatorAddress = originatorAddress;
+  }
+  Ipv4Address GetOriginatorAddress () const
+  {
+    return m_originatorAddress;
+  }
+
+  void SetTimeToLive (uint8_t timeToLive)
+  {
+    m_timeToLive = timeToLive;
+  }
+  uint8_t GetTimeToLive () const
+  {
+    return m_timeToLive;
+  }
+
+  void SetHopCount (uint8_t hopCount)
+  {
+    m_hopCount = hopCount;
+  }
+  uint8_t GetHopCount () const
+  {
+    return m_hopCount;
+  }
+
+  void SetMessageSequenceNumber (uint16_t messageSequenceNumber)
+  {
+    m_messageSequenceNumber = messageSequenceNumber;
+  }
+  uint16_t GetMessageSequenceNumber () const
+  {
+    return m_messageSequenceNumber;
+  }
+
+  void SetMessageSize (uint16_t messageSize)
+  {
+    m_messageSize = messageSize;
+  }
+  uint16_t GetMessageSize () const
+  {
+    return m_messageSize;
+  }
+  
+private:
+  MessageType m_messageType;
+  uint8_t m_vTime;
+  Ipv4Address m_originatorAddress;
+  uint8_t m_timeToLive;
+  uint8_t m_hopCount;
+  uint16_t m_messageSequenceNumber;
+  uint16_t m_messageSize;
+
+  virtual void PrintTo (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void SerializeTo (Buffer::Iterator start) const;
+  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
+  virtual std::string DoGetName (void) const { return "OlsrMessage"; }
+};
+
+// 5.1.  MID Message Format
+//
+//    The proposed format of a MID message is as follows:
+//
+//        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
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                    OLSR Interface Address                     |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                    OLSR Interface Address                     |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                              ...                              |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+class OlsrMidMessageHeader : public Header
+{
+public:
+
+  OlsrMidMessageHeader ();
+  virtual ~OlsrMidMessageHeader ();
+
+  void SetMessageSize (uint32_t messageSize) {
+    m_messageSize = messageSize;
+  }
+  uint32_t GetMessageSize () const {
+    return m_messageSize;
+  }
+  
+  const std::vector<Ipv4Address> & GetInterfaceAddresses () const
+  {
+    return m_interfaceAddresses;
+  }
+  void SetInterfaceAddresses (const std::vector<Ipv4Address> &addresses)
+  {
+    m_interfaceAddresses = addresses;
+  }
+  
+  
+private:
+  std::vector<Ipv4Address> m_interfaceAddresses;
+  uint32_t m_messageSize; // has to be manually set before deserialization
+
+  virtual void PrintTo (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void SerializeTo (Buffer::Iterator start) const;
+  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
+  virtual std::string DoGetName (void) const { return "OlsrMidMessage"; }
+};
+
+// 6.1.  HELLO Message Format
+//
+//        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
+//
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |          Reserved             |     Htime     |  Willingness  |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |   Link Code   |   Reserved    |       Link Message Size       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                  Neighbor Interface Address                   |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                  Neighbor Interface Address                   |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       :                             .  .  .                           :
+//       :                                                               :
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |   Link Code   |   Reserved    |       Link Message Size       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                  Neighbor Interface Address                   |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                  Neighbor Interface Address                   |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       :                                                               :
+//       :                                       :
+//    (etc.)
+class OlsrHelloMessageHeader : public Header
+{
+public:
+
+  OlsrHelloMessageHeader ();
+  virtual ~OlsrHelloMessageHeader ();
+
+  
+  struct LinkMessage {
+    uint8_t linkCode;
+    std::vector<Ipv4Address> neighborInterfaceAddresses;
+  };
+
+
+  void SetMessageSize (uint32_t messageSize) {
+    m_messageSize = messageSize;
+  }
+  uint32_t GetMessageSize () const {
+    return m_messageSize;
+  }
+
+  void SetWillingness (uint8_t willingness)
+  {
+    m_willingness = willingness;
+  }
+  uint8_t GetWillingness () const
+  {
+    return m_willingness;
+  }
+
+  void SetHTime (Time time)
+  {
+    m_hTime = OlsrSecondsToEmf (time.GetSeconds ());
+  }
+  Time GetHTime () const
+  {
+    return Seconds (OlsrEmfToSeconds (m_hTime));
+  }
+
+  const std::vector<LinkMessage> & GetLinkMessages () const
+  {
+    return m_linkMessages;
+  }
+  void SetLinkMessages (const std::vector<LinkMessage> &linkMessages)
+  {
+    m_linkMessages = linkMessages;
+  }
+  
+private:
+  uint8_t m_hTime;
+  uint8_t m_willingness;
+  uint32_t m_messageSize; // has to be manually set before deserialization
+  std::vector<LinkMessage> m_linkMessages;
+
+  virtual void PrintTo (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void SerializeTo (Buffer::Iterator start) const;
+  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
+  virtual std::string DoGetName (void) const { return "OlsrHelloMessage"; }
+};
+
+// 9.1.  TC Message Format
+//
+//    The proposed format of a TC message is as follows:
+//
+//        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
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |              ANSN             |           Reserved            |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |               Advertised Neighbor Main Address                |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |               Advertised Neighbor Main Address                |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                              ...                              |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+class OlsrTcMessageHeader : public Header
+{
+public:
+
+  OlsrTcMessageHeader ();
+  virtual ~OlsrTcMessageHeader ();
+
+  void SetMessageSize (uint32_t messageSize) {
+    m_messageSize = messageSize;
+  }
+  uint32_t GetMessageSize () const {
+    return m_messageSize;
+  }
+
+  const std::vector<Ipv4Address> & GetNeighborAddresses () const
+  {
+    return m_neighborAddresses;
+  }
+  void SetNeighborAddresses (const std::vector<Ipv4Address> &addresses)
+  {
+    m_neighborAddresses = addresses;
+  }
+
+  void SetAnsn (uint16_t ansn)
+  {
+    m_ansn = ansn;
+  }
+  uint16_t GetAnsn () const
+  {
+    return m_ansn;
+  }
+  
+private:
+  std::vector<Ipv4Address> m_neighborAddresses;
+  uint16_t m_ansn;
+
+  uint32_t m_messageSize; // has to be manually set before deserialization
+
+  virtual void PrintTo (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void SerializeTo (Buffer::Iterator start) const;
+  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
+  virtual std::string DoGetName (void) const { return "OlsrTcMessage"; }
+};
+
+
+// 12.1.  HNA Message Format
+//
+//    The proposed format of an HNA-message is:
+//
+//        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
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                         Network Address                       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                             Netmask                           |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                         Network Address                       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                             Netmask                           |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                              ...                              |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+// Note: HNA stands for Host Network Association
+class OlsrHnaMessageHeader : public Header
+{
+public:
+
+  OlsrHnaMessageHeader ();
+  virtual ~OlsrHnaMessageHeader ();
+
+  struct Association
+  {
+    Ipv4Address address;
+    Ipv4Mask mask;
+  };
+
+  void SetMessageSize (uint32_t messageSize)
+  {
+    m_messageSize = messageSize;
+  }
+  uint32_t GetMessageSize () const
+  {
+    return m_messageSize;
+  }
+
+  const std::vector<Association> & GetAssociations () const
+  {
+    return m_associations;
+  }
+  void SetAssociations (const std::vector<Association> &associations)
+  {
+    m_associations = associations;
+  }
+  
+private:
+  std::vector<Association> m_associations;
+  uint32_t m_messageSize; // has to be manually set before deserialization
+
+  virtual void PrintTo (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void SerializeTo (Buffer::Iterator start) const;
+  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
+  virtual std::string DoGetName (void) const { return "OlsrHnaMessage"; }
+};
+
+
+}; // namespace ns3
+
+#endif /* OLSR_HEADER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-private.h	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,187 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/***************************************************************************
+ *   Copyright (C) 2004 by Francisco J. Ros                                *
+ *   fjrm@dif.um.es                                                        *
+ *                                                                         *
+ *   Modified on 2007 for NS-3 by Gustavo J. A. M. Carneiro, INESC Porto   *
+ *                                <gjc@inescporto.pt>                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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 __OLSR_H__
+#define __OLSR_H__
+
+#include "olsr.h"
+
+#include <vector>
+
+#include "olsr-header.h"
+#include "olsr-state.h"
+#include "routing-table.h"
+#include "olsr-repositories.h"
+#include "ns3/object.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+#include "ns3/socket.h"
+#include "ns3/timer.h"
+
+
+namespace ns3 { namespace olsr {
+
+
+
+class Olsr : public ::ns3::Olsr
+{
+  friend class OlsrTest;
+
+public:
+  Olsr (Ptr<Node> node);
+
+  virtual void Start ();
+  virtual void SetMainInterface (uint32_t interface);
+
+private:
+
+  /// Address of the routing agent.
+  Ipv4Address m_routingAgentAddr;
+	
+  /// Packets sequence number counter.
+  uint16_t m_packetSequenceNumber;
+  /// Messages sequence number counter.
+  uint16_t m_messageSequenceNumber;
+  /// Advertised Neighbor Set sequence number.
+  uint16_t m_ansn;
+  
+  /// HELLO messages' emission interval.
+  Time m_helloInterval;
+  /// TC messages' emission interval.
+  Time m_tcInterval;
+  /// MID messages' emission interval.
+  Time m_midInterval;
+  /// Willingness for forwarding packets on behalf of other nodes.
+  uint8_t m_willingness;
+  /// Determines if layer 2 notifications are enabled or not.
+  bool m_useL2Notifications;
+	
+  /// Routing table.
+  Ptr<RoutingTable> m_routingTable;
+  /// Internal state with all needed data structs.
+  OlsrState m_state;
+
+  Ptr<Ipv4> m_ipv4;
+	
+protected:
+  void DoDispose ();
+  void SendPacket (Packet packet);
+	
+  /// Increments packet sequence number and returns the new value.
+  inline uint16_t GetPacketSequenceNumber ();
+  /// Increments message sequence number and returns the new value.
+  inline uint16_t GetMessageSequenceNumber ();
+	
+  void RecvOlsr (Ptr<Socket> socket,
+                 const uint8_t *dataPtr, uint32_t dataSize,
+                 const Ipv4Address &sourceAddr,
+                 uint16_t sourcePort);
+
+  void MprComputation ();
+  void RoutingTableComputation ();
+  Ipv4Address GetMainAddress (Ipv4Address iface_addr);
+
+  // Timer handlers
+  Timer<> m_helloTimer;
+  void HelloTimerExpire ();
+  
+  Timer<> m_tcTimer;
+  void TcTimerExpire ();
+
+  Timer<> m_midTimer;
+  void MidTimerExpire ();
+
+  void DupTupleTimerExpire (DuplicateTuple tuple);
+  bool m_linkTupleTimerFirstTime;
+  void LinkTupleTimerExpire (LinkTuple tuple);
+  void Nb2hopTupleTimerExpire (TwoHopNeighborTuple tuple);
+  void MprSelTupleTimerExpire (MprSelectorTuple tuple);
+  void TopologyTupleTimerExpire (TopologyTuple tuple);
+  void IfaceAssocTupleTimerExpire (IfaceAssocTuple tuple);
+
+  /// A list of pending messages which are buffered awaiting for being sent.
+  std::vector<Packet> m_queuedMessages;
+  Timer<> m_queuedMessagesTimer; // timer for throttling outgoing messages
+
+  void ForwardDefault (OlsrMessageHeader olsrMessage,
+                       Packet messagePayload,
+                       DuplicateTuple *duplicated,
+                       const Ipv4Address &localIface,
+                       const Ipv4Address &senderAddress);
+  void QueueMessage (Packet message, Time delay);
+  void SendQueuedMessages ();
+  void SendHello ();
+  void SendTc ();
+  void SendMid ();
+
+  void NeighborLoss (const LinkTuple &tuple);
+  void AddDuplicateTuple (const DuplicateTuple &tuple);
+  void RemoveDuplicateTuple (const DuplicateTuple &tuple);
+  LinkTuple & AddLinkTuple (const LinkTuple &tuple, uint8_t willingness);
+  void RemoveLinkTuple (const LinkTuple &tuple);
+  void LinkTupleUpdated (const LinkTuple &tuple);
+  void AddNeighborTuple (const NeighborTuple &tuple);
+  void RemoveNeighborTuple (const NeighborTuple &tuple);
+  void AddTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
+  void RemoveTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
+  void AddMprSelectorTuple (const MprSelectorTuple  &tuple);
+  void RemoveMprSelectorTuple (const MprSelectorTuple &tuple);
+  void AddTopologyTuple (const TopologyTuple &tuple);
+  void RemoveTopologyTuple (const TopologyTuple &tuple);
+  void AddIfaceAssocTuple (const IfaceAssocTuple &tuple);
+  void RemoveIfaceAssocTuple (const IfaceAssocTuple &tuple);
+
+  void ProcessHello (const OlsrMessageHeader &msg,
+                     const OlsrHelloMessageHeader &hello,
+                     const Ipv4Address &receiverIface,
+                     const Ipv4Address &senderIface);
+  void ProcessTc (const OlsrMessageHeader &msg,
+                  const OlsrTcMessageHeader &tc,
+                  const Ipv4Address &senderIface);
+  void ProcessMid (const OlsrMessageHeader &msg,
+                   const OlsrMidMessageHeader &mid,
+                   const Ipv4Address &senderIface);
+
+  void LinkSensing (const OlsrMessageHeader &msg,
+                    const OlsrHelloMessageHeader &hello,
+                    const Ipv4Address &receiverIface,
+                    const Ipv4Address &sender_iface);
+  void PopulateNeighborSet (const OlsrMessageHeader &msg,
+                            const OlsrHelloMessageHeader &hello);
+  void PopulateTwoHopNeighborSet (const OlsrMessageHeader &msg,
+                                  const OlsrHelloMessageHeader &hello);
+  void PopulateMprSelectorSet (const OlsrMessageHeader &msg,
+                               const OlsrHelloMessageHeader &hello);
+
+  int Degree (NeighborTuple const &tuple);
+
+  Ipv4Address m_mainAddress;
+  Ptr<Socket> m_receiveSocket; // UDP socket for receving OSLR packets
+  Ptr<Socket> m_sendSocket; // UDP socket for sending OSLR packets
+};
+
+}}; // namespace ns3, olsr
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-repositories.h	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,200 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/***************************************************************************
+ *   Copyright (C) 2004 by Francisco J. Ros                                *
+ *   fjrm@dif.um.es                                                        *
+ *                                                                         *
+ *   Modified on 2007 for NS-3 by Gustavo J. A. M. Carneiro, INESC Porto   *
+ *                                <gjc@inescporto.pt>                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+///
+/// \file	OLSR_repositories.h
+/// \brief	Here are defined all data structures needed by an OLSR node.
+///
+
+#ifndef __OLSR_REPOSITORIES_H__
+#define __OLSR_REPOSITORIES_H__
+
+#include <set>
+#include <vector>
+
+#include "ns3/ipv4-address.h"
+#include "ns3/nstime.h"
+
+namespace ns3 { namespace olsr {
+
+
+
+/// An Interface Association Tuple.
+struct IfaceAssocTuple
+{
+  /// Interface address of a node.
+  Ipv4Address ifaceAddr;
+  /// Main address of the node.
+  Ipv4Address mainAddr;
+  /// Time at which this tuple expires and must be removed.
+  Time time;
+};
+
+static inline bool
+operator == (const IfaceAssocTuple &a, const IfaceAssocTuple &b)
+{
+  return (a.ifaceAddr == b.ifaceAddr
+          && a.mainAddr == b.mainAddr);
+}
+
+/// A Link Tuple.
+struct LinkTuple
+{
+  /// Interface address of the local node.
+  Ipv4Address localIfaceAddr;
+  /// Interface address of the neighbor node.
+  Ipv4Address neighborIfaceAddr;
+  /// The link is considered bidirectional until this time.
+  Time symTime;
+  /// The link is considered unidirectional until this time.
+  Time asymTime;
+  /// The link is considered lost until this time (used for link layer notification).
+  Time lostTime;
+  /// Time at which this tuple expires and must be removed.
+  Time time;
+};
+
+static inline bool
+operator == (const LinkTuple &a, const LinkTuple &b)
+{
+  return (a.localIfaceAddr == b.localIfaceAddr
+          && a.neighborIfaceAddr == b.neighborIfaceAddr);
+}
+
+/// A Neighbor Tuple.
+struct NeighborTuple
+{
+  /// Main address of a neighbor node.
+  Ipv4Address neighborMainAddr;
+  /// Neighbor Type and Link Type at the four less significative digits.
+  enum Status {
+    STATUS_NOT_SYM = 0, // "not symmetric"
+    STATUS_SYM = 1, // "symmetric"
+  } status;
+  /// A value between 0 and 7 specifying the node's willingness to carry traffic on behalf of other nodes.
+  uint8_t willingness;
+};
+
+static inline bool
+operator == (const NeighborTuple &a, const NeighborTuple &b)
+{
+  return (a.neighborMainAddr == b.neighborMainAddr
+          && a.status == b.status
+          && a.willingness == b.willingness);
+}
+
+/// A 2-hop Tuple.
+struct TwoHopNeighborTuple
+{
+  /// Main address of a neighbor.
+  Ipv4Address neighborMainAddr;
+  /// Main address of a 2-hop neighbor with a symmetric link to nb_main_addr.
+  Ipv4Address twoHopNeighborAddr;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;        // previously called 'time_'
+};
+
+static inline bool
+operator == (const TwoHopNeighborTuple &a, const TwoHopNeighborTuple &b)
+{
+  return (a.neighborMainAddr == b.neighborMainAddr
+          && a.twoHopNeighborAddr == b.twoHopNeighborAddr);
+}
+
+/// An MPR-Selector Tuple.
+struct MprSelectorTuple
+{
+  /// Main address of a node which have selected this node as a MPR.
+  Ipv4Address mainAddr;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;       // previously called 'time_'
+};
+
+static inline bool
+operator == (const MprSelectorTuple &a, const MprSelectorTuple &b)
+{
+  return (a.mainAddr == b.mainAddr);
+}
+
+
+/// The type "list of interface addresses"
+//typedef std::vector<nsaddr_t> addr_list_t;
+
+/// A Duplicate Tuple
+struct DuplicateTuple
+{
+  /// Originator address of the message.
+  Ipv4Address address;
+  /// Message sequence number.
+  uint16_t sequenceNumber;
+  /// Indicates whether the message has been retransmitted or not.
+  bool retransmitted;
+  /// List of interfaces which the message has been received on.
+  std::vector<Ipv4Address> ifaceList;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;
+};
+
+static inline bool
+operator == (const DuplicateTuple &a, const DuplicateTuple &b)
+{
+  return (a.address == b.address
+          && a.sequenceNumber == b.sequenceNumber);
+}
+
+/// A Topology Tuple
+struct TopologyTuple
+{
+  /// Main address of the destination.
+  Ipv4Address destAddr;
+  /// Main address of a node which is a neighbor of the destination.
+  Ipv4Address lastAddr;
+  /// Sequence number.
+  uint16_t sequenceNumber;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;
+};
+
+static inline bool
+operator == (const TopologyTuple &a, const TopologyTuple &b)
+{
+  return (a.destAddr == b.destAddr
+          && a.lastAddr == b.lastAddr
+          && a.sequenceNumber == b.sequenceNumber);
+}
+
+
+typedef std::set<Ipv4Address> 			MprSet;	///< MPR Set type.
+typedef std::vector<MprSelectorTuple>		MprSelectorSet;	///< MPR Selector Set type.
+typedef std::vector<LinkTuple>			LinkSet;	///< Link Set type.
+typedef std::vector<NeighborTuple>		NeighborSet;	///< Neighbor Set type.
+typedef std::vector<TwoHopNeighborTuple>	TwoHopNeighborSet; ///< 2-hop Neighbor Set type.
+typedef std::vector<TopologyTuple>		TopologySet;	///< Topology Set type.
+typedef std::vector<DuplicateTuple>		DuplicateSet;	///< Duplicate Set type.
+typedef std::vector<IfaceAssocTuple>		IfaceAssocSet; ///< Interface Association Set type.
+
+
+}}; // namespace ns3, olsr
+
+#endif  /* __OLSR_REPOSITORIES_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-state.cc	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,438 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/***************************************************************************
+ *   Copyright (C) 2004 by Francisco J. Ros                                *
+ *   fjrm@dif.um.es                                                        *
+ *                                                                         *
+ *   Modified for NS-3 by Gustavo J. A. M. Carneiro on 2007                *
+ *   gjc@inescporto.pt                                                     *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+///
+/// \file	OlsrState.cc
+/// \brief	Implementation of all functions needed for manipulating the internal
+///		state of an OLSR node.
+///
+
+#include "olsr-state.h"
+
+
+namespace ns3 { namespace olsr {
+
+
+/********** MPR Selector Set Manipulation **********/
+
+MprSelectorTuple*
+OlsrState::FindMprSelectorTuple (Ipv4Address const &mainAddr)
+{
+  for (MprSelectorSet::iterator it = m_mprSelectorSet.begin ();
+       it != m_mprSelectorSet.end (); it++)
+    {
+      if (it->mainAddr == mainAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseMprSelectorTuple (const MprSelectorTuple &tuple)
+{
+  for (MprSelectorSet::iterator it = m_mprSelectorSet.begin ();
+       it != m_mprSelectorSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_mprSelectorSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::EraseMprSelectorTuples (const Ipv4Address &mainAddr)
+{
+  for (MprSelectorSet::iterator it = m_mprSelectorSet.begin ();
+       it != m_mprSelectorSet.end (); it++)
+    {
+      if (it->mainAddr == mainAddr)
+        {
+          it = m_mprSelectorSet.erase (it);
+          it--;
+        }
+    }
+}
+
+void
+OlsrState::InsertMprSelectorTuple (MprSelectorTuple const &tuple)
+{
+  m_mprSelectorSet.push_back (tuple);
+}
+
+/********** Neighbor Set Manipulation **********/
+
+NeighborTuple*
+OlsrState::FindNeighborTuple (Ipv4Address const &mainAddr)
+{
+  for (NeighborSet::iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == mainAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+NeighborTuple*
+OlsrState::FindSymNeighborTuple (Ipv4Address const &mainAddr)
+{
+  for (NeighborSet::iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == mainAddr && it->status == NeighborTuple::STATUS_SYM)
+        return &(*it);
+    }
+  return NULL;
+}
+
+NeighborTuple*
+OlsrState::FindNeighborTuple (Ipv4Address const &mainAddr, uint8_t willingness)
+{
+  for (NeighborSet::iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == mainAddr && it->willingness == willingness)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseNeighborTuple (const NeighborTuple &tuple)
+{
+  for (NeighborSet::iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_neighborSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::EraseNeighborTuple (const Ipv4Address &mainAddr)
+{
+  for (NeighborSet::iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == mainAddr)
+        {
+          it = m_neighborSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::InsertNeighborTuple (NeighborTuple const &tuple)
+{
+  m_neighborSet.push_back (tuple);
+}
+
+/********** Neighbor 2 Hop Set Manipulation **********/
+
+TwoHopNeighborTuple*
+OlsrState::FindTwoHopNeighborTuple (Ipv4Address const &neighborMainAddr,
+                                    Ipv4Address const &twoHopNeighborAddr)
+{
+  for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
+       it != m_twoHopNeighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == neighborMainAddr
+          && it->twoHopNeighborAddr == twoHopNeighborAddr)
+        {
+          return &(*it);
+        }
+  }
+  return NULL;
+}
+
+void
+OlsrState::EraseTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
+{
+  for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
+       it != m_twoHopNeighborSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_twoHopNeighborSet.erase(it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::EraseTwoHopNeighborTuples (const Ipv4Address &neighborMainAddr,
+                                      const Ipv4Address &twoHopNeighborAddr)
+{
+  for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
+       it != m_twoHopNeighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == neighborMainAddr
+          && it->twoHopNeighborAddr == twoHopNeighborAddr)
+        {
+          it = m_twoHopNeighborSet.erase (it);
+          it--; // FIXME: is this correct in the case 'it' pointed to the first element?
+        }
+    }
+}
+
+void
+OlsrState::EraseTwoHopNeighborTuples (const Ipv4Address &neighborMainAddr)
+{
+  for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
+       it != m_twoHopNeighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == neighborMainAddr) {
+        it = m_twoHopNeighborSet.erase (it);
+        it--;
+      }
+    }
+}
+
+void
+OlsrState::InsertTwoHopNeighborTuple (TwoHopNeighborTuple const &tuple){
+  m_twoHopNeighborSet.push_back (tuple);
+}
+
+/********** MPR Set Manipulation **********/
+
+bool
+OlsrState::FindMprAddress (Ipv4Address const &addr)
+{
+  MprSet::iterator it = m_mprSet.find (addr);
+  return (it != m_mprSet.end ());
+}
+
+void
+OlsrState::InsertMprAddress (Ipv4Address const & addr)
+{
+  m_mprSet.insert (addr);
+}
+
+void
+OlsrState::ClearMprSet ()
+{
+  m_mprSet.clear ();
+}
+
+/********** Duplicate Set Manipulation **********/
+
+DuplicateTuple*
+OlsrState::FindDuplicateTuple (Ipv4Address const &addr, uint16_t sequenceNumber)
+{
+  for (DuplicateSet::iterator it = m_duplicateSet.begin ();
+       it != m_duplicateSet.end(); it++)
+    {
+      if (it->address == addr && it->sequenceNumber == sequenceNumber)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseDuplicateTuple (const DuplicateTuple &tuple)
+{
+  for (DuplicateSet::iterator it = m_duplicateSet.begin ();
+       it != m_duplicateSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_duplicateSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::InsertDuplicateTuple (DuplicateTuple const &tuple)
+{
+  m_duplicateSet.push_back (tuple);
+}
+
+/********** Link Set Manipulation **********/
+
+LinkTuple*
+OlsrState::FindLinkTuple (Ipv4Address const & ifaceAddr)
+{
+  for (LinkSet::iterator it = m_linkSet.begin ();
+       it != m_linkSet.end (); it++)
+    {
+      if (it->neighborIfaceAddr == ifaceAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+LinkTuple*
+OlsrState::FindSymLinkTuple (Ipv4Address const &ifaceAddr, Time now)
+{
+  for (LinkSet::iterator it = m_linkSet.begin ();
+       it != m_linkSet.end (); it++)
+    {
+      if (it->neighborIfaceAddr == ifaceAddr)
+        {
+          if (it->symTime > now)
+            return &(*it);
+          else
+            break;
+        }
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseLinkTuple (const LinkTuple &tuple)
+{
+  for (LinkSet::iterator it = m_linkSet.begin ();
+       it != m_linkSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_linkSet.erase (it);
+          break;
+        }
+    }
+}
+
+LinkTuple&
+OlsrState::InsertLinkTuple (LinkTuple const &tuple)
+{
+  m_linkSet.push_back (tuple);
+  return m_linkSet.back ();
+}
+
+/********** Topology Set Manipulation **********/
+
+TopologyTuple*
+OlsrState::FindTopologyTuple (Ipv4Address const &destAddr,
+                              Ipv4Address const &lastAddr)
+{
+  for (TopologySet::iterator it = m_topologySet.begin ();
+       it != m_topologySet.end (); it++)
+    {
+      if (it->destAddr == destAddr && it->lastAddr == lastAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+TopologyTuple*
+OlsrState::FindNewerTopologyTuple (Ipv4Address const & lastAddr, uint16_t ansn)
+{
+  for (TopologySet::iterator it = m_topologySet.begin ();
+       it != m_topologySet.end (); it++)
+    {
+      if (it->lastAddr == lastAddr && it->sequenceNumber > ansn)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseTopologyTuple(const TopologyTuple &tuple)
+{
+  for (TopologySet::iterator it = m_topologySet.begin ();
+       it != m_topologySet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_topologySet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::EraseOlderTopologyTuples (const Ipv4Address &lastAddr, uint16_t ansn)
+{
+  for (TopologySet::iterator it = m_topologySet.begin();
+       it != m_topologySet.end(); it++)
+    {
+      if (it->lastAddr == lastAddr && it->sequenceNumber < ansn)
+        {
+          it = m_topologySet.erase (it);
+          it--;
+        }
+    }
+}
+
+void
+OlsrState::InsertTopologyTuple (TopologyTuple const &tuple)
+{
+  m_topologySet.push_back (tuple);
+}
+
+/********** Interface Association Set Manipulation **********/
+
+IfaceAssocTuple*
+OlsrState::FindIfaceAssocTuple (Ipv4Address const &ifaceAddr)
+{
+  for (IfaceAssocSet::iterator it = m_ifaceAssocSet.begin ();
+       it != m_ifaceAssocSet.end (); it++)
+    {
+      if (it->ifaceAddr == ifaceAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseIfaceAssocTuple (const IfaceAssocTuple &tuple)
+{
+  for (IfaceAssocSet::iterator it = m_ifaceAssocSet.begin ();
+       it != m_ifaceAssocSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_ifaceAssocSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::InsertIfaceAssocTuple (const IfaceAssocTuple &tuple)
+{
+  m_ifaceAssocSet.push_back (tuple);
+}
+
+std::vector<Ipv4Address>
+OlsrState::FindNeighborInterfaces (const Ipv4Address &neighborMainAddr) const
+{
+  std::vector<Ipv4Address> retval;
+  for (IfaceAssocSet::const_iterator it = m_ifaceAssocSet.begin ();
+       it != m_ifaceAssocSet.end (); it++)
+    {
+      if (it->mainAddr == neighborMainAddr)
+        retval.push_back (it->ifaceAddr);
+    }
+  return retval;
+}
+
+}}; // namespace ns3, olsr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-state.h	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,147 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/***************************************************************************
+ *   Copyright (C) 2004 by Francisco J. Ros                                *
+ *   fjrm@dif.um.es                                                        *
+ *                                                                         *
+ *   Modified for NS-3 by Gustavo J. A. M. Carneiro on 2007                *
+ *   gjc@inescporto.pt                                                     *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+///
+/// \file	OLSR_state.h
+/// \brief	This header file declares and defines internal state of an OLSR node.
+///
+
+#ifndef __OLSR_state_h__
+#define __OLSR_state_h__
+
+#include "olsr-repositories.h"
+
+namespace ns3 { namespace olsr {
+
+/// This class encapsulates all data structures needed for maintaining internal state of an OLSR node.
+class OlsrState
+{
+  //  friend class Olsr;
+  
+protected:
+  LinkSet m_linkSet;	///< Link Set (RFC 3626, section 4.2.1).
+  NeighborSet m_neighborSet;		///< Neighbor Set (RFC 3626, section 4.3.1).
+  TwoHopNeighborSet m_twoHopNeighborSet;	///< 2-hop Neighbor Set (RFC 3626, section 4.3.2).
+  TopologySet m_topologySet;	///< Topology Set (RFC 3626, section 4.4).
+  MprSet m_mprSet;	///< MPR Set (RFC 3626, section 4.3.3).
+  MprSelectorSet m_mprSelectorSet;	///< MPR Selector Set (RFC 3626, section 4.3.4).
+  DuplicateSet m_duplicateSet;	///< Duplicate Set (RFC 3626, section 3.4).
+  IfaceAssocSet m_ifaceAssocSet;	///< Interface Association Set (RFC 3626, section 4.1).
+
+public:
+
+  // MPR selector
+  const MprSelectorSet & GetMprSelectors () const
+  {
+    return m_mprSelectorSet;
+  }
+  MprSelectorTuple* FindMprSelectorTuple (const Ipv4Address &mainAddr);
+  void EraseMprSelectorTuple (const MprSelectorTuple &tuple);
+  void EraseMprSelectorTuples (const Ipv4Address &mainAddr);
+  void InsertMprSelectorTuple (const MprSelectorTuple &tuple);
+
+  // Neighbor
+  const NeighborSet & GetNeighbors () const
+  {
+    return m_neighborSet;
+  }
+  NeighborTuple* FindNeighborTuple (const Ipv4Address &mainAddr);
+  NeighborTuple* FindSymNeighborTuple (const Ipv4Address &mainAddr);
+  NeighborTuple* FindNeighborTuple (const Ipv4Address &mainAddr,
+                                    uint8_t willingness);
+  void EraseNeighborTuple (const NeighborTuple &neighborTuple);
+  void EraseNeighborTuple (const Ipv4Address &mainAddr);
+  void InsertNeighborTuple (const NeighborTuple &tuple);
+
+  // Two-hop neighbor
+  const TwoHopNeighborSet & GetTwoHopNeighbors () const
+  {
+    return m_twoHopNeighborSet;
+  }
+  TwoHopNeighborTuple* FindTwoHopNeighborTuple (const Ipv4Address &neighbor,
+                                                const Ipv4Address &twoHopNeighbor);
+  void EraseTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
+  void EraseTwoHopNeighborTuples (const Ipv4Address &neighbor);
+  void EraseTwoHopNeighborTuples (const Ipv4Address &neighbor,
+                                  const Ipv4Address &twoHopNeighbor);
+  void InsertTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
+
+  // MPR
+  bool FindMprAddress (const Ipv4Address &address);
+  void InsertMprAddress (const Ipv4Address &address);
+  void ClearMprSet ();
+
+  // Duplicate
+  DuplicateTuple* FindDuplicateTuple (const Ipv4Address &address,
+                                      uint16_t sequenceNumber);
+  void EraseDuplicateTuple (const DuplicateTuple &tuple);
+  void InsertDuplicateTuple (const DuplicateTuple &tuple);
+
+  // Link
+  const LinkSet & GetLinks () const
+  {
+    return m_linkSet;
+  }
+  LinkTuple* FindLinkTuple (const Ipv4Address &ifaceAddr);
+  LinkTuple* FindSymLinkTuple (const Ipv4Address &ifaceAddr, Time time);
+  void EraseLinkTuple (const LinkTuple &tuple);
+  LinkTuple& InsertLinkTuple (const LinkTuple &tuple);
+
+  // Topology
+  const TopologySet & GetTopologySet () const
+  {
+    return m_topologySet;
+  }
+  TopologyTuple* FindTopologyTuple (const Ipv4Address &destAddr,
+                                    const Ipv4Address &lastAddr);
+  TopologyTuple* FindNewerTopologyTuple (const Ipv4Address &lastAddr,
+                                         uint16_t ansn);
+  void EraseTopologyTuple (const TopologyTuple &tuple);
+  void EraseOlderTopologyTuples (const Ipv4Address &lastAddr,
+                                 uint16_t ansn);
+  void InsertTopologyTuple (const TopologyTuple &tuple);
+
+  // Interface association
+  const IfaceAssocSet & GetIfaceAssocSet () const
+  {
+    return m_ifaceAssocSet;
+  }
+  IfaceAssocSet & GetIfaceAssocSetMutable ()
+  {
+    return m_ifaceAssocSet;
+  }
+  IfaceAssocTuple* FindIfaceAssocTuple (const Ipv4Address &ifaceAddr);
+  void EraseIfaceAssocTuple (const IfaceAssocTuple &tuple);
+  void InsertIfaceAssocTuple (const IfaceAssocTuple &tuple);
+
+  // Returns a vector of all interfaces of a given neighbor, with the
+  // exception of the "main" one.
+  std::vector<Ipv4Address>
+  FindNeighborInterfaces (const Ipv4Address &neighborMainAddr) const;
+
+};
+
+}}; // namespace ns3, olsr
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr.cc	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,2135 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/***************************************************************************
+ *   Copyright (C) 2004 by Francisco J. Ros                                *
+ *   fjrm@dif.um.es                                                        *
+ *                                                                         *
+ *   Modified on 2007 for NS-3 by Gustavo J. A. M. Carneiro, INESC Porto   *
+ *                                <gjc@inescporto.pt>                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+///
+/// \file	OLSR.cc
+/// \brief	Implementation of OLSR agent and related classes.
+///
+/// This is the main file of this software because %OLSR's behaviour is
+/// implemented here.
+///
+
+#include <math.h>
+// #include <limits.h>
+// #include <address.h>
+// #include <ip.h>
+// #include <cmu-trace.h>
+#include <map>
+#include "olsr-private.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp.h"
+#include "ns3/internet-node.h"
+#include "ns3/simulator.h"
+#include "ns3/debug.h"
+#include "ns3/random-variable.h"
+
+#include <iomanip>
+
+
+/********** Useful macros **********/
+
+///
+/// \brief Gets the delay between a given time and the current time.
+///
+/// If given time is previous to the current one, then this macro returns
+/// a number close to 0. This is used for scheduling events at a certain moment.
+///
+#define DELAY(time) (((time) < (Simulator::Now ())) ? Seconds (0.000001) : \
+                     (time - Simulator::Now () + Seconds (0.000001)))
+
+
+
+/********** Intervals **********/
+
+/// HELLO messages emission interval.
+#define OLSR_HELLO_INTERVAL	Seconds (2)
+
+/// TC messages emission interval.
+#define OLSR_TC_INTERVAL	Seconds (5)
+
+/// MID messages emission interval.
+#define OLSR_MID_INTERVAL	OLSR_TC_INTERVAL
+
+///
+/// \brief Period at which a node must cite every link and every neighbor.
+///
+/// We only use this value in order to define OLSR_NEIGHB_HOLD_TIME.
+///
+#define OLSR_REFRESH_INTERVAL	Seconds (2)
+
+
+/********** Holding times **********/
+
+/// Neighbor holding time.
+#define OLSR_NEIGHB_HOLD_TIME	(Scalar (3) * OLSR_REFRESH_INTERVAL)
+/// Top holding time.
+#define OLSR_TOP_HOLD_TIME	(Scalar (3) * OLSR_TC_INTERVAL)
+/// Dup holding time.
+#define OLSR_DUP_HOLD_TIME	Seconds (30)
+/// MID holding time.
+#define OLSR_MID_HOLD_TIME	(Scalar (3) * OLSR_MID_INTERVAL)
+
+
+/********** Link types **********/
+
+/// Unspecified link type.
+#define OLSR_UNSPEC_LINK	0
+/// Asymmetric link type.
+#define OLSR_ASYM_LINK		1
+/// Symmetric link type.
+#define OLSR_SYM_LINK		2
+/// Lost link type.
+#define OLSR_LOST_LINK		3
+
+/********** Neighbor types **********/
+
+/// Not neighbor type.
+#define OLSR_NOT_NEIGH		0
+/// Symmetric neighbor type.
+#define OLSR_SYM_NEIGH		1
+/// Asymmetric neighbor type.
+#define OLSR_MPR_NEIGH		2
+
+
+/********** Willingness **********/
+
+/// Willingness for forwarding packets from other nodes: never.
+#define OLSR_WILL_NEVER		0
+/// Willingness for forwarding packets from other nodes: low.
+#define OLSR_WILL_LOW		1
+/// Willingness for forwarding packets from other nodes: medium.
+#define OLSR_WILL_DEFAULT	3
+/// Willingness for forwarding packets from other nodes: high.
+#define OLSR_WILL_HIGH		6
+/// Willingness for forwarding packets from other nodes: always.
+#define OLSR_WILL_ALWAYS	7
+
+
+/********** Miscellaneous constants **********/
+
+/// Maximum allowed jitter.
+#define OLSR_MAXJITTER		(OLSR_HELLO_INTERVAL.GetSeconds () / 4)
+/// Maximum allowed sequence number.
+#define OLSR_MAX_SEQ_NUM	65535
+/// Random number between [0-OLSR_MAXJITTER] used to jitter OLSR packet transmission.
+#define JITTER (Seconds (UniformVariable::GetSingleValue (0, OLSR_MAXJITTER)))
+
+
+#define OLSR_PORT_NUMBER 698
+/// Maximum number of messages per packet.
+#define OLSR_MAX_MSGS		64
+
+/// Maximum number of hellos per message (4 possible link types * 3 possible nb types).
+#define OLSR_MAX_HELLOS		12
+
+/// Maximum number of addresses advertised on a message.
+#define OLSR_MAX_ADDRS		64
+
+
+namespace ns3 {
+
+const InterfaceId Olsr::iid = MakeInterfaceId ("Olsr", Object::iid);
+const ClassId Olsr::cid = MakeClassId< olsr::Olsr, Ptr<Node> > ("Olsr", Olsr::iid);
+
+namespace olsr {
+
+NS_DEBUG_COMPONENT_DEFINE ("Olsr");
+
+
+/********** OLSR class **********/
+
+
+Olsr::Olsr (Ptr<Node> node)
+  :
+  m_useL2Notifications (false),
+  m_helloTimer (OLSR_HELLO_INTERVAL, MakeCallback (&Olsr::HelloTimerExpire, this)),
+  m_tcTimer (OLSR_TC_INTERVAL, MakeCallback (&Olsr::TcTimerExpire, this)),
+  m_midTimer (OLSR_MID_INTERVAL, MakeCallback (&Olsr::MidTimerExpire, this)), 
+  m_queuedMessagesTimer (MakeCallback (&Olsr::SendQueuedMessages, this))
+{
+  SetInterfaceId (Olsr::iid);
+
+  // Aggregate with the Node, so that OLSR dies when the node is destroyed.
+  node->AddInterface (this);
+
+  m_packetSequenceNumber = OLSR_MAX_SEQ_NUM;
+  m_messageSequenceNumber = OLSR_MAX_SEQ_NUM;
+  m_ansn = OLSR_MAX_SEQ_NUM;
+
+  m_helloInterval = OLSR_HELLO_INTERVAL;
+  m_tcInterval = OLSR_TC_INTERVAL;
+  m_midInterval = OLSR_MID_INTERVAL;
+  m_willingness = OLSR_WILL_ALWAYS;
+
+  m_linkTupleTimerFirstTime = true;
+
+  m_ipv4 = node->QueryInterface<Ipv4> (Ipv4::iid);
+  NS_ASSERT (m_ipv4);
+
+  Ptr<SocketFactory> socketFactory = node->QueryInterface<SocketFactory> (Udp::iid);
+
+  m_receiveSocket = socketFactory->CreateSocket ();
+  if (m_receiveSocket->Bind (OLSR_PORT_NUMBER))
+    NS_ASSERT_MSG (false, "Failed to bind() OLSR receive socket");
+
+  m_sendSocket = socketFactory->CreateSocket ();
+  m_sendSocket->Connect (Ipv4Address (0xffffffff), OLSR_PORT_NUMBER);
+
+}
+
+void Olsr::DoDispose ()
+{
+  m_ipv4 = 0;
+  m_receiveSocket->Dispose ();
+  m_receiveSocket = 0;
+  m_sendSocket->Dispose ();
+  m_sendSocket = 0;  
+  m_routingTable->Dispose ();
+  m_routingTable = 0;
+
+  Object::DoDispose ();
+}
+
+void Olsr::Start ()
+{
+  if (m_mainAddress == Ipv4Address ())
+    {
+      Ipv4Address loopback ("127.0.0.1");
+      for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+        {
+          Ipv4Address addr = m_ipv4->GetAddress (i);
+          if (addr != loopback)
+            {
+              m_mainAddress = addr;
+              break;
+            }
+        }
+
+      NS_ASSERT (m_mainAddress != Ipv4Address ());
+    }
+
+  NS_DEBUG ("Starting OLSR on node " << m_mainAddress);
+
+  m_routingTable = Create<RoutingTable> (m_ipv4, m_mainAddress);
+  // Add OLSR as routing protocol, with slightly lower priority than
+  // static routing.
+  m_ipv4->AddRoutingProtocol (m_routingTable, -10);
+
+  if (m_sendSocket->Bind (m_mainAddress, OLSR_PORT_NUMBER))
+    NS_ASSERT_MSG (false, "Failed to bind() OLSR send socket");
+  m_receiveSocket->Recv (MakeCallback (&Olsr::RecvOlsr,  this));
+  m_helloTimer.Expire ();
+  m_tcTimer.Expire ();
+  m_midTimer.Expire ();
+
+  NS_DEBUG ("OLSR on node " << m_mainAddress << " started");
+}
+
+void Olsr::SetMainInterface (uint32_t interface)
+{
+  m_mainAddress = m_ipv4->GetAddress (interface);
+}
+
+
+//
+// \brief Processes an incoming %OLSR packet following RFC 3626 specification.
+void
+Olsr::RecvOlsr (Ptr<Socket> socket,
+                const uint8_t *dataPtr, uint32_t dataSize,
+                const Ipv4Address &sourceAddress,
+                uint16_t sourcePort)
+{
+  NS_DEBUG ("OLSR node " << m_mainAddress << " received a OLSR packet");
+
+  // All routing messages are sent from and to port RT_PORT,
+  // so we check it.
+  NS_ASSERT (sourcePort == OLSR_PORT_NUMBER);
+  
+  Packet packet (dataPtr, dataSize);
+
+  OlsrPacketHeader olsrPacketHeader;
+  packet.RemoveHeader (olsrPacketHeader);
+  NS_ASSERT (olsrPacketHeader.GetPacketLength () >= olsrPacketHeader.GetSize ());
+  uint32_t sizeLeft = olsrPacketHeader.GetPacketLength () - olsrPacketHeader.GetSize ();
+  
+  while (sizeLeft)
+    {
+      OlsrMessageHeader messageHeader;
+      NS_ASSERT (sizeLeft >= messageHeader.GetSize ());
+      if (packet.RemoveHeader (messageHeader) == 0)
+        NS_ASSERT (false);
+      
+      sizeLeft -= messageHeader.GetMessageSize ();
+
+      NS_DEBUG ("Olsr Msg received with type "
+                << std::dec << int (messageHeader.GetMessageType ())
+                << " TTL=" << int (messageHeader.GetTimeToLive ())
+                << " origAddr=" << messageHeader.GetOriginatorAddress ());
+
+      // If ttl is less than or equal to zero, or
+      // the receiver is the same as the originator,
+      // the message must be silently dropped
+      if (messageHeader.GetTimeToLive () == 0
+          || messageHeader.GetOriginatorAddress () == m_mainAddress)
+        {
+          packet.RemoveAtStart (messageHeader.GetMessageSize ()
+                                - messageHeader.GetSize ());
+          continue;
+        }
+
+      // Save the original message payload for forwarding
+      Packet messagePayload = packet.CreateFragment
+        (0, messageHeader.GetMessageSize () - messageHeader.GetSize ());
+      
+      // If the message has been processed it must not be processed again
+      bool do_forwarding = true;
+      DuplicateTuple *duplicated = m_state.FindDuplicateTuple
+        (messageHeader.GetOriginatorAddress (),
+         messageHeader.GetMessageSequenceNumber ());
+      
+      if (duplicated == NULL)
+        {
+          OlsrHelloMessageHeader helloMsg;
+          OlsrTcMessageHeader tcMsg;
+          OlsrMidMessageHeader midMsg;
+
+          switch (messageHeader.GetMessageType ())
+            {
+            case OlsrMessageHeader::HELLO_MESSAGE:
+              helloMsg.SetMessageSize (messageHeader.GetMessageSize () - messageHeader.GetSize ());
+              packet.RemoveHeader (helloMsg);
+              NS_DEBUG ("OLSR node received HELLO message of size " << messageHeader.GetMessageSize ());
+              ProcessHello(messageHeader, helloMsg, m_mainAddress, sourceAddress);
+              break;
+
+            case OlsrMessageHeader::TC_MESSAGE:
+              tcMsg.SetMessageSize (messageHeader.GetMessageSize () - messageHeader.GetSize ());
+              packet.RemoveHeader (tcMsg);
+              NS_DEBUG ("OLSR node received TC message of size " << messageHeader.GetMessageSize ());
+              ProcessTc(messageHeader, tcMsg, sourceAddress);
+              break;
+
+            case OlsrMessageHeader::MID_MESSAGE:
+              midMsg.SetMessageSize (messageHeader.GetMessageSize () - messageHeader.GetSize ());
+              packet.RemoveHeader (midMsg);
+              NS_DEBUG ("OLSR node received MID message of size " << messageHeader.GetMessageSize ());
+              ProcessMid(messageHeader, midMsg, sourceAddress);
+              break;
+
+            default:
+              packet.RemoveAtStart (messageHeader.GetMessageSize () - messageHeader.GetSize ());
+              NS_DEBUG ("OLSR message type " <<
+                        int (messageHeader.GetMessageType ()) <<
+                        " not implemented");
+            }
+        }
+      else
+        {
+          NS_DEBUG ("OLSR message is duplicated, not reading it.");
+          packet.RemoveAtStart (messageHeader.GetMessageSize () - messageHeader.GetSize ());
+      
+          // If the message has been considered for forwarding, it should
+          // not be retransmitted again
+          for (std::vector<Ipv4Address>::const_iterator it = duplicated->ifaceList.begin ();
+               it != duplicated->ifaceList.end(); it++)
+            {
+              if (*it == m_mainAddress)
+                {
+                  do_forwarding = false;
+                  break;
+                }
+            }
+        }
+      
+      if (do_forwarding)
+        {
+          // HELLO messages are never forwarded.
+          // TC and MID messages are forwarded using the default algorithm.
+          // Remaining messages are also forwarded using the default algorithm.
+          if (messageHeader.GetMessageType ()  != OlsrMessageHeader::HELLO_MESSAGE)
+            ForwardDefault (messageHeader, messagePayload, duplicated,
+                            m_mainAddress, sourceAddress);
+        }
+	
+    }
+
+  // After processing all OLSR messages, we must recompute the routing table
+  RoutingTableComputation ();
+}
+
+///
+/// \brief This auxiliary function (defined in RFC 3626) is used for calculating the MPR Set.
+///
+/// \param tuple the neighbor tuple which has the main address of the node we are going to calculate its degree to.
+/// \return the degree of the node.
+///
+int
+Olsr::Degree (NeighborTuple const &tuple)
+{
+  int degree = 0;
+  for (TwoHopNeighborSet::const_iterator it = m_state.GetTwoHopNeighbors ().begin ();
+       it != m_state.GetTwoHopNeighbors ().end (); it++)
+    {
+      TwoHopNeighborTuple const &nb2hop_tuple = *it;
+      if (nb2hop_tuple.neighborMainAddr == tuple.neighborMainAddr)
+        {
+          NeighborTuple *nb_tuple =
+            m_state.FindNeighborTuple (nb2hop_tuple.neighborMainAddr);
+          if (nb_tuple == NULL)
+            degree++;
+        }
+    }
+  return degree;
+}
+
+///
+/// \brief Computates MPR set of a node following RFC 3626 hints.
+///
+void
+Olsr::MprComputation()
+{
+  // MPR computation should be done for each interface. See section 8.3.1
+  // (RFC 3626) for details.
+	
+  m_state.ClearMprSet ();
+  
+  // N is the subset of neighbors of the node, which are
+  // neighbor "of the interface I"
+  NeighborSet N;
+  for (NeighborSet::const_iterator it = m_state.GetNeighbors ().begin();
+       it != m_state.GetNeighbors ().end (); it++)
+    {
+      if ((*it).status == NeighborTuple::STATUS_SYM) // I think that we need this check
+        N.push_back (*it);
+    }
+	
+  // N2 is the set of 2-hop neighbors reachable from "the interface
+  // I", excluding:
+  // (i)   the nodes only reachable by members of N with willingness WILL_NEVER
+  // (ii)  the node performing the computation
+  // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
+  //       link to this node on some interface.
+  TwoHopNeighborSet N2;
+  for (TwoHopNeighborSet::const_iterator it = m_state.GetTwoHopNeighbors ().begin ();
+       it != m_state.GetTwoHopNeighbors ().end (); it++)
+    {
+      TwoHopNeighborTuple const &twoHopNeigh = *it;
+      bool ok = true;
+      NeighborTuple *nb_tuple = m_state.FindSymNeighborTuple (twoHopNeigh.neighborMainAddr);
+      if (nb_tuple == NULL)
+        {
+          ok = false;
+        }
+      else
+        {
+          nb_tuple = m_state.FindNeighborTuple (twoHopNeigh.neighborMainAddr, OLSR_WILL_NEVER);
+          if (nb_tuple != NULL)
+            {
+              ok = false;
+            }
+          else
+            {
+              nb_tuple = m_state.FindSymNeighborTuple (twoHopNeigh.neighborMainAddr);
+              if (nb_tuple != NULL)
+                ok = false;
+            }
+        }
+
+      if (ok)
+        N2.push_back (twoHopNeigh);
+    }
+	
+  // 1. Start with an MPR set made of all members of N with
+  // N_willingness equal to WILL_ALWAYS
+  for (NeighborSet::const_iterator it = N.begin (); it != N.end (); it++)
+    {
+      NeighborTuple const &nb_tuple = *it;
+      if (nb_tuple.willingness == OLSR_WILL_ALWAYS)
+        m_state.InsertMprAddress (nb_tuple.neighborMainAddr);
+    }
+  
+  // 2. Calculate D(y), where y is a member of N, for all nodes in N.
+  // We will do this later.
+  // FIXME
+	
+  // 3. Add to the MPR set those nodes in N, which are the *only*
+  // nodes to provide reachability to a node in N2. Remove the
+  // nodes from N2 which are now covered by a node in the MPR set.
+  MprSet foundset;
+  std::set<Ipv4Address> deleted_addrs;
+  for (TwoHopNeighborSet::iterator it = N2.begin (); it != N2.end (); it++)
+    {
+      TwoHopNeighborTuple const &nb2hop_tuple1 = *it;
+		
+      MprSet::const_iterator pos = foundset.find (nb2hop_tuple1.twoHopNeighborAddr);
+      if (pos != foundset.end ())
+        continue;
+		
+      bool found = false;
+      for (NeighborSet::const_iterator it2 = N.begin ();
+           it2 != N.end (); it2++)
+        {
+          if ((*it2).neighborMainAddr == nb2hop_tuple1.neighborMainAddr) {
+            found = true;
+            break;
+          }
+        }
+      if (!found)
+        continue;
+		
+      found = false;
+      for (TwoHopNeighborSet::const_iterator it2 = it + 1;
+           it2 != N2.end (); it2++)
+        {
+          TwoHopNeighborTuple const &nb2hop_tuple2 = *it2;
+          if (nb2hop_tuple1.twoHopNeighborAddr == nb2hop_tuple2.twoHopNeighborAddr)
+            {
+              foundset.insert (nb2hop_tuple1.twoHopNeighborAddr);
+              found = true;
+              break;
+            }
+        }
+      if (!found)
+        {
+          m_state.InsertMprAddress (nb2hop_tuple1.neighborMainAddr);
+          
+          for (TwoHopNeighborSet::iterator it2 = it + 1; it2 != N2.end (); it2++)
+            {
+              TwoHopNeighborTuple const &nb2hop_tuple2 = *it2;
+              if (nb2hop_tuple1.neighborMainAddr == nb2hop_tuple2.neighborMainAddr)
+                {
+                  deleted_addrs.insert (nb2hop_tuple2.twoHopNeighborAddr);
+                  it2 = N2.erase (it2);
+                  it2--;
+                }
+            }
+          it = N2.erase (it);
+          it--;
+        }
+		
+      for (std::set<Ipv4Address>::iterator it2 = deleted_addrs.begin ();
+           it2 != deleted_addrs.end ();
+           it2++)
+        {
+          for (TwoHopNeighborSet::iterator it3 = N2.begin ();
+               it3 != N2.end ();
+               it3++)
+            {
+              if ((*it3).twoHopNeighborAddr == *it2)
+                {
+                  it3 = N2.erase (it3);
+                  it3--;
+                  // I have to reset the external iterator because it
+                  // may have been invalidated by the latter deletion
+                  it = N2.begin ();
+                  it--;
+                }
+            }
+        }
+      deleted_addrs.clear ();
+    }
+	
+  // 4. While there exist nodes in N2 which are not covered by at
+  // least one node in the MPR set:
+  while (N2.begin () != N2.end ())
+    {
+      // 4.1. For each node in N, calculate the reachability, i.e., the
+      // number of nodes in N2 which are not yet covered by at
+      // least one node in the MPR set, and which are reachable
+      // through this 1-hop neighbor
+      std::map<int, std::vector<const NeighborTuple *> > reachability;
+      std::set<int> rs;
+      for (NeighborSet::iterator it = N.begin(); it != N.end(); it++)
+        {
+          NeighborTuple const &nb_tuple = *it;
+          int r = 0;
+          for (TwoHopNeighborSet::iterator it2 = N2.begin (); it2 != N2.end (); it2++)
+            {
+              TwoHopNeighborTuple const &nb2hop_tuple = *it2;
+              if (nb_tuple.neighborMainAddr == nb2hop_tuple.neighborMainAddr)
+                r++;
+            }
+          rs.insert (r);
+          reachability[r].push_back (&nb_tuple);
+        }
+      
+      // 4.2. Select as a MPR the node with highest N_willingness among
+      // the nodes in N with non-zero reachability. In case of
+      // multiple choice select the node which provides
+      // reachability to the maximum number of nodes in N2. In
+      // case of multiple nodes providing the same amount of
+      // reachability, select the node as MPR whose D(y) is
+      // greater. Remove the nodes from N2 which are now covered
+      // by a node in the MPR set.
+      NeighborTuple const *max = NULL;
+      int max_r = 0;
+      for (std::set<int>::iterator it = rs.begin (); it != rs.end (); it++)
+        {
+          int r = *it;
+          if (r > 0)
+            {
+              for (std::vector<const NeighborTuple *>::iterator it2 = reachability[r].begin ();
+                   it2 != reachability[r].end ();
+                   it2++)
+                {
+                  const NeighborTuple *nb_tuple = *it2;
+                  if (max == NULL || nb_tuple->willingness > max->willingness)
+                    {
+                      max = nb_tuple;
+                      max_r = r;
+                    }
+                  else if (nb_tuple->willingness == max->willingness)
+                    {
+                      if (r > max_r)
+                        {
+                          max = nb_tuple;
+                          max_r = r;
+                        }
+                      else if (r == max_r)
+                        {
+                          if (Degree (*nb_tuple) > Degree (*max))
+                            {
+                              max = nb_tuple;
+                              max_r = r;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+      if (max != NULL)
+        {
+          m_state.InsertMprAddress (max->neighborMainAddr);
+          std::set<Ipv4Address> nb2hop_addrs;
+          for (TwoHopNeighborSet::iterator it = N2.begin ();
+               it != N2.end (); it++)
+            {
+              TwoHopNeighborTuple const &nb2hop_tuple = *it;
+              if (nb2hop_tuple.neighborMainAddr == max->neighborMainAddr)
+                {
+                  nb2hop_addrs.insert (nb2hop_tuple.twoHopNeighborAddr);
+                  it = N2.erase (it);
+                  it--;
+                }
+            }
+          for (TwoHopNeighborSet::iterator it = N2.begin ();
+               it != N2.end (); it++)
+            {
+              TwoHopNeighborTuple const &nb2hop_tuple = *it;
+              std::set<Ipv4Address>::iterator it2 =
+                nb2hop_addrs.find (nb2hop_tuple.twoHopNeighborAddr);
+              if (it2 != nb2hop_addrs.end ())
+                {
+                  it = N2.erase (it);
+                  it--;
+                }
+            }
+        }
+    }
+}
+
+///
+/// \brief Gets the main address associated with a given interface address.
+///
+/// \param iface_addr the interface address.
+/// \return the corresponding main address.
+///
+Ipv4Address
+Olsr::GetMainAddress (Ipv4Address iface_addr)
+{
+  IfaceAssocTuple *tuple =
+    m_state.FindIfaceAssocTuple (iface_addr);
+  
+  if (tuple != NULL)
+    return tuple->mainAddr;
+  else
+    return iface_addr;
+}
+
+///
+/// \brief Creates the routing table of the node following RFC 3626 hints.
+///
+void
+Olsr::RoutingTableComputation ()
+{
+  // 1. All the entries from the routing table are removed.
+  m_routingTable->Clear ();
+	
+  // 2. The new routing entries are added starting with the
+  // symmetric neighbors (h=1) as the destination nodes.
+  for (NeighborSet::const_iterator it = m_state.GetNeighbors ().begin ();
+       it != m_state.GetNeighbors ().end(); it++)
+    {
+      NeighborTuple const &nb_tuple = *it;
+      if (nb_tuple.status == NeighborTuple::STATUS_SYM)
+        {
+          bool nb_main_addr = false;
+          const LinkTuple *lt = NULL;
+          for (LinkSet::const_iterator it2 = m_state.GetLinks ().begin();
+               it2 != m_state.GetLinks ().end(); it2++)
+            {
+              LinkTuple const &link_tuple = *it2;
+              if ((GetMainAddress (link_tuple.neighborIfaceAddr)
+                   == nb_tuple.neighborMainAddr)
+                  && link_tuple.time >= Simulator::Now ())
+                {
+                  lt = &link_tuple;
+                  m_routingTable->AddEntry (link_tuple.neighborIfaceAddr,
+                                            link_tuple.neighborIfaceAddr,
+                                            link_tuple.localIfaceAddr,
+                                            1);
+                  if (link_tuple.neighborIfaceAddr
+                      == nb_tuple.neighborMainAddr)
+                    nb_main_addr = true;
+                }
+            }
+          if (!nb_main_addr && lt != NULL)
+            {
+              m_routingTable->AddEntry(nb_tuple.neighborMainAddr,
+                                       lt->neighborIfaceAddr,
+                                       lt->localIfaceAddr,
+                                       1);
+            }
+        }
+    }
+  
+  // N2 is the set of 2-hop neighbors reachable from this node, excluding:
+  // (i)   the nodes only reachable by members of N with willingness WILL_NEVER
+  // (ii)  the node performing the computation
+  // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
+  //       link to this node on some interface.
+  for (TwoHopNeighborSet::const_iterator it = m_state.GetTwoHopNeighbors ().begin ();
+       it != m_state.GetTwoHopNeighbors ().end (); it++)
+    {
+      TwoHopNeighborTuple const &nb2hop_tuple = *it;
+      bool ok = true;
+      NeighborTuple *nb_tuple = m_state.FindSymNeighborTuple
+        (nb2hop_tuple.neighborMainAddr);
+      if (nb_tuple == NULL)
+        ok = false;
+      else
+        {
+          nb_tuple = m_state.FindNeighborTuple (nb2hop_tuple.neighborMainAddr,
+                                                OLSR_WILL_NEVER);
+          if (nb_tuple != NULL)
+            ok = false;
+          else
+            {
+              nb_tuple = m_state.FindSymNeighborTuple (nb2hop_tuple.twoHopNeighborAddr);
+
+              if (nb_tuple != NULL)
+                ok = false;
+            }
+        }
+
+      // 3. For each node in N2 create a new entry in the routing table
+      if (ok)
+        {
+          RoutingTableEntry entry;
+          bool found_entry = m_routingTable->Lookup (nb2hop_tuple.neighborMainAddr, entry);
+          NS_ASSERT (found_entry);
+          m_routingTable->AddEntry (nb2hop_tuple.twoHopNeighborAddr,
+                                    entry.nextAddr,
+                                    entry.interface,
+                                    2);
+        }
+    }
+  
+  for (uint32_t h = 2; ; h++)
+    {
+      bool added = false;
+		
+      // 4.1. For each topology entry in the topology table, if its
+      // T_dest_addr does not correspond to R_dest_addr of any
+      // route entry in the routing table AND its T_last_addr
+      // corresponds to R_dest_addr of a route entry whose R_dist
+      // is equal to h, then a new route entry MUST be recorded in
+      // the routing table (if it does not already exist)
+      for (TopologySet::const_iterator it = m_state.GetTopologySet ().begin ();
+           it != m_state.GetTopologySet ().end ();
+           it++)
+        {
+          TopologyTuple const &topology_tuple = *it;
+          RoutingTableEntry entry1, entry2;
+          bool have_entry1 = m_routingTable->Lookup (topology_tuple.destAddr, entry1);
+          bool have_entry2 = m_routingTable->Lookup (topology_tuple.lastAddr, entry2);
+          if (!have_entry1 && have_entry2 && entry2.distance == h)
+            {
+              m_routingTable->AddEntry (topology_tuple.destAddr,
+                                        entry2.nextAddr,
+                                        entry2.interface,
+                                        h + 1);
+              added = true;
+            }
+        }
+		
+      // 5. For each entry in the multiple interface association base
+      // where there exists a routing entry such that:
+      //	R_dest_addr  == I_main_addr  (of the multiple interface association entry)
+      // AND there is no routing entry such that:
+      //	R_dest_addr  == I_iface_addr
+      // then a route entry is created in the routing table
+      for (IfaceAssocSet::const_iterator it = m_state.GetIfaceAssocSet ().begin ();
+           it != m_state.GetIfaceAssocSet ().end ();
+           it++)
+        {
+          IfaceAssocTuple const &tuple = *it;
+          RoutingTableEntry entry1, entry2;
+          bool have_entry1 = m_routingTable->Lookup (tuple.mainAddr, entry1);
+          bool have_entry2 = m_routingTable->Lookup (tuple.ifaceAddr, entry2);
+          if (have_entry1 && !have_entry2)
+            {
+              m_routingTable->AddEntry (tuple.ifaceAddr,
+                                        entry1.nextAddr,
+                                        entry1.interface,
+                                        entry1.distance);
+              added = true;
+            }
+        }
+
+      if (!added)
+        break;
+    }
+}
+
+
+///
+/// \brief Processes a HELLO message following RFC 3626 specification.
+///
+/// Link sensing and population of the Neighbor Set, 2-hop Neighbor Set and MPR
+/// Selector Set are performed.
+///
+/// \param msg the %OLSR message which contains the HELLO message.
+/// \param receiver_iface the address of the interface where the message was received from.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+Olsr::ProcessHello (const OlsrMessageHeader &msg,
+                    const OlsrHelloMessageHeader &hello,
+                    const Ipv4Address &receiverIface,
+                    const Ipv4Address &senderIface)
+{
+  LinkSensing (msg, hello, receiverIface, senderIface);
+  PopulateNeighborSet (msg, hello);
+  PopulateTwoHopNeighborSet (msg, hello);
+  MprComputation ();
+  PopulateMprSelectorSet (msg, hello);
+}
+
+///
+/// \brief Processes a TC message following RFC 3626 specification.
+///
+/// The Topology Set is updated (if needed) with the information of
+/// the received TC message.
+///
+/// \param msg the %OLSR message which contains the TC message.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+Olsr::ProcessTc (const OlsrMessageHeader &msg,
+                 const OlsrTcMessageHeader &tc,
+                 const Ipv4Address &senderIface)
+{
+  Time now = Simulator::Now ();
+	
+  // 1. If the sender interface of this message is not in the symmetric
+  // 1-hop neighborhood of this node, the message MUST be discarded.
+  LinkTuple *link_tuple = m_state.FindSymLinkTuple (senderIface, now);
+  if (link_tuple == NULL)
+    return;
+	
+  // 2. If there exist some tuple in the topology set where:
+  // 	T_last_addr == originator address AND
+  // 	T_seq       >  ANSN,
+  // then further processing of this TC message MUST NOT be
+  // performed.
+  TopologyTuple *topologyTuple =
+    m_state.FindNewerTopologyTuple (msg.GetOriginatorAddress (), tc.GetAnsn ());
+  if (topologyTuple != NULL)
+    return;
+	
+  // 3. All tuples in the topology set where:
+  //	T_last_addr == originator address AND
+  //	T_seq       <  ANSN
+  // MUST be removed from the topology set.
+  m_state.EraseOlderTopologyTuples (msg.GetOriginatorAddress (), tc.GetAnsn ());
+
+  // 4. For each of the advertised neighbor main address received in
+  // the TC message:
+  for (std::vector<Ipv4Address>::const_iterator i = tc.GetNeighborAddresses ().begin ();
+       i != tc.GetNeighborAddresses ().end (); i++)
+    {
+      const Ipv4Address &addr = *i;
+      // 4.1. If there exist some tuple in the topology set where:
+      // 	T_dest_addr == advertised neighbor main address, AND
+      // 	T_last_addr == originator address,
+      // then the holding time of that tuple MUST be set to:
+      // 	T_time      =  current time + validity time.
+      TopologyTuple *topologyTuple =
+        m_state.FindTopologyTuple (addr, msg.GetOriginatorAddress ());
+
+      if (topologyTuple != NULL)
+        {
+          topologyTuple->expirationTime = now + msg.GetVTime ();
+        }
+      else
+        {
+          // 4.2. Otherwise, a new tuple MUST be recorded in the topology
+          // set where:
+          //	T_dest_addr = advertised neighbor main address,
+          //	T_last_addr = originator address,
+          //	T_seq       = ANSN,
+          //	T_time      = current time + validity time.
+          TopologyTuple topologyTuple;;
+          topologyTuple.destAddr = addr;
+          topologyTuple.lastAddr = msg.GetOriginatorAddress ();
+          topologyTuple.sequenceNumber = tc.GetAnsn ();
+          topologyTuple.expirationTime = now + msg.GetVTime ();
+          AddTopologyTuple (topologyTuple);
+
+          // Schedules topology tuple deletion
+          Simulator::Schedule (DELAY (topologyTuple.expirationTime),
+                               &Olsr::TopologyTupleTimerExpire,
+                               this, topologyTuple);
+        }
+    }
+}
+
+///
+/// \brief Processes a MID message following RFC 3626 specification.
+///
+/// The Interface Association Set is updated (if needed) with the information
+/// of the received MID message.
+///
+/// \param msg the %OLSR message which contains the MID message.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+Olsr::ProcessMid (const OlsrMessageHeader &msg,
+                  const OlsrMidMessageHeader &mid,
+                  const Ipv4Address &senderIface)
+{
+  Time now = Simulator::Now ();
+	
+  // 1. If the sender interface of this message is not in the symmetric
+  // 1-hop neighborhood of this node, the message MUST be discarded.
+  LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderIface, now);
+  if (linkTuple == NULL)
+    return;
+	
+  // 2. For each interface address listed in the MID message
+  const std::vector<Ipv4Address> &addrs = mid.GetInterfaceAddresses ();
+  for (std::vector<Ipv4Address>::const_iterator i = addrs.begin ();
+       i != addrs.end (); i++)
+    {
+      bool updated = false;
+      IfaceAssocSet &ifaceAssoc = m_state.GetIfaceAssocSetMutable ();
+      for (IfaceAssocSet::iterator tuple = ifaceAssoc.begin();
+           tuple != ifaceAssoc.end(); tuple++)
+        {
+          if (tuple->ifaceAddr == *i
+              && tuple->mainAddr == msg.GetOriginatorAddress ())
+            {
+              tuple->time = now + msg.GetVTime ();
+              updated = true;
+            }
+        }
+      if (!updated)
+        {
+          IfaceAssocTuple tuple;
+          tuple.ifaceAddr = *i;
+          tuple.mainAddr = msg.GetOriginatorAddress ();
+          tuple.time = now + msg.GetVTime ();
+          AddIfaceAssocTuple (tuple);
+          // Schedules iface association tuple deletion
+          Simulator::Schedule (DELAY (tuple.time),
+                               &Olsr::IfaceAssocTupleTimerExpire, this, tuple);
+        }
+    }
+}
+
+
+///
+/// \brief OLSR's default forwarding algorithm.
+///
+/// See RFC 3626 for details.
+///
+/// \param p the %OLSR packet which has been received.
+/// \param msg the %OLSR message which must be forwarded.
+/// \param dup_tuple NULL if the message has never been considered for forwarding,
+/// or a duplicate tuple in other case.
+/// \param local_iface the address of the interface where the message was received from.
+///
+void
+Olsr::ForwardDefault (OlsrMessageHeader olsrMessage,
+                      Packet messagePayload,
+                      DuplicateTuple *duplicated,
+                      const Ipv4Address &localIface,
+                      const Ipv4Address &senderAddress)
+{
+  Time now = Simulator::Now ();
+  
+  // If the sender interface address is not in the symmetric
+  // 1-hop neighborhood the message must not be forwarded
+  LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderAddress, now);
+  if (linkTuple == NULL)
+    return;
+
+  // If the message has already been considered for forwarding,
+  // it must not be retransmitted again
+  if (duplicated != NULL && duplicated->retransmitted)
+    {
+//       debug("%f: Node %d does not forward a message received"
+//             " from %d because it is duplicated\n",
+//             Simulator::Now (),
+//             OLSR::node_id(ra_addr()),
+//             OLSR::node_id(dup_tuple->addr()));
+      return;
+    }
+	
+  // If the sender interface address is an interface address
+  // of a MPR selector of this node and ttl is greater than 1,
+  // the message must be retransmitted
+  bool retransmitted = false;
+  if (olsrMessage.GetTimeToLive () > 1)
+    {
+      MprSelectorTuple *mprselTuple =
+        m_state.FindMprSelectorTuple (GetMainAddress (senderAddress));
+      if (mprselTuple != NULL)
+        {
+          olsrMessage.SetTimeToLive (olsrMessage.GetTimeToLive () - 1);
+          olsrMessage.SetHopCount (olsrMessage.GetHopCount () + 1);
+          // We have to introduce a random delay to avoid
+          // synchronization with neighbors.
+          messagePayload.AddHeader (olsrMessage);
+          QueueMessage (messagePayload, JITTER);
+          retransmitted = true;
+        }
+    }
+	
+  // Update duplicate tuple...
+  if (duplicated != NULL)
+    {
+      duplicated->expirationTime = now + OLSR_DUP_HOLD_TIME;
+      duplicated->retransmitted = retransmitted;
+      duplicated->ifaceList.push_back (localIface);
+    }
+  // ...or create a new one
+  else
+    {
+      DuplicateTuple newDup;
+      newDup.address = olsrMessage.GetOriginatorAddress ();
+      newDup.sequenceNumber = olsrMessage.GetMessageSequenceNumber ();
+      newDup.expirationTime = now + OLSR_DUP_HOLD_TIME;
+      newDup.retransmitted = retransmitted;
+      newDup.ifaceList.push_back (localIface);
+      AddDuplicateTuple (newDup);
+      // Schedule dup tuple deletion
+      Simulator::Schedule (OLSR_DUP_HOLD_TIME,
+                           &Olsr::DupTupleTimerExpire, this, newDup);
+    }
+}
+
+///
+/// \brief Enques an %OLSR message which will be sent with a delay of (0, delay].
+///
+/// This buffering system is used in order to piggyback several %OLSR messages in
+/// a same %OLSR packet.
+///
+/// \param msg the %OLSR message which must be sent.
+/// \param delay maximum delay the %OLSR message is going to be buffered.
+///
+void
+Olsr::QueueMessage (Packet message, Time delay)
+{
+  m_queuedMessages.push_back (message);
+  if (not m_queuedMessagesTimer.IsRunning ())
+    {
+      m_queuedMessagesTimer.SetInterval (delay);
+      m_queuedMessagesTimer.Schedule ();
+    }
+}
+
+void
+Olsr::SendPacket (Packet packet)
+{
+  NS_DEBUG ("OLSR node " << m_mainAddress << " sending a OLSR packet");
+  // Add a header
+  OlsrPacketHeader header;
+  header.SetPacketLength (header.GetSize () + packet.GetSize ());
+  header.SetPacketSequenceNumber (GetPacketSequenceNumber ());
+  packet.AddHeader (header);
+  // Send it
+  m_sendSocket->Send (packet.PeekData (), packet.GetSize ());
+}
+
+///
+/// \brief Creates as many %OLSR packets as needed in order to send all buffered
+/// %OLSR messages.
+///
+/// Maximum number of messages which can be contained in an %OLSR packet is
+/// dictated by OLSR_MAX_MSGS constant.
+///
+void
+Olsr::SendQueuedMessages ()
+{
+  Packet packet;
+  int numMessages = 0;
+
+  NS_DEBUG ("Olsr node " << m_mainAddress << ": SendQueuedMessages");
+
+  for (std::vector<Packet>::const_iterator messagePkt = m_queuedMessages.begin ();
+       messagePkt != m_queuedMessages.end ();
+       messagePkt++)
+    {
+      packet.AddAtEnd (*messagePkt);
+      if (++numMessages == OLSR_MAX_MSGS)
+        {
+          SendPacket (packet);
+          // Reset variables for next packet
+          numMessages = 0;
+          packet = Packet ();
+        }
+    }
+
+  if (packet.GetSize ())
+    {
+      SendPacket (packet);
+    }
+
+  m_queuedMessages.clear ();
+}
+
+///
+/// \brief Creates a new %OLSR HELLO message which is buffered for being sent later on.
+///
+void
+Olsr::SendHello ()
+{
+  OlsrMessageHeader msg;
+  OlsrHelloMessageHeader hello;
+  Time now = Simulator::Now ();
+
+  msg.SetMessageType (OlsrMessageHeader::HELLO_MESSAGE);
+  msg.SetVTime (OLSR_NEIGHB_HOLD_TIME);
+  msg.SetOriginatorAddress (m_mainAddress);
+  msg.SetTimeToLive (1);
+  msg.SetHopCount (0);
+  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+
+  hello.SetHTime (m_helloInterval);
+  hello.SetWillingness (m_willingness);
+
+  std::vector<OlsrHelloMessageHeader::LinkMessage> linkMessages;
+	
+  for (LinkSet::const_iterator link_tuple = m_state.GetLinks ().begin ();
+       link_tuple != m_state.GetLinks ().end (); link_tuple++)
+    {
+      if (not (link_tuple->localIfaceAddr == m_mainAddress
+               && link_tuple->time >= now))
+        continue;
+
+      uint8_t link_type, nb_type;
+			
+      // Establishes link type
+      if (m_useL2Notifications && link_tuple->lostTime >= now)
+        {
+          link_type = OLSR_LOST_LINK;
+        }
+      else if (link_tuple->symTime >= now)
+        {
+          link_type = OLSR_SYM_LINK;
+        }
+      else if (link_tuple->asymTime >= now)
+        {
+          link_type = OLSR_ASYM_LINK;
+        }
+      else
+        {
+          link_type = OLSR_LOST_LINK;
+        }
+      // Establishes neighbor type.
+      if (m_state.FindMprAddress (GetMainAddress (link_tuple->neighborIfaceAddr)))
+        {
+          nb_type = OLSR_MPR_NEIGH;
+        }
+      else
+        {
+          bool ok = false;
+          for (NeighborSet::const_iterator nb_tuple = m_state.GetNeighbors ().begin ();
+               nb_tuple != m_state.GetNeighbors ().end ();
+               nb_tuple++)
+            {
+              if (nb_tuple->neighborMainAddr == link_tuple->neighborIfaceAddr)
+                {
+                  if (nb_tuple->status == NeighborTuple::STATUS_SYM)
+                    {
+                      nb_type = OLSR_SYM_NEIGH;
+                    }
+                  else if (nb_tuple->status == NeighborTuple::STATUS_NOT_SYM)
+                    {
+                      nb_type = OLSR_NOT_NEIGH;
+                    }
+                  else
+                    {
+                      NS_ASSERT (!"There is a neighbor tuple with an unknown status!\n");
+                    }
+                  ok = true;
+                  break;
+                }
+            }
+          if (!ok)
+            {
+              NS_ASSERT (!"Link tuple has no corresponding neighbor tuple\n");
+            }
+        }
+
+      OlsrHelloMessageHeader::LinkMessage linkMessage;
+      linkMessage.linkCode = (link_type & 0x03) | ((nb_type << 2) & 0x0f);
+      linkMessage.neighborInterfaceAddresses.push_back
+        (link_tuple->neighborIfaceAddr);
+
+      std::vector<Ipv4Address> interfaces =
+        m_state.FindNeighborInterfaces (link_tuple->neighborIfaceAddr);
+
+      linkMessage.neighborInterfaceAddresses.insert
+        (linkMessage.neighborInterfaceAddresses.end (),
+         interfaces.begin (), interfaces.end ());
+
+      linkMessages.push_back (linkMessage);
+    }
+  hello.SetLinkMessages (linkMessages);
+  Packet packet;
+  packet.AddHeader (hello);
+  NS_DEBUG ("OLSR HELLO message size: " << int (packet.GetSize () + msg.GetSize ())
+            << " (with " << int (linkMessages.size ()) << " link messages)");
+  msg.SetMessageSize (packet.GetSize () + msg.GetSize ());
+  packet.AddHeader (msg);
+  QueueMessage (packet, JITTER);
+}
+
+///
+/// \brief Creates a new %OLSR TC message which is buffered for being sent later on.
+///
+void
+Olsr::SendTc ()
+{
+  OlsrMessageHeader msg;
+  OlsrTcMessageHeader tc;
+
+  msg.SetMessageType (OlsrMessageHeader::TC_MESSAGE);
+  msg.SetVTime (OLSR_TOP_HOLD_TIME);
+  msg.SetOriginatorAddress (m_mainAddress);
+  msg.SetTimeToLive (255);
+  msg.SetHopCount (0);
+  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+  
+  tc.SetAnsn (m_ansn);
+  std::vector<Ipv4Address> neighbors;
+  for (MprSelectorSet::const_iterator mprsel_tuple = m_state.GetMprSelectors ().begin();
+       mprsel_tuple != m_state.GetMprSelectors ().end(); mprsel_tuple++)
+    {
+      neighbors.push_back (mprsel_tuple->mainAddr);
+    }
+  tc.SetNeighborAddresses (neighbors);
+
+  Packet packet;
+  packet.AddHeader (tc);
+  msg.SetMessageSize (packet.GetSize () + msg.GetSize ());
+  packet.AddHeader (msg);
+  QueueMessage (packet, JITTER);
+}
+
+///
+/// \brief Creates a new %OLSR MID message which is buffered for being sent later on.
+///
+void
+Olsr::SendMid ()
+{
+  OlsrMessageHeader msg;
+  OlsrMidMessageHeader mid;
+
+  // A node which has only a single interface address participating in
+  // the MANET (i.e., running OLSR), MUST NOT generate any MID
+  // message.
+
+  // A node with several interfaces, where only one is participating
+  // in the MANET and running OLSR (e.g., a node is connected to a
+  // wired network as well as to a MANET) MUST NOT generate any MID
+  // messages.
+
+  // A node with several interfaces, where more than one is
+  // participating in the MANET and running OLSR MUST generate MID
+  // messages as specified.
+
+  // [ Note: assuming here that all interfaces participate in the
+  // MANET; later we may want to make this configurable. ]
+
+  Ipv4Address loopback ("127.0.0.1");
+  std::vector<Ipv4Address> addresses;
+  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+    {
+      Ipv4Address addr = m_ipv4->GetAddress (i);
+      if (addr != m_mainAddress && addr != loopback)
+        addresses.push_back (addr);
+    }
+  if (addresses.size () == 0)
+    return;
+  mid.SetInterfaceAddresses (addresses);
+  
+  msg.SetMessageType (OlsrMessageHeader::MID_MESSAGE);
+  msg.SetVTime (OLSR_MID_HOLD_TIME);
+  msg.SetOriginatorAddress (m_mainAddress);
+  msg.SetTimeToLive (255);
+  msg.SetHopCount (0);
+  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+
+  Packet packet;
+  packet.AddHeader (mid);
+  msg.SetMessageSize (packet.GetSize () + msg.GetSize ());
+  packet.AddHeader (msg);
+  QueueMessage (packet, JITTER);
+}
+
+///
+/// \brief	Updates Link Set according to a new received HELLO message (following RFC 3626
+///		specification). Neighbor Set is also updated if needed.
+///
+/// \param msg the OLSR message which contains the HELLO message.
+/// \param receiver_iface the address of the interface where the message was received from.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+Olsr::LinkSensing (const OlsrMessageHeader &msg,
+                   const OlsrHelloMessageHeader &hello,
+                   const Ipv4Address &receiverIface,
+                   const Ipv4Address &senderIface)
+{
+  Time now = Simulator::Now ();
+  bool updated = false;
+  bool created = false;
+	
+  LinkTuple *link_tuple = m_state.FindLinkTuple (senderIface);
+  if (link_tuple == NULL)
+    {
+      LinkTuple newLinkTuple;
+      // We have to create a new tuple
+      newLinkTuple.neighborIfaceAddr = senderIface;
+      newLinkTuple.localIfaceAddr = receiverIface;
+      newLinkTuple.symTime = now - Seconds (1);
+      newLinkTuple.lostTime = Seconds (0);
+      newLinkTuple.time = now + msg.GetVTime ();
+      link_tuple = &AddLinkTuple (newLinkTuple, hello.GetWillingness ());
+      created = true;
+    }
+  else
+    updated = true;
+	
+  link_tuple->asymTime = now + msg.GetVTime ();
+  for (std::vector<OlsrHelloMessageHeader::LinkMessage>::const_iterator linkMessage =
+         hello.GetLinkMessages ().begin ();
+       linkMessage != hello.GetLinkMessages ().end ();
+       linkMessage++)
+    {
+      int lt = linkMessage->linkCode & 0x03; // Link Type
+      int nt = linkMessage->linkCode >> 2; // Neighbor Type
+      
+      // We must not process invalid advertised links
+      if ((lt == OLSR_SYM_LINK && nt == OLSR_NOT_NEIGH) ||
+          (nt != OLSR_SYM_NEIGH && nt != OLSR_MPR_NEIGH
+           && nt != OLSR_NOT_NEIGH))
+        {
+          continue;
+        }
+		
+      for (std::vector<Ipv4Address>::const_iterator neighIfaceAddr =
+             linkMessage->neighborInterfaceAddresses.begin ();
+           neighIfaceAddr != linkMessage->neighborInterfaceAddresses.end ();
+           neighIfaceAddr++)
+        {
+          if (*neighIfaceAddr == receiverIface)
+            {
+              if (lt == OLSR_LOST_LINK)
+                {
+                  link_tuple->symTime = now - Seconds (1);
+                  updated = true;
+                }
+              else if (lt == OLSR_SYM_LINK || lt == OLSR_ASYM_LINK)
+                {
+                  link_tuple->symTime = now + msg.GetVTime ();
+                  link_tuple->time = link_tuple->symTime + OLSR_NEIGHB_HOLD_TIME;
+                  link_tuple->lostTime = Seconds (0);
+                  updated = true;
+                }
+              break;
+            }
+        }
+    }
+  link_tuple->time = std::max(link_tuple->time, link_tuple->asymTime);
+
+  if (updated)
+    LinkTupleUpdated (*link_tuple);
+
+  // Schedules link tuple deletion
+  if (created && link_tuple != NULL)
+    {
+      Simulator::Schedule (DELAY (std::min (link_tuple->time, link_tuple->symTime)),
+                           &Olsr::LinkTupleTimerExpire, this, *link_tuple);
+    }
+}
+
+///
+/// \brief	Updates the Neighbor Set according to the information contained in a new received
+///		HELLO message (following RFC 3626).
+///
+/// \param msg the %OLSR message which contains the HELLO message.
+///
+void
+Olsr::PopulateNeighborSet (const OlsrMessageHeader &msg,
+                           const OlsrHelloMessageHeader &hello)
+{
+  NeighborTuple *nb_tuple = m_state.FindNeighborTuple (msg.GetOriginatorAddress ());
+  if (nb_tuple != NULL)
+    nb_tuple->willingness = hello.GetWillingness ();
+}
+
+
+///
+/// \brief	Updates the 2-hop Neighbor Set according to the information contained in a new
+///		received HELLO message (following RFC 3626).
+///
+/// \param msg the %OLSR message which contains the HELLO message.
+///
+void
+Olsr::PopulateTwoHopNeighborSet (const OlsrMessageHeader &msg,
+                                 const OlsrHelloMessageHeader &hello)
+{
+  Time now = Simulator::Now ();
+	
+  for (LinkSet::const_iterator link_tuple = m_state.GetLinks ().begin ();
+       link_tuple != m_state.GetLinks ().end (); link_tuple++)
+    {
+      if (GetMainAddress (link_tuple->neighborIfaceAddr) == msg.GetOriginatorAddress ())
+        {
+          if (link_tuple->symTime >= now)
+            {
+              typedef std::vector<OlsrHelloMessageHeader::LinkMessage> LinkMessageVec;
+              for (LinkMessageVec::const_iterator linkMessage =
+                     hello.GetLinkMessages ().begin ();
+                   linkMessage != hello.GetLinkMessages ().end ();
+                   linkMessage++)
+                {
+                  int nt = linkMessage->linkCode >> 2;
+
+                  for (std::vector<Ipv4Address>::const_iterator nb2hop_addr =
+                         linkMessage->neighborInterfaceAddresses.begin ();
+                       nb2hop_addr != linkMessage->neighborInterfaceAddresses.end ();
+                       nb2hop_addr++)
+                    {
+                      if (nt == OLSR_SYM_NEIGH || nt == OLSR_MPR_NEIGH)
+                        {
+                          // if the main address of the 2-hop
+                          // neighbor address = main address of
+                          // the receiving node: silently
+                          // discard the 2-hop neighbor address
+                          if (*nb2hop_addr != m_routingAgentAddr)
+                            {
+                              // Otherwise, a 2-hop tuple is created
+                              TwoHopNeighborTuple *nb2hop_tuple =
+                                m_state.FindTwoHopNeighborTuple (msg.GetOriginatorAddress (),
+                                                                 *nb2hop_addr);
+                              if (nb2hop_tuple == NULL)
+                                {
+                                  TwoHopNeighborTuple new_nb2hop_tuple;
+                                  new_nb2hop_tuple.neighborMainAddr = msg.GetOriginatorAddress ();
+                                  new_nb2hop_tuple.twoHopNeighborAddr = *nb2hop_addr;
+                                  AddTwoHopNeighborTuple (new_nb2hop_tuple);
+                                  new_nb2hop_tuple.expirationTime =
+                                    now + msg.GetVTime ();
+                                  // Schedules nb2hop tuple
+                                  // deletion
+                                  Simulator::Schedule (DELAY (new_nb2hop_tuple.expirationTime),
+                                                       &Olsr::Nb2hopTupleTimerExpire, this,
+                                                       new_nb2hop_tuple);
+                                }
+                              else
+                                {
+                                  nb2hop_tuple->expirationTime =
+                                    now + msg.GetVTime ();
+                                }
+								
+                            }
+                        }
+                      else if (nt == OLSR_NOT_NEIGH)
+                        {
+                          // For each 2-hop node listed in the HELLO
+                          // message with Neighbor Type equal to
+                          // NOT_NEIGH all 2-hop tuples where:
+                          // N_neighbor_main_addr == Originator
+                          // Address AND N_2hop_addr  == main address
+                          // of the 2-hop neighbor are deleted.
+                          m_state.EraseTwoHopNeighborTuples
+                            (msg.GetOriginatorAddress (), *nb2hop_addr);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+
+///
+/// \brief	Updates the MPR Selector Set according to the information contained in a new
+///		received HELLO message (following RFC 3626).
+///
+/// \param msg the %OLSR message which contains the HELLO message.
+///
+void
+Olsr::PopulateMprSelectorSet (const OlsrMessageHeader &msg,
+                              const OlsrHelloMessageHeader &hello)
+{
+  Time now = Simulator::Now ();
+	
+  typedef std::vector<OlsrHelloMessageHeader::LinkMessage> LinkMessageVec;
+  for (LinkMessageVec::const_iterator linkMessage = hello.GetLinkMessages ().begin ();
+       linkMessage != hello.GetLinkMessages ().end ();
+       linkMessage++)
+    {
+      int nt = linkMessage->linkCode >> 2;
+      if (nt == OLSR_MPR_NEIGH)
+        {
+          for (std::vector<Ipv4Address>::const_iterator nb_iface_addr =
+                 linkMessage->neighborInterfaceAddresses.begin ();
+               nb_iface_addr != linkMessage->neighborInterfaceAddresses.end ();
+               nb_iface_addr++)
+            {
+              if (*nb_iface_addr == m_mainAddress)
+                {
+                  // We must create a new entry into the mpr selector set
+                  MprSelectorTuple *existing_mprsel_tuple =
+                    m_state.FindMprSelectorTuple (msg.GetOriginatorAddress ());
+                  if (existing_mprsel_tuple == NULL)
+                    {
+                      MprSelectorTuple mprsel_tuple;
+
+                      mprsel_tuple.mainAddr = msg.GetOriginatorAddress ();
+                      mprsel_tuple.expirationTime = now + msg.GetVTime ();
+                      AddMprSelectorTuple (mprsel_tuple);
+
+                      // Schedules mpr selector tuple deletion
+                      Simulator::Schedule (DELAY (mprsel_tuple.expirationTime),
+                                           &Olsr::MprSelTupleTimerExpire,
+                                           this, mprsel_tuple);
+                    }
+                  else
+                    {
+                      existing_mprsel_tuple->expirationTime = now + msg.GetVTime ();
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+#if 0
+///
+/// \brief	Drops a given packet because it couldn't be delivered to the corresponding
+///		destination by the MAC layer. This may cause a neighbor loss, and appropiate
+///		actions are then taken.
+///
+/// \param p the packet which couldn't be delivered by the MAC layer.
+///
+void
+OLSR::mac_failed(Packet* p) {
+	double now		= Simulator::Now ();
+	struct hdr_ip* ih	= HDR_IP(p);
+	struct hdr_cmn* ch	= HDR_CMN(p);
+	
+	debug("%f: Node %d MAC Layer detects a breakage on link to %d\n",
+		now,
+		OLSR::node_id(ra_addr()),
+		OLSR::node_id(ch->next_hop()));
+	
+	if ((u_int32_t)ih->daddr() == IP_BROADCAST) {
+		drop(p, DROP_RTR_MAC_CALLBACK);
+		return;
+	}
+	
+	OLSR_link_tuple* link_tuple = state_.find_link_tuple(ch->next_hop());
+	if (link_tuple != NULL) {
+		link_tuple->lost_time()	= now + OLSR_NEIGHB_HOLD_TIME;
+		link_tuple->time()	= now + OLSR_NEIGHB_HOLD_TIME;
+		nb_loss(link_tuple);
+	}
+	drop(p, DROP_RTR_MAC_CALLBACK);
+}
+#endif
+
+
+
+
+///
+/// \brief Performs all actions needed when a neighbor loss occurs.
+///
+/// Neighbor Set, 2-hop Neighbor Set, MPR Set and MPR Selector Set are updated.
+///
+/// \param tuple link tuple with the information of the link to the neighbor which has been lost.
+///
+void
+Olsr::NeighborLoss (const LinkTuple &tuple)
+{
+//   debug("%f: Node %d detects neighbor %d loss\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborIfaceAddr));
+	
+  LinkTupleUpdated (tuple);
+  m_state.EraseTwoHopNeighborTuples (GetMainAddress (tuple.neighborIfaceAddr));
+  m_state.EraseMprSelectorTuples (GetMainAddress (tuple.neighborIfaceAddr));
+  
+  MprComputation();
+  RoutingTableComputation();
+}
+
+///
+/// \brief Adds a duplicate tuple to the Duplicate Set.
+///
+/// \param tuple the duplicate tuple to be added.
+///
+void
+Olsr::AddDuplicateTuple (const DuplicateTuple &tuple)
+{
+	/*debug("%f: Node %d adds dup tuple: addr = %d seq_num = %d\n",
+		Simulator::Now (),
+		OLSR::node_id(ra_addr()),
+		OLSR::node_id(tuple->addr()),
+		tuple->seq_num());*/
+  m_state.InsertDuplicateTuple (tuple);
+}
+
+///
+/// \brief Removes a duplicate tuple from the Duplicate Set.
+///
+/// \param tuple the duplicate tuple to be removed.
+///
+void
+Olsr::RemoveDuplicateTuple (const DuplicateTuple &tuple)
+{
+  /*debug("%f: Node %d removes dup tuple: addr = %d seq_num = %d\n",
+    Simulator::Now (),
+    OLSR::node_id(ra_addr()),
+    OLSR::node_id(tuple->addr()),
+    tuple->seq_num());*/
+  m_state.EraseDuplicateTuple (tuple);
+}
+
+///
+/// \brief Adds a link tuple to the Link Set (and an associated neighbor tuple to the Neighbor Set).
+///
+/// \param tuple the link tuple to be added.
+/// \param willingness willingness of the node which is going to be inserted in the Neighbor Set.
+///
+LinkTuple&
+Olsr::AddLinkTuple (const LinkTuple &tuple, uint8_t willingness)
+{
+//   debug("%f: Node %d adds link tuple: nb_addr = %d\n",
+//         now,
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborIfaceAddr));
+  LinkTuple &addedLinkTuple = m_state.InsertLinkTuple (tuple);
+  // Creates associated neighbor tuple
+  NeighborTuple nb_tuple;
+  nb_tuple.neighborMainAddr = GetMainAddress (tuple.neighborIfaceAddr);
+  nb_tuple.willingness = willingness;
+
+  if (tuple.symTime >= Simulator::Now ())
+    nb_tuple.status = NeighborTuple::STATUS_SYM;
+  else
+    nb_tuple.status = NeighborTuple::STATUS_NOT_SYM;
+
+  AddNeighborTuple (nb_tuple);
+  return addedLinkTuple;
+}
+
+///
+/// \brief Removes a link tuple from the Link Set.
+///
+/// \param tuple the link tuple to be removed.
+///
+void
+Olsr::RemoveLinkTuple (const LinkTuple &tuple)
+{
+//   nsaddr_t nb_addr	= get_main_addr(tuple->neighborIfaceAddr);
+//   double now		= Simulator::Now ();
+	
+//   debug("%f: Node %d removes link tuple: nb_addr = %d\n",
+//         now,
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborIfaceAddr));
+	// Prints this here cause we are not actually calling rm_nb_tuple() (efficiency stuff)
+  // 	debug("%f: Node %d removes neighbor tuple: nb_addr = %d\n",
+  // 		now,
+  // 		OLSR::node_id(ra_addr()),
+  // 		OLSR::node_id(nb_addr));
+
+  m_state.EraseLinkTuple (tuple);
+  m_state.EraseNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
+}
+
+///
+/// \brief	This function is invoked when a link tuple is updated. Its aim is to
+///		also update the corresponding neighbor tuple if it is needed.
+///
+/// \param tuple the link tuple which has been updated.
+///
+void
+Olsr::LinkTupleUpdated (const LinkTuple &tuple)
+{
+  // Each time a link tuple changes, the associated neighbor tuple must be recomputed
+  NeighborTuple *nb_tuple =
+    m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
+  if (nb_tuple != NULL)
+    {
+      if (m_useL2Notifications && tuple.lostTime >= Simulator::Now ())
+        {
+          nb_tuple->status = NeighborTuple::STATUS_NOT_SYM;
+        }
+      else if (tuple.symTime >= Simulator::Now ())
+        {
+          nb_tuple->status = NeighborTuple::STATUS_SYM;
+        }
+      else
+        {
+          nb_tuple->status = NeighborTuple::STATUS_NOT_SYM;
+        }
+    }
+	
+//   debug("%f: Node %d has updated link tuple: nb_addr = %d status = %s\n",
+//         now,
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborIfaceAddr),
+//         ((nb_tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+
+}
+
+///
+/// \brief Adds a neighbor tuple to the Neighbor Set.
+///
+/// \param tuple the neighbor tuple to be added.
+///
+void
+Olsr::AddNeighborTuple (const NeighborTuple &tuple)
+{
+//   debug("%f: Node %d adds neighbor tuple: nb_addr = %d status = %s\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+  
+  m_state.InsertNeighborTuple (tuple);
+}
+
+///
+/// \brief Removes a neighbor tuple from the Neighbor Set.
+///
+/// \param tuple the neighbor tuple to be removed.
+///
+void
+Olsr::RemoveNeighborTuple (const NeighborTuple &tuple)
+{
+//   debug("%f: Node %d removes neighbor tuple: nb_addr = %d status = %s\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+	
+  m_state.EraseNeighborTuple (tuple);
+}
+
+///
+/// \brief Adds a 2-hop neighbor tuple to the 2-hop Neighbor Set.
+///
+/// \param tuple the 2-hop neighbor tuple to be added.
+///
+void
+Olsr::AddTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
+{
+//   debug("%f: Node %d adds 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         OLSR::node_id(tuple->twoHopNeighborAddr));
+  
+  m_state.InsertTwoHopNeighborTuple (tuple);
+}
+
+///
+/// \brief Removes a 2-hop neighbor tuple from the 2-hop Neighbor Set.
+///
+/// \param tuple the 2-hop neighbor tuple to be removed.
+///
+void
+Olsr::RemoveTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
+{
+//   debug("%f: Node %d removes 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         OLSR::node_id(tuple->twoHopNeighborAddr));
+
+  m_state.EraseTwoHopNeighborTuple (tuple);
+}
+
+///
+/// \brief Adds an MPR selector tuple to the MPR Selector Set.
+///
+/// Advertised Neighbor Sequence Number (ANSN) is also updated.
+///
+/// \param tuple the MPR selector tuple to be added.
+///
+void
+Olsr::AddMprSelectorTuple (const MprSelectorTuple  &tuple)
+{
+//   debug("%f: Node %d adds MPR selector tuple: nb_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->main_addr()));
+  
+  m_state.InsertMprSelectorTuple (tuple);
+  m_ansn = (m_ansn + 1) % (OLSR_MAX_SEQ_NUM + 1);
+}
+
+///
+/// \brief Removes an MPR selector tuple from the MPR Selector Set.
+///
+/// Advertised Neighbor Sequence Number (ANSN) is also updated.
+///
+/// \param tuple the MPR selector tuple to be removed.
+///
+void
+Olsr::RemoveMprSelectorTuple (const MprSelectorTuple &tuple)
+{
+//   debug("%f: Node %d removes MPR selector tuple: nb_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->main_addr()));
+  
+  m_state.EraseMprSelectorTuple (tuple);
+  m_ansn = (m_ansn + 1) % (OLSR_MAX_SEQ_NUM + 1);
+}
+
+///
+/// \brief Adds a topology tuple to the Topology Set.
+///
+/// \param tuple the topology tuple to be added.
+///
+void
+Olsr::AddTopologyTuple (const TopologyTuple &tuple)
+{
+//   debug("%f: Node %d adds topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->dest_addr()),
+//         OLSR::node_id(tuple->last_addr()),
+//         tuple->seq());
+
+  m_state.InsertTopologyTuple(tuple);
+}
+
+///
+/// \brief Removes a topology tuple from the Topology Set.
+///
+/// \param tuple the topology tuple to be removed.
+///
+void
+Olsr::RemoveTopologyTuple (const TopologyTuple &tuple)
+{
+//   debug("%f: Node %d removes topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->dest_addr()),
+//         OLSR::node_id(tuple->last_addr()),
+//         tuple->seq());
+
+  m_state.EraseTopologyTuple (tuple);
+}
+
+///
+/// \brief Adds an interface association tuple to the Interface Association Set.
+///
+/// \param tuple the interface association tuple to be added.
+///
+void
+Olsr::AddIfaceAssocTuple (const IfaceAssocTuple &tuple)
+{
+//   debug("%f: Node %d adds iface association tuple: main_addr = %d iface_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->main_addr()),
+//         OLSR::node_id(tuple->iface_addr()));
+
+  m_state.InsertIfaceAssocTuple (tuple);
+}
+
+///
+/// \brief Removes an interface association tuple from the Interface Association Set.
+///
+/// \param tuple the interface association tuple to be removed.
+///
+void
+Olsr::RemoveIfaceAssocTuple (const IfaceAssocTuple &tuple)
+{
+//   debug("%f: Node %d removes iface association tuple: main_addr = %d iface_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->main_addr()),
+//         OLSR::node_id(tuple->iface_addr()));
+
+  m_state.EraseIfaceAssocTuple (tuple);
+}
+
+
+uint16_t Olsr::GetPacketSequenceNumber ()
+{
+  m_packetSequenceNumber = (m_packetSequenceNumber + 1) % (OLSR_MAX_SEQ_NUM + 1);
+  return m_packetSequenceNumber;
+}
+
+/// Increments message sequence number and returns the new value.
+uint16_t Olsr::GetMessageSequenceNumber ()
+{
+  m_messageSequenceNumber = (m_messageSequenceNumber + 1) % (OLSR_MAX_SEQ_NUM + 1);
+  return m_messageSequenceNumber;
+}
+
+
+///
+/// \brief Sends a HELLO message and reschedules the HELLO timer.
+/// \param e The event which has expired.
+///
+void
+Olsr::HelloTimerExpire ()
+{
+  SendHello ();
+  m_helloTimer.Schedule ();
+}
+
+///
+/// \brief Sends a TC message (if there exists any MPR selector) and reschedules the TC timer.
+/// \param e The event which has expired.
+///
+void
+Olsr::TcTimerExpire ()
+{
+  if (m_state.GetMprSelectors ().size () > 0)
+    SendTc ();
+  m_tcTimer.Schedule ();
+}
+
+///
+/// \brief Sends a MID message (if the node has more than one interface) and resets the MID timer.
+/// \warning Currently it does nothing because there is no support for multiple interfaces.
+/// \param e The event which has expired.
+///
+void
+Olsr::MidTimerExpire ()
+{
+  SendMid ();
+  m_midTimer.Schedule ();
+}
+
+///
+/// \brief Removes tuple_ if expired. Else timer is rescheduled to expire at tuple_->time().
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param e The event which has expired.
+///
+void
+Olsr::DupTupleTimerExpire (DuplicateTuple tuple)
+{
+  if (tuple.expirationTime < Simulator::Now ())
+    {
+      RemoveDuplicateTuple (tuple);
+    }
+  else
+    Simulator::Schedule (DELAY (tuple.expirationTime), &Olsr::DupTupleTimerExpire, this, tuple);
+}
+
+///
+/// \brief Removes tuple_ if expired. Else if symmetric time
+/// has expired then it is assumed a neighbor loss and agent_->nb_loss()
+/// is called. In this case the timer is rescheduled to expire at
+/// tuple_->time(). Otherwise the timer is rescheduled to expire at
+/// the minimum between tuple_->time() and tuple_->sym_time().
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param e The event which has expired.
+///
+void
+Olsr::LinkTupleTimerExpire (LinkTuple tuple)
+{
+  Time now = Simulator::Now ();
+	
+  if (tuple.time < now)
+    {
+      RemoveLinkTuple (tuple);
+    }
+  else if (tuple.symTime < now)
+    {
+      if (m_linkTupleTimerFirstTime)
+        m_linkTupleTimerFirstTime = false;
+      else
+        NeighborLoss (tuple);
+
+      Simulator::Schedule (DELAY(tuple.time),
+                           &Olsr::LinkTupleTimerExpire, this, tuple);
+
+    }
+  else
+    Simulator::Schedule (DELAY (std::min (tuple.time, tuple.symTime)),
+                         &Olsr::LinkTupleTimerExpire, this, tuple);
+}
+
+///
+/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param e The event which has expired.
+///
+void
+Olsr::Nb2hopTupleTimerExpire (TwoHopNeighborTuple tuple)
+{
+  if (tuple.expirationTime < Simulator::Now ())
+    {
+      RemoveTwoHopNeighborTuple (tuple);
+    }
+  else
+    Simulator::Schedule (DELAY (tuple.expirationTime),
+                         &Olsr::Nb2hopTupleTimerExpire, this, tuple);
+}
+
+///
+/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param e The event which has expired.
+///
+void
+Olsr::MprSelTupleTimerExpire (MprSelectorTuple tuple)
+{
+  if (tuple.expirationTime < Simulator::Now ())
+    {
+      RemoveMprSelectorTuple (tuple);
+    }
+  else
+    Simulator::Schedule (DELAY (tuple.expirationTime),
+                         &Olsr::MprSelTupleTimerExpire, this, tuple);
+}
+
+///
+/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param e The event which has expired.
+///
+void
+Olsr::TopologyTupleTimerExpire (TopologyTuple tuple)
+{
+  if (tuple.expirationTime < Simulator::Now ())
+    {
+      RemoveTopologyTuple (tuple);
+    }
+  else
+    Simulator::Schedule (DELAY (tuple.expirationTime),
+                         &Olsr::TopologyTupleTimerExpire, this, tuple);
+}
+
+///
+/// \brief Removes tuple_ if expired. Else timer is rescheduled to expire at tuple_->time().
+/// \warning Actually this is never invoked because there is no support for multiple interfaces.
+/// \param e The event which has expired.
+///
+void
+Olsr::IfaceAssocTupleTimerExpire (IfaceAssocTuple tuple)
+{
+  if (tuple.time < Simulator::Now ())
+    {
+      RemoveIfaceAssocTuple (tuple);
+    }
+  else
+    Simulator::Schedule (DELAY (tuple.time),
+                         &Olsr::IfaceAssocTupleTimerExpire, this, tuple);
+}
+
+
+
+}}; // namespace ns3, olsr
+
+
+
+#ifdef RUN_SELF_TESTS
+
+
+#include "ns3/test.h"
+
+namespace ns3 { namespace olsr {
+
+class OlsrTest : public ns3::Test {
+private:
+public:
+  OlsrTest ();
+  virtual bool RunTests (void);
+
+
+};
+
+OlsrTest::OlsrTest ()
+  : ns3::Test ("Olsr")
+{}
+
+
+bool 
+OlsrTest::RunTests (void)
+{
+  bool result = true;
+
+
+  return result;
+}
+
+static OlsrTest gOlsrTest;
+
+}}; // namespace
+
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr.h	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,45 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#ifndef OLSR_H
+#define OLSR_H
+
+#include "ns3/node.h"
+#include "ns3/component-manager.h"
+
+namespace ns3 {
+
+
+class Olsr : public Object
+{
+public:
+  static const InterfaceId iid;
+  static const ClassId cid;
+
+  virtual void Start () = 0;
+  virtual void SetMainInterface (uint32_t interface) = 0;
+};
+
+
+}; // namespace ns3
+
+#endif /* OLSR_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/routing-table.cc	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,270 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/***************************************************************************
+ *   Copyright (C) 2004 by Francisco J. Ros                                *
+ *   fjrm@dif.um.es                                                        *
+ *                                                                         *
+ *   Modified on 2007 for NS-3 by Gustavo J. A. M. Carneiro, INESC Porto   *
+ *                                <gjc@inescporto.pt>                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+///
+/// \file	OLSR_rtable.cc
+/// \brief	Implementation of our routing table.
+///
+
+#include "routing-table.h"
+#include "ns3/packet.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/debug.h"
+
+namespace ns3 { namespace olsr {
+
+NS_DEBUG_COMPONENT_DEFINE ("OlsrRoutingTable");
+
+///
+/// \brief Clears the routing table and frees the memory assigned to each one of its entries.
+///
+void
+RoutingTable::Clear ()
+{
+  m_table.clear ();
+}
+
+///
+/// \brief Deletes the entry whose destination address is given.
+/// \param dest	address of the destination node.
+///
+void
+RoutingTable::RemoveEntry (Ipv4Address const &dest)
+{
+  m_table.erase (dest);
+}
+
+///
+/// \brief Looks up an entry for the specified destination address.
+/// \param dest	destination address.
+/// \param outEntry output parameter to hold the routing entry result, if fuond
+/// \return	true if found, false if not found
+///
+bool
+RoutingTable::Lookup (Ipv4Address const &dest,
+                      RoutingTableEntry &outEntry) const
+{
+  // Get the iterator at "dest" position
+  std::map<Ipv4Address, RoutingTableEntry>::const_iterator it =
+    m_table.find (dest);
+  // If there is no route to "dest", return NULL
+  if (it == m_table.end ())
+    return false;
+  outEntry = it->second;
+  return true;
+}
+
+///
+/// \brief	Finds the appropiate entry which must be used in order to forward
+///		a data packet to a next hop (given a destination).
+///
+/// Imagine a routing table like this: [A,B] [B,C] [C,C]; being each pair of the
+/// form [dest addr,next-hop addr]. In this case, if this function is invoked with
+/// [A,B] then pair [C,C] is returned because C is the next hop that must be used
+/// to forward a data packet destined to A. That is, C is a neighbor of this node,
+/// but B isn't. This function finds the appropiate neighbor for forwarding a packet.
+///
+/// \param entry	the routing table entry which indicates the destination node
+///			we are interested in.
+/// \return		the appropiate routing table entry which indicates the next
+///			hop which must be used for forwarding a data packet, or NULL
+///			if there is no such entry.
+///
+bool
+RoutingTable::FindSendEntry (RoutingTableEntry const &entry,
+                             RoutingTableEntry &outEntry) const
+{
+  outEntry = entry;
+  while (outEntry.destAddr != outEntry.nextAddr)
+    {
+      if (not Lookup(outEntry.nextAddr, outEntry))
+        return false;
+    }
+  return true;
+}
+
+
+bool
+RoutingTable::RequestRoute (const Ipv4Header &ipHeader,
+                            Packet packet,
+                            RouteReplyCallback routeReply)
+{
+  RoutingTableEntry entry1, entry2;
+  if (Lookup (ipHeader.GetDestination (), entry1))
+    {
+      bool foundSendEntry = FindSendEntry (entry1, entry2);
+      NS_ASSERT (foundSendEntry);
+      Ipv4Route route = Ipv4Route::CreateHostRouteTo
+        (ipHeader.GetDestination (), entry2.nextAddr, entry2.interface);
+
+      NS_DEBUG ("Olsr node" << m_mainAddress
+                << ": RouteRequest for dest=" << ipHeader.GetDestination ()
+                << " --> destHop=" << entry2.nextAddr
+                << " interface=" << entry2.interface);
+      
+      routeReply (true, route, packet, ipHeader);
+      return true;
+    }
+  else
+    {
+      NS_DEBUG ("Olsr node" << m_mainAddress
+                << ": RouteRequest for dest=" << ipHeader.GetDestination ()
+                << " --> NOT FOUND");
+      return false;
+    }
+}
+
+
+///
+/// \brief Adds a new entry into the routing table.
+///
+/// If an entry for the given destination existed, it is deleted and freed.
+///
+/// \param dest		address of the destination node.
+/// \param next		address of the next hop node.
+/// \param iface	address of the local interface.
+/// \param dist		distance to the destination node.
+///
+void
+RoutingTable::AddEntry (Ipv4Address const &dest,
+                        Ipv4Address const &next,
+                        uint32_t interface,
+                        uint32_t distance)
+{
+  // Creates a new rt entry with specified values
+  RoutingTableEntry &entry = m_table[dest];
+
+  entry.destAddr = dest;
+  entry.nextAddr = next;
+  entry.interface = interface;
+  entry.distance = distance;
+}
+
+void
+RoutingTable::AddEntry (Ipv4Address const &dest,
+                        Ipv4Address const &next,
+                        Ipv4Address const &interfaceAddress,
+                        uint32_t distance)
+{
+  RoutingTableEntry entry;
+  NS_ASSERT (m_ipv4);
+  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+    {
+      if (m_ipv4->GetAddress (i) == interfaceAddress)
+        {
+          AddEntry (dest, next, i, distance);
+          return;
+        }
+    }
+  NS_ASSERT (false); // should not be reached
+  AddEntry (dest, next, 0, distance);
+}
+
+
+///
+/// \brief Returns the number of entries in the routing table.
+/// \return the number of entries in the routing table.
+///
+// u_int32_t
+// RoutingTable::size() {
+// 	return rt_.size();
+// }
+
+}}; // namespace ns3, olsr
+
+
+
+#ifdef RUN_SELF_TESTS
+
+
+#include "ns3/test.h"
+
+
+namespace ns3 { namespace olsr {
+
+class OlsrRoutingTableTest : public ns3::Test {
+private:
+public:
+  OlsrRoutingTableTest ();
+  virtual bool RunTests (void);
+
+
+};
+
+OlsrRoutingTableTest::OlsrRoutingTableTest ()
+  : ns3::Test ("OlsrRoutingTable")
+{}
+
+
+bool 
+OlsrRoutingTableTest::RunTests (void)
+{
+  bool result = true;
+
+  RoutingTable table;
+
+  table.AddEntry (Ipv4Address ("1.2.3.5"),
+                  Ipv4Address ("1.2.3.4"),
+                  0,
+                  1);
+
+  table.AddEntry (Ipv4Address ("1.2.3.4"),
+                  Ipv4Address ("1.2.3.4"),
+                  0,
+                  1);
+  
+  RoutingTableEntry entry1;
+  NS_TEST_ASSERT (table.Lookup (Ipv4Address ("1.2.3.5"), entry1));
+  NS_TEST_ASSERT_EQUAL (entry1.destAddr, Ipv4Address ("1.2.3.5"));
+  NS_TEST_ASSERT_EQUAL (entry1.nextAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (entry1.interface, 0);
+  NS_TEST_ASSERT_EQUAL (entry1.distance, 1);
+
+  RoutingTableEntry entry2;
+  NS_TEST_ASSERT (table.Lookup (Ipv4Address ("1.2.3.4"), entry2));
+  NS_TEST_ASSERT_EQUAL (entry2.destAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (entry2.nextAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (entry2.interface, 0);
+  NS_TEST_ASSERT_EQUAL (entry2.distance, 1);
+
+  RoutingTableEntry sendEntry;
+  NS_TEST_ASSERT (table.FindSendEntry (entry1, sendEntry));
+  NS_TEST_ASSERT_EQUAL (sendEntry.destAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (sendEntry.nextAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (sendEntry.interface, 0);
+  NS_TEST_ASSERT_EQUAL (sendEntry.distance, 1);
+
+  table.RemoveEntry (Ipv4Address ("1.2.3.5"));
+  RoutingTableEntry removedEntry;
+  NS_TEST_ASSERT (not table.Lookup (Ipv4Address ("1.2.3.5"), removedEntry));
+
+  return result;
+}
+
+static OlsrRoutingTableTest gOlsrRoutingTableTest;
+
+}}; // namespace
+
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/routing-table.h	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,110 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/***************************************************************************
+ *   Copyright (C) 2004 by Francisco J. Ros                                *
+ *   fjrm@dif.um.es                                                        *
+ *                                                                         *
+ *   Modified on 2007 for NS-3 by Gustavo J. A. M. Carneiro, INESC Porto   *
+ *                                <gjc@inescporto.pt>                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+///
+/// \file	OLSR_rtable.h
+/// \brief	Header file for routing table's related stuff.
+///
+
+#ifndef __OLSR_RTABLE_H__
+#define __OLSR_RTABLE_H__
+
+#include "ns3/ipv4.h"
+#include <map>
+
+
+namespace ns3 { namespace olsr {
+
+/// An %OLSR's routing table entry.
+struct RoutingTableEntry
+{
+  Ipv4Address destAddr;	///< Address of the destination node.
+  Ipv4Address nextAddr;	///< Address of the next hop.
+  uint32_t interface; ///< Interface index
+  uint32_t distance; ///< Distance in hops to the destination.
+
+  RoutingTableEntry () : // default values
+    destAddr (), nextAddr (),
+    interface (0), distance (0) {};
+};
+
+///
+/// \brief Defines rtable_t as a map of OLSR_rt_entry, whose key is the destination address.
+///
+/// The routing table is thus defined as pairs: [dest address, entry]. Each element
+/// of the pair can be accesed via "first" and "second" members.
+///
+//typedef std::map<Ipv4Address, RoutingTableEntry> RoutingTable;
+
+///
+/// \brief This class is a representation of the OLSR's Routing Table.
+///
+class RoutingTable : public Ipv4RoutingProtocol
+{
+  std::map<Ipv4Address, RoutingTableEntry> m_table; ///< Data structure for the routing table.
+  Ptr<Ipv4> m_ipv4;
+
+  Ipv4Address m_mainAddress; // used only for printing debug messages
+
+  void DoDispose ()
+  {
+    m_ipv4 = 0;
+    Ipv4RoutingProtocol::DoDispose ();
+  }
+  
+public:
+	
+  RoutingTable () {}
+  RoutingTable (Ptr<Ipv4> ipv4, const Ipv4Address &mainAddress)
+    :
+    m_ipv4 (ipv4),
+    m_mainAddress (mainAddress)
+  {}
+
+  ~RoutingTable () {}
+  
+  void Clear ();
+  void RemoveEntry (const Ipv4Address &dest);
+  void AddEntry (const Ipv4Address &dest,
+                 const Ipv4Address &next,
+                 uint32_t interface,
+                 uint32_t distance);
+  void AddEntry (const Ipv4Address &dest,
+                 const Ipv4Address &next,
+                 const Ipv4Address &interfaceAddress,
+                 uint32_t distance);
+  bool Lookup (const Ipv4Address &dest,
+               RoutingTableEntry &outEntry) const;
+  bool FindSendEntry (const RoutingTableEntry &entry,
+                      RoutingTableEntry &outEntry) const;
+
+  // From Ipv4RoutingProtocol
+  virtual bool RequestRoute (const Ipv4Header &ipHeader,
+                             Packet packet,
+                             RouteReplyCallback routeReply);
+};
+
+}}; // namespace ns3, olsr
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/wscript	Thu Jul 26 12:49:00 2007 +0100
@@ -0,0 +1,19 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    obj = bld.create_obj('cpp', 'shlib')
+    obj.name = 'ns3-olsr'
+    obj.target = obj.name
+    obj.uselib_local = ['ns3-internet-node']
+    obj.includes = '.'
+    obj.source = [
+        'olsr-header.cc',
+        'olsr-state.cc',
+        'routing-table.cc',
+        'olsr.cc',
+        ]
+
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'olsr.h',
+        ]
--- a/src/wscript	Thu Jul 26 12:27:49 2007 +0100
+++ b/src/wscript	Thu Jul 26 12:49:00 2007 +0100
@@ -17,6 +17,7 @@
     'internet-node',
     'devices/p2p',
     'applications',
+    'routing/olsr',
     'mobility',
     )