--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-routing-protocol.cc Mon Mar 23 14:37:43 2009 +0100
@@ -0,0 +1,2681 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Francisco J. Ros <fjrm@dif.um.es>
+ * Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+
+///
+/// \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.
+///
+
+#define NS_LOG_APPEND_CONTEXT \
+ if (GetObject<Node> ()) { std::clog << "[node " << GetObject<Node> ()->GetId () << "] "; }
+
+
+#include "olsr-routing-protocol.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+#include "ns3/random-variable.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/boolean.h"
+#include "ns3/uinteger.h"
+#include "ns3/enum.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/ipv4-header.h"
+
+/********** 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)))
+
+
+
+///
+/// \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) * m_tcInterval)
+/// Dup holding time.
+#define OLSR_DUP_HOLD_TIME Seconds (30)
+/// MID holding time.
+#define OLSR_MID_HOLD_TIME (Scalar (3) * m_midInterval)
+
+
+/********** 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 (m_helloInterval.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().GetValue (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 {
+namespace olsr {
+
+NS_LOG_COMPONENT_DEFINE ("OlsrAgent");
+
+
+/********** OLSR class **********/
+
+NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol);
+
+TypeId
+RoutingProtocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::olsr::RoutingProtocol")
+ .SetParent<Ipv4RoutingProtocol> ()
+ .AddConstructor<RoutingProtocol> ()
+ .AddAttribute ("HelloInterval", "HELLO messages emission interval.",
+ TimeValue (Seconds (2)),
+ MakeTimeAccessor (&RoutingProtocol::m_helloInterval),
+ MakeTimeChecker ())
+ .AddAttribute ("TcInterval", "TC messages emission interval.",
+ TimeValue (Seconds (5)),
+ MakeTimeAccessor (&RoutingProtocol::m_tcInterval),
+ MakeTimeChecker ())
+ .AddAttribute ("MidInterval", "MID messages emission interval. Normally it is equal to TcInterval.",
+ TimeValue (Seconds (5)),
+ MakeTimeAccessor (&RoutingProtocol::m_midInterval),
+ MakeTimeChecker ())
+ .AddAttribute ("Willingness", "Willingness of a node to carry and forward traffic for other nodes.",
+ EnumValue (OLSR_WILL_DEFAULT),
+ MakeEnumAccessor (&RoutingProtocol::m_willingness),
+ MakeEnumChecker (OLSR_WILL_NEVER, "never",
+ OLSR_WILL_LOW, "low",
+ OLSR_WILL_DEFAULT, "default",
+ OLSR_WILL_HIGH, "high",
+ OLSR_WILL_ALWAYS, "always"))
+ .AddTraceSource ("Rx", "Receive OLSR packet.",
+ MakeTraceSourceAccessor (&RoutingProtocol::m_rxPacketTrace))
+ .AddTraceSource ("Tx", "Send OLSR packet.",
+ MakeTraceSourceAccessor (&RoutingProtocol::m_txPacketTrace))
+ .AddTraceSource ("RoutingTableChanged", "The OLSR routing table has changed.",
+ MakeTraceSourceAccessor (&RoutingProtocol::m_routingTableChanged))
+ ;
+ return tid;
+}
+
+
+RoutingProtocol::RoutingProtocol ()
+ :
+ m_helloTimer (Timer::CANCEL_ON_DESTROY),
+ m_tcTimer (Timer::CANCEL_ON_DESTROY),
+ m_midTimer (Timer::CANCEL_ON_DESTROY)
+{}
+
+RoutingProtocol::~RoutingProtocol ()
+{}
+
+void
+RoutingProtocol::SetNode (Ptr<Node> node)
+{
+ NS_LOG_DEBUG ("Created olsr::RoutingProtocol");
+ m_helloTimer.SetFunction (&RoutingProtocol::HelloTimerExpire, this);
+ m_tcTimer.SetFunction (&RoutingProtocol::TcTimerExpire, this);
+ m_midTimer.SetFunction (&RoutingProtocol::MidTimerExpire, this);
+ m_queuedMessagesTimer.SetFunction (&RoutingProtocol::SendQueuedMessages, this);
+
+ m_packetSequenceNumber = OLSR_MAX_SEQ_NUM;
+ m_messageSequenceNumber = OLSR_MAX_SEQ_NUM;
+ m_ansn = OLSR_MAX_SEQ_NUM;
+
+ m_linkTupleTimerFirstTime = true;
+
+ m_ipv4 = node->GetObject<Ipv4> ();
+ NS_ASSERT (m_ipv4);
+}
+
+void RoutingProtocol::DoDispose ()
+{
+ m_ipv4 = 0;
+
+ for (std::map< Ptr<Socket>, Ipv4Address >::iterator iter = m_socketAddresses.begin ();
+ iter != m_socketAddresses.end (); iter++)
+ {
+ iter->first->Close ();
+ }
+ m_socketAddresses.clear ();
+
+ Ipv4RoutingProtocol::DoDispose ();
+}
+
+void RoutingProtocol::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_LOG_DEBUG ("Starting OLSR on node " << m_mainAddress);
+
+ 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)
+ continue;
+
+ if (addr != m_mainAddress)
+ {
+ // Create never expiring interface association tuple entries for our
+ // own network interfaces, so that GetMainAddress () works to
+ // translate the node's own interface addresses into the main address.
+ IfaceAssocTuple tuple;
+ tuple.ifaceAddr = addr;
+ tuple.mainAddr = m_mainAddress;
+ AddIfaceAssocTuple (tuple);
+ NS_ASSERT (GetMainAddress (addr) == m_mainAddress);
+ }
+
+ // Create a socket to listen only on this interface
+ Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),
+ UdpSocketFactory::GetTypeId());
+ socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvOlsr, this));
+ if (socket->Bind (InetSocketAddress (addr, OLSR_PORT_NUMBER)))
+ {
+ NS_FATAL_ERROR ("Failed to bind() OLSR receive socket");
+ }
+ socket->Connect (InetSocketAddress (Ipv4Address (0xffffffff), OLSR_PORT_NUMBER));
+ m_socketAddresses[socket] = addr;
+ }
+
+ HelloTimerExpire ();
+ TcTimerExpire ();
+ MidTimerExpire ();
+
+ NS_LOG_DEBUG ("OLSR on node " << m_mainAddress << " started");
+}
+
+void RoutingProtocol::SetMainInterface (uint32_t interface)
+{
+ m_mainAddress = m_ipv4->GetAddress (interface);
+}
+
+
+//
+// \brief Processes an incoming %OLSR packet following RFC 3626 specification.
+void
+RoutingProtocol::RecvOlsr (Ptr<Socket> socket)
+{
+ Ptr<Packet> receivedPacket;
+ Address sourceAddress;
+ receivedPacket = socket->RecvFrom (sourceAddress);
+
+ InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
+ Ipv4Address senderIfaceAddr = inetSourceAddr.GetIpv4 ();
+ Ipv4Address receiverIfaceAddr = m_socketAddresses[socket];
+ NS_ASSERT (receiverIfaceAddr != Ipv4Address ());
+ NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " received a OLSR packet from "
+ << senderIfaceAddr << " to " << receiverIfaceAddr);
+
+ // All routing messages are sent from and to port RT_PORT,
+ // so we check it.
+ NS_ASSERT (inetSourceAddr.GetPort () == OLSR_PORT_NUMBER);
+
+ Ptr<Packet> packet = receivedPacket;
+
+ olsr::PacketHeader olsrPacketHeader;
+ packet->RemoveHeader (olsrPacketHeader);
+ NS_ASSERT (olsrPacketHeader.GetPacketLength () >= olsrPacketHeader.GetSerializedSize ());
+ uint32_t sizeLeft = olsrPacketHeader.GetPacketLength () - olsrPacketHeader.GetSerializedSize ();
+
+ MessageList messages;
+
+ while (sizeLeft)
+ {
+ MessageHeader messageHeader;
+ if (packet->RemoveHeader (messageHeader) == 0)
+ NS_ASSERT (false);
+
+ sizeLeft -= messageHeader.GetSerializedSize ();
+
+ NS_LOG_DEBUG ("Olsr Msg received with type "
+ << std::dec << int (messageHeader.GetMessageType ())
+ << " TTL=" << int (messageHeader.GetTimeToLive ())
+ << " origAddr=" << messageHeader.GetOriginatorAddress ());
+ messages.push_back (messageHeader);
+ }
+
+ m_rxPacketTrace (olsrPacketHeader, messages);
+
+ for (MessageList::const_iterator messageIter = messages.begin ();
+ messageIter != messages.end (); messageIter++)
+ {
+ const MessageHeader &messageHeader = *messageIter;
+ // 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.GetSerializedSize ()
+ - messageHeader.GetSerializedSize ());
+ continue;
+ }
+
+ // 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 ());
+
+ // Get main address of the peer, which may be different from the packet source address
+// const IfaceAssocTuple *ifaceAssoc = m_state.FindIfaceAssocTuple (inetSourceAddr.GetIpv4 ());
+// Ipv4Address peerMainAddress;
+// if (ifaceAssoc != NULL)
+// {
+// peerMainAddress = ifaceAssoc->mainAddr;
+// }
+// else
+// {
+// peerMainAddress = inetSourceAddr.GetIpv4 () ;
+// }
+
+ if (duplicated == NULL)
+ {
+ switch (messageHeader.GetMessageType ())
+ {
+ case olsr::MessageHeader::HELLO_MESSAGE:
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s OLSR node " << m_mainAddress
+ << " received HELLO message of size " << messageHeader.GetSerializedSize ());
+ ProcessHello (messageHeader, receiverIfaceAddr, senderIfaceAddr);
+ break;
+
+ case olsr::MessageHeader::TC_MESSAGE:
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s OLSR node " << m_mainAddress
+ << " received TC message of size " << messageHeader.GetSerializedSize ());
+ ProcessTc (messageHeader, senderIfaceAddr);
+ break;
+
+ case olsr::MessageHeader::MID_MESSAGE:
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s OLSR node " << m_mainAddress
+ << " received MID message of size " << messageHeader.GetSerializedSize ());
+ ProcessMid (messageHeader, senderIfaceAddr);
+ break;
+
+ default:
+ NS_LOG_DEBUG ("OLSR message type " <<
+ int (messageHeader.GetMessageType ()) <<
+ " not implemented");
+ }
+ }
+ else
+ {
+ NS_LOG_DEBUG ("OLSR message is duplicated, not reading it.");
+
+ // 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 == receiverIfaceAddr)
+ {
+ 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 () != olsr::MessageHeader::HELLO_MESSAGE)
+ {
+ ForwardDefault (messageHeader, duplicated,
+ receiverIfaceAddr, inetSourceAddr.GetIpv4 ());
+ }
+ }
+
+ }
+
+ // 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
+RoutingProtocol::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)
+ {
+ const 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
+RoutingProtocol::MprComputation()
+{
+ NS_LOG_FUNCTION (this);
+
+ // MPR computation should be done for each interface. See section 8.3.1
+ // (RFC 3626) for details.
+ MprSet mprSet;
+
+
+ // N is the subset of neighbors of the node, which are
+ // neighbor "of the interface I"
+ NeighborSet N;
+ for (NeighborSet::const_iterator neighbor = m_state.GetNeighbors ().begin();
+ neighbor != m_state.GetNeighbors ().end (); neighbor++)
+ {
+ if (neighbor->status == NeighborTuple::STATUS_SYM) // I think that we need this check
+ {
+ N.push_back (*neighbor);
+ }
+ }
+
+ // 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 twoHopNeigh = m_state.GetTwoHopNeighbors ().begin ();
+ twoHopNeigh != m_state.GetTwoHopNeighbors ().end (); twoHopNeigh++)
+ {
+ // excluding:
+ // (ii) the node performing the computation
+ if (twoHopNeigh->twoHopNeighborAddr == m_mainAddress)
+ {
+ continue;
+ }
+
+ // excluding:
+ // (i) the nodes only reachable by members of N with willingness WILL_NEVER
+ bool ok = false;
+ for (NeighborSet::const_iterator neigh = N.begin ();
+ neigh != N.end (); neigh++)
+ {
+ if (neigh->neighborMainAddr == twoHopNeigh->neighborMainAddr)
+ {
+ if (neigh->willingness == OLSR_WILL_NEVER)
+ {
+ ok = false;
+ break;
+ }
+ else
+ {
+ ok = true;
+ break;
+ }
+ }
+ }
+ if (!ok)
+ {
+ continue;
+ }
+
+ // excluding:
+ // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
+ // link to this node on some interface.
+ for (NeighborSet::const_iterator neigh = N.begin ();
+ neigh != N.end (); neigh++)
+ {
+ if (neigh->neighborMainAddr == twoHopNeigh->twoHopNeighborAddr)
+ {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ N2.push_back (*twoHopNeigh);
+ }
+ }
+
+ NS_LOG_DEBUG ("Size of N2: " << N2.size ());
+
+ // 1. Start with an MPR set made of all members of N with
+ // N_willingness equal to WILL_ALWAYS
+ for (NeighborSet::const_iterator neighbor = N.begin (); neighbor != N.end (); neighbor++)
+ {
+ if (neighbor->willingness == OLSR_WILL_ALWAYS)
+ {
+ mprSet.insert (neighbor->neighborMainAddr);
+ // (not in RFC but I think is needed: remove the 2-hop
+ // neighbors reachable by the MPR from N2)
+ for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
+ twoHopNeigh != N2.end (); )
+ {
+ if (twoHopNeigh->neighborMainAddr == neighbor->neighborMainAddr)
+ {
+ twoHopNeigh = N2.erase (twoHopNeigh);
+ }
+ else
+ {
+ twoHopNeigh++;
+ }
+ }
+ }
+ }
+
+ // 2. Calculate D(y), where y is a member of N, for all nodes in N.
+ // (we do this later)
+
+ // 3. Add to the MPR set those nodes in N, which are the *only*
+ // nodes to provide reachability to a node in N2.
+ std::set<Ipv4Address> coveredTwoHopNeighbors;
+ for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin (); twoHopNeigh != N2.end (); twoHopNeigh++)
+ {
+ NeighborSet::const_iterator onlyNeighbor = N.end ();
+
+ for (NeighborSet::const_iterator neighbor = N.begin ();
+ neighbor != N.end (); neighbor++)
+ {
+ if (neighbor->neighborMainAddr == twoHopNeigh->neighborMainAddr)
+ {
+ if (onlyNeighbor == N.end ())
+ {
+ onlyNeighbor = neighbor;
+ }
+ else
+ {
+ onlyNeighbor = N.end ();
+ break;
+ }
+ }
+ }
+ if (onlyNeighbor != N.end ())
+ {
+ mprSet.insert (onlyNeighbor->neighborMainAddr);
+ coveredTwoHopNeighbors.insert (twoHopNeigh->twoHopNeighborAddr);
+ }
+ }
+ // Remove the nodes from N2 which are now covered by a node in the MPR set.
+ for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
+ twoHopNeigh != N2.end (); )
+ {
+ if (coveredTwoHopNeighbors.find (twoHopNeigh->twoHopNeighborAddr) != coveredTwoHopNeighbors.end ())
+ {
+ twoHopNeigh = N2.erase (twoHopNeigh);
+ }
+ else
+ {
+ twoHopNeigh++;
+ }
+ }
+
+ // 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)
+ {
+ continue;
+ }
+ 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)
+ {
+ mprSet.insert (max->neighborMainAddr);
+ for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
+ twoHopNeigh != N2.end (); )
+ {
+ if (twoHopNeigh->neighborMainAddr == max->neighborMainAddr)
+ {
+ twoHopNeigh = N2.erase (twoHopNeigh);
+ }
+ else
+ {
+ twoHopNeigh++;
+ }
+ }
+ }
+ }
+
+#ifdef NS3_LOG_ENABLE
+ {
+ std::ostringstream os;
+ os << "[";
+ for (MprSet::const_iterator iter = mprSet.begin ();
+ iter != mprSet.end (); iter++)
+ {
+ MprSet::const_iterator next = iter;
+ next++;
+ os << *iter;
+ if (next != mprSet.end ())
+ os << ", ";
+ }
+ os << "]";
+ NS_LOG_DEBUG ("Computed MPR set for node " << m_mainAddress << ": " << os.str ());
+ }
+#endif
+
+ m_state.SetMprSet (mprSet);
+}
+
+///
+/// \brief Gets the main address associated with a given interface address.
+///
+/// \param iface_addr the interface address.
+/// \return the corresponding main address.
+///
+Ipv4Address
+RoutingProtocol::GetMainAddress (Ipv4Address iface_addr) const
+{
+ const 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
+RoutingProtocol::RoutingTableComputation ()
+{
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " s: Node " << m_mainAddress
+ << ": RoutingTableComputation begin...");
+
+ // 1. All the entries from the routing table are removed.
+ Clear ();
+
+ // 2. The new routing entries are added starting with the
+ // symmetric neighbors (h=1) as the destination nodes.
+ const NeighborSet &neighborSet = m_state.GetNeighbors ();
+ for (NeighborSet::const_iterator it = neighborSet.begin ();
+ it != neighborSet.end(); it++)
+ {
+ NeighborTuple const &nb_tuple = *it;
+ NS_LOG_DEBUG ("Looking at neighbor tuple: " << nb_tuple);
+ if (nb_tuple.status == NeighborTuple::STATUS_SYM)
+ {
+ bool nb_main_addr = false;
+ const LinkTuple *lt = NULL;
+ const LinkSet &linkSet = m_state.GetLinks ();
+ for (LinkSet::const_iterator it2 = linkSet.begin();
+ it2 != linkSet.end(); it2++)
+ {
+ LinkTuple const &link_tuple = *it2;
+ NS_LOG_DEBUG ("Looking at link tuple: " << link_tuple
+ << (link_tuple.time >= Simulator::Now ()? "" : " (expired)"));
+ if ((GetMainAddress (link_tuple.neighborIfaceAddr) == nb_tuple.neighborMainAddr)
+ && link_tuple.time >= Simulator::Now ())
+ {
+ NS_LOG_LOGIC ("Link tuple matches neighbor " << nb_tuple.neighborMainAddr
+ << " => adding routing table entry to neighbor");
+ lt = &link_tuple;
+ AddEntry (link_tuple.neighborIfaceAddr,
+ link_tuple.neighborIfaceAddr,
+ link_tuple.localIfaceAddr,
+ 1);
+ if (link_tuple.neighborIfaceAddr == nb_tuple.neighborMainAddr)
+ {
+ nb_main_addr = true;
+ }
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Link tuple: linkMainAddress= " << GetMainAddress (link_tuple.neighborIfaceAddr)
+ << "; neighborMainAddr = " << nb_tuple.neighborMainAddr
+ << "; expired=" << int (link_tuple.time < Simulator::Now ())
+ << " => IGNORE");
+ }
+ }
+
+ // If, in the above, no R_dest_addr is equal to the main
+ // address of the neighbor, then another new routing entry
+ // with MUST be added, with:
+ // R_dest_addr = main address of the neighbor;
+ // R_next_addr = L_neighbor_iface_addr of one of the
+ // associated link tuple with L_time >= current time;
+ // R_dist = 1;
+ // R_iface_addr = L_local_iface_addr of the
+ // associated link tuple.
+ if (!nb_main_addr && lt != NULL)
+ {
+ NS_LOG_LOGIC ("no R_dest_addr is equal to the main address of the neighbor "
+ "=> adding additional routing entry");
+ AddEntry(nb_tuple.neighborMainAddr,
+ lt->neighborIfaceAddr,
+ lt->localIfaceAddr,
+ 1);
+ }
+ }
+ }
+
+ // 3. for each node in N2, i.e., a 2-hop neighbor which is not a
+ // neighbor node or the node itself, and such that there exist at
+ // least one entry in the 2-hop neighbor set where
+ // N_neighbor_main_addr correspond to a neighbor node with
+ // willingness different of WILL_NEVER,
+ const TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
+ for (TwoHopNeighborSet::const_iterator it = twoHopNeighbors.begin ();
+ it != twoHopNeighbors.end (); it++)
+ {
+ TwoHopNeighborTuple const &nb2hop_tuple = *it;
+
+ NS_LOG_LOGIC ("Looking at two-hop neighbor tuple: " << nb2hop_tuple);
+
+ // a 2-hop neighbor which is not a neighbor node or the node itself
+ if (m_state.FindNeighborTuple (nb2hop_tuple.twoHopNeighborAddr))
+ {
+ NS_LOG_LOGIC ("Two-hop neighbor tuple is also neighbor; skipped.");
+ continue;
+ }
+
+ if (nb2hop_tuple.twoHopNeighborAddr == m_mainAddress)
+ {
+ NS_LOG_LOGIC ("Two-hop neighbor is self; skipped.");
+ continue;
+ }
+
+ // ...and such that there exist at least one entry in the 2-hop
+ // neighbor set where N_neighbor_main_addr correspond to a
+ // neighbor node with willingness different of WILL_NEVER...
+ bool nb2hopOk = false;
+ for (NeighborSet::const_iterator neighbor = neighborSet.begin ();
+ neighbor != neighborSet.end(); neighbor++)
+ {
+ if (neighbor->neighborMainAddr == nb2hop_tuple.neighborMainAddr
+ && neighbor->willingness != OLSR_WILL_NEVER)
+ {
+ nb2hopOk = true;
+ break;
+ }
+ }
+ if (!nb2hopOk)
+ {
+ NS_LOG_LOGIC ("Two-hop neighbor tuple skipped: 2-hop neighbor "
+ << nb2hop_tuple.twoHopNeighborAddr
+ << " is attached to neighbor " << nb2hop_tuple.neighborMainAddr
+ << ", which was not found in the Neighbor Set.");
+ continue;
+ }
+
+ // one selects one 2-hop tuple and creates one entry in the routing table with:
+ // R_dest_addr = the main address of the 2-hop neighbor;
+ // R_next_addr = the R_next_addr of the entry in the
+ // routing table with:
+ // R_dest_addr == N_neighbor_main_addr
+ // of the 2-hop tuple;
+ // R_dist = 2;
+ // R_iface_addr = the R_iface_addr of the entry in the
+ // routing table with:
+ // R_dest_addr == N_neighbor_main_addr
+ // of the 2-hop tuple;
+ RoutingTableEntry entry;
+ bool foundEntry = Lookup (nb2hop_tuple.neighborMainAddr, entry);
+ if (foundEntry)
+ {
+ NS_LOG_LOGIC ("Adding routing entry for two-hop neighbor.");
+ AddEntry (nb2hop_tuple.twoHopNeighborAddr,
+ entry.nextAddr,
+ entry.interface,
+ 2);
+ }
+ else
+ {
+ NS_LOG_LOGIC ("NOT adding routing entry for two-hop neighbor ("
+ << nb2hop_tuple.twoHopNeighborAddr
+ << " not found in the routing table)");
+ }
+ }
+
+ for (uint32_t h = 2; ; h++)
+ {
+ bool added = false;
+
+ // 3.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)
+ const TopologySet &topology = m_state.GetTopologySet ();
+ for (TopologySet::const_iterator it = topology.begin ();
+ it != topology.end (); it++)
+ {
+ const TopologyTuple &topology_tuple = *it;
+ NS_LOG_LOGIC ("Looking at topology tuple: " << topology_tuple);
+
+ RoutingTableEntry destAddrEntry, lastAddrEntry;
+ bool have_destAddrEntry = Lookup (topology_tuple.destAddr, destAddrEntry);
+ bool have_lastAddrEntry = Lookup (topology_tuple.lastAddr, lastAddrEntry);
+ if (!have_destAddrEntry && have_lastAddrEntry && lastAddrEntry.distance == h)
+ {
+ NS_LOG_LOGIC ("Adding routing table entry based on the topology tuple.");
+ // then a new route entry MUST be recorded in
+ // the routing table (if it does not already exist) where:
+ // R_dest_addr = T_dest_addr;
+ // R_next_addr = R_next_addr of the recorded
+ // route entry where:
+ // R_dest_addr == T_last_addr
+ // R_dist = h+1; and
+ // R_iface_addr = R_iface_addr of the recorded
+ // route entry where:
+ // R_dest_addr == T_last_addr.
+ AddEntry (topology_tuple.destAddr,
+ lastAddrEntry.nextAddr,
+ lastAddrEntry.interface,
+ h + 1);
+ added = true;
+ }
+ else
+ {
+ NS_LOG_LOGIC ("NOT adding routing table entry based on the topology tuple: "
+ "have_destAddrEntry=" << have_destAddrEntry
+ << " have_lastAddrEntry=" << have_lastAddrEntry
+ << " lastAddrEntry.distance=" << (int) lastAddrEntry.distance
+ << " (h=" << h << ")");
+ }
+ }
+
+ if (!added)
+ break;
+ }
+
+ // 4. 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
+ const IfaceAssocSet &ifaceAssocSet = m_state.GetIfaceAssocSet ();
+ for (IfaceAssocSet::const_iterator it = ifaceAssocSet.begin ();
+ it != ifaceAssocSet.end (); it++)
+ {
+ IfaceAssocTuple const &tuple = *it;
+ RoutingTableEntry entry1, entry2;
+ bool have_entry1 = Lookup (tuple.mainAddr, entry1);
+ bool have_entry2 = Lookup (tuple.ifaceAddr, entry2);
+ if (have_entry1 && !have_entry2)
+ {
+ // then a route entry is created in the routing table with:
+ // R_dest_addr = I_iface_addr (of the multiple interface
+ // association entry)
+ // R_next_addr = R_next_addr (of the recorded route entry)
+ // R_dist = R_dist (of the recorded route entry)
+ // R_iface_addr = R_iface_addr (of the recorded route entry).
+ AddEntry (tuple.ifaceAddr,
+ entry1.nextAddr,
+ entry1.interface,
+ entry1.distance);
+ }
+ }
+
+ NS_LOG_DEBUG ("Node " << m_mainAddress << ": RoutingTableComputation end.");
+ m_routingTableChanged (GetSize ());
+}
+
+
+///
+/// \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
+RoutingProtocol::ProcessHello (const olsr::MessageHeader &msg,
+ const Ipv4Address &receiverIface,
+ const Ipv4Address &senderIface)
+{
+ const olsr::MessageHeader::Hello &hello = msg.GetHello ();
+
+ LinkSensing (msg, hello, receiverIface, senderIface);
+
+#ifdef NS3_LOG_ENABLE
+ {
+ const LinkSet &links = m_state.GetLinks ();
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s ** BEGIN dump Link Set for OLSR Node " << m_mainAddress);
+ for (LinkSet::const_iterator link = links.begin (); link != links.end (); link++)
+ {
+ NS_LOG_DEBUG(*link);
+ }
+ NS_LOG_DEBUG ("** END dump Link Set for OLSR Node " << m_mainAddress);
+
+ const NeighborSet &neighbors = m_state.GetNeighbors ();
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s ** BEGIN dump Neighbor Set for OLSR Node " << m_mainAddress);
+ for (NeighborSet::const_iterator neighbor = neighbors.begin (); neighbor != neighbors.end (); neighbor++)
+ {
+ NS_LOG_DEBUG(*neighbor);
+ }
+ NS_LOG_DEBUG ("** END dump Neighbor Set for OLSR Node " << m_mainAddress);
+ }
+#endif
+
+ PopulateNeighborSet (msg, hello);
+ PopulateTwoHopNeighborSet (msg, hello);
+
+#ifdef NS3_LOG_ENABLE
+ {
+ const TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s ** BEGIN dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress);
+ for (TwoHopNeighborSet::const_iterator tuple = twoHopNeighbors.begin ();
+ tuple != twoHopNeighbors.end (); tuple++)
+ {
+ NS_LOG_DEBUG(*tuple);
+ }
+ NS_LOG_DEBUG ("** END dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress);
+ }
+#endif
+
+ 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
+RoutingProtocol::ProcessTc (const olsr::MessageHeader &msg,
+ const Ipv4Address &senderIface)
+{
+ const olsr::MessageHeader::Tc &tc = msg.GetTc ();
+ 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.
+ const 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.
+ const TopologyTuple *topologyTuple =
+ m_state.FindNewerTopologyTuple (msg.GetOriginatorAddress (), tc.ansn);
+ 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.ansn);
+
+ // 4. For each of the advertised neighbor main address received in
+ // the TC message:
+ for (std::vector<Ipv4Address>::const_iterator i = tc.neighborAddresses.begin ();
+ i != tc.neighborAddresses.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.ansn;
+ topologyTuple.expirationTime = now + msg.GetVTime ();
+ AddTopologyTuple (topologyTuple);
+
+ // Schedules topology tuple deletion
+ m_events.Track (Simulator::Schedule (DELAY (topologyTuple.expirationTime),
+ &RoutingProtocol::TopologyTupleTimerExpire,
+ this,
+ topologyTuple.destAddr,
+ topologyTuple.lastAddr));
+ }
+ }
+
+#ifdef NS3_LOG_ENABLE
+ {
+ const TopologySet &topology = m_state.GetTopologySet ();
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s ** BEGIN dump TopologySet for OLSR Node " << m_mainAddress);
+ for (TopologySet::const_iterator tuple = topology.begin ();
+ tuple != topology.end (); tuple++)
+ {
+ NS_LOG_DEBUG (*tuple);
+ }
+ NS_LOG_DEBUG ("** END dump TopologySet Set for OLSR Node " << m_mainAddress);
+ }
+#endif
+}
+
+///
+/// \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
+RoutingProtocol::ProcessMid (const olsr::MessageHeader &msg,
+ const Ipv4Address &senderIface)
+{
+ const olsr::MessageHeader::Mid &mid = msg.GetMid ();
+ Time now = Simulator::Now ();
+
+ NS_LOG_DEBUG ("Node " << m_mainAddress << " ProcessMid from " << senderIface);
+ // 1. If the sender interface of this message is not in the symmetric
+ // 1-hop neighborhood of this node, the message MUST be discarded.
+ const LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderIface, now);
+ if (linkTuple == NULL)
+ {
+ NS_LOG_LOGIC ("Node " << m_mainAddress <<
+ ": the sender interface of this message is not in the "
+ "symmetric 1-hop neighborhood of this node,"
+ " the message MUST be discarded.");
+ return;
+ }
+
+ // 2. For each interface address listed in the MID message
+ for (std::vector<Ipv4Address>::const_iterator i = mid.interfaceAddresses.begin ();
+ i != mid.interfaceAddresses.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 ())
+ {
+ NS_LOG_LOGIC ("IfaceAssoc updated: " << *tuple);
+ 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);
+ NS_LOG_LOGIC ("New IfaceAssoc added: " << tuple);
+ // Schedules iface association tuple deletion
+ Simulator::Schedule (DELAY (tuple.time),
+ &RoutingProtocol::IfaceAssocTupleTimerExpire, this, tuple.ifaceAddr);
+ }
+ }
+
+ // 3. (not part of the RFC) iterate over all NeighborTuple's and
+ // TwoHopNeighborTuples, update the neighbor addresses taking into account
+ // the new MID information.
+ NeighborSet &neighbors = m_state.GetNeighbors ();
+ for (NeighborSet::iterator neighbor = neighbors.begin (); neighbor != neighbors.end(); neighbor++)
+ {
+ neighbor->neighborMainAddr = GetMainAddress (neighbor->neighborMainAddr);
+ }
+
+ TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
+ for (TwoHopNeighborSet::iterator twoHopNeighbor = twoHopNeighbors.begin ();
+ twoHopNeighbor != twoHopNeighbors.end(); twoHopNeighbor++)
+ {
+ twoHopNeighbor->neighborMainAddr = GetMainAddress (twoHopNeighbor->neighborMainAddr);
+ twoHopNeighbor->twoHopNeighborAddr = GetMainAddress (twoHopNeighbor->twoHopNeighborAddr);
+ }
+ NS_LOG_DEBUG ("Node " << m_mainAddress << " ProcessMid from " << senderIface << " -> END.");
+}
+
+
+///
+/// \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
+RoutingProtocol::ForwardDefault (olsr::MessageHeader olsrMessage,
+ 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
+ const 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)
+ {
+ NS_LOG_LOGIC (Simulator::Now () << "Node " << m_mainAddress << " does not forward a message received"
+ " from " << olsrMessage.GetOriginatorAddress () << " because it is duplicated");
+ 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)
+ {
+ const 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.
+ QueueMessage (olsrMessage, 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,
+ &RoutingProtocol::DupTupleTimerExpire, this,
+ newDup.address, newDup.sequenceNumber);
+ }
+}
+
+///
+/// \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
+RoutingProtocol::QueueMessage (const olsr::MessageHeader &message, Time delay)
+{
+ m_queuedMessages.push_back (message);
+ if (not m_queuedMessagesTimer.IsRunning ())
+ {
+ m_queuedMessagesTimer.SetDelay (delay);
+ m_queuedMessagesTimer.Schedule ();
+ }
+}
+
+void
+RoutingProtocol::SendPacket (Ptr<Packet> packet,
+ const MessageList &containedMessages)
+{
+ NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " sending a OLSR packet");
+
+ // Add a header
+ olsr::PacketHeader header;
+ header.SetPacketLength (header.GetSerializedSize () + packet->GetSize ());
+ header.SetPacketSequenceNumber (GetPacketSequenceNumber ());
+ packet->AddHeader (header);
+
+ // Trace it
+ m_txPacketTrace (header, containedMessages);
+
+ // Send it
+ m_socketAddresses.begin ()->first->Send (packet);
+}
+
+///
+/// \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
+RoutingProtocol::SendQueuedMessages ()
+{
+ Ptr<Packet> packet = Create<Packet> ();
+ int numMessages = 0;
+
+ NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": SendQueuedMessages");
+
+ MessageList msglist;
+
+ for (std::vector<olsr::MessageHeader>::const_iterator message = m_queuedMessages.begin ();
+ message != m_queuedMessages.end ();
+ message++)
+ {
+ Ptr<Packet> p = Create<Packet> ();
+ p->AddHeader (*message);
+ packet->AddAtEnd (p);
+ msglist.push_back (*message);
+ if (++numMessages == OLSR_MAX_MSGS)
+ {
+ SendPacket (packet, msglist);
+ msglist.clear ();
+ // Reset variables for next packet
+ numMessages = 0;
+ packet = Create<Packet> ();
+ }
+ }
+
+ if (packet->GetSize ())
+ {
+ SendPacket (packet, msglist);
+ }
+
+ m_queuedMessages.clear ();
+}
+
+///
+/// \brief Creates a new %OLSR HELLO message which is buffered for being sent later on.
+///
+void
+RoutingProtocol::SendHello ()
+{
+ NS_LOG_FUNCTION (this);
+
+ olsr::MessageHeader msg;
+ Time now = Simulator::Now ();
+
+ msg.SetVTime (OLSR_NEIGHB_HOLD_TIME);
+ msg.SetOriginatorAddress (m_mainAddress);
+ msg.SetTimeToLive (1);
+ msg.SetHopCount (0);
+ msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+ olsr::MessageHeader::Hello &hello = msg.GetHello ();
+
+ hello.SetHTime (Scalar (3) * m_helloInterval);
+ hello.willingness = m_willingness;
+
+ std::vector<olsr::MessageHeader::Hello::LinkMessage>
+ &linkMessages = hello.linkMessages;
+
+ const LinkSet &links = m_state.GetLinks ();
+ for (LinkSet::const_iterator link_tuple = links.begin ();
+ link_tuple != links.end (); link_tuple++)
+ {
+ if (!(GetMainAddress (link_tuple->localIfaceAddr) == m_mainAddress
+ && link_tuple->time >= now))
+ {
+ continue;
+ }
+
+ uint8_t link_type, nb_type = 0xff;
+
+ // Establishes link type
+ 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;
+ NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
+ << " to be 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 == GetMainAddress (link_tuple->neighborIfaceAddr))
+ {
+ if (nb_tuple->status == NeighborTuple::STATUS_SYM)
+ {
+ NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
+ << " to be SYM_NEIGH.");
+ nb_type = OLSR_SYM_NEIGH;
+ }
+ else if (nb_tuple->status == NeighborTuple::STATUS_NOT_SYM)
+ {
+ nb_type = OLSR_NOT_NEIGH;
+ NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
+ << " to be NOT_NEIGH.");
+ }
+ else
+ {
+ NS_FATAL_ERROR ("There is a neighbor tuple with an unknown status!\n");
+ }
+ ok = true;
+ break;
+ }
+ }
+ if (!ok)
+ {
+ NS_LOG_WARN ("I don't know the neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr) << "!!!");
+ continue;
+ }
+ }
+
+ olsr::MessageHeader::Hello::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);
+ }
+ NS_LOG_DEBUG ("OLSR HELLO message size: " << int (msg.GetSerializedSize ())
+ << " (with " << int (linkMessages.size ()) << " link messages)");
+ QueueMessage (msg, JITTER);
+}
+
+///
+/// \brief Creates a new %OLSR TC message which is buffered for being sent later on.
+///
+void
+RoutingProtocol::SendTc ()
+{
+ NS_LOG_FUNCTION (this);
+
+ olsr::MessageHeader msg;
+
+ msg.SetVTime (OLSR_TOP_HOLD_TIME);
+ msg.SetOriginatorAddress (m_mainAddress);
+ msg.SetTimeToLive (255);
+ msg.SetHopCount (0);
+ msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+
+ olsr::MessageHeader::Tc &tc = msg.GetTc ();
+ tc.ansn = m_ansn;
+ for (MprSelectorSet::const_iterator mprsel_tuple = m_state.GetMprSelectors ().begin();
+ mprsel_tuple != m_state.GetMprSelectors ().end(); mprsel_tuple++)
+ {
+ tc.neighborAddresses.push_back (mprsel_tuple->mainAddr);
+ }
+ QueueMessage (msg, JITTER);
+}
+
+///
+/// \brief Creates a new %OLSR MID message which is buffered for being sent later on.
+///
+void
+RoutingProtocol::SendMid ()
+{
+ olsr::MessageHeader msg;
+ olsr::MessageHeader::Mid &mid = msg.GetMid ();
+
+ // 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");
+ for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+ {
+ Ipv4Address addr = m_ipv4->GetAddress (i);
+ if (addr != m_mainAddress && addr != loopback)
+ mid.interfaceAddresses.push_back (addr);
+ }
+ if (mid.interfaceAddresses.size () == 0)
+ return;
+
+ msg.SetVTime (OLSR_MID_HOLD_TIME);
+ msg.SetOriginatorAddress (m_mainAddress);
+ msg.SetTimeToLive (255);
+ msg.SetHopCount (0);
+ msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+
+ QueueMessage (msg, JITTER);
+}
+
+///
+/// \brief Updates Link Set according to a new received HELLO message (following RFC 3626
+/// specification). Neighbor Set is also updated if needed.
+void
+RoutingProtocol::LinkSensing (const olsr::MessageHeader &msg,
+ const olsr::MessageHeader::Hello &hello,
+ const Ipv4Address &receiverIface,
+ const Ipv4Address &senderIface)
+{
+ Time now = Simulator::Now ();
+ bool updated = false;
+ bool created = false;
+ NS_LOG_DEBUG ("@" << now.GetSeconds () << ": Olsr node " << m_mainAddress
+ << ": LinkSensing(receiverIface=" << receiverIface
+ << ", senderIface=" << senderIface << ") BEGIN");
+
+ NS_ASSERT (msg.GetVTime () > Seconds (0));
+ 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.time = now + msg.GetVTime ();
+ link_tuple = &m_state.InsertLinkTuple (newLinkTuple);
+ created = true;
+ NS_LOG_LOGIC ("Existing link tuple did not exist => creating new one");
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Existing link tuple already exists => will update it");
+ updated = true;
+ }
+
+ link_tuple->asymTime = now + msg.GetVTime ();
+ for (std::vector<olsr::MessageHeader::Hello::LinkMessage>::const_iterator linkMessage =
+ hello.linkMessages.begin ();
+ linkMessage != hello.linkMessages.end ();
+ linkMessage++)
+ {
+ int lt = linkMessage->linkCode & 0x03; // Link Type
+ int nt = (linkMessage->linkCode >> 2) & 0x03; // Neighbor Type
+
+#ifdef NS3_LOG_ENABLE
+ const char *linkTypeName;
+ switch (lt)
+ {
+ case OLSR_UNSPEC_LINK: linkTypeName = "UNSPEC_LINK"; break;
+ case OLSR_ASYM_LINK: linkTypeName = "ASYM_LINK"; break;
+ case OLSR_SYM_LINK: linkTypeName = "SYM_LINK"; break;
+ case OLSR_LOST_LINK: linkTypeName = "LOST_LINK"; break;
+ default: linkTypeName = "(invalid value!)";
+ }
+
+ const char *neighborTypeName;
+ switch (nt)
+ {
+ case OLSR_NOT_NEIGH: neighborTypeName = "NOT_NEIGH"; break;
+ case OLSR_SYM_NEIGH: neighborTypeName = "SYM_NEIGH"; break;
+ case OLSR_MPR_NEIGH: neighborTypeName = "MPR_NEIGH"; break;
+ default: neighborTypeName = "(invalid value!)";
+ }
+
+ NS_LOG_DEBUG ("Looking at HELLO link messages with Link Type "
+ << lt << " (" << linkTypeName
+ << ") and Neighbor Type " << nt
+ << " (" << neighborTypeName << ")");
+#endif
+
+ // 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))
+ {
+ NS_LOG_LOGIC ("HELLO link code is invalid => IGNORING");
+ continue;
+ }
+
+ for (std::vector<Ipv4Address>::const_iterator neighIfaceAddr =
+ linkMessage->neighborInterfaceAddresses.begin ();
+ neighIfaceAddr != linkMessage->neighborInterfaceAddresses.end ();
+ neighIfaceAddr++)
+ {
+ NS_LOG_DEBUG (" -> Neighbor: " << *neighIfaceAddr);
+ if (*neighIfaceAddr == receiverIface)
+ {
+ if (lt == OLSR_LOST_LINK)
+ {
+ NS_LOG_LOGIC ("link is LOST => expiring it");
+ link_tuple->symTime = now - Seconds (1);
+ updated = true;
+ }
+ else if (lt == OLSR_SYM_LINK || lt == OLSR_ASYM_LINK)
+ {
+ NS_LOG_DEBUG (*link_tuple << ": link is SYM or ASYM => should become SYM now"
+ " (symTime being increased to " << now + msg.GetVTime ());
+ link_tuple->symTime = now + msg.GetVTime ();
+ link_tuple->time = link_tuple->symTime + OLSR_NEIGHB_HOLD_TIME;
+ updated = true;
+ }
+ else
+ {
+ NS_FATAL_ERROR ("bad link type");
+ }
+ break;
+ }
+ else
+ {
+ NS_LOG_DEBUG (" \\-> *neighIfaceAddr (" << *neighIfaceAddr
+ << " != receiverIface (" << receiverIface << ") => IGNORING!");
+ }
+ }
+ NS_LOG_DEBUG ("Link tuple updated: " << int (updated));
+ }
+ link_tuple->time = std::max(link_tuple->time, link_tuple->asymTime);
+
+ if (updated)
+ {
+ LinkTupleUpdated (*link_tuple, hello.willingness);
+ }
+
+ // Schedules link tuple deletion
+ if (created && link_tuple != NULL)
+ {
+ LinkTupleAdded (*link_tuple, hello.willingness);
+ m_events.Track (Simulator::Schedule (DELAY (std::min (link_tuple->time, link_tuple->symTime)),
+ &RoutingProtocol::LinkTupleTimerExpire, this,
+ link_tuple->neighborIfaceAddr));
+ }
+ NS_LOG_DEBUG ("@" << now.GetSeconds () << ": Olsr node " << m_mainAddress
+ << ": LinkSensing END");
+}
+
+///
+/// \brief Updates the Neighbor Set according to the information contained in a new received
+/// HELLO message (following RFC 3626).
+void
+RoutingProtocol::PopulateNeighborSet (const olsr::MessageHeader &msg,
+ const olsr::MessageHeader::Hello &hello)
+{
+ NeighborTuple *nb_tuple = m_state.FindNeighborTuple (msg.GetOriginatorAddress ());
+ if (nb_tuple != NULL)
+ {
+ nb_tuple->willingness = hello.willingness;
+ }
+}
+
+
+///
+/// \brief Updates the 2-hop Neighbor Set according to the information contained in a new
+/// received HELLO message (following RFC 3626).
+void
+RoutingProtocol::PopulateTwoHopNeighborSet (const olsr::MessageHeader &msg,
+ const olsr::MessageHeader::Hello &hello)
+{
+ Time now = Simulator::Now ();
+
+ NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": PopulateTwoHopNeighborSet BEGIN");
+
+ for (LinkSet::const_iterator link_tuple = m_state.GetLinks ().begin ();
+ link_tuple != m_state.GetLinks ().end (); link_tuple++)
+ {
+ NS_LOG_LOGIC ("Looking at link tuple: " << *link_tuple);
+ if (GetMainAddress (link_tuple->neighborIfaceAddr) != msg.GetOriginatorAddress ())
+ {
+ NS_LOG_LOGIC ("Link tuple ignored: "
+ "GetMainAddress (link_tuple->neighborIfaceAddr) != msg.GetOriginatorAddress ()");
+ NS_LOG_LOGIC ("(GetMainAddress(" << link_tuple->neighborIfaceAddr << "): "
+ << GetMainAddress (link_tuple->neighborIfaceAddr)
+ << "; msg.GetOriginatorAddress (): " << msg.GetOriginatorAddress ());
+ continue;
+ }
+
+ if (link_tuple->symTime < now)
+ {
+ NS_LOG_LOGIC ("Link tuple ignored: expired.");
+ continue;
+ }
+
+ typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
+ for (LinkMessageVec::const_iterator linkMessage = hello.linkMessages.begin ();
+ linkMessage != hello.linkMessages.end (); linkMessage++)
+ {
+ int neighborType = (linkMessage->linkCode >> 2) & 0x3;
+#ifdef NS3_LOG_ENABLE
+ const char *neighborTypeNames[3] = { "NOT_NEIGH", "SYM_NEIGH", "MPR_NEIGH" };
+ const char *neighborTypeName = ((neighborType < 3)?
+ neighborTypeNames[neighborType]
+ : "(invalid value)");
+ NS_LOG_DEBUG ("Looking at Link Message from HELLO message: neighborType="
+ << neighborType << " (" << neighborTypeName << ")");
+#endif
+
+ for (std::vector<Ipv4Address>::const_iterator nb2hop_addr_iter =
+ linkMessage->neighborInterfaceAddresses.begin ();
+ nb2hop_addr_iter != linkMessage->neighborInterfaceAddresses.end ();
+ nb2hop_addr_iter++)
+ {
+ Ipv4Address nb2hop_addr = GetMainAddress (*nb2hop_addr_iter);
+ NS_LOG_DEBUG ("Looking at 2-hop neighbor address from HELLO message: "
+ << *nb2hop_addr_iter
+ << " (main address is " << nb2hop_addr << ")");
+ if (neighborType == OLSR_SYM_NEIGH || neighborType == 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)
+ {
+ NS_LOG_LOGIC ("Ignoring 2-hop neighbor (it is the node itself)");
+ continue;
+ }
+
+ // Otherwise, a 2-hop tuple is created
+ TwoHopNeighborTuple *nb2hop_tuple =
+ m_state.FindTwoHopNeighborTuple (msg.GetOriginatorAddress (), nb2hop_addr);
+ NS_LOG_LOGIC ("Adding the 2-hop neighbor"
+ << (nb2hop_tuple? " (refreshing existing entry)" : ""));
+ if (nb2hop_tuple == NULL)
+ {
+ TwoHopNeighborTuple new_nb2hop_tuple;
+ new_nb2hop_tuple.neighborMainAddr = msg.GetOriginatorAddress ();
+ new_nb2hop_tuple.twoHopNeighborAddr = nb2hop_addr;
+ new_nb2hop_tuple.expirationTime = now + msg.GetVTime ();
+ AddTwoHopNeighborTuple (new_nb2hop_tuple);
+ // Schedules nb2hop tuple deletion
+ m_events.Track (Simulator::Schedule (DELAY (new_nb2hop_tuple.expirationTime),
+ &RoutingProtocol::Nb2hopTupleTimerExpire, this,
+ new_nb2hop_tuple.neighborMainAddr,
+ new_nb2hop_tuple.twoHopNeighborAddr));
+ }
+ else
+ {
+ nb2hop_tuple->expirationTime = now + msg.GetVTime ();
+ }
+ }
+ else if (neighborType == 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.
+ NS_LOG_LOGIC ("2-hop neighbor is NOT_NEIGH => deleting matching 2-hop neighbor state");
+ m_state.EraseTwoHopNeighborTuples (msg.GetOriginatorAddress (), nb2hop_addr);
+ }
+ else
+ {
+ NS_LOG_LOGIC ("*** WARNING *** Ignoring link message (inside HELLO) with bad"
+ " neighbor type value: " << neighborType);
+ }
+ }
+ }
+ }
+
+ NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": PopulateTwoHopNeighborSet END");
+}
+
+
+
+///
+/// \brief Updates the MPR Selector Set according to the information contained in a new
+/// received HELLO message (following RFC 3626).
+void
+RoutingProtocol::PopulateMprSelectorSet (const olsr::MessageHeader &msg,
+ const olsr::MessageHeader::Hello &hello)
+{
+ NS_LOG_FUNCTION (this);
+
+ Time now = Simulator::Now ();
+
+ typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
+ for (LinkMessageVec::const_iterator linkMessage = hello.linkMessages.begin ();
+ linkMessage != hello.linkMessages.end ();
+ linkMessage++)
+ {
+ int nt = linkMessage->linkCode >> 2;
+ if (nt == OLSR_MPR_NEIGH)
+ {
+ NS_LOG_DEBUG ("Processing a link message with neighbor type MPR_NEIGH");
+
+ for (std::vector<Ipv4Address>::const_iterator nb_iface_addr =
+ linkMessage->neighborInterfaceAddresses.begin ();
+ nb_iface_addr != linkMessage->neighborInterfaceAddresses.end ();
+ nb_iface_addr++)
+ {
+ if (GetMainAddress (*nb_iface_addr) == m_mainAddress)
+ {
+ NS_LOG_DEBUG ("Adding entry to mpr selector set for neighbor " << *nb_iface_addr);
+
+ // 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
+ m_events.Track (Simulator::Schedule
+ (DELAY (mprsel_tuple.expirationTime),
+ &RoutingProtocol::MprSelTupleTimerExpire, this,
+ mprsel_tuple.mainAddr));
+ }
+ else
+ {
+ existing_mprsel_tuple->expirationTime = now + msg.GetVTime ();
+ }
+ }
+ }
+ }
+ }
+ NS_LOG_DEBUG ("Computed MPR selector set for node " << m_mainAddress << ": " << m_state.PrintMprSelectorSet ());
+}
+
+
+#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(Ptr<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
+RoutingProtocol::NeighborLoss (const LinkTuple &tuple)
+{
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s: OLSR Node " << m_mainAddress
+ << " LinkTuple " << tuple.neighborIfaceAddr << " -> neighbor loss.");
+ LinkTupleUpdated (tuple, OLSR_WILL_DEFAULT);
+ 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
+RoutingProtocol::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
+RoutingProtocol::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);
+}
+
+void
+RoutingProtocol::LinkTupleAdded (const LinkTuple &tuple, uint8_t willingness)
+{
+ // 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);
+}
+
+///
+/// \brief Removes a link tuple from the Link Set.
+///
+/// \param tuple the link tuple to be removed.
+///
+void
+RoutingProtocol::RemoveLinkTuple (const LinkTuple &tuple)
+{
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s: OLSR Node " << m_mainAddress
+ << " LinkTuple " << tuple << " REMOVED.");
+
+ 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
+RoutingProtocol::LinkTupleUpdated (const LinkTuple &tuple, uint8_t willingness)
+{
+ // Each time a link tuple changes, the associated neighbor tuple must be recomputed
+
+ NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+ << "s: OLSR Node " << m_mainAddress
+ << " LinkTuple " << tuple << " UPDATED.");
+
+ NeighborTuple *nb_tuple =
+ m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
+
+ if (nb_tuple == NULL)
+ {
+ LinkTupleAdded (tuple, willingness);
+ nb_tuple = m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
+ }
+
+ if (nb_tuple != NULL)
+ {
+#ifdef NS3_LOG_ENABLE
+ int statusBefore = nb_tuple->status;
+#endif
+ if (tuple.symTime >= Simulator::Now ())
+ {
+ nb_tuple->status = NeighborTuple::STATUS_SYM;
+ NS_LOG_DEBUG (*nb_tuple << "->status = STATUS_SYM; changed:"
+ << int (statusBefore != nb_tuple->status));
+ }
+ else
+ {
+ nb_tuple->status = NeighborTuple::STATUS_NOT_SYM;
+ NS_LOG_DEBUG (*nb_tuple << "->status = STATUS_NOT_SYM; changed:"
+ << int (statusBefore != nb_tuple->status));
+ }
+ }
+ else
+ {
+ NS_LOG_WARN ("ERROR! Wanted to update a NeighborTuple but none was found!");
+ }
+}
+
+///
+/// \brief Adds a neighbor tuple to the Neighbor Set.
+///
+/// \param tuple the neighbor tuple to be added.
+///
+void
+RoutingProtocol::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);
+ IncrementAnsn ();
+}
+
+///
+/// \brief Removes a neighbor tuple from the Neighbor Set.
+///
+/// \param tuple the neighbor tuple to be removed.
+///
+void
+RoutingProtocol::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);
+ IncrementAnsn ();
+}
+
+///
+/// \brief Adds a 2-hop neighbor tuple to the 2-hop Neighbor Set.
+///
+/// \param tuple the 2-hop neighbor tuple to be added.
+///
+void
+RoutingProtocol::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
+RoutingProtocol::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);
+}
+
+void
+RoutingProtocol::IncrementAnsn ()
+{
+ m_ansn = (m_ansn + 1) % (OLSR_MAX_SEQ_NUM + 1);
+}
+
+///
+/// \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
+RoutingProtocol::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);
+ IncrementAnsn ();
+}
+
+///
+/// \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
+RoutingProtocol::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);
+ IncrementAnsn ();
+}
+
+///
+/// \brief Adds a topology tuple to the Topology Set.
+///
+/// \param tuple the topology tuple to be added.
+///
+void
+RoutingProtocol::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
+RoutingProtocol::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
+RoutingProtocol::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
+RoutingProtocol::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 RoutingProtocol::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 RoutingProtocol::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
+RoutingProtocol::HelloTimerExpire ()
+{
+ SendHello ();
+ m_helloTimer.Schedule (m_helloInterval);
+}
+
+///
+/// \brief Sends a TC message (if there exists any MPR selector) and reschedules the TC timer.
+/// \param e The event which has expired.
+///
+void
+RoutingProtocol::TcTimerExpire ()
+{
+ if (m_state.GetMprSelectors ().size () > 0)
+ {
+ SendTc ();
+ }
+ else
+ {
+ NS_LOG_DEBUG ("Not sending any TC, no one selected me as MPR.");
+ }
+ m_tcTimer.Schedule (m_tcInterval);
+}
+
+///
+/// \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
+RoutingProtocol::MidTimerExpire ()
+{
+ SendMid ();
+ m_midTimer.Schedule (m_midInterval);
+}
+
+///
+/// \brief Removes tuple if expired. Else timer is rescheduled to expire at tuple.expirationTime.
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param tuple The tuple which has expired.
+///
+void
+RoutingProtocol::DupTupleTimerExpire (Ipv4Address address, uint16_t sequenceNumber)
+{
+ DuplicateTuple *tuple =
+ m_state.FindDuplicateTuple (address, sequenceNumber);
+ if (tuple == NULL)
+ {
+ return;
+ }
+ if (tuple->expirationTime < Simulator::Now ())
+ {
+ RemoveDuplicateTuple (*tuple);
+ }
+ else
+ {
+ m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
+ &RoutingProtocol::DupTupleTimerExpire, this,
+ address, sequenceNumber));
+ }
+}
+
+///
+/// \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
+RoutingProtocol::LinkTupleTimerExpire (Ipv4Address neighborIfaceAddr)
+{
+ Time now = Simulator::Now ();
+
+ // the tuple parameter may be a stale copy; get a newer version from m_state
+ LinkTuple *tuple = m_state.FindLinkTuple (neighborIfaceAddr);
+ if (tuple == NULL)
+ {
+ return;
+ }
+ if (tuple->time < now)
+ {
+ RemoveLinkTuple (*tuple);
+ }
+ else if (tuple->symTime < now)
+ {
+ if (m_linkTupleTimerFirstTime)
+ m_linkTupleTimerFirstTime = false;
+ else
+ NeighborLoss (*tuple);
+
+ m_events.Track (Simulator::Schedule (DELAY (tuple->time),
+ &RoutingProtocol::LinkTupleTimerExpire, this,
+ neighborIfaceAddr));
+ }
+ else
+ {
+ m_events.Track (Simulator::Schedule (DELAY (std::min (tuple->time, tuple->symTime)),
+ &RoutingProtocol::LinkTupleTimerExpire, this,
+ neighborIfaceAddr));
+ }
+}
+
+///
+/// \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
+RoutingProtocol::Nb2hopTupleTimerExpire (Ipv4Address neighborMainAddr, Ipv4Address twoHopNeighborAddr)
+{
+ TwoHopNeighborTuple *tuple;
+ tuple = m_state.FindTwoHopNeighborTuple (neighborMainAddr, twoHopNeighborAddr);
+ if (tuple == NULL)
+ {
+ return;
+ }
+ if (tuple->expirationTime < Simulator::Now ())
+ {
+ RemoveTwoHopNeighborTuple (*tuple);
+ }
+ else
+ {
+ m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
+ &RoutingProtocol::Nb2hopTupleTimerExpire,
+ this, neighborMainAddr, twoHopNeighborAddr));
+ }
+}
+
+///
+/// \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
+RoutingProtocol::MprSelTupleTimerExpire (Ipv4Address mainAddr)
+{
+ MprSelectorTuple *tuple = m_state.FindMprSelectorTuple (mainAddr);
+ if (tuple == NULL)
+ {
+ return;
+ }
+ if (tuple->expirationTime < Simulator::Now ())
+ {
+ RemoveMprSelectorTuple (*tuple);
+ }
+ else
+ {
+ m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
+ &RoutingProtocol::MprSelTupleTimerExpire,
+ this, mainAddr));
+ }
+}
+
+///
+/// \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
+RoutingProtocol::TopologyTupleTimerExpire (Ipv4Address destAddr, Ipv4Address lastAddr)
+{
+ TopologyTuple *tuple = m_state.FindTopologyTuple (destAddr, lastAddr);
+ if (tuple == NULL)
+ {
+ return;
+ }
+ if (tuple->expirationTime < Simulator::Now ())
+ {
+ RemoveTopologyTuple (*tuple);
+ }
+ else
+ {
+ m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
+ &RoutingProtocol::TopologyTupleTimerExpire,
+ this, tuple->destAddr, tuple->lastAddr));
+ }
+}
+
+///
+/// \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
+RoutingProtocol::IfaceAssocTupleTimerExpire (Ipv4Address ifaceAddr)
+{
+ IfaceAssocTuple *tuple = m_state.FindIfaceAssocTuple (ifaceAddr);
+ if (tuple == NULL)
+ {
+ return;
+ }
+ if (tuple->time < Simulator::Now ())
+ {
+ RemoveIfaceAssocTuple (*tuple);
+ }
+ else
+ {
+ m_events.Track (Simulator::Schedule (DELAY (tuple->time),
+ &RoutingProtocol::IfaceAssocTupleTimerExpire,
+ this, ifaceAddr));
+ }
+}
+
+///
+/// \brief Clears the routing table and frees the memory assigned to each one of its entries.
+///
+void
+RoutingProtocol::Clear ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_table.clear ();
+}
+
+///
+/// \brief Deletes the entry whose destination address is given.
+/// \param dest address of the destination node.
+///
+void
+RoutingProtocol::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
+RoutingProtocol::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
+RoutingProtocol::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
+RoutingProtocol::RequestRoute (uint32_t ifIndex,
+ const Ipv4Header &ipHeader,
+ Ptr<Packet> packet,
+ RouteReplyCallback routeReply)
+{
+ RoutingTableEntry entry1, entry2;
+ if (Lookup (ipHeader.GetDestination (), entry1))
+ {
+ bool foundSendEntry = FindSendEntry (entry1, entry2);
+ if (!foundSendEntry)
+ NS_FATAL_ERROR ("FindSendEntry failure");
+
+ Ipv4Route route = Ipv4Route::CreateHostRouteTo
+ (ipHeader.GetDestination (), entry2.nextAddr, entry2.interface);
+
+ NS_LOG_DEBUG ("Olsr node " << m_mainAddress
+ << ": RouteRequest for dest=" << ipHeader.GetDestination ()
+ << " --> nestHop=" << entry2.nextAddr
+ << " interface=" << entry2.interface);
+
+ routeReply (true, route, packet, ipHeader);
+ return true;
+ }
+ else
+ {
+#ifdef NS3_LOG_ENABLE
+ NS_LOG_DEBUG ("Olsr node " << m_mainAddress
+ << ": RouteRequest for dest=" << ipHeader.GetDestination ()
+ << " --> NOT FOUND; ** Dumping routing table...");
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator iter = m_table.begin ();
+ iter != m_table.end (); iter++)
+ {
+ NS_LOG_DEBUG ("dest=" << iter->first << " --> next=" << iter->second.nextAddr
+ << " via interface " << iter->second.interface);
+ }
+
+ NS_LOG_DEBUG ("** Routing table dump end.");
+#endif
+ return false;
+ }
+}
+
+bool
+RoutingProtocol::RequestIfIndex (Ipv4Address destination,
+ uint32_t& ifIndex)
+{
+ RoutingTableEntry entry1, entry2;
+ if (Lookup (destination, entry1))
+ {
+ bool foundSendEntry = FindSendEntry (entry1, entry2);
+ if (!foundSendEntry)
+ NS_FATAL_ERROR ("FindSendEntry failure");
+ ifIndex = entry2.interface;
+ return true;
+ }
+ else
+ {
+ 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
+RoutingProtocol::AddEntry (Ipv4Address const &dest,
+ Ipv4Address const &next,
+ uint32_t interface,
+ uint32_t distance)
+{
+ NS_LOG_FUNCTION (this << dest << next << interface << distance << m_mainAddress);
+
+ NS_ASSERT (distance > 0);
+
+ // 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
+RoutingProtocol::AddEntry (Ipv4Address const &dest,
+ Ipv4Address const &next,
+ Ipv4Address const &interfaceAddress,
+ uint32_t distance)
+{
+ NS_LOG_FUNCTION (this << dest << next << interfaceAddress << distance << m_mainAddress);
+
+ NS_ASSERT (distance > 0);
+ NS_ASSERT (m_ipv4);
+
+ RoutingTableEntry entry;
+ 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);
+}
+
+
+std::vector<RoutingTableEntry>
+RoutingProtocol::GetEntries () const
+{
+ std::vector<RoutingTableEntry> retval;
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator iter = m_table.begin ();
+ iter != m_table.end (); iter++)
+ {
+ retval.push_back (iter->second);
+ }
+ return retval;
+}
+
+
+}} // namespace olsr, ns3
+
+