Add OLSR routing support, (loosely) based on Francisco J. Ros's NS-2 code (University of Murcia).
--- /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',
)