src/routing/olsr/olsr-agent-impl.cc
author Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
Tue Dec 02 18:42:24 2008 +0000 (2008-12-02)
changeset 3970 8658841e4782
parent 3853 f04e7f61b1ed
child 4218 debf1a8a96d3
permissions -rw-r--r--
Fix a couple of OLSR bugs (#415)

- Added a lot more logging messages;

- When "link sensing" tries to update a link tuple for a neighbor that has been removed, just re-add the neighbor, rather than silently failing;

- The optimization of not recomputing the routing table if we think no state has changed has been removed: it turned out to be just too buggy and the code base makes it difficult to catch all places where a state mofication is done. Instead now we just recompute the table for any message processed, like the RFC says.
gjc@1716
     1
/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
gjc@1752
     2
/*
gjc@1752
     3
 * Copyright (c) 2004 Francisco J. Ros 
gjc@1752
     4
 * Copyright (c) 2007 INESC Porto
gjc@1752
     5
 *
gjc@1752
     6
 * This program is free software; you can redistribute it and/or modify
gjc@1752
     7
 * it under the terms of the GNU General Public License version 2 as
gjc@1752
     8
 * published by the Free Software Foundation;
gjc@1752
     9
 *
gjc@1752
    10
 * This program is distributed in the hope that it will be useful,
gjc@1752
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
gjc@1752
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
gjc@1752
    13
 * GNU General Public License for more details.
gjc@1752
    14
 *
gjc@1752
    15
 * You should have received a copy of the GNU General Public License
gjc@1752
    16
 * along with this program; if not, write to the Free Software
gjc@1752
    17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
gjc@1752
    18
 *
gjc@1752
    19
 * Authors: Francisco J. Ros  <fjrm@dif.um.es>
gjc@1752
    20
 *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
gjc@1752
    21
 */
gjc@1752
    22
gjc@1716
    23
gjc@1716
    24
///
gjc@1716
    25
/// \file	OLSR.cc
gjc@1716
    26
/// \brief	Implementation of OLSR agent and related classes.
gjc@1716
    27
///
gjc@1716
    28
/// This is the main file of this software because %OLSR's behaviour is
gjc@1716
    29
/// implemented here.
gjc@1716
    30
///
gjc@1716
    31
gjc@3970
    32
#define NS_LOG_APPEND_CONTEXT                                   \
gjc@3970
    33
  if (GetObject<Node> ()) { std::clog << "[node " << GetObject<Node> ()->GetId () << "] "; }
gjc@3970
    34
gjc@3970
    35
gjc@1731
    36
#include "olsr-agent-impl.h"
gjc@1716
    37
#include "ns3/socket-factory.h"
tomh@3125
    38
#include "ns3/udp-socket-factory.h"
gjc@1716
    39
#include "ns3/simulator.h"
mathieu@1804
    40
#include "ns3/log.h"
gjc@1716
    41
#include "ns3/random-variable.h"
gjc@1740
    42
#include "ns3/inet-socket-address.h"
mathieu@2484
    43
#include "ns3/boolean.h"
mathieu@2484
    44
#include "ns3/uinteger.h"
gjc@3233
    45
#include "ns3/enum.h"
mathieu@2484
    46
#include "ns3/trace-source-accessor.h"
gjc@1716
    47
gjc@1716
    48
/********** Useful macros **********/
gjc@1716
    49
gjc@1716
    50
///
gjc@1716
    51
/// \brief Gets the delay between a given time and the current time.
gjc@1716
    52
///
gjc@1716
    53
/// If given time is previous to the current one, then this macro returns
gjc@1716
    54
/// a number close to 0. This is used for scheduling events at a certain moment.
gjc@1716
    55
///
gjc@1716
    56
#define DELAY(time) (((time) < (Simulator::Now ())) ? Seconds (0.000001) : \
gjc@1716
    57
                     (time - Simulator::Now () + Seconds (0.000001)))
gjc@1716
    58
gjc@1716
    59
gjc@1716
    60
gjc@1716
    61
///
gjc@1716
    62
/// \brief Period at which a node must cite every link and every neighbor.
gjc@1716
    63
///
gjc@1716
    64
/// We only use this value in order to define OLSR_NEIGHB_HOLD_TIME.
gjc@1716
    65
///
gjc@1716
    66
#define OLSR_REFRESH_INTERVAL	Seconds (2)
gjc@1716
    67
gjc@1716
    68
gjc@1716
    69
/********** Holding times **********/
gjc@1716
    70
gjc@1716
    71
/// Neighbor holding time.
gjc@1716
    72
#define OLSR_NEIGHB_HOLD_TIME	(Scalar (3) * OLSR_REFRESH_INTERVAL)
gjc@1716
    73
/// Top holding time.
gjc@3233
    74
#define OLSR_TOP_HOLD_TIME	(Scalar (3) * m_tcInterval)
gjc@1716
    75
/// Dup holding time.
gjc@1716
    76
#define OLSR_DUP_HOLD_TIME	Seconds (30)
gjc@1716
    77
/// MID holding time.
gjc@3233
    78
#define OLSR_MID_HOLD_TIME	(Scalar (3) * m_midInterval)
gjc@1716
    79
gjc@1716
    80
gjc@1716
    81
/********** Link types **********/
gjc@1716
    82
gjc@1716
    83
/// Unspecified link type.
gjc@1716
    84
#define OLSR_UNSPEC_LINK	0
gjc@1716
    85
/// Asymmetric link type.
gjc@1716
    86
#define OLSR_ASYM_LINK		1
gjc@1716
    87
/// Symmetric link type.
gjc@1716
    88
#define OLSR_SYM_LINK		2
gjc@1716
    89
/// Lost link type.
gjc@1716
    90
#define OLSR_LOST_LINK		3
gjc@1716
    91
gjc@1716
    92
/********** Neighbor types **********/
gjc@1716
    93
gjc@1716
    94
/// Not neighbor type.
gjc@1716
    95
#define OLSR_NOT_NEIGH		0
gjc@1716
    96
/// Symmetric neighbor type.
gjc@1716
    97
#define OLSR_SYM_NEIGH		1
gjc@1716
    98
/// Asymmetric neighbor type.
gjc@1716
    99
#define OLSR_MPR_NEIGH		2
gjc@1716
   100
gjc@1716
   101
gjc@1716
   102
/********** Willingness **********/
gjc@1716
   103
gjc@1716
   104
/// Willingness for forwarding packets from other nodes: never.
gjc@1716
   105
#define OLSR_WILL_NEVER		0
gjc@1716
   106
/// Willingness for forwarding packets from other nodes: low.
gjc@1716
   107
#define OLSR_WILL_LOW		1
gjc@1716
   108
/// Willingness for forwarding packets from other nodes: medium.
gjc@1716
   109
#define OLSR_WILL_DEFAULT	3
gjc@1716
   110
/// Willingness for forwarding packets from other nodes: high.
gjc@1716
   111
#define OLSR_WILL_HIGH		6
gjc@1716
   112
/// Willingness for forwarding packets from other nodes: always.
gjc@1716
   113
#define OLSR_WILL_ALWAYS	7
gjc@1716
   114
gjc@1716
   115
gjc@1716
   116
/********** Miscellaneous constants **********/
gjc@1716
   117
gjc@1716
   118
/// Maximum allowed jitter.
gjc@3233
   119
#define OLSR_MAXJITTER		(m_helloInterval.GetSeconds () / 4)
gjc@1716
   120
/// Maximum allowed sequence number.
gjc@1716
   121
#define OLSR_MAX_SEQ_NUM	65535
gjc@1716
   122
/// Random number between [0-OLSR_MAXJITTER] used to jitter OLSR packet transmission.
gjc@1716
   123
#define JITTER (Seconds (UniformVariable::GetSingleValue (0, OLSR_MAXJITTER)))
gjc@1716
   124
gjc@1716
   125
gjc@1716
   126
#define OLSR_PORT_NUMBER 698
gjc@1716
   127
/// Maximum number of messages per packet.
gjc@1716
   128
#define OLSR_MAX_MSGS		64
gjc@1716
   129
gjc@1716
   130
/// Maximum number of hellos per message (4 possible link types * 3 possible nb types).
gjc@1716
   131
#define OLSR_MAX_HELLOS		12
gjc@1716
   132
gjc@1716
   133
/// Maximum number of addresses advertised on a message.
gjc@1716
   134
#define OLSR_MAX_ADDRS		64
gjc@1716
   135
gjc@1716
   136
gjc@1716
   137
namespace ns3 {
gjc@1801
   138
namespace olsr {
gjc@1716
   139
mathieu@1804
   140
NS_LOG_COMPONENT_DEFINE ("OlsrAgent");
gjc@1716
   141
gjc@1716
   142
gjc@1716
   143
/********** OLSR class **********/
gjc@1716
   144
mathieu@2249
   145
NS_OBJECT_ENSURE_REGISTERED (AgentImpl);
mathieu@2249
   146
mathieu@2250
   147
TypeId 
mathieu@2251
   148
AgentImpl::GetTypeId (void)
mathieu@2249
   149
{
mathieu@2602
   150
  static TypeId tid = TypeId ("ns3::olsr::AgentImpl")
mathieu@2249
   151
    .SetParent<Agent> ()
mathieu@2484
   152
    .AddConstructor<AgentImpl> ()
gjc@3233
   153
    .AddAttribute ("HelloInterval", "HELLO messages emission interval.",
gjc@3233
   154
                   TimeValue (Seconds (2)),
mathieu@2484
   155
                   MakeTimeAccessor (&AgentImpl::m_helloInterval),
mathieu@2484
   156
                   MakeTimeChecker ())
gjc@3233
   157
    .AddAttribute ("TcInterval", "TC messages emission interval.",
gjc@3233
   158
                   TimeValue (Seconds (5)),
mathieu@2484
   159
                   MakeTimeAccessor (&AgentImpl::m_tcInterval),
mathieu@2484
   160
                   MakeTimeChecker ())
gjc@3233
   161
    .AddAttribute ("MidInterval", "MID messages emission interval.  Normally it is equal to TcInterval.",
gjc@3233
   162
                   TimeValue (Seconds (5)),
mathieu@2484
   163
                   MakeTimeAccessor (&AgentImpl::m_midInterval),
mathieu@2484
   164
                   MakeTimeChecker ())
gjc@3233
   165
    .AddAttribute ("Willingness", "Willingness of a node to carry and forward traffic for other nodes.",
gjc@3233
   166
                   EnumValue (OLSR_WILL_DEFAULT),
gjc@3233
   167
                   MakeEnumAccessor (&AgentImpl::m_willingness),
gjc@3233
   168
                   MakeEnumChecker (OLSR_WILL_NEVER, "never",
gjc@3233
   169
                                    OLSR_WILL_LOW, "low",
gjc@3233
   170
                                    OLSR_WILL_DEFAULT, "default",
gjc@3233
   171
                                    OLSR_WILL_HIGH, "high",
gjc@3233
   172
                                    OLSR_WILL_ALWAYS, "always"))
mathieu@2484
   173
    .AddTraceSource ("Rx", "Receive OLSR packet.",
mathieu@2484
   174
                     MakeTraceSourceAccessor (&AgentImpl::m_rxPacketTrace))
mathieu@2484
   175
    .AddTraceSource ("Tx", "Send OLSR packet.",
mathieu@2484
   176
                     MakeTraceSourceAccessor (&AgentImpl::m_txPacketTrace))
mathieu@2503
   177
    .AddTraceSource ("RoutingTableChanged", "The OLSR routing table has changed.",
mathieu@2503
   178
		     MakeTraceSourceAccessor (&AgentImpl::m_routingTableChanged))
mathieu@2484
   179
    ;
mathieu@2252
   180
  return tid;
mathieu@2249
   181
}
mathieu@2249
   182
gjc@1716
   183
mathieu@2484
   184
AgentImpl::AgentImpl ()
gjc@1716
   185
  :
gjc@1768
   186
  m_helloTimer (Timer::CANCEL_ON_DESTROY),
gjc@1768
   187
  m_tcTimer (Timer::CANCEL_ON_DESTROY),
gjc@1768
   188
  m_midTimer (Timer::CANCEL_ON_DESTROY)
mathieu@2484
   189
{}
mathieu@2484
   190
mathieu@2900
   191
AgentImpl::~AgentImpl ()
mathieu@2900
   192
{}
mathieu@2900
   193
mathieu@2484
   194
void
mathieu@2484
   195
AgentImpl::SetNode (Ptr<Node> node)
gjc@1716
   196
{
gjc@2296
   197
  NS_LOG_DEBUG ("Created olsr::AgentImpl");
gjc@1801
   198
  m_helloTimer.SetFunction (&AgentImpl::HelloTimerExpire, this);
gjc@1801
   199
  m_tcTimer.SetFunction (&AgentImpl::TcTimerExpire, this);
gjc@1801
   200
  m_midTimer.SetFunction (&AgentImpl::MidTimerExpire, this);
gjc@1801
   201
  m_queuedMessagesTimer.SetFunction (&AgentImpl::SendQueuedMessages, this);
gjc@1765
   202
gjc@1716
   203
  m_packetSequenceNumber = OLSR_MAX_SEQ_NUM;
gjc@1716
   204
  m_messageSequenceNumber = OLSR_MAX_SEQ_NUM;
gjc@1716
   205
  m_ansn = OLSR_MAX_SEQ_NUM;
gjc@1716
   206
gjc@1716
   207
  m_linkTupleTimerFirstTime = true;
gjc@1716
   208
mathieu@2257
   209
  m_ipv4 = node->GetObject<Ipv4> ();
gjc@1716
   210
  NS_ASSERT (m_ipv4);
gjc@1716
   211
}
gjc@1716
   212
gjc@1801
   213
void AgentImpl::DoDispose ()
gjc@1716
   214
{
gjc@1716
   215
  m_ipv4 = 0;
gjc@2328
   216
gjc@2328
   217
  for (std::map< Ptr<Socket>, Ipv4Address >::iterator iter = m_socketAddresses.begin ();
gjc@2328
   218
       iter != m_socketAddresses.end (); iter++)
gjc@1779
   219
    {
gjc@2328
   220
      iter->first->Dispose ();
gjc@1779
   221
    }
gjc@2328
   222
  m_socketAddresses.clear ();
gjc@2328
   223
gjc@1779
   224
  if (m_routingTable)
gjc@1779
   225
    {
gjc@1779
   226
      m_routingTable->Dispose ();
gjc@1779
   227
      m_routingTable = 0;
gjc@1779
   228
    }
gjc@1716
   229
gjc@1716
   230
  Object::DoDispose ();
gjc@1716
   231
}
gjc@1716
   232
gjc@1801
   233
void AgentImpl::Start ()
gjc@1716
   234
{
gjc@1716
   235
  if (m_mainAddress == Ipv4Address ())
gjc@1716
   236
    {
gjc@1716
   237
      Ipv4Address loopback ("127.0.0.1");
gjc@1716
   238
      for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
gjc@1716
   239
        {
gjc@1716
   240
          Ipv4Address addr = m_ipv4->GetAddress (i);
gjc@1716
   241
          if (addr != loopback)
gjc@1716
   242
            {
gjc@1716
   243
              m_mainAddress = addr;
gjc@1716
   244
              break;
gjc@1716
   245
            }
gjc@1716
   246
        }
gjc@1716
   247
gjc@1716
   248
      NS_ASSERT (m_mainAddress != Ipv4Address ());
gjc@1716
   249
    }
gjc@1716
   250
mathieu@1804
   251
  NS_LOG_DEBUG ("Starting OLSR on node " << m_mainAddress);
gjc@1716
   252
mathieu@2592
   253
  m_routingTable = CreateObject<RoutingTable> ();
mathieu@2592
   254
  m_routingTable->SetIpv4 (m_ipv4);
mathieu@2592
   255
  m_routingTable->SetMainAddress (m_mainAddress);
gjc@2334
   256
  // Add OLSR as routing protocol, with slightly higher priority than
gjc@1716
   257
  // static routing.
gjc@2334
   258
  m_ipv4->AddRoutingProtocol (m_routingTable, 10);
tomh@3116
   259
  
gjc@2328
   260
  Ipv4Address loopback ("127.0.0.1");
gjc@2328
   261
  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
gjc@2328
   262
    {
gjc@2328
   263
      Ipv4Address addr = m_ipv4->GetAddress (i);
gjc@2328
   264
      if (addr == loopback)
gjc@2328
   265
        continue;
gjc@2328
   266
gjc@2328
   267
      if (addr != m_mainAddress)
gjc@2328
   268
        {
gjc@2328
   269
          // Create never expiring interface association tuple entries for our
gjc@2328
   270
          // own network interfaces, so that GetMainAddress () works to
gjc@2328
   271
          // translate the node's own interface addresses into the main address.
gjc@2328
   272
          IfaceAssocTuple tuple;
gjc@2328
   273
          tuple.ifaceAddr = addr;
gjc@2328
   274
          tuple.mainAddr = m_mainAddress;
gjc@2328
   275
          AddIfaceAssocTuple (tuple);
gjc@2328
   276
          NS_ASSERT (GetMainAddress (addr) == m_mainAddress);
gjc@2328
   277
        }
gjc@2328
   278
gjc@2328
   279
      // Create a socket to listen only on this interface
tomh@3116
   280
      Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (), 
tomh@3125
   281
        UdpSocketFactory::GetTypeId()); 
tomh@3102
   282
      socket->SetRecvCallback (MakeCallback (&AgentImpl::RecvOlsr,  this));
gjc@2328
   283
      if (socket->Bind (InetSocketAddress (addr, OLSR_PORT_NUMBER)))
gjc@2328
   284
        {
gjc@2328
   285
          NS_FATAL_ERROR ("Failed to bind() OLSR receive socket");
gjc@2328
   286
        }
gjc@2328
   287
      socket->Connect (InetSocketAddress (Ipv4Address (0xffffffff), OLSR_PORT_NUMBER));
gjc@2328
   288
      m_socketAddresses[socket] = addr;
gjc@2328
   289
    }
gjc@1723
   290
gjc@1723
   291
  HelloTimerExpire ();
gjc@1723
   292
  TcTimerExpire ();
gjc@1723
   293
  MidTimerExpire ();
gjc@1716
   294
mathieu@1804
   295
  NS_LOG_DEBUG ("OLSR on node " << m_mainAddress << " started");
gjc@1716
   296
}
gjc@1716
   297
gjc@1801
   298
void AgentImpl::SetMainInterface (uint32_t interface)
gjc@1716
   299
{
gjc@1716
   300
  m_mainAddress = m_ipv4->GetAddress (interface);
gjc@1716
   301
}
gjc@1716
   302
gjc@1716
   303
gjc@1716
   304
//
gjc@1716
   305
// \brief Processes an incoming %OLSR packet following RFC 3626 specification.
gjc@1716
   306
void
tomh@3098
   307
AgentImpl::RecvOlsr (Ptr<Socket> socket)
gjc@1716
   308
{
tomh@3098
   309
  Ptr<Packet> receivedPacket;
tomh@3270
   310
  Address sourceAddress;
tomh@3270
   311
  receivedPacket = socket->RecvFrom (sourceAddress);
tomh@3098
   312
gjc@1740
   313
  InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
gjc@2328
   314
  Ipv4Address senderIfaceAddr = inetSourceAddr.GetIpv4 ();
gjc@2328
   315
  Ipv4Address receiverIfaceAddr = m_socketAddresses[socket];
gjc@2328
   316
  NS_ASSERT (receiverIfaceAddr != Ipv4Address ());
gjc@2328
   317
  NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " received a OLSR packet from "
gjc@2328
   318
                << senderIfaceAddr << " to " << receiverIfaceAddr);
gjc@1740
   319
  
gjc@1716
   320
  // All routing messages are sent from and to port RT_PORT,
gjc@1716
   321
  // so we check it.
gjc@1740
   322
  NS_ASSERT (inetSourceAddr.GetPort () == OLSR_PORT_NUMBER);
gjc@1716
   323
  
craigdo@1868
   324
  Ptr<Packet> packet = receivedPacket;
gjc@1716
   325
gjc@1801
   326
  olsr::PacketHeader olsrPacketHeader;
craigdo@1868
   327
  packet->RemoveHeader (olsrPacketHeader);
gjc@1740
   328
  NS_ASSERT (olsrPacketHeader.GetPacketLength () >= olsrPacketHeader.GetSerializedSize ());
gjc@1740
   329
  uint32_t sizeLeft = olsrPacketHeader.GetPacketLength () - olsrPacketHeader.GetSerializedSize ();
gjc@1803
   330
gjc@1803
   331
  MessageList messages;
gjc@1716
   332
  
gjc@1716
   333
  while (sizeLeft)
gjc@1716
   334
    {
gjc@1803
   335
      MessageHeader messageHeader;
craigdo@1868
   336
      if (packet->RemoveHeader (messageHeader) == 0)
gjc@1716
   337
        NS_ASSERT (false);
gjc@1716
   338
      
gjc@1755
   339
      sizeLeft -= messageHeader.GetSerializedSize ();
gjc@1716
   340
mathieu@1804
   341
      NS_LOG_DEBUG ("Olsr Msg received with type "
gjc@1716
   342
                << std::dec << int (messageHeader.GetMessageType ())
gjc@1716
   343
                << " TTL=" << int (messageHeader.GetTimeToLive ())
gjc@1716
   344
                << " origAddr=" << messageHeader.GetOriginatorAddress ());
gjc@1803
   345
      messages.push_back (messageHeader);
gjc@1803
   346
    }
gjc@1716
   347
gjc@1803
   348
  m_rxPacketTrace (olsrPacketHeader, messages);
gjc@1803
   349
gjc@1803
   350
  for (MessageList::const_iterator messageIter = messages.begin ();
gjc@1803
   351
       messageIter != messages.end (); messageIter++)
gjc@1803
   352
    {
gjc@1803
   353
      const MessageHeader &messageHeader = *messageIter;
gjc@1716
   354
      // If ttl is less than or equal to zero, or
gjc@1716
   355
      // the receiver is the same as the originator,
gjc@1716
   356
      // the message must be silently dropped
gjc@1716
   357
      if (messageHeader.GetTimeToLive () == 0
gjc@1716
   358
          || messageHeader.GetOriginatorAddress () == m_mainAddress)
gjc@1716
   359
        {
craigdo@1868
   360
          packet->RemoveAtStart (messageHeader.GetSerializedSize ()
craigdo@1868
   361
                                 - messageHeader.GetSerializedSize ());
gjc@1716
   362
          continue;
gjc@1716
   363
        }
gjc@1716
   364
gjc@1716
   365
      // If the message has been processed it must not be processed again
gjc@1716
   366
      bool do_forwarding = true;
gjc@1716
   367
      DuplicateTuple *duplicated = m_state.FindDuplicateTuple
gjc@1716
   368
        (messageHeader.GetOriginatorAddress (),
gjc@1716
   369
         messageHeader.GetMessageSequenceNumber ());
gjc@2306
   370
gjc@2306
   371
      // Get main address of the peer, which may be different from the packet source address
gjc@2328
   372
//       const IfaceAssocTuple *ifaceAssoc = m_state.FindIfaceAssocTuple (inetSourceAddr.GetIpv4 ());
gjc@2328
   373
//       Ipv4Address peerMainAddress;
gjc@2328
   374
//       if (ifaceAssoc != NULL)
gjc@2328
   375
//         {
gjc@2328
   376
//           peerMainAddress = ifaceAssoc->mainAddr;
gjc@2328
   377
//         }
gjc@2328
   378
//       else
gjc@2328
   379
//         {
gjc@2328
   380
//           peerMainAddress = inetSourceAddr.GetIpv4 () ;
gjc@2328
   381
//         }
gjc@1716
   382
      
gjc@1716
   383
      if (duplicated == NULL)
gjc@1716
   384
        {
gjc@1716
   385
          switch (messageHeader.GetMessageType ())
gjc@1716
   386
            {
gjc@1801
   387
            case olsr::MessageHeader::HELLO_MESSAGE:
gjc@2328
   388
              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
   389
                            << "s OLSR node " << m_mainAddress
gjc@2328
   390
                            << " received HELLO message of size " << messageHeader.GetSerializedSize ());
gjc@2328
   391
              ProcessHello (messageHeader, receiverIfaceAddr, senderIfaceAddr);
gjc@1716
   392
              break;
gjc@1716
   393
gjc@1801
   394
            case olsr::MessageHeader::TC_MESSAGE:
gjc@2328
   395
              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
   396
                            << "s OLSR node " << m_mainAddress
gjc@2328
   397
                            << " received TC message of size " << messageHeader.GetSerializedSize ());
gjc@2328
   398
              ProcessTc (messageHeader, senderIfaceAddr);
gjc@1716
   399
              break;
gjc@1716
   400
gjc@1801
   401
            case olsr::MessageHeader::MID_MESSAGE:
gjc@2328
   402
              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
   403
                            << "s OLSR node " << m_mainAddress
gjc@2328
   404
                            <<  " received MID message of size " << messageHeader.GetSerializedSize ());
gjc@2328
   405
              ProcessMid (messageHeader, senderIfaceAddr);
gjc@1716
   406
              break;
gjc@1716
   407
gjc@1716
   408
            default:
mathieu@1804
   409
              NS_LOG_DEBUG ("OLSR message type " <<
gjc@1716
   410
                        int (messageHeader.GetMessageType ()) <<
gjc@1716
   411
                        " not implemented");
gjc@1716
   412
            }
gjc@1716
   413
        }
gjc@1716
   414
      else
gjc@1716
   415
        {
mathieu@1804
   416
          NS_LOG_DEBUG ("OLSR message is duplicated, not reading it.");
gjc@1716
   417
      
gjc@1716
   418
          // If the message has been considered for forwarding, it should
gjc@1716
   419
          // not be retransmitted again
gjc@1716
   420
          for (std::vector<Ipv4Address>::const_iterator it = duplicated->ifaceList.begin ();
gjc@1716
   421
               it != duplicated->ifaceList.end(); it++)
gjc@1716
   422
            {
gjc@2328
   423
              if (*it == receiverIfaceAddr)
gjc@1716
   424
                {
gjc@1716
   425
                  do_forwarding = false;
gjc@1716
   426
                  break;
gjc@1716
   427
                }
gjc@1716
   428
            }
gjc@1716
   429
        }
gjc@1716
   430
      
gjc@1716
   431
      if (do_forwarding)
gjc@1716
   432
        {
gjc@1716
   433
          // HELLO messages are never forwarded.
gjc@1716
   434
          // TC and MID messages are forwarded using the default algorithm.
gjc@1716
   435
          // Remaining messages are also forwarded using the default algorithm.
gjc@1801
   436
          if (messageHeader.GetMessageType ()  != olsr::MessageHeader::HELLO_MESSAGE)
gjc@2328
   437
            {
gjc@2328
   438
              ForwardDefault (messageHeader, duplicated,
gjc@2328
   439
                              receiverIfaceAddr, inetSourceAddr.GetIpv4 ());
gjc@2328
   440
            }
gjc@1716
   441
        }
gjc@1716
   442
	
gjc@1716
   443
    }
gjc@1716
   444
gjc@1716
   445
  // After processing all OLSR messages, we must recompute the routing table
gjc@3970
   446
  RoutingTableComputation ();
gjc@1716
   447
}
gjc@1716
   448
gjc@1716
   449
///
gjc@1716
   450
/// \brief This auxiliary function (defined in RFC 3626) is used for calculating the MPR Set.
gjc@1716
   451
///
gjc@1716
   452
/// \param tuple the neighbor tuple which has the main address of the node we are going to calculate its degree to.
gjc@1716
   453
/// \return the degree of the node.
gjc@1716
   454
///
gjc@1716
   455
int
gjc@1801
   456
AgentImpl::Degree (NeighborTuple const &tuple)
gjc@1716
   457
{
gjc@1716
   458
  int degree = 0;
gjc@1716
   459
  for (TwoHopNeighborSet::const_iterator it = m_state.GetTwoHopNeighbors ().begin ();
gjc@1716
   460
       it != m_state.GetTwoHopNeighbors ().end (); it++)
gjc@1716
   461
    {
gjc@1716
   462
      TwoHopNeighborTuple const &nb2hop_tuple = *it;
gjc@1716
   463
      if (nb2hop_tuple.neighborMainAddr == tuple.neighborMainAddr)
gjc@1716
   464
        {
gjc@3970
   465
          const NeighborTuple *nb_tuple =
gjc@1716
   466
            m_state.FindNeighborTuple (nb2hop_tuple.neighborMainAddr);
gjc@1716
   467
          if (nb_tuple == NULL)
gjc@1716
   468
            degree++;
gjc@1716
   469
        }
gjc@1716
   470
    }
gjc@1716
   471
  return degree;
gjc@1716
   472
}
gjc@1716
   473
gjc@1716
   474
///
gjc@1716
   475
/// \brief Computates MPR set of a node following RFC 3626 hints.
gjc@1716
   476
///
gjc@1716
   477
void
gjc@1801
   478
AgentImpl::MprComputation()
gjc@1716
   479
{
gjc@3970
   480
  NS_LOG_FUNCTION (this);
gjc@3970
   481
  
gjc@1716
   482
  // MPR computation should be done for each interface. See section 8.3.1
gjc@1716
   483
  // (RFC 3626) for details.
gjc@2361
   484
  MprSet mprSet;
gjc@1716
   485
	
gjc@1716
   486
  
gjc@1716
   487
  // N is the subset of neighbors of the node, which are
gjc@1716
   488
  // neighbor "of the interface I"
gjc@1716
   489
  NeighborSet N;
gjc@2361
   490
  for (NeighborSet::const_iterator neighbor = m_state.GetNeighbors ().begin();
gjc@2361
   491
       neighbor != m_state.GetNeighbors ().end (); neighbor++)
gjc@1716
   492
    {
gjc@2361
   493
      if (neighbor->status == NeighborTuple::STATUS_SYM) // I think that we need this check
gjc@2361
   494
        {
gjc@2361
   495
          N.push_back (*neighbor);
gjc@2361
   496
        }
gjc@1716
   497
    }
gjc@1716
   498
	
gjc@1716
   499
  // N2 is the set of 2-hop neighbors reachable from "the interface
gjc@1716
   500
  // I", excluding:
gjc@1716
   501
  // (i)   the nodes only reachable by members of N with willingness WILL_NEVER
gjc@1716
   502
  // (ii)  the node performing the computation
gjc@1716
   503
  // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
gjc@1716
   504
  //       link to this node on some interface.
gjc@1716
   505
  TwoHopNeighborSet N2;
gjc@2361
   506
  for (TwoHopNeighborSet::const_iterator twoHopNeigh = m_state.GetTwoHopNeighbors ().begin ();
gjc@2361
   507
       twoHopNeigh != m_state.GetTwoHopNeighbors ().end (); twoHopNeigh++)
gjc@1716
   508
    {
gjc@2361
   509
      // excluding:
gjc@2361
   510
      // (ii)  the node performing the computation
gjc@2361
   511
      if (twoHopNeigh->twoHopNeighborAddr == m_mainAddress)
gjc@1716
   512
        {
gjc@2361
   513
          continue;
gjc@1716
   514
        }
gjc@2361
   515
gjc@2361
   516
      //  excluding:
gjc@2361
   517
      // (i)   the nodes only reachable by members of N with willingness WILL_NEVER      
gjc@2361
   518
      bool ok = false;
gjc@2361
   519
      for (NeighborSet::const_iterator neigh = N.begin ();
gjc@2361
   520
           neigh != N.end (); neigh++)
gjc@1716
   521
        {
gjc@2361
   522
          if (neigh->neighborMainAddr == twoHopNeigh->neighborMainAddr)
gjc@2361
   523
            {
gjc@2361
   524
              if (neigh->willingness == OLSR_WILL_NEVER)
gjc@2361
   525
                {
gjc@2361
   526
                  ok = false;
gjc@2361
   527
                  break;
gjc@2361
   528
                }
gjc@2361
   529
              else
gjc@2361
   530
                {
gjc@2361
   531
                  ok = true;
gjc@2361
   532
                  break;
gjc@2361
   533
                }
gjc@2361
   534
            }
gjc@2361
   535
        }
gjc@2361
   536
      if (!ok)
gjc@2361
   537
        {
gjc@2361
   538
          continue;
gjc@2361
   539
        }
gjc@2361
   540
      
gjc@2361
   541
      // excluding:
gjc@2361
   542
      // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
gjc@2361
   543
      //       link to this node on some interface.
gjc@2361
   544
      for (NeighborSet::const_iterator neigh = N.begin ();
gjc@2361
   545
           neigh != N.end (); neigh++)
gjc@2361
   546
        {
gjc@2361
   547
          if (neigh->neighborMainAddr == twoHopNeigh->twoHopNeighborAddr)
gjc@1716
   548
            {
gjc@1716
   549
              ok = false;
gjc@2361
   550
              break;
gjc@1716
   551
            }
gjc@1716
   552
        }
gjc@1716
   553
gjc@1716
   554
      if (ok)
gjc@2361
   555
        {
gjc@2361
   556
          N2.push_back (*twoHopNeigh);
gjc@2361
   557
        }
gjc@1716
   558
    }
gjc@2361
   559
gjc@3970
   560
  NS_LOG_DEBUG ("Size of N2: " << N2.size ());  
gjc@3970
   561
gjc@1716
   562
  // 1. Start with an MPR set made of all members of N with
gjc@1716
   563
  // N_willingness equal to WILL_ALWAYS
gjc@2361
   564
  for (NeighborSet::const_iterator neighbor = N.begin (); neighbor != N.end (); neighbor++)
gjc@1716
   565
    {
gjc@2361
   566
      if (neighbor->willingness == OLSR_WILL_ALWAYS)
gjc@2361
   567
        {
gjc@2361
   568
          mprSet.insert (neighbor->neighborMainAddr);
gjc@2361
   569
          // (not in RFC but I think is needed: remove the 2-hop
gjc@2361
   570
          // neighbors reachable by the MPR from N2)
gjc@2361
   571
          for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
gjc@2916
   572
               twoHopNeigh != N2.end (); )
gjc@2361
   573
            {
gjc@2361
   574
              if (twoHopNeigh->neighborMainAddr == neighbor->neighborMainAddr)
gjc@2361
   575
                {
gjc@2361
   576
                  twoHopNeigh = N2.erase (twoHopNeigh);
gjc@2916
   577
                }
gjc@2916
   578
              else
gjc@2916
   579
                {
gjc@2916
   580
                  twoHopNeigh++;
gjc@2361
   581
                }
gjc@2361
   582
            }
gjc@2361
   583
        }
gjc@1716
   584
    }
gjc@1716
   585
  
gjc@1716
   586
  // 2. Calculate D(y), where y is a member of N, for all nodes in N.
gjc@2361
   587
  // (we do this later)
gjc@1716
   588
	
gjc@1716
   589
  // 3. Add to the MPR set those nodes in N, which are the *only*
gjc@2361
   590
  // nodes to provide reachability to a node in N2.
gjc@2361
   591
  std::set<Ipv4Address> coveredTwoHopNeighbors;
gjc@2361
   592
  for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin (); twoHopNeigh != N2.end (); twoHopNeigh++)
gjc@1716
   593
    {
gjc@2361
   594
      NeighborSet::const_iterator onlyNeighbor = N.end ();
gjc@2361
   595
      
gjc@2361
   596
      for (NeighborSet::const_iterator neighbor = N.begin ();
gjc@2361
   597
           neighbor != N.end (); neighbor++)
gjc@1716
   598
        {
gjc@2361
   599
          if (neighbor->neighborMainAddr == twoHopNeigh->neighborMainAddr)
gjc@1716
   600
            {
gjc@2361
   601
              if (onlyNeighbor == N.end ())
gjc@1716
   602
                {
gjc@2361
   603
                  onlyNeighbor = neighbor;
gjc@1716
   604
                }
gjc@2361
   605
              else
gjc@1716
   606
                {
gjc@2361
   607
                  onlyNeighbor = N.end ();
gjc@2361
   608
                  break;
gjc@1716
   609
                }
gjc@1716
   610
            }
gjc@1716
   611
        }
gjc@2361
   612
      if (onlyNeighbor != N.end ())
gjc@2361
   613
        {
gjc@2361
   614
          mprSet.insert (onlyNeighbor->neighborMainAddr);
gjc@2361
   615
          coveredTwoHopNeighbors.insert (twoHopNeigh->twoHopNeighborAddr);
gjc@2361
   616
        }
gjc@2361
   617
    }
gjc@2361
   618
  // Remove the nodes from N2 which are now covered by a node in the MPR set.
gjc@2361
   619
  for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
gjc@2916
   620
       twoHopNeigh != N2.end (); )
gjc@2361
   621
    {
gjc@2361
   622
      if (coveredTwoHopNeighbors.find (twoHopNeigh->twoHopNeighborAddr) != coveredTwoHopNeighbors.end ())
gjc@2361
   623
        {
gjc@2361
   624
          twoHopNeigh = N2.erase (twoHopNeigh);
gjc@2916
   625
        }
gjc@2916
   626
      else
gjc@2916
   627
        {
gjc@2916
   628
          twoHopNeigh++;
gjc@2361
   629
        }
gjc@1716
   630
    }
gjc@1716
   631
	
gjc@1716
   632
  // 4. While there exist nodes in N2 which are not covered by at
gjc@1716
   633
  // least one node in the MPR set:
gjc@1716
   634
  while (N2.begin () != N2.end ())
gjc@1716
   635
    {
gjc@1716
   636
      // 4.1. For each node in N, calculate the reachability, i.e., the
gjc@1716
   637
      // number of nodes in N2 which are not yet covered by at
gjc@1716
   638
      // least one node in the MPR set, and which are reachable
gjc@1716
   639
      // through this 1-hop neighbor
gjc@1716
   640
      std::map<int, std::vector<const NeighborTuple *> > reachability;
gjc@1716
   641
      std::set<int> rs;
gjc@1716
   642
      for (NeighborSet::iterator it = N.begin(); it != N.end(); it++)
gjc@1716
   643
        {
gjc@1716
   644
          NeighborTuple const &nb_tuple = *it;
gjc@1716
   645
          int r = 0;
gjc@1716
   646
          for (TwoHopNeighborSet::iterator it2 = N2.begin (); it2 != N2.end (); it2++)
gjc@1716
   647
            {
gjc@1716
   648
              TwoHopNeighborTuple const &nb2hop_tuple = *it2;
gjc@1716
   649
              if (nb_tuple.neighborMainAddr == nb2hop_tuple.neighborMainAddr)
gjc@1716
   650
                r++;
gjc@1716
   651
            }
gjc@1716
   652
          rs.insert (r);
gjc@1716
   653
          reachability[r].push_back (&nb_tuple);
gjc@1716
   654
        }
gjc@1716
   655
      
gjc@1716
   656
      // 4.2. Select as a MPR the node with highest N_willingness among
gjc@1716
   657
      // the nodes in N with non-zero reachability. In case of
gjc@1716
   658
      // multiple choice select the node which provides
gjc@1716
   659
      // reachability to the maximum number of nodes in N2. In
gjc@1716
   660
      // case of multiple nodes providing the same amount of
gjc@1716
   661
      // reachability, select the node as MPR whose D(y) is
gjc@1716
   662
      // greater. Remove the nodes from N2 which are now covered
gjc@1716
   663
      // by a node in the MPR set.
gjc@1716
   664
      NeighborTuple const *max = NULL;
gjc@1716
   665
      int max_r = 0;
gjc@1716
   666
      for (std::set<int>::iterator it = rs.begin (); it != rs.end (); it++)
gjc@1716
   667
        {
gjc@1716
   668
          int r = *it;
gjc@2361
   669
          if (r == 0)
gjc@1716
   670
            {
gjc@2361
   671
              continue;
gjc@2361
   672
            }
gjc@2361
   673
          for (std::vector<const NeighborTuple *>::iterator it2 = reachability[r].begin ();
gjc@2361
   674
               it2 != reachability[r].end (); it2++)
gjc@2361
   675
            {
gjc@2361
   676
              const NeighborTuple *nb_tuple = *it2;
gjc@2361
   677
              if (max == NULL || nb_tuple->willingness > max->willingness)
gjc@1716
   678
                {
gjc@2361
   679
                  max = nb_tuple;
gjc@2361
   680
                  max_r = r;
gjc@2361
   681
                }
gjc@2361
   682
              else if (nb_tuple->willingness == max->willingness)
gjc@2361
   683
                {
gjc@2361
   684
                  if (r > max_r)
gjc@1716
   685
                    {
gjc@1716
   686
                      max = nb_tuple;
gjc@1716
   687
                      max_r = r;
gjc@1716
   688
                    }
gjc@2361
   689
                  else if (r == max_r)
gjc@1716
   690
                    {
gjc@2361
   691
                      if (Degree (*nb_tuple) > Degree (*max))
gjc@1716
   692
                        {
gjc@1716
   693
                          max = nb_tuple;
gjc@1716
   694
                          max_r = r;
gjc@1716
   695
                        }
gjc@1716
   696
                    }
gjc@1716
   697
                }
gjc@1716
   698
            }
gjc@1716
   699
        }
gjc@1716
   700
gjc@1716
   701
      if (max != NULL)
gjc@1716
   702
        {
gjc@2361
   703
          mprSet.insert (max->neighborMainAddr);
gjc@2361
   704
          for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
gjc@2916
   705
               twoHopNeigh != N2.end (); )
gjc@1716
   706
            {
gjc@2361
   707
              if (twoHopNeigh->neighborMainAddr == max->neighborMainAddr)
gjc@1716
   708
                {
gjc@2361
   709
                  twoHopNeigh = N2.erase (twoHopNeigh);
gjc@2916
   710
                }
gjc@2916
   711
              else
gjc@2916
   712
                {
gjc@2916
   713
                  twoHopNeigh++;
gjc@1716
   714
                }
gjc@1716
   715
            }
gjc@1716
   716
        }
gjc@1716
   717
    }
gjc@2361
   718
gjc@3970
   719
#ifdef NS3_LOG_ENABLE
gjc@3970
   720
  {
gjc@3970
   721
    std::ostringstream os;
gjc@3970
   722
    os << "[";
gjc@3970
   723
    for (MprSet::const_iterator iter = mprSet.begin ();
gjc@3970
   724
         iter != mprSet.end (); iter++)
gjc@3970
   725
      {
gjc@3970
   726
        MprSet::const_iterator next = iter;
gjc@3970
   727
        next++;
gjc@3970
   728
        os << *iter;
gjc@3970
   729
        if (next != mprSet.end ())
gjc@3970
   730
          os << ", ";
gjc@3970
   731
      }
gjc@3970
   732
    os << "]";
gjc@3970
   733
    NS_LOG_DEBUG ("Computed MPR set for node " << m_mainAddress << ": " << os.str ());
gjc@3970
   734
  }
gjc@3970
   735
#endif
gjc@3970
   736
gjc@2361
   737
  m_state.SetMprSet (mprSet);
gjc@1716
   738
}
gjc@1716
   739
gjc@1716
   740
///
gjc@1716
   741
/// \brief Gets the main address associated with a given interface address.
gjc@1716
   742
///
gjc@1716
   743
/// \param iface_addr the interface address.
gjc@1716
   744
/// \return the corresponding main address.
gjc@1716
   745
///
gjc@1716
   746
Ipv4Address
gjc@1801
   747
AgentImpl::GetMainAddress (Ipv4Address iface_addr) const
gjc@1716
   748
{
gjc@1798
   749
  const IfaceAssocTuple *tuple =
gjc@1716
   750
    m_state.FindIfaceAssocTuple (iface_addr);
gjc@1716
   751
  
gjc@1716
   752
  if (tuple != NULL)
gjc@1716
   753
    return tuple->mainAddr;
gjc@1716
   754
  else
gjc@1716
   755
    return iface_addr;
gjc@1716
   756
}
gjc@1716
   757
gjc@1716
   758
///
gjc@1716
   759
/// \brief Creates the routing table of the node following RFC 3626 hints.
gjc@1716
   760
///
gjc@1716
   761
void
gjc@1801
   762
AgentImpl::RoutingTableComputation ()
gjc@1716
   763
{
gjc@2328
   764
  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " s: Node " << m_mainAddress
gjc@2328
   765
                << ": RoutingTableComputation begin...");
gjc@2328
   766
gjc@1716
   767
  // 1. All the entries from the routing table are removed.
gjc@1716
   768
  m_routingTable->Clear ();
gjc@1716
   769
	
gjc@1716
   770
  // 2. The new routing entries are added starting with the
gjc@1716
   771
  // symmetric neighbors (h=1) as the destination nodes.
gjc@2328
   772
  const NeighborSet &neighborSet = m_state.GetNeighbors ();
gjc@2328
   773
  for (NeighborSet::const_iterator it = neighborSet.begin ();
gjc@2328
   774
       it != neighborSet.end(); it++)
gjc@1716
   775
    {
gjc@1716
   776
      NeighborTuple const &nb_tuple = *it;
gjc@2328
   777
      NS_LOG_DEBUG ("Looking at neighbor tuple: " << nb_tuple);
gjc@1716
   778
      if (nb_tuple.status == NeighborTuple::STATUS_SYM)
gjc@1716
   779
        {
gjc@1716
   780
          bool nb_main_addr = false;
gjc@1716
   781
          const LinkTuple *lt = NULL;
gjc@2328
   782
          const LinkSet &linkSet = m_state.GetLinks ();
gjc@2328
   783
          for (LinkSet::const_iterator it2 = linkSet.begin();
gjc@2328
   784
               it2 != linkSet.end(); it2++)
gjc@1716
   785
            {
gjc@1716
   786
              LinkTuple const &link_tuple = *it2;
gjc@2328
   787
              NS_LOG_DEBUG ("Looking at link tuple: " << link_tuple
gjc@2328
   788
                            << (link_tuple.time >= Simulator::Now ()? "" : " (expired)"));
gjc@2328
   789
              if ((GetMainAddress (link_tuple.neighborIfaceAddr) == nb_tuple.neighborMainAddr)
gjc@1716
   790
                  && link_tuple.time >= Simulator::Now ())
gjc@1716
   791
                {
gjc@2328
   792
                  NS_LOG_LOGIC ("Link tuple matches neighbor " << nb_tuple.neighborMainAddr
gjc@2328
   793
                                << " => adding routing table entry to neighbor");
gjc@1716
   794
                  lt = &link_tuple;
gjc@1716
   795
                  m_routingTable->AddEntry (link_tuple.neighborIfaceAddr,
gjc@1716
   796
                                            link_tuple.neighborIfaceAddr,
gjc@1716
   797
                                            link_tuple.localIfaceAddr,
gjc@1716
   798
                                            1);
gjc@2328
   799
                  if (link_tuple.neighborIfaceAddr == nb_tuple.neighborMainAddr)
gjc@2328
   800
                    {
gjc@2328
   801
                      nb_main_addr = true;
gjc@2328
   802
                    }
gjc@2328
   803
                }
gjc@2328
   804
              else
gjc@2328
   805
                {
gjc@2328
   806
                  NS_LOG_LOGIC ("Link tuple: linkMainAddress= " << GetMainAddress (link_tuple.neighborIfaceAddr)
gjc@2328
   807
                                << "; neighborMainAddr =  " << nb_tuple.neighborMainAddr
gjc@2328
   808
                                << "; expired=" << int (link_tuple.time < Simulator::Now ())
gjc@2328
   809
                                << " => IGNORE");
gjc@1716
   810
                }
gjc@1716
   811
            }
gjc@2328
   812
gjc@2328
   813
          // If, in the above, no R_dest_addr is equal to the main
gjc@2328
   814
          // address of the neighbor, then another new routing entry
gjc@2328
   815
          // with MUST be added, with:
gjc@2328
   816
          //      R_dest_addr  = main address of the neighbor;
gjc@2328
   817
          //      R_next_addr  = L_neighbor_iface_addr of one of the
gjc@2328
   818
          //                     associated link tuple with L_time >= current time;
gjc@2328
   819
          //      R_dist       = 1;
gjc@2328
   820
          //      R_iface_addr = L_local_iface_addr of the
gjc@2328
   821
          //                     associated link tuple.
gjc@1716
   822
          if (!nb_main_addr && lt != NULL)
gjc@1716
   823
            {
gjc@2328
   824
              NS_LOG_LOGIC ("no R_dest_addr is equal to the main address of the neighbor "
gjc@2328
   825
                            "=> adding additional routing entry");
gjc@1716
   826
              m_routingTable->AddEntry(nb_tuple.neighborMainAddr,
gjc@1716
   827
                                       lt->neighborIfaceAddr,
gjc@1716
   828
                                       lt->localIfaceAddr,
gjc@1716
   829
                                       1);
gjc@1716
   830
            }
gjc@1716
   831
        }
gjc@1716
   832
    }
gjc@1716
   833
  
gjc@2328
   834
  //  3. for each node in N2, i.e., a 2-hop neighbor which is not a
gjc@2328
   835
  //  neighbor node or the node itself, and such that there exist at
gjc@2328
   836
  //  least one entry in the 2-hop neighbor set where
gjc@2328
   837
  //  N_neighbor_main_addr correspond to a neighbor node with
gjc@2328
   838
  //  willingness different of WILL_NEVER,
gjc@2328
   839
  const TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
gjc@2328
   840
  for (TwoHopNeighborSet::const_iterator it = twoHopNeighbors.begin ();
gjc@2328
   841
       it != twoHopNeighbors.end (); it++)
gjc@1716
   842
    {
gjc@1716
   843
      TwoHopNeighborTuple const &nb2hop_tuple = *it;
gjc@2328
   844
gjc@2328
   845
      NS_LOG_LOGIC ("Looking at two-hop neighbor tuple: " << nb2hop_tuple);
gjc@2328
   846
gjc@2328
   847
      // a 2-hop neighbor which is not a neighbor node or the node itself
gjc@2328
   848
      if (m_state.FindNeighborTuple (nb2hop_tuple.twoHopNeighborAddr))
gjc@2328
   849
        {
gjc@2328
   850
          NS_LOG_LOGIC ("Two-hop neighbor tuple is also neighbor; skipped.");
gjc@2328
   851
          continue;
gjc@2328
   852
        }
gjc@2328
   853
gjc@2328
   854
      if (nb2hop_tuple.twoHopNeighborAddr == m_mainAddress)
gjc@2328
   855
        {
gjc@2328
   856
          NS_LOG_LOGIC ("Two-hop neighbor is self; skipped.");
gjc@2328
   857
          continue;
gjc@2328
   858
        }
gjc@2328
   859
gjc@2328
   860
      // ...and such that there exist at least one entry in the 2-hop
gjc@2328
   861
      // neighbor set where N_neighbor_main_addr correspond to a
gjc@2328
   862
      // neighbor node with willingness different of WILL_NEVER...
gjc@2328
   863
      bool nb2hopOk = false;
gjc@2328
   864
      for (NeighborSet::const_iterator neighbor = neighborSet.begin ();
gjc@2328
   865
           neighbor != neighborSet.end(); neighbor++)
gjc@2328
   866
        {
gjc@2328
   867
          if (neighbor->neighborMainAddr == nb2hop_tuple.neighborMainAddr
gjc@2328
   868
              && neighbor->willingness != OLSR_WILL_NEVER)
gjc@2328
   869
            {
gjc@2328
   870
              nb2hopOk = true;
gjc@2328
   871
              break;
gjc@2328
   872
            }
gjc@2328
   873
        }
gjc@2328
   874
      if (!nb2hopOk)
gjc@2328
   875
        {
gjc@2328
   876
          NS_LOG_LOGIC ("Two-hop neighbor tuple skipped: 2-hop neighbor "
gjc@2328
   877
                        << nb2hop_tuple.twoHopNeighborAddr
gjc@2328
   878
                        << " is attached to neighbor " << nb2hop_tuple.neighborMainAddr
gjc@2328
   879
                        << ", which was not found in the Neighbor Set.");
gjc@2328
   880
          continue;
gjc@2328
   881
        }
gjc@2328
   882
      
gjc@2328
   883
      // one selects one 2-hop tuple and creates one entry in the routing table with:
gjc@2328
   884
      //                R_dest_addr  =  the main address of the 2-hop neighbor;
gjc@2328
   885
      //                R_next_addr  = the R_next_addr of the entry in the
gjc@2328
   886
      //                               routing table with:
gjc@2328
   887
      //                                   R_dest_addr == N_neighbor_main_addr
gjc@2328
   888
      //                                                  of the 2-hop tuple;
gjc@2328
   889
      //                R_dist       = 2;
gjc@2328
   890
      //                R_iface_addr = the R_iface_addr of the entry in the
gjc@2328
   891
      //                               routing table with:
gjc@2328
   892
      //                                   R_dest_addr == N_neighbor_main_addr
gjc@2328
   893
      //                                                  of the 2-hop tuple;
gjc@2328
   894
      RoutingTableEntry entry;
gjc@2328
   895
      bool foundEntry = m_routingTable->Lookup (nb2hop_tuple.neighborMainAddr, entry);
gjc@2328
   896
      if (foundEntry)
gjc@2328
   897
        {
gjc@2328
   898
          NS_LOG_LOGIC ("Adding routing entry for two-hop neighbor.");
gjc@2328
   899
          m_routingTable->AddEntry (nb2hop_tuple.twoHopNeighborAddr,
gjc@2328
   900
                                    entry.nextAddr,
gjc@2328
   901
                                    entry.interface,
gjc@2328
   902
                                    2);
gjc@2328
   903
        }
gjc@1716
   904
      else
gjc@1716
   905
        {
gjc@2328
   906
          NS_LOG_LOGIC ("NOT adding routing entry for two-hop neighbor ("
gjc@2328
   907
                        << nb2hop_tuple.twoHopNeighborAddr
gjc@2328
   908
                        << " not found in the routing table)");
gjc@1716
   909
        }
gjc@1716
   910
    }
gjc@1716
   911
  
gjc@1716
   912
  for (uint32_t h = 2; ; h++)
gjc@1716
   913
    {
gjc@1716
   914
      bool added = false;
gjc@1716
   915
		
gjc@2328
   916
      // 3.1. For each topology entry in the topology table, if its
gjc@1716
   917
      // T_dest_addr does not correspond to R_dest_addr of any
gjc@1716
   918
      // route entry in the routing table AND its T_last_addr
gjc@1716
   919
      // corresponds to R_dest_addr of a route entry whose R_dist
gjc@1716
   920
      // is equal to h, then a new route entry MUST be recorded in
gjc@1716
   921
      // the routing table (if it does not already exist)
gjc@2328
   922
      const TopologySet &topology = m_state.GetTopologySet ();
gjc@2328
   923
      for (TopologySet::const_iterator it = topology.begin ();
gjc@2328
   924
           it != topology.end (); it++)
gjc@1716
   925
        {
gjc@2328
   926
          const TopologyTuple &topology_tuple = *it;
gjc@2328
   927
          NS_LOG_LOGIC ("Looking at topology tuple: " << topology_tuple);
gjc@2328
   928
gjc@2328
   929
          RoutingTableEntry destAddrEntry, lastAddrEntry;
gjc@2328
   930
          bool have_destAddrEntry = m_routingTable->Lookup (topology_tuple.destAddr, destAddrEntry);
gjc@2328
   931
          bool have_lastAddrEntry = m_routingTable->Lookup (topology_tuple.lastAddr, lastAddrEntry);
gjc@2328
   932
          if (!have_destAddrEntry && have_lastAddrEntry && lastAddrEntry.distance == h)
gjc@1716
   933
            {
gjc@2328
   934
              NS_LOG_LOGIC ("Adding routing table entry based on the topology tuple.");
gjc@2328
   935
              // then a new route entry MUST be recorded in
gjc@2328
   936
              //                the routing table (if it does not already exist) where:
gjc@2328
   937
              //                     R_dest_addr  = T_dest_addr;
gjc@2328
   938
              //                     R_next_addr  = R_next_addr of the recorded
gjc@2328
   939
              //                                    route entry where:
gjc@2328
   940
              //                                    R_dest_addr == T_last_addr
gjc@2328
   941
              //                     R_dist       = h+1; and
gjc@2328
   942
              //                     R_iface_addr = R_iface_addr of the recorded
gjc@2328
   943
              //                                    route entry where:
gjc@2328
   944
              //                                       R_dest_addr == T_last_addr.
gjc@1716
   945
              m_routingTable->AddEntry (topology_tuple.destAddr,
gjc@2328
   946
                                        lastAddrEntry.nextAddr,
gjc@2328
   947
                                        lastAddrEntry.interface,
gjc@1716
   948
                                        h + 1);
gjc@1716
   949
              added = true;
gjc@1716
   950
            }
gjc@2328
   951
          else
gjc@1716
   952
            {
gjc@2328
   953
              NS_LOG_LOGIC ("NOT adding routing table entry based on the topology tuple: "
gjc@2328
   954
                            "have_destAddrEntry=" << have_destAddrEntry
gjc@2328
   955
                            << " have_lastAddrEntry=" << have_lastAddrEntry
gjc@2328
   956
                            << " lastAddrEntry.distance=" << (int) lastAddrEntry.distance
gjc@2328
   957
                            << " (h=" << h << ")");
gjc@1716
   958
            }
gjc@1716
   959
        }
gjc@2328
   960
      
gjc@1716
   961
      if (!added)
gjc@1716
   962
        break;
gjc@1716
   963
    }
gjc@2328
   964
gjc@2328
   965
  // 4. For each entry in the multiple interface association base
gjc@2328
   966
  // where there exists a routing entry such that:
gjc@2328
   967
  //	R_dest_addr  == I_main_addr  (of the multiple interface association entry)
gjc@2328
   968
  // AND there is no routing entry such that:
gjc@2328
   969
  //	R_dest_addr  == I_iface_addr
gjc@2328
   970
  const IfaceAssocSet &ifaceAssocSet = m_state.GetIfaceAssocSet ();
gjc@2328
   971
  for (IfaceAssocSet::const_iterator it = ifaceAssocSet.begin ();
gjc@2328
   972
       it != ifaceAssocSet.end (); it++)
gjc@2328
   973
    {
gjc@2328
   974
      IfaceAssocTuple const &tuple = *it;
gjc@2328
   975
      RoutingTableEntry entry1, entry2;
gjc@2328
   976
      bool have_entry1 = m_routingTable->Lookup (tuple.mainAddr, entry1);
gjc@2328
   977
      bool have_entry2 = m_routingTable->Lookup (tuple.ifaceAddr, entry2);
gjc@2328
   978
      if (have_entry1 && !have_entry2)
gjc@2328
   979
        {
gjc@2328
   980
          // then a route entry is created in the routing table with:
gjc@2328
   981
          //       R_dest_addr  =  I_iface_addr (of the multiple interface
gjc@2328
   982
          //                                     association entry)
gjc@2328
   983
          //       R_next_addr  =  R_next_addr  (of the recorded route entry)
gjc@2328
   984
          //       R_dist       =  R_dist       (of the recorded route entry)
gjc@2328
   985
          //       R_iface_addr =  R_iface_addr (of the recorded route entry).
gjc@2328
   986
          m_routingTable->AddEntry (tuple.ifaceAddr,
gjc@2328
   987
                                    entry1.nextAddr,
gjc@2328
   988
                                    entry1.interface,
gjc@2328
   989
                                    entry1.distance);
gjc@2328
   990
        }
gjc@2328
   991
    }
gjc@2328
   992
gjc@2328
   993
  NS_LOG_DEBUG ("Node " << m_mainAddress << ": RoutingTableComputation end.");
gjc@2333
   994
  m_routingTableChanged (m_routingTable->GetSize ());
gjc@1716
   995
}
gjc@1716
   996
gjc@1716
   997
gjc@1716
   998
///
gjc@1716
   999
/// \brief Processes a HELLO message following RFC 3626 specification.
gjc@1716
  1000
///
gjc@1716
  1001
/// Link sensing and population of the Neighbor Set, 2-hop Neighbor Set and MPR
gjc@1716
  1002
/// Selector Set are performed.
gjc@1716
  1003
///
gjc@1716
  1004
/// \param msg the %OLSR message which contains the HELLO message.
gjc@1716
  1005
/// \param receiver_iface the address of the interface where the message was received from.
gjc@1716
  1006
/// \param sender_iface the address of the interface where the message was sent from.
gjc@1716
  1007
///
gjc@1716
  1008
void
gjc@1801
  1009
AgentImpl::ProcessHello (const olsr::MessageHeader &msg,
gjc@2328
  1010
                         const Ipv4Address &receiverIface,
gjc@2328
  1011
                         const Ipv4Address &senderIface)
gjc@1716
  1012
{
gjc@1801
  1013
  const olsr::MessageHeader::Hello &hello = msg.GetHello ();
gjc@2328
  1014
gjc@1716
  1015
  LinkSensing (msg, hello, receiverIface, senderIface);
gjc@2328
  1016
gjc@2328
  1017
#ifdef NS3_LOG_ENABLE
gjc@2328
  1018
  {
gjc@2328
  1019
    const LinkSet &links = m_state.GetLinks ();
gjc@2328
  1020
    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
  1021
                  << "s ** BEGIN dump Link Set for OLSR Node " << m_mainAddress);
gjc@2328
  1022
    for (LinkSet::const_iterator link = links.begin (); link != links.end (); link++)
gjc@2328
  1023
      {
gjc@2328
  1024
        NS_LOG_DEBUG(*link);
gjc@2328
  1025
      }
gjc@2328
  1026
    NS_LOG_DEBUG ("** END dump Link Set for OLSR Node " << m_mainAddress);
gjc@2328
  1027
gjc@2328
  1028
    const NeighborSet &neighbors = m_state.GetNeighbors ();
gjc@2328
  1029
    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
  1030
                  << "s ** BEGIN dump Neighbor Set for OLSR Node " << m_mainAddress);
gjc@2328
  1031
    for (NeighborSet::const_iterator neighbor = neighbors.begin (); neighbor != neighbors.end (); neighbor++)
gjc@2328
  1032
      {
gjc@2328
  1033
        NS_LOG_DEBUG(*neighbor);
gjc@2328
  1034
      }
gjc@2328
  1035
    NS_LOG_DEBUG ("** END dump Neighbor Set for OLSR Node " << m_mainAddress);
gjc@2328
  1036
  }
gjc@2328
  1037
#endif
gjc@2328
  1038
gjc@1716
  1039
  PopulateNeighborSet (msg, hello);
gjc@1716
  1040
  PopulateTwoHopNeighborSet (msg, hello);
gjc@2328
  1041
gjc@2328
  1042
#ifdef NS3_LOG_ENABLE
gjc@2328
  1043
  {
gjc@2328
  1044
    const TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
gjc@2328
  1045
    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
  1046
                  << "s ** BEGIN dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress);
gjc@2328
  1047
    for (TwoHopNeighborSet::const_iterator tuple = twoHopNeighbors.begin ();
gjc@2328
  1048
         tuple != twoHopNeighbors.end (); tuple++)
gjc@2328
  1049
      {
gjc@2328
  1050
        NS_LOG_DEBUG(*tuple);
gjc@2328
  1051
      }
gjc@2328
  1052
    NS_LOG_DEBUG ("** END dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress);
gjc@2328
  1053
  }
gjc@2328
  1054
#endif
gjc@2328
  1055
gjc@1716
  1056
  MprComputation ();
gjc@1716
  1057
  PopulateMprSelectorSet (msg, hello);
gjc@1716
  1058
}
gjc@1716
  1059
gjc@1716
  1060
///
gjc@1716
  1061
/// \brief Processes a TC message following RFC 3626 specification.
gjc@1716
  1062
///
gjc@1716
  1063
/// The Topology Set is updated (if needed) with the information of
gjc@1716
  1064
/// the received TC message.
gjc@1716
  1065
///
gjc@1716
  1066
/// \param msg the %OLSR message which contains the TC message.
gjc@1716
  1067
/// \param sender_iface the address of the interface where the message was sent from.
gjc@1716
  1068
///
gjc@1716
  1069
void
gjc@1801
  1070
AgentImpl::ProcessTc (const olsr::MessageHeader &msg,
gjc@2328
  1071
                      const Ipv4Address &senderIface)
gjc@1716
  1072
{
gjc@1801
  1073
  const olsr::MessageHeader::Tc &tc = msg.GetTc ();
gjc@1716
  1074
  Time now = Simulator::Now ();
gjc@1716
  1075
	
gjc@1716
  1076
  // 1. If the sender interface of this message is not in the symmetric
gjc@1716
  1077
  // 1-hop neighborhood of this node, the message MUST be discarded.
gjc@3970
  1078
  const LinkTuple *link_tuple = m_state.FindSymLinkTuple (senderIface, now);
gjc@1716
  1079
  if (link_tuple == NULL)
gjc@1716
  1080
    return;
gjc@1716
  1081
	
gjc@1716
  1082
  // 2. If there exist some tuple in the topology set where:
gjc@1716
  1083
  // 	T_last_addr == originator address AND
gjc@1716
  1084
  // 	T_seq       >  ANSN,
gjc@1716
  1085
  // then further processing of this TC message MUST NOT be
gjc@1716
  1086
  // performed.
gjc@3970
  1087
  const TopologyTuple *topologyTuple =
gjc@1755
  1088
    m_state.FindNewerTopologyTuple (msg.GetOriginatorAddress (), tc.ansn);
gjc@1716
  1089
  if (topologyTuple != NULL)
gjc@1716
  1090
    return;
gjc@1716
  1091
	
gjc@1716
  1092
  // 3. All tuples in the topology set where:
gjc@1716
  1093
  //	T_last_addr == originator address AND
gjc@1716
  1094
  //	T_seq       <  ANSN
gjc@1716
  1095
  // MUST be removed from the topology set.
gjc@1755
  1096
  m_state.EraseOlderTopologyTuples (msg.GetOriginatorAddress (), tc.ansn);
gjc@1716
  1097
gjc@1716
  1098
  // 4. For each of the advertised neighbor main address received in
gjc@1716
  1099
  // the TC message:
gjc@1755
  1100
  for (std::vector<Ipv4Address>::const_iterator i = tc.neighborAddresses.begin ();
gjc@1755
  1101
       i != tc.neighborAddresses.end (); i++)
gjc@1716
  1102
    {
gjc@1716
  1103
      const Ipv4Address &addr = *i;
gjc@1716
  1104
      // 4.1. If there exist some tuple in the topology set where:
gjc@1716
  1105
      // 	T_dest_addr == advertised neighbor main address, AND
gjc@1716
  1106
      // 	T_last_addr == originator address,
gjc@1716
  1107
      // then the holding time of that tuple MUST be set to:
gjc@1716
  1108
      // 	T_time      =  current time + validity time.
gjc@1716
  1109
      TopologyTuple *topologyTuple =
gjc@1716
  1110
        m_state.FindTopologyTuple (addr, msg.GetOriginatorAddress ());
gjc@1716
  1111
gjc@1716
  1112
      if (topologyTuple != NULL)
gjc@1716
  1113
        {
gjc@1716
  1114
          topologyTuple->expirationTime = now + msg.GetVTime ();
gjc@1716
  1115
        }
gjc@1716
  1116
      else
gjc@1716
  1117
        {
gjc@1716
  1118
          // 4.2. Otherwise, a new tuple MUST be recorded in the topology
gjc@1716
  1119
          // set where:
gjc@1716
  1120
          //	T_dest_addr = advertised neighbor main address,
gjc@1716
  1121
          //	T_last_addr = originator address,
gjc@1716
  1122
          //	T_seq       = ANSN,
gjc@1716
  1123
          //	T_time      = current time + validity time.
gjc@1716
  1124
          TopologyTuple topologyTuple;;
gjc@1716
  1125
          topologyTuple.destAddr = addr;
gjc@1716
  1126
          topologyTuple.lastAddr = msg.GetOriginatorAddress ();
gjc@1755
  1127
          topologyTuple.sequenceNumber = tc.ansn;
gjc@1716
  1128
          topologyTuple.expirationTime = now + msg.GetVTime ();
gjc@1716
  1129
          AddTopologyTuple (topologyTuple);
gjc@1716
  1130
gjc@1716
  1131
          // Schedules topology tuple deletion
gjc@1768
  1132
          m_events.Track (Simulator::Schedule (DELAY (topologyTuple.expirationTime),
gjc@1801
  1133
                                               &AgentImpl::TopologyTupleTimerExpire,
gjc@2358
  1134
                                               this,
gjc@2358
  1135
                                               topologyTuple.destAddr,
gjc@2358
  1136
                                               topologyTuple.lastAddr));
gjc@1716
  1137
        }
gjc@1716
  1138
    }
gjc@2328
  1139
gjc@2328
  1140
#ifdef NS3_LOG_ENABLE
gjc@2328
  1141
  {
gjc@2328
  1142
    const TopologySet &topology = m_state.GetTopologySet ();
gjc@2328
  1143
    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
  1144
                  << "s ** BEGIN dump TopologySet for OLSR Node " << m_mainAddress);
gjc@2328
  1145
    for (TopologySet::const_iterator tuple = topology.begin ();
gjc@2328
  1146
         tuple != topology.end (); tuple++)
gjc@2328
  1147
      {
gjc@2328
  1148
        NS_LOG_DEBUG (*tuple);
gjc@2328
  1149
      }
gjc@2328
  1150
    NS_LOG_DEBUG ("** END dump TopologySet Set for OLSR Node " << m_mainAddress);
gjc@2328
  1151
  }
gjc@2328
  1152
#endif
gjc@1716
  1153
}
gjc@1716
  1154
gjc@1716
  1155
///
gjc@1716
  1156
/// \brief Processes a MID message following RFC 3626 specification.
gjc@1716
  1157
///
gjc@1716
  1158
/// The Interface Association Set is updated (if needed) with the information
gjc@1716
  1159
/// of the received MID message.
gjc@1716
  1160
///
gjc@1716
  1161
/// \param msg the %OLSR message which contains the MID message.
gjc@1716
  1162
/// \param sender_iface the address of the interface where the message was sent from.
gjc@1716
  1163
///
gjc@1716
  1164
void
gjc@1801
  1165
AgentImpl::ProcessMid (const olsr::MessageHeader &msg,
gjc@2328
  1166
                       const Ipv4Address &senderIface)
gjc@1716
  1167
{
gjc@1801
  1168
  const olsr::MessageHeader::Mid &mid = msg.GetMid ();
gjc@1716
  1169
  Time now = Simulator::Now ();
gjc@2328
  1170
  
gjc@2328
  1171
  NS_LOG_DEBUG ("Node " << m_mainAddress << " ProcessMid from " << senderIface);
gjc@1716
  1172
  // 1. If the sender interface of this message is not in the symmetric
gjc@1716
  1173
  // 1-hop neighborhood of this node, the message MUST be discarded.
gjc@3970
  1174
  const LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderIface, now);
gjc@1716
  1175
  if (linkTuple == NULL)
gjc@2328
  1176
    {
gjc@2328
  1177
      NS_LOG_LOGIC ("Node " << m_mainAddress <<
gjc@2328
  1178
                    ": the sender interface of this message is not in the "
gjc@2328
  1179
                    "symmetric 1-hop neighborhood of this node,"
gjc@2328
  1180
                    " the message MUST be discarded.");
gjc@2328
  1181
      return;
gjc@2328
  1182
    }
gjc@1716
  1183
	
gjc@1716
  1184
  // 2. For each interface address listed in the MID message
gjc@1755
  1185
  for (std::vector<Ipv4Address>::const_iterator i = mid.interfaceAddresses.begin ();
gjc@1755
  1186
       i != mid.interfaceAddresses.end (); i++)
gjc@1716
  1187
    {
gjc@1716
  1188
      bool updated = false;
gjc@1716
  1189
      IfaceAssocSet &ifaceAssoc = m_state.GetIfaceAssocSetMutable ();
gjc@1716
  1190
      for (IfaceAssocSet::iterator tuple = ifaceAssoc.begin();
gjc@1716
  1191
           tuple != ifaceAssoc.end(); tuple++)
gjc@1716
  1192
        {
gjc@1716
  1193
          if (tuple->ifaceAddr == *i
gjc@1716
  1194
              && tuple->mainAddr == msg.GetOriginatorAddress ())
gjc@1716
  1195
            {
gjc@2328
  1196
              NS_LOG_LOGIC ("IfaceAssoc updated: " << *tuple);
gjc@1716
  1197
              tuple->time = now + msg.GetVTime ();
gjc@1716
  1198
              updated = true;
gjc@1716
  1199
            }
gjc@1716
  1200
        }
gjc@1716
  1201
      if (!updated)
gjc@1716
  1202
        {
gjc@1716
  1203
          IfaceAssocTuple tuple;
gjc@1716
  1204
          tuple.ifaceAddr = *i;
gjc@1716
  1205
          tuple.mainAddr = msg.GetOriginatorAddress ();
gjc@1716
  1206
          tuple.time = now + msg.GetVTime ();
gjc@1716
  1207
          AddIfaceAssocTuple (tuple);
gjc@2328
  1208
          NS_LOG_LOGIC ("New IfaceAssoc added: " << tuple);
gjc@1716
  1209
          // Schedules iface association tuple deletion
gjc@1716
  1210
          Simulator::Schedule (DELAY (tuple.time),
gjc@2358
  1211
                               &AgentImpl::IfaceAssocTupleTimerExpire, this, tuple.ifaceAddr);
gjc@1716
  1212
        }
gjc@1716
  1213
    }
gjc@2328
  1214
gjc@2328
  1215
  // 3. (not part of the RFC) iterate over all NeighborTuple's and
gjc@2328
  1216
  // TwoHopNeighborTuples, update the neighbor addresses taking into account
gjc@2328
  1217
  // the new MID information.
gjc@2328
  1218
  NeighborSet &neighbors = m_state.GetNeighbors ();
gjc@2328
  1219
  for (NeighborSet::iterator neighbor = neighbors.begin (); neighbor != neighbors.end(); neighbor++)
gjc@2328
  1220
    {
gjc@2328
  1221
      neighbor->neighborMainAddr = GetMainAddress (neighbor->neighborMainAddr);
gjc@2328
  1222
    }
gjc@2328
  1223
gjc@2328
  1224
  TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
gjc@2328
  1225
  for (TwoHopNeighborSet::iterator twoHopNeighbor = twoHopNeighbors.begin ();
gjc@2328
  1226
       twoHopNeighbor != twoHopNeighbors.end(); twoHopNeighbor++)
gjc@2328
  1227
    {
gjc@2328
  1228
      twoHopNeighbor->neighborMainAddr = GetMainAddress (twoHopNeighbor->neighborMainAddr);
gjc@2328
  1229
      twoHopNeighbor->twoHopNeighborAddr = GetMainAddress (twoHopNeighbor->twoHopNeighborAddr);
gjc@2328
  1230
    }
gjc@2328
  1231
  NS_LOG_DEBUG ("Node " << m_mainAddress << " ProcessMid from " << senderIface << " -> END.");
gjc@1716
  1232
}
gjc@1716
  1233
gjc@1716
  1234
gjc@1716
  1235
///
gjc@1716
  1236
/// \brief OLSR's default forwarding algorithm.
gjc@1716
  1237
///
gjc@1716
  1238
/// See RFC 3626 for details.
gjc@1716
  1239
///
gjc@1716
  1240
/// \param p the %OLSR packet which has been received.
gjc@1716
  1241
/// \param msg the %OLSR message which must be forwarded.
gjc@1716
  1242
/// \param dup_tuple NULL if the message has never been considered for forwarding,
gjc@1716
  1243
/// or a duplicate tuple in other case.
gjc@1716
  1244
/// \param local_iface the address of the interface where the message was received from.
gjc@1716
  1245
///
gjc@1716
  1246
void
gjc@1801
  1247
AgentImpl::ForwardDefault (olsr::MessageHeader olsrMessage,
gjc@1732
  1248
                               DuplicateTuple *duplicated,
gjc@1732
  1249
                               const Ipv4Address &localIface,
gjc@1732
  1250
                               const Ipv4Address &senderAddress)
gjc@1716
  1251
{
gjc@1716
  1252
  Time now = Simulator::Now ();
gjc@1716
  1253
  
gjc@1716
  1254
  // If the sender interface address is not in the symmetric
gjc@1716
  1255
  // 1-hop neighborhood the message must not be forwarded
gjc@3970
  1256
  const LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderAddress, now);
gjc@1716
  1257
  if (linkTuple == NULL)
gjc@1716
  1258
    return;
gjc@1716
  1259
gjc@1716
  1260
  // If the message has already been considered for forwarding,
gjc@1716
  1261
  // it must not be retransmitted again
gjc@1716
  1262
  if (duplicated != NULL && duplicated->retransmitted)
gjc@1716
  1263
    {
gjc@2328
  1264
      NS_LOG_LOGIC (Simulator::Now () << "Node " << m_mainAddress << " does not forward a message received"
gjc@2328
  1265
                    " from " << olsrMessage.GetOriginatorAddress () << " because it is duplicated");
gjc@1716
  1266
      return;
gjc@1716
  1267
    }
gjc@1716
  1268
	
gjc@1716
  1269
  // If the sender interface address is an interface address
gjc@1716
  1270
  // of a MPR selector of this node and ttl is greater than 1,
gjc@1716
  1271
  // the message must be retransmitted
gjc@1716
  1272
  bool retransmitted = false;
gjc@1716
  1273
  if (olsrMessage.GetTimeToLive () > 1)
gjc@1716
  1274
    {
gjc@3970
  1275
      const MprSelectorTuple *mprselTuple =
gjc@1716
  1276
        m_state.FindMprSelectorTuple (GetMainAddress (senderAddress));
gjc@1716
  1277
      if (mprselTuple != NULL)
gjc@1716
  1278
        {
gjc@1716
  1279
          olsrMessage.SetTimeToLive (olsrMessage.GetTimeToLive () - 1);
gjc@1716
  1280
          olsrMessage.SetHopCount (olsrMessage.GetHopCount () + 1);
gjc@1716
  1281
          // We have to introduce a random delay to avoid
gjc@1716
  1282
          // synchronization with neighbors.
gjc@1755
  1283
          QueueMessage (olsrMessage, JITTER);
gjc@1716
  1284
          retransmitted = true;
gjc@1716
  1285
        }
gjc@1716
  1286
    }
gjc@1716
  1287
	
gjc@1716
  1288
  // Update duplicate tuple...
gjc@1716
  1289
  if (duplicated != NULL)
gjc@1716
  1290
    {
gjc@1716
  1291
      duplicated->expirationTime = now + OLSR_DUP_HOLD_TIME;
gjc@1716
  1292
      duplicated->retransmitted = retransmitted;
gjc@1716
  1293
      duplicated->ifaceList.push_back (localIface);
gjc@1716
  1294
    }
gjc@1716
  1295
  // ...or create a new one
gjc@1716
  1296
  else
gjc@1716
  1297
    {
gjc@1716
  1298
      DuplicateTuple newDup;
gjc@1716
  1299
      newDup.address = olsrMessage.GetOriginatorAddress ();
gjc@1716
  1300
      newDup.sequenceNumber = olsrMessage.GetMessageSequenceNumber ();
gjc@1716
  1301
      newDup.expirationTime = now + OLSR_DUP_HOLD_TIME;
gjc@1716
  1302
      newDup.retransmitted = retransmitted;
gjc@1716
  1303
      newDup.ifaceList.push_back (localIface);
gjc@1716
  1304
      AddDuplicateTuple (newDup);
gjc@1716
  1305
      // Schedule dup tuple deletion
gjc@1716
  1306
      Simulator::Schedule (OLSR_DUP_HOLD_TIME,
gjc@2358
  1307
                           &AgentImpl::DupTupleTimerExpire, this,
gjc@2358
  1308
                           newDup.address, newDup.sequenceNumber);
gjc@1716
  1309
    }
gjc@1716
  1310
}
gjc@1716
  1311
gjc@1716
  1312
///
gjc@1716
  1313
/// \brief Enques an %OLSR message which will be sent with a delay of (0, delay].
gjc@1716
  1314
///
gjc@1716
  1315
/// This buffering system is used in order to piggyback several %OLSR messages in
gjc@1716
  1316
/// a same %OLSR packet.
gjc@1716
  1317
///
gjc@1716
  1318
/// \param msg the %OLSR message which must be sent.
gjc@1716
  1319
/// \param delay maximum delay the %OLSR message is going to be buffered.
gjc@1716
  1320
///
gjc@1716
  1321
void
gjc@1801
  1322
AgentImpl::QueueMessage (const olsr::MessageHeader &message, Time delay)
gjc@1716
  1323
{
gjc@1716
  1324
  m_queuedMessages.push_back (message);
gjc@1730
  1325
  if (not m_queuedMessagesTimer.IsRunning ())
gjc@1716
  1326
    {
gjc@1765
  1327
      m_queuedMessagesTimer.SetDelay (delay);
gjc@1765
  1328
      m_queuedMessagesTimer.Schedule ();
gjc@1716
  1329
    }
gjc@1716
  1330
}
gjc@1716
  1331
gjc@1716
  1332
void
craigdo@1868
  1333
AgentImpl::SendPacket (Ptr<Packet> packet, 
craigdo@1868
  1334
                       const MessageList &containedMessages)
gjc@1716
  1335
{
mathieu@1804
  1336
  NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " sending a OLSR packet");
gjc@1803
  1337
gjc@1716
  1338
  // Add a header
gjc@1801
  1339
  olsr::PacketHeader header;
craigdo@1868
  1340
  header.SetPacketLength (header.GetSerializedSize () + packet->GetSize ());
gjc@1716
  1341
  header.SetPacketSequenceNumber (GetPacketSequenceNumber ());
craigdo@1868
  1342
  packet->AddHeader (header);
gjc@1803
  1343
gjc@1803
  1344
  // Trace it
gjc@1803
  1345
  m_txPacketTrace (header, containedMessages);
gjc@1803
  1346
gjc@1716
  1347
  // Send it
gjc@2328
  1348
  m_socketAddresses.begin ()->first->Send (packet);
gjc@1716
  1349
}
gjc@1716
  1350
gjc@1716
  1351
///
gjc@1716
  1352
/// \brief Creates as many %OLSR packets as needed in order to send all buffered
gjc@1716
  1353
/// %OLSR messages.
gjc@1716
  1354
///
gjc@1716
  1355
/// Maximum number of messages which can be contained in an %OLSR packet is
gjc@1716
  1356
/// dictated by OLSR_MAX_MSGS constant.
gjc@1716
  1357
///
gjc@1716
  1358
void
gjc@1801
  1359
AgentImpl::SendQueuedMessages ()
gjc@1716
  1360
{
craigdo@1868
  1361
  Ptr<Packet> packet = Create<Packet> ();
gjc@1716
  1362
  int numMessages = 0;
gjc@1716
  1363
mathieu@1804
  1364
  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": SendQueuedMessages");
gjc@1716
  1365
gjc@1803
  1366
  MessageList msglist;
gjc@1803
  1367
gjc@1801
  1368
  for (std::vector<olsr::MessageHeader>::const_iterator message = m_queuedMessages.begin ();
gjc@1755
  1369
       message != m_queuedMessages.end ();
gjc@1755
  1370
       message++)
gjc@1716
  1371
    {
craigdo@1868
  1372
      Ptr<Packet> p = Create<Packet> ();
craigdo@1868
  1373
      p->AddHeader (*message);
craigdo@1868
  1374
      packet->AddAtEnd (p);
gjc@1803
  1375
      msglist.push_back (*message);
gjc@1716
  1376
      if (++numMessages == OLSR_MAX_MSGS)
gjc@1716
  1377
        {
gjc@1803
  1378
          SendPacket (packet, msglist);
gjc@1803
  1379
          msglist.clear ();
gjc@1716
  1380
          // Reset variables for next packet
gjc@1716
  1381
          numMessages = 0;
craigdo@1868
  1382
          packet = Create<Packet> ();
gjc@1716
  1383
        }
gjc@1716
  1384
    }
gjc@1716
  1385
craigdo@1868
  1386
  if (packet->GetSize ())
gjc@1716
  1387
    {
gjc@1803
  1388
      SendPacket (packet, msglist);
gjc@1716
  1389
    }
gjc@1716
  1390
gjc@1716
  1391
  m_queuedMessages.clear ();
gjc@1716
  1392
}
gjc@1716
  1393
gjc@1716
  1394
///
gjc@1716
  1395
/// \brief Creates a new %OLSR HELLO message which is buffered for being sent later on.
gjc@1716
  1396
///
gjc@1716
  1397
void
gjc@1801
  1398
AgentImpl::SendHello ()
gjc@1716
  1399
{
gjc@3970
  1400
  NS_LOG_FUNCTION (this);
gjc@3970
  1401
  
gjc@1801
  1402
  olsr::MessageHeader msg;
gjc@1716
  1403
  Time now = Simulator::Now ();
gjc@1716
  1404
gjc@1716
  1405
  msg.SetVTime (OLSR_NEIGHB_HOLD_TIME);
gjc@1716
  1406
  msg.SetOriginatorAddress (m_mainAddress);
gjc@1716
  1407
  msg.SetTimeToLive (1);
gjc@1716
  1408
  msg.SetHopCount (0);
gjc@1716
  1409
  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
gjc@1801
  1410
  olsr::MessageHeader::Hello &hello = msg.GetHello ();
gjc@1716
  1411
gjc@3487
  1412
  hello.SetHTime (Scalar (3) * m_helloInterval);
gjc@1755
  1413
  hello.willingness = m_willingness;
gjc@1716
  1414
gjc@1801
  1415
  std::vector<olsr::MessageHeader::Hello::LinkMessage>
gjc@1755
  1416
    &linkMessages = hello.linkMessages;
gjc@1716
  1417
	
gjc@2328
  1418
  const LinkSet &links = m_state.GetLinks ();
gjc@2328
  1419
  for (LinkSet::const_iterator link_tuple = links.begin ();
gjc@2328
  1420
       link_tuple != links.end (); link_tuple++)
gjc@1716
  1421
    {
gjc@2328
  1422
      if (!(GetMainAddress (link_tuple->localIfaceAddr) == m_mainAddress
gjc@2328
  1423
            && link_tuple->time >= now))
gjc@2328
  1424
        {
gjc@2328
  1425
          continue;
gjc@2328
  1426
        }
gjc@1716
  1427
gjc@1762
  1428
      uint8_t link_type, nb_type = 0xff;
gjc@1716
  1429
			
gjc@1716
  1430
      // Establishes link type
gjc@2328
  1431
      if (link_tuple->symTime >= now)
gjc@1716
  1432
        {
gjc@1716
  1433
          link_type = OLSR_SYM_LINK;
gjc@1716
  1434
        }
gjc@1716
  1435
      else if (link_tuple->asymTime >= now)
gjc@1716
  1436
        {
gjc@1716
  1437
          link_type = OLSR_ASYM_LINK;
gjc@1716
  1438
        }
gjc@1716
  1439
      else
gjc@1716
  1440
        {
gjc@1716
  1441
          link_type = OLSR_LOST_LINK;
gjc@1716
  1442
        }
gjc@1716
  1443
      // Establishes neighbor type.
gjc@1716
  1444
      if (m_state.FindMprAddress (GetMainAddress (link_tuple->neighborIfaceAddr)))
gjc@1716
  1445
        {
gjc@1716
  1446
          nb_type = OLSR_MPR_NEIGH;
gjc@3970
  1447
          NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
gjc@3970
  1448
                        << " to be MPR_NEIGH.");
gjc@1716
  1449
        }
gjc@1716
  1450
      else
gjc@1716
  1451
        {
gjc@1716
  1452
          bool ok = false;
gjc@1716
  1453
          for (NeighborSet::const_iterator nb_tuple = m_state.GetNeighbors ().begin ();
gjc@1716
  1454
               nb_tuple != m_state.GetNeighbors ().end ();
gjc@1716
  1455
               nb_tuple++)
gjc@1716
  1456
            {
gjc@2328
  1457
              if (nb_tuple->neighborMainAddr == GetMainAddress (link_tuple->neighborIfaceAddr))
gjc@1716
  1458
                {
gjc@1716
  1459
                  if (nb_tuple->status == NeighborTuple::STATUS_SYM)
gjc@1716
  1460
                    {
gjc@3970
  1461
                      NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
gjc@3970
  1462
                                    << " to be SYM_NEIGH.");
gjc@1716
  1463
                      nb_type = OLSR_SYM_NEIGH;
gjc@1716
  1464
                    }
gjc@1716
  1465
                  else if (nb_tuple->status == NeighborTuple::STATUS_NOT_SYM)
gjc@1716
  1466
                    {
gjc@1716
  1467
                      nb_type = OLSR_NOT_NEIGH;
gjc@3970
  1468
                      NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
gjc@3970
  1469
                                    << " to be NOT_NEIGH.");
gjc@1716
  1470
                    }
gjc@1716
  1471
                  else
gjc@1716
  1472
                    {
gjc@2328
  1473
                      NS_FATAL_ERROR ("There is a neighbor tuple with an unknown status!\n");
gjc@1716
  1474
                    }
gjc@1716
  1475
                  ok = true;
gjc@1716
  1476
                  break;
gjc@1716
  1477
                }
gjc@1716
  1478
            }
gjc@1716
  1479
          if (!ok)
gjc@1716
  1480
            {
gjc@3970
  1481
              NS_LOG_WARN ("I don't know the neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr) << "!!!");
gjc@2308
  1482
              continue;
gjc@1716
  1483
            }
gjc@1716
  1484
        }
gjc@1716
  1485
gjc@1801
  1486
      olsr::MessageHeader::Hello::LinkMessage linkMessage;
gjc@1716
  1487
      linkMessage.linkCode = (link_type & 0x03) | ((nb_type << 2) & 0x0f);
gjc@1716
  1488
      linkMessage.neighborInterfaceAddresses.push_back
gjc@1716
  1489
        (link_tuple->neighborIfaceAddr);
gjc@1716
  1490
gjc@1716
  1491
      std::vector<Ipv4Address> interfaces =
gjc@1716
  1492
        m_state.FindNeighborInterfaces (link_tuple->neighborIfaceAddr);
gjc@1716
  1493
gjc@1716
  1494
      linkMessage.neighborInterfaceAddresses.insert
gjc@1716
  1495
        (linkMessage.neighborInterfaceAddresses.end (),
gjc@1716
  1496
         interfaces.begin (), interfaces.end ());
gjc@1716
  1497
gjc@1716
  1498
      linkMessages.push_back (linkMessage);
gjc@1716
  1499
    }
mathieu@1804
  1500
  NS_LOG_DEBUG ("OLSR HELLO message size: " << int (msg.GetSerializedSize ())
mathieu@1804
  1501
                << " (with " << int (linkMessages.size ()) << " link messages)");
gjc@1755
  1502
  QueueMessage (msg, JITTER);
gjc@1716
  1503
}
gjc@1716
  1504
gjc@1716
  1505
///
gjc@1716
  1506
/// \brief Creates a new %OLSR TC message which is buffered for being sent later on.
gjc@1716
  1507
///
gjc@1716
  1508
void
gjc@1801
  1509
AgentImpl::SendTc ()
gjc@1716
  1510
{
gjc@3970
  1511
  NS_LOG_FUNCTION (this);
gjc@3970
  1512
  
gjc@1801
  1513
  olsr::MessageHeader msg;
gjc@1716
  1514
gjc@1716
  1515
  msg.SetVTime (OLSR_TOP_HOLD_TIME);
gjc@1716
  1516
  msg.SetOriginatorAddress (m_mainAddress);
gjc@1716
  1517
  msg.SetTimeToLive (255);
gjc@1716
  1518
  msg.SetHopCount (0);
gjc@1716
  1519
  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
gjc@1716
  1520
  
gjc@1801
  1521
  olsr::MessageHeader::Tc &tc = msg.GetTc ();
gjc@1755
  1522
  tc.ansn = m_ansn;
gjc@1716
  1523
  for (MprSelectorSet::const_iterator mprsel_tuple = m_state.GetMprSelectors ().begin();
gjc@1716
  1524
       mprsel_tuple != m_state.GetMprSelectors ().end(); mprsel_tuple++)
gjc@1716
  1525
    {
gjc@1755
  1526
      tc.neighborAddresses.push_back (mprsel_tuple->mainAddr);
gjc@1716
  1527
    }
gjc@1755
  1528
  QueueMessage (msg, JITTER);
gjc@1716
  1529
}
gjc@1716
  1530
gjc@1716
  1531
///
gjc@1716
  1532
/// \brief Creates a new %OLSR MID message which is buffered for being sent later on.
gjc@1716
  1533
///
gjc@1716
  1534
void
gjc@1801
  1535
AgentImpl::SendMid ()
gjc@1716
  1536
{
gjc@1801
  1537
  olsr::MessageHeader msg;
gjc@1801
  1538
  olsr::MessageHeader::Mid &mid = msg.GetMid ();
gjc@1716
  1539
gjc@1716
  1540
  // A node which has only a single interface address participating in
gjc@1716
  1541
  // the MANET (i.e., running OLSR), MUST NOT generate any MID
gjc@1716
  1542
  // message.
gjc@1716
  1543
gjc@1716
  1544
  // A node with several interfaces, where only one is participating
gjc@1716
  1545
  // in the MANET and running OLSR (e.g., a node is connected to a
gjc@1716
  1546
  // wired network as well as to a MANET) MUST NOT generate any MID
gjc@1716
  1547
  // messages.
gjc@1716
  1548
gjc@1716
  1549
  // A node with several interfaces, where more than one is
gjc@1716
  1550
  // participating in the MANET and running OLSR MUST generate MID
gjc@1716
  1551
  // messages as specified.
gjc@1716
  1552
gjc@1716
  1553
  // [ Note: assuming here that all interfaces participate in the
gjc@1716
  1554
  // MANET; later we may want to make this configurable. ]
gjc@1716
  1555
gjc@1716
  1556
  Ipv4Address loopback ("127.0.0.1");
gjc@1716
  1557
  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
gjc@1716
  1558
    {
gjc@1716
  1559
      Ipv4Address addr = m_ipv4->GetAddress (i);
gjc@1716
  1560
      if (addr != m_mainAddress && addr != loopback)
gjc@1755
  1561
        mid.interfaceAddresses.push_back (addr);
gjc@1716
  1562
    }
gjc@1755
  1563
  if (mid.interfaceAddresses.size () == 0)
gjc@1716
  1564
    return;
gjc@1716
  1565
  
gjc@1716
  1566
  msg.SetVTime (OLSR_MID_HOLD_TIME);
gjc@1716
  1567
  msg.SetOriginatorAddress (m_mainAddress);
gjc@1716
  1568
  msg.SetTimeToLive (255);
gjc@1716
  1569
  msg.SetHopCount (0);
gjc@1716
  1570
  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
gjc@1716
  1571
gjc@1755
  1572
  QueueMessage (msg, JITTER);
gjc@1716
  1573
}
gjc@1716
  1574
gjc@1716
  1575
///
gjc@1716
  1576
/// \brief	Updates Link Set according to a new received HELLO message (following RFC 3626
gjc@1716
  1577
///		specification). Neighbor Set is also updated if needed.
gjc@1716
  1578
void
gjc@1801
  1579
AgentImpl::LinkSensing (const olsr::MessageHeader &msg,
gjc@2328
  1580
                        const olsr::MessageHeader::Hello &hello,
gjc@2328
  1581
                        const Ipv4Address &receiverIface,
gjc@2328
  1582
                        const Ipv4Address &senderIface)
gjc@1716
  1583
{
gjc@1716
  1584
  Time now = Simulator::Now ();
gjc@1716
  1585
  bool updated = false;
gjc@1716
  1586
  bool created = false;
gjc@2328
  1587
  NS_LOG_DEBUG ("@" << now.GetSeconds () << ": Olsr node " << m_mainAddress
gjc@2328
  1588
                << ": LinkSensing(receiverIface=" << receiverIface
gjc@2328
  1589
                << ", senderIface=" << senderIface << ") BEGIN");
gjc@1716
  1590
	
gjc@2328
  1591
  NS_ASSERT (msg.GetVTime () > Seconds (0));
gjc@1716
  1592
  LinkTuple *link_tuple = m_state.FindLinkTuple (senderIface);
gjc@1716
  1593
  if (link_tuple == NULL)
gjc@1716
  1594
    {
gjc@1716
  1595
      LinkTuple newLinkTuple;
gjc@1716
  1596
      // We have to create a new tuple
gjc@1716
  1597
      newLinkTuple.neighborIfaceAddr = senderIface;
gjc@1716
  1598
      newLinkTuple.localIfaceAddr = receiverIface;
gjc@1716
  1599
      newLinkTuple.symTime = now - Seconds (1);
gjc@1716
  1600
      newLinkTuple.time = now + msg.GetVTime ();
gjc@2328
  1601
      link_tuple = &m_state.InsertLinkTuple (newLinkTuple);
gjc@1716
  1602
      created = true;
gjc@2328
  1603
      NS_LOG_LOGIC ("Existing link tuple did not exist => creating new one");
gjc@1716
  1604
    }
gjc@1716
  1605
  else
gjc@2328
  1606
    {
gjc@2328
  1607
      NS_LOG_LOGIC ("Existing link tuple already exists => will update it");
gjc@2328
  1608
      updated = true;
gjc@2328
  1609
    }
gjc@1716
  1610
	
gjc@1716
  1611
  link_tuple->asymTime = now + msg.GetVTime ();
gjc@1801
  1612
  for (std::vector<olsr::MessageHeader::Hello::LinkMessage>::const_iterator linkMessage =
gjc@1755
  1613
         hello.linkMessages.begin ();
gjc@1755
  1614
       linkMessage != hello.linkMessages.end ();
gjc@1716
  1615
       linkMessage++)
gjc@1716
  1616
    {
gjc@1716
  1617
      int lt = linkMessage->linkCode & 0x03; // Link Type
gjc@2328
  1618
      int nt = (linkMessage->linkCode >> 2) & 0x03; // Neighbor Type
gjc@2328
  1619
gjc@2328
  1620
#ifdef NS3_LOG_ENABLE
gjc@2328
  1621
      const char *linkTypeName;
gjc@2328
  1622
      switch (lt)
gjc@2328
  1623
        {
gjc@2328
  1624
        case OLSR_UNSPEC_LINK: linkTypeName = "UNSPEC_LINK"; break;
gjc@2328
  1625
        case OLSR_ASYM_LINK: linkTypeName = "ASYM_LINK"; break;
gjc@2328
  1626
        case OLSR_SYM_LINK: linkTypeName = "SYM_LINK"; break;
gjc@2328
  1627
        case OLSR_LOST_LINK: linkTypeName = "LOST_LINK"; break;
gjc@2328
  1628
        default: linkTypeName = "(invalid value!)";
gjc@2328
  1629
        }
gjc@2328
  1630
gjc@2328
  1631
      const char *neighborTypeName;
gjc@2328
  1632
      switch (nt)
gjc@2328
  1633
        {
gjc@2328
  1634
        case OLSR_NOT_NEIGH: neighborTypeName = "NOT_NEIGH"; break;
gjc@2328
  1635
        case OLSR_SYM_NEIGH: neighborTypeName = "SYM_NEIGH"; break;
gjc@2328
  1636
        case OLSR_MPR_NEIGH: neighborTypeName = "MPR_NEIGH"; break;
gjc@2328
  1637
        default: neighborTypeName = "(invalid value!)";
gjc@2328
  1638
        }
gjc@2328
  1639
gjc@2328
  1640
      NS_LOG_DEBUG ("Looking at HELLO link messages with Link Type "
gjc@2328
  1641
                    << lt << " (" << linkTypeName
gjc@2328
  1642
                    << ") and Neighbor Type " << nt
gjc@2328
  1643
                    << " (" << neighborTypeName << ")");
gjc@2328
  1644
#endif
gjc@2328
  1645
gjc@1716
  1646
      // We must not process invalid advertised links
gjc@1716
  1647
      if ((lt == OLSR_SYM_LINK && nt == OLSR_NOT_NEIGH) ||
gjc@1716
  1648
          (nt != OLSR_SYM_NEIGH && nt != OLSR_MPR_NEIGH
gjc@1716
  1649
           && nt != OLSR_NOT_NEIGH))
gjc@1716
  1650
        {
gjc@2328
  1651
          NS_LOG_LOGIC ("HELLO link code is invalid => IGNORING");
gjc@1716
  1652
          continue;
gjc@1716
  1653
        }
gjc@2328
  1654
      
gjc@1716
  1655
      for (std::vector<Ipv4Address>::const_iterator neighIfaceAddr =
gjc@1716
  1656
             linkMessage->neighborInterfaceAddresses.begin ();
gjc@1716
  1657
           neighIfaceAddr != linkMessage->neighborInterfaceAddresses.end ();
gjc@1716
  1658
           neighIfaceAddr++)
gjc@1716
  1659
        {
gjc@2328
  1660
          NS_LOG_DEBUG ("   -> Neighbor: " << *neighIfaceAddr);
gjc@1716
  1661
          if (*neighIfaceAddr == receiverIface)
gjc@1716
  1662
            {
gjc@1716
  1663
              if (lt == OLSR_LOST_LINK)
gjc@1716
  1664
                {
gjc@2328
  1665
                  NS_LOG_LOGIC ("link is LOST => expiring it");
gjc@1716
  1666
                  link_tuple->symTime = now - Seconds (1);
gjc@1716
  1667
                  updated = true;
gjc@1716
  1668
                }
gjc@1716
  1669
              else if (lt == OLSR_SYM_LINK || lt == OLSR_ASYM_LINK)
gjc@1716
  1670
                {
gjc@2328
  1671
                  NS_LOG_DEBUG (*link_tuple << ": link is SYM or ASYM => should become SYM now"
gjc@2328
  1672
                                " (symTime being increased to " << now + msg.GetVTime ());
gjc@1716
  1673
                  link_tuple->symTime = now + msg.GetVTime ();
gjc@1716
  1674
                  link_tuple->time = link_tuple->symTime + OLSR_NEIGHB_HOLD_TIME;
gjc@1716
  1675
                  updated = true;
gjc@1716
  1676
                }
gjc@2328
  1677
              else
gjc@2328
  1678
                {
gjc@2328
  1679
                  NS_FATAL_ERROR ("bad link type");
gjc@2328
  1680
                }
gjc@1716
  1681
              break;
gjc@1716
  1682
            }
gjc@2328
  1683
          else
gjc@2328
  1684
            {
gjc@2328
  1685
              NS_LOG_DEBUG ("     \\-> *neighIfaceAddr (" << *neighIfaceAddr
gjc@2328
  1686
                            << " != receiverIface (" << receiverIface << ") => IGNORING!");
gjc@2328
  1687
            }
gjc@1716
  1688
        }
gjc@2328
  1689
      NS_LOG_DEBUG ("Link tuple updated: " << int (updated));
gjc@1716
  1690
    }
gjc@1716
  1691
  link_tuple->time = std::max(link_tuple->time, link_tuple->asymTime);
gjc@1716
  1692
gjc@1716
  1693
  if (updated)
gjc@2328
  1694
    {
gjc@3970
  1695
      LinkTupleUpdated (*link_tuple, hello.willingness);
gjc@2328
  1696
    }
gjc@1716
  1697
gjc@1716
  1698
  // Schedules link tuple deletion
gjc@1716
  1699
  if (created && link_tuple != NULL)
gjc@1716
  1700
    {
gjc@2328
  1701
      LinkTupleAdded (*link_tuple, hello.willingness);
gjc@1768
  1702
      m_events.Track (Simulator::Schedule (DELAY (std::min (link_tuple->time, link_tuple->symTime)),
gjc@2358
  1703
                                           &AgentImpl::LinkTupleTimerExpire, this,
gjc@2358
  1704
                                           link_tuple->neighborIfaceAddr));
gjc@1716
  1705
    }
gjc@2328
  1706
  NS_LOG_DEBUG ("@" << now.GetSeconds () << ": Olsr node " << m_mainAddress
gjc@2328
  1707
                << ": LinkSensing END");
gjc@1716
  1708
}
gjc@1716
  1709
gjc@1716
  1710
///
gjc@1716
  1711
/// \brief	Updates the Neighbor Set according to the information contained in a new received
gjc@1716
  1712
///		HELLO message (following RFC 3626).
gjc@1716
  1713
void
gjc@1801
  1714
AgentImpl::PopulateNeighborSet (const olsr::MessageHeader &msg,
gjc@2328
  1715
                                const olsr::MessageHeader::Hello &hello)
gjc@1716
  1716
{
gjc@1716
  1717
  NeighborTuple *nb_tuple = m_state.FindNeighborTuple (msg.GetOriginatorAddress ());
gjc@1716
  1718
  if (nb_tuple != NULL)
gjc@3970
  1719
    {
gjc@3970
  1720
      nb_tuple->willingness = hello.willingness;
gjc@3970
  1721
    }
gjc@1716
  1722
}
gjc@1716
  1723
gjc@1716
  1724
gjc@1716
  1725
///
gjc@1716
  1726
/// \brief	Updates the 2-hop Neighbor Set according to the information contained in a new
gjc@1716
  1727
///		received HELLO message (following RFC 3626).
gjc@1716
  1728
void
gjc@1801
  1729
AgentImpl::PopulateTwoHopNeighborSet (const olsr::MessageHeader &msg,
gjc@2328
  1730
                                      const olsr::MessageHeader::Hello &hello)
gjc@1716
  1731
{
gjc@1716
  1732
  Time now = Simulator::Now ();
gjc@2328
  1733
gjc@2328
  1734
  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": PopulateTwoHopNeighborSet BEGIN");
gjc@1716
  1735
	
gjc@1716
  1736
  for (LinkSet::const_iterator link_tuple = m_state.GetLinks ().begin ();
gjc@1716
  1737
       link_tuple != m_state.GetLinks ().end (); link_tuple++)
gjc@1716
  1738
    {
gjc@2328
  1739
      NS_LOG_LOGIC ("Looking at link tuple: " << *link_tuple);
gjc@2328
  1740
      if (GetMainAddress (link_tuple->neighborIfaceAddr) != msg.GetOriginatorAddress ())
gjc@1716
  1741
        {
gjc@2328
  1742
          NS_LOG_LOGIC ("Link tuple ignored: "
gjc@2328
  1743
                        "GetMainAddress (link_tuple->neighborIfaceAddr) != msg.GetOriginatorAddress ()");
gjc@2328
  1744
          NS_LOG_LOGIC ("(GetMainAddress(" << link_tuple->neighborIfaceAddr << "): "
gjc@2328
  1745
                        << GetMainAddress (link_tuple->neighborIfaceAddr)
gjc@2328
  1746
                        << "; msg.GetOriginatorAddress (): " << msg.GetOriginatorAddress ());
gjc@2328
  1747
          continue;
gjc@2328
  1748
        }
gjc@2328
  1749
gjc@2328
  1750
      if (link_tuple->symTime < now)
gjc@2328
  1751
        {
gjc@2328
  1752
          NS_LOG_LOGIC ("Link tuple ignored: expired.");
gjc@2328
  1753
          continue;
gjc@2328
  1754
        }
gjc@2328
  1755
gjc@2328
  1756
      typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
gjc@2328
  1757
      for (LinkMessageVec::const_iterator linkMessage = hello.linkMessages.begin ();
gjc@2328
  1758
           linkMessage != hello.linkMessages.end (); linkMessage++)
gjc@2328
  1759
        {
gjc@2328
  1760
          int neighborType = (linkMessage->linkCode >> 2) & 0x3;
gjc@2328
  1761
#ifdef NS3_LOG_ENABLE
gjc@2328
  1762
          const char *neighborTypeNames[3] = { "NOT_NEIGH", "SYM_NEIGH", "MPR_NEIGH" };
gjc@2328
  1763
          const char *neighborTypeName = ((neighborType < 3)?
gjc@2328
  1764
                                          neighborTypeNames[neighborType]
gjc@2328
  1765
                                          : "(invalid value)");
gjc@2328
  1766
          NS_LOG_DEBUG ("Looking at Link Message from HELLO message: neighborType="
gjc@2328
  1767
                        << neighborType << " (" << neighborTypeName << ")");
gjc@2328
  1768
#endif
gjc@2328
  1769
gjc@2328
  1770
          for (std::vector<Ipv4Address>::const_iterator nb2hop_addr_iter =
gjc@2328
  1771
                 linkMessage->neighborInterfaceAddresses.begin ();
gjc@2328
  1772
               nb2hop_addr_iter != linkMessage->neighborInterfaceAddresses.end ();
gjc@2328
  1773
               nb2hop_addr_iter++)
gjc@1716
  1774
            {
gjc@2328
  1775
              Ipv4Address nb2hop_addr = GetMainAddress (*nb2hop_addr_iter);
gjc@2328
  1776
              NS_LOG_DEBUG ("Looking at 2-hop neighbor address from HELLO message: "
gjc@2328
  1777
                            << *nb2hop_addr_iter
gjc@2328
  1778
                            << " (main address is " << nb2hop_addr << ")");
gjc@2328
  1779
              if (neighborType == OLSR_SYM_NEIGH || neighborType == OLSR_MPR_NEIGH)
gjc@1716
  1780
                {
gjc@2328
  1781
                  // If the main address of the 2-hop neighbor address == main address
gjc@2328
  1782
                  // of the receiving node, silently discard the 2-hop
gjc@2328
  1783
                  // neighbor address.
gjc@2328
  1784
                  if (nb2hop_addr == m_routingAgentAddr)
gjc@2328
  1785
                    {
gjc@2328
  1786
                      NS_LOG_LOGIC ("Ignoring 2-hop neighbor (it is the node itself)");
gjc@2328
  1787
                      continue;
gjc@2328
  1788
                    }
gjc@1716
  1789
gjc@2328
  1790
                  // Otherwise, a 2-hop tuple is created
gjc@2328
  1791
                  TwoHopNeighborTuple *nb2hop_tuple =
gjc@2328
  1792
                    m_state.FindTwoHopNeighborTuple (msg.GetOriginatorAddress (), nb2hop_addr);
gjc@2328
  1793
                  NS_LOG_LOGIC ("Adding the 2-hop neighbor"
gjc@2328
  1794
                                << (nb2hop_tuple? " (refreshing existing entry)" : ""));
gjc@2328
  1795
                  if (nb2hop_tuple == NULL)
gjc@1716
  1796
                    {
gjc@2328
  1797
                      TwoHopNeighborTuple new_nb2hop_tuple;
gjc@2328
  1798
                      new_nb2hop_tuple.neighborMainAddr = msg.GetOriginatorAddress ();
gjc@2328
  1799
                      new_nb2hop_tuple.twoHopNeighborAddr = nb2hop_addr;
gjc@2328
  1800
                      new_nb2hop_tuple.expirationTime = now + msg.GetVTime ();
gjc@2328
  1801
                      AddTwoHopNeighborTuple (new_nb2hop_tuple);
gjc@2328
  1802
                      // Schedules nb2hop tuple deletion
gjc@2328
  1803
                      m_events.Track (Simulator::Schedule (DELAY (new_nb2hop_tuple.expirationTime),
gjc@2328
  1804
                                                           &AgentImpl::Nb2hopTupleTimerExpire, this,
gjc@2358
  1805
                                                           new_nb2hop_tuple.neighborMainAddr,
gjc@2358
  1806
                                                           new_nb2hop_tuple.twoHopNeighborAddr));
gjc@1716
  1807
                    }
gjc@2328
  1808
                  else
gjc@2328
  1809
                    {
gjc@2328
  1810
                      nb2hop_tuple->expirationTime = now + msg.GetVTime ();
gjc@2328
  1811
                    }
gjc@2328
  1812
                }
gjc@2328
  1813
              else if (neighborType == OLSR_NOT_NEIGH)
gjc@2328
  1814
                {
gjc@2328
  1815
                  // For each 2-hop node listed in the HELLO message
gjc@2328
  1816
                  // with Neighbor Type equal to NOT_NEIGH all 2-hop
gjc@2328
  1817
                  // tuples where: N_neighbor_main_addr == Originator
gjc@2328
  1818
                  // Address AND N_2hop_addr == main address of the
gjc@2328
  1819
                  // 2-hop neighbor are deleted.
gjc@2328
  1820
                  NS_LOG_LOGIC ("2-hop neighbor is NOT_NEIGH => deleting matching 2-hop neighbor state");
gjc@2328
  1821
                  m_state.EraseTwoHopNeighborTuples (msg.GetOriginatorAddress (), nb2hop_addr);
gjc@2328
  1822
                }
gjc@2328
  1823
              else
gjc@2328
  1824
                {
gjc@2328
  1825
                  NS_LOG_LOGIC ("*** WARNING *** Ignoring link message (inside HELLO) with bad"
gjc@2328
  1826
                                " neighbor type value: " << neighborType);
gjc@1716
  1827
                }
gjc@1716
  1828
            }
gjc@1716
  1829
        }
gjc@1716
  1830
    }
gjc@2328
  1831
gjc@2328
  1832
  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": PopulateTwoHopNeighborSet END");
gjc@1716
  1833
}
gjc@1716
  1834
gjc@1716
  1835
gjc@1716
  1836
gjc@1716
  1837
///
gjc@1716
  1838
/// \brief	Updates the MPR Selector Set according to the information contained in a new
gjc@1716
  1839
///		received HELLO message (following RFC 3626).
gjc@1716
  1840
void
gjc@1801
  1841
AgentImpl::PopulateMprSelectorSet (const olsr::MessageHeader &msg,
gjc@1801
  1842
                                       const olsr::MessageHeader::Hello &hello)
gjc@1716
  1843
{
gjc@3970
  1844
  NS_LOG_FUNCTION (this);
gjc@3970
  1845
  
gjc@1716
  1846
  Time now = Simulator::Now ();
gjc@1716
  1847
	
gjc@1801
  1848
  typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
gjc@1755
  1849
  for (LinkMessageVec::const_iterator linkMessage = hello.linkMessages.begin ();
gjc@1755
  1850
       linkMessage != hello.linkMessages.end ();
gjc@1716
  1851
       linkMessage++)
gjc@1716
  1852
    {
gjc@1716
  1853
      int nt = linkMessage->linkCode >> 2;
gjc@1716
  1854
      if (nt == OLSR_MPR_NEIGH)
gjc@1716
  1855
        {
gjc@3970
  1856
          NS_LOG_DEBUG ("Processing a link message with neighbor type MPR_NEIGH");
gjc@3970
  1857
          
gjc@1716
  1858
          for (std::vector<Ipv4Address>::const_iterator nb_iface_addr =
gjc@1716
  1859
                 linkMessage->neighborInterfaceAddresses.begin ();
gjc@1716
  1860
               nb_iface_addr != linkMessage->neighborInterfaceAddresses.end ();
gjc@1716
  1861
               nb_iface_addr++)
gjc@1716
  1862
            {
gjc@2328
  1863
              if (GetMainAddress (*nb_iface_addr) == m_mainAddress)
gjc@1716
  1864
                {
gjc@3970
  1865
                  NS_LOG_DEBUG ("Adding entry to mpr selector set for neighbor " << *nb_iface_addr);
gjc@3970
  1866
                  
gjc@1716
  1867
                  // We must create a new entry into the mpr selector set
gjc@1716
  1868
                  MprSelectorTuple *existing_mprsel_tuple =
gjc@1716
  1869
                    m_state.FindMprSelectorTuple (msg.GetOriginatorAddress ());
gjc@1716
  1870
                  if (existing_mprsel_tuple == NULL)
gjc@1716
  1871
                    {
gjc@1716
  1872
                      MprSelectorTuple mprsel_tuple;
gjc@1716
  1873
gjc@1716
  1874
                      mprsel_tuple.mainAddr = msg.GetOriginatorAddress ();
gjc@1716
  1875
                      mprsel_tuple.expirationTime = now + msg.GetVTime ();
gjc@1716
  1876
                      AddMprSelectorTuple (mprsel_tuple);
gjc@1716
  1877
gjc@1716
  1878
                      // Schedules mpr selector tuple deletion
gjc@1768
  1879
                      m_events.Track (Simulator::Schedule
gjc@1768
  1880
                                      (DELAY (mprsel_tuple.expirationTime),
gjc@1801
  1881
                                       &AgentImpl::MprSelTupleTimerExpire, this,
gjc@2358
  1882
                                       mprsel_tuple.mainAddr));
gjc@1716
  1883
                    }
gjc@1716
  1884
                  else
gjc@1716
  1885
                    {
gjc@1716
  1886
                      existing_mprsel_tuple->expirationTime = now + msg.GetVTime ();
gjc@1716
  1887
                    }
gjc@1716
  1888
                }
gjc@1716
  1889
            }
gjc@1716
  1890
        }
gjc@1716
  1891
    }
gjc@3970
  1892
  NS_LOG_DEBUG ("Computed MPR selector set for node " << m_mainAddress << ": " << m_state.PrintMprSelectorSet ());
gjc@1716
  1893
}
gjc@1716
  1894
gjc@1716
  1895
gjc@1716
  1896
#if 0
gjc@1716
  1897
///
gjc@1716
  1898
/// \brief	Drops a given packet because it couldn't be delivered to the corresponding
gjc@1716
  1899
///		destination by the MAC layer. This may cause a neighbor loss, and appropiate
gjc@1716
  1900
///		actions are then taken.
gjc@1716
  1901
///
gjc@1716
  1902
/// \param p the packet which couldn't be delivered by the MAC layer.
gjc@1716
  1903
///
gjc@1716
  1904
void
craigdo@1868
  1905
OLSR::mac_failed(Ptr<Packet> p) {
gjc@1716
  1906
	double now		= Simulator::Now ();
gjc@1716
  1907
	struct hdr_ip* ih	= HDR_IP(p);
gjc@1716
  1908
	struct hdr_cmn* ch	= HDR_CMN(p);
gjc@1716
  1909
	
gjc@1716
  1910
	debug("%f: Node %d MAC Layer detects a breakage on link to %d\n",
gjc@1716
  1911
		now,
gjc@1716
  1912
		OLSR::node_id(ra_addr()),
gjc@1716
  1913
		OLSR::node_id(ch->next_hop()));
gjc@1716
  1914
	
gjc@1716
  1915
	if ((u_int32_t)ih->daddr() == IP_BROADCAST) {
gjc@1716
  1916
		drop(p, DROP_RTR_MAC_CALLBACK);
gjc@1716
  1917
		return;
gjc@1716
  1918
	}
gjc@1716
  1919
	
gjc@1716
  1920
	OLSR_link_tuple* link_tuple = state_.find_link_tuple(ch->next_hop());
gjc@1716
  1921
	if (link_tuple != NULL) {
gjc@1716
  1922
		link_tuple->lost_time()	= now + OLSR_NEIGHB_HOLD_TIME;
gjc@1716
  1923
		link_tuple->time()	= now + OLSR_NEIGHB_HOLD_TIME;
gjc@1716
  1924
		nb_loss(link_tuple);
gjc@1716
  1925
	}
gjc@1716
  1926
	drop(p, DROP_RTR_MAC_CALLBACK);
gjc@1716
  1927
}
gjc@1716
  1928
#endif
gjc@1716
  1929
gjc@1716
  1930
gjc@1716
  1931
gjc@1716
  1932
gjc@1716
  1933
///
gjc@1716
  1934
/// \brief Performs all actions needed when a neighbor loss occurs.
gjc@1716
  1935
///
gjc@1716
  1936
/// Neighbor Set, 2-hop Neighbor Set, MPR Set and MPR Selector Set are updated.
gjc@1716
  1937
///
gjc@1716
  1938
/// \param tuple link tuple with the information of the link to the neighbor which has been lost.
gjc@1716
  1939
///
gjc@1716
  1940
void
gjc@1801
  1941
AgentImpl::NeighborLoss (const LinkTuple &tuple)
gjc@1716
  1942
{
gjc@2328
  1943
  NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
  1944
                << "s: OLSR Node " << m_mainAddress
gjc@2328
  1945
                << " LinkTuple " << tuple.neighborIfaceAddr << " -> neighbor loss.");
gjc@3970
  1946
  LinkTupleUpdated (tuple, OLSR_WILL_DEFAULT);
gjc@1716
  1947
  m_state.EraseTwoHopNeighborTuples (GetMainAddress (tuple.neighborIfaceAddr));
gjc@1716
  1948
  m_state.EraseMprSelectorTuples (GetMainAddress (tuple.neighborIfaceAddr));
gjc@1716
  1949
  
gjc@2328
  1950
  MprComputation ();
gjc@2328
  1951
  RoutingTableComputation ();
gjc@1716
  1952
}
gjc@1716
  1953
gjc@1716
  1954
///
gjc@1716
  1955
/// \brief Adds a duplicate tuple to the Duplicate Set.
gjc@1716
  1956
///
gjc@1716
  1957
/// \param tuple the duplicate tuple to be added.
gjc@1716
  1958
///
gjc@1716
  1959
void
gjc@1801
  1960
AgentImpl::AddDuplicateTuple (const DuplicateTuple &tuple)
gjc@1716
  1961
{
gjc@1716
  1962
	/*debug("%f: Node %d adds dup tuple: addr = %d seq_num = %d\n",
gjc@1716
  1963
		Simulator::Now (),
gjc@1716
  1964
		OLSR::node_id(ra_addr()),
gjc@1716
  1965
		OLSR::node_id(tuple->addr()),
gjc@1716
  1966
		tuple->seq_num());*/
gjc@1716
  1967
  m_state.InsertDuplicateTuple (tuple);
gjc@1716
  1968
}
gjc@1716
  1969
gjc@1716
  1970
///
gjc@1716
  1971
/// \brief Removes a duplicate tuple from the Duplicate Set.
gjc@1716
  1972
///
gjc@1716
  1973
/// \param tuple the duplicate tuple to be removed.
gjc@1716
  1974
///
gjc@1716
  1975
void
gjc@1801
  1976
AgentImpl::RemoveDuplicateTuple (const DuplicateTuple &tuple)
gjc@1716
  1977
{
gjc@1716
  1978
  /*debug("%f: Node %d removes dup tuple: addr = %d seq_num = %d\n",
gjc@1716
  1979
    Simulator::Now (),
gjc@1716
  1980
    OLSR::node_id(ra_addr()),
gjc@1716
  1981
    OLSR::node_id(tuple->addr()),
gjc@1716
  1982
    tuple->seq_num());*/
gjc@1716
  1983
  m_state.EraseDuplicateTuple (tuple);
gjc@1716
  1984
}
gjc@1716
  1985
gjc@2328
  1986
void
gjc@2328
  1987
AgentImpl::LinkTupleAdded (const LinkTuple &tuple, uint8_t willingness)
gjc@1716
  1988
{
gjc@1716
  1989
  // Creates associated neighbor tuple
gjc@1716
  1990
  NeighborTuple nb_tuple;
gjc@1716
  1991
  nb_tuple.neighborMainAddr = GetMainAddress (tuple.neighborIfaceAddr);
gjc@1716
  1992
  nb_tuple.willingness = willingness;
gjc@1716
  1993
gjc@1716
  1994
  if (tuple.symTime >= Simulator::Now ())
gjc@2328
  1995
    {
gjc@2328
  1996
      nb_tuple.status = NeighborTuple::STATUS_SYM;
gjc@2328
  1997
    }
gjc@1716
  1998
  else
gjc@2328
  1999
    {
gjc@2328
  2000
      nb_tuple.status = NeighborTuple::STATUS_NOT_SYM;
gjc@2328
  2001
    }
gjc@1716
  2002
gjc@1716
  2003
  AddNeighborTuple (nb_tuple);
gjc@1716
  2004
}
gjc@1716
  2005
gjc@1716
  2006
///
gjc@1716
  2007
/// \brief Removes a link tuple from the Link Set.
gjc@1716
  2008
///
gjc@1716
  2009
/// \param tuple the link tuple to be removed.
gjc@1716
  2010
///
gjc@1716
  2011
void
gjc@1801
  2012
AgentImpl::RemoveLinkTuple (const LinkTuple &tuple)
gjc@1716
  2013
{
gjc@2328
  2014
  NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
  2015
                << "s: OLSR Node " << m_mainAddress
gjc@2328
  2016
                << " LinkTuple " << tuple << " REMOVED.");
gjc@1716
  2017
gjc@1716
  2018
  m_state.EraseLinkTuple (tuple);
gjc@1716
  2019
  m_state.EraseNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
gjc@2328
  2020
gjc@1716
  2021
}
gjc@1716
  2022
gjc@1716
  2023
///
gjc@1716
  2024
/// \brief	This function is invoked when a link tuple is updated. Its aim is to
gjc@1716
  2025
///		also update the corresponding neighbor tuple if it is needed.
gjc@1716
  2026
///
gjc@1716
  2027
/// \param tuple the link tuple which has been updated.
gjc@1716
  2028
///
gjc@1716
  2029
void
gjc@3970
  2030
AgentImpl::LinkTupleUpdated (const LinkTuple &tuple, uint8_t willingness)
gjc@1716
  2031
{
gjc@1716
  2032
  // Each time a link tuple changes, the associated neighbor tuple must be recomputed
gjc@2328
  2033
gjc@2328
  2034
  NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
gjc@2328
  2035
                << "s: OLSR Node " << m_mainAddress
gjc@2328
  2036
                << " LinkTuple " << tuple << " UPDATED.");
gjc@2328
  2037
gjc@1716
  2038
  NeighborTuple *nb_tuple =
gjc@1716
  2039
    m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
gjc@3970
  2040
  
gjc@3970
  2041
  if (nb_tuple == NULL)
gjc@3970
  2042
    {
gjc@3970
  2043
      LinkTupleAdded (tuple, willingness);
gjc@3970
  2044
      nb_tuple = m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
gjc@3970
  2045
    }
gjc@2328
  2046
gjc@1716
  2047
  if (nb_tuple != NULL)
gjc@1716
  2048
    {
gjc@2328
  2049
#ifdef NS3_LOG_ENABLE
gjc@2328
  2050
      int statusBefore = nb_tuple->status;
gjc@2328
  2051
#endif
gjc@2328
  2052
      if (tuple.symTime >= Simulator::Now ())
gjc@1716
  2053
        {
gjc@1716
  2054
          nb_tuple->status = NeighborTuple::STATUS_SYM;
gjc@2328
  2055
          NS_LOG_DEBUG (*nb_tuple << "->status = STATUS_SYM; changed:"
gjc@2328
  2056
                        << int (statusBefore != nb_tuple->status));
gjc@1716
  2057
        }
gjc@1716
  2058
      else
gjc@1716
  2059
        {
gjc@1716
  2060
          nb_tuple->status = NeighborTuple::STATUS_NOT_SYM;
gjc@2328
  2061
          NS_LOG_DEBUG (*nb_tuple << "->status = STATUS_NOT_SYM; changed:"
gjc@2328
  2062
                        << int (statusBefore != nb_tuple->status));
gjc@1716
  2063
        }
gjc@1716
  2064
    }
gjc@3970
  2065
  else
gjc@3970
  2066
    {
gjc@3970
  2067
      NS_LOG_WARN ("ERROR! Wanted to update a NeighborTuple but none was found!");
gjc@3970
  2068
    }
gjc@1716
  2069
}
gjc@1716
  2070
gjc@1716
  2071
///
gjc@1716
  2072
/// \brief Adds a neighbor tuple to the Neighbor Set.
gjc@1716
  2073
///
gjc@1716
  2074
/// \param tuple the neighbor tuple to be added.
gjc@1716
  2075
///
gjc@1716
  2076
void
gjc@1801
  2077
AgentImpl::AddNeighborTuple (const NeighborTuple &tuple)
gjc@1716
  2078
{
gjc@1716
  2079
//   debug("%f: Node %d adds neighbor tuple: nb_addr = %d status = %s\n",
gjc@1716
  2080
//         Simulator::Now (),
gjc@1716
  2081
//         OLSR::node_id(ra_addr()),
gjc@1716
  2082
//         OLSR::node_id(tuple->neighborMainAddr),
gjc@1716
  2083
//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
gjc@1716
  2084
  
gjc@1716
  2085
  m_state.InsertNeighborTuple (tuple);
gjc@2328
  2086
  IncrementAnsn ();
gjc@1716
  2087
}
gjc@1716
  2088
gjc@1716
  2089
///
gjc@1716
  2090
/// \brief Removes a neighbor tuple from the Neighbor Set.
gjc@1716
  2091
///
gjc@1716
  2092
/// \param tuple the neighbor tuple to be removed.
gjc@1716
  2093
///
gjc@1716
  2094
void
gjc@1801
  2095
AgentImpl::RemoveNeighborTuple (const NeighborTuple &tuple)
gjc@1716
  2096
{
gjc@1716
  2097
//   debug("%f: Node %d removes neighbor tuple: nb_addr = %d status = %s\n",
gjc@1716
  2098
//         Simulator::Now (),
gjc@1716
  2099
//         OLSR::node_id(ra_addr()),
gjc@1716
  2100
//         OLSR::node_id(tuple->neighborMainAddr),
gjc@1716
  2101
//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
gjc@1716
  2102
	
gjc@1716
  2103
  m_state.EraseNeighborTuple (tuple);
gjc@2328
  2104
  IncrementAnsn ();
gjc@1716
  2105
}
gjc@1716
  2106
gjc@1716
  2107
///
gjc@1716
  2108
/// \brief Adds a 2-hop neighbor tuple to the 2-hop Neighbor Set.
gjc@1716
  2109
///
gjc@1716
  2110
/// \param tuple the 2-hop neighbor tuple to be added.
gjc@1716
  2111
///
gjc@1716
  2112
void
gjc@1801
  2113
AgentImpl::AddTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
gjc@1716
  2114
{
gjc@1716
  2115
//   debug("%f: Node %d adds 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
gjc@1716
  2116
//         Simulator::Now (),
gjc@1716
  2117
//         OLSR::node_id(ra_addr()),
gjc@1716
  2118
//         OLSR::node_id(tuple->neighborMainAddr),
gjc@1716
  2119
//         OLSR::node_id(tuple->twoHopNeighborAddr));
gjc@1716
  2120
  
gjc@1716
  2121
  m_state.InsertTwoHopNeighborTuple (tuple);
gjc@1716
  2122
}
gjc@1716
  2123
gjc@1716
  2124
///
gjc@1716
  2125
/// \brief Removes a 2-hop neighbor tuple from the 2-hop Neighbor Set.
gjc@1716
  2126
///
gjc@1716
  2127
/// \param tuple the 2-hop neighbor tuple to be removed.
gjc@1716
  2128
///
gjc@1716
  2129
void
gjc@1801
  2130
AgentImpl::RemoveTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
gjc@1716
  2131
{
gjc@1716
  2132
//   debug("%f: Node %d removes 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
gjc@1716
  2133
//         Simulator::Now (),
gjc@1716
  2134
//         OLSR::node_id(ra_addr()),
gjc@1716
  2135
//         OLSR::node_id(tuple->neighborMainAddr),
gjc@1716
  2136
//         OLSR::node_id(tuple->twoHopNeighborAddr));
gjc@1716
  2137
gjc@1716
  2138
  m_state.EraseTwoHopNeighborTuple (tuple);
gjc@1716
  2139
}
gjc@1716
  2140
gjc@2328
  2141
void
gjc@2328
  2142
AgentImpl::IncrementAnsn ()
gjc@2328
  2143
{
gjc@2328
  2144
  m_ansn = (m_ansn + 1) % (OLSR_MAX_SEQ_NUM + 1);
gjc@2328
  2145
}
gjc@2328
  2146
gjc@1716
  2147
///
gjc@1716
  2148
/// \brief Adds an MPR selector tuple to the MPR Selector Set.
gjc@1716
  2149
///
gjc@1716
  2150
/// Advertised Neighbor Sequence Number (ANSN) is also updated.
gjc@1716
  2151
///
gjc@1716
  2152
/// \param tuple the MPR selector tuple to be added.
gjc@1716
  2153
///
gjc@1716
  2154
void
gjc@1801
  2155
AgentImpl::AddMprSelectorTuple (const MprSelectorTuple  &tuple)
gjc@1716
  2156
{
gjc@1716
  2157
//   debug("%f: Node %d adds MPR selector tuple: nb_addr = %d\n",
gjc@1716
  2158
//         Simulator::Now (),
gjc@1716
  2159
//         OLSR::node_id(ra_addr()),
gjc@1716
  2160
//         OLSR::node_id(tuple->main_addr()));
gjc@1716
  2161
  
gjc@1716
  2162
  m_state.InsertMprSelectorTuple (tuple);
gjc@2328
  2163
  IncrementAnsn ();
gjc@1716
  2164
}
gjc@1716
  2165
gjc@1716
  2166
///
gjc@1716
  2167
/// \brief Removes an MPR selector tuple from the MPR Selector Set.
gjc@1716
  2168
///
gjc@1716
  2169
/// Advertised Neighbor Sequence Number (ANSN) is also updated.
gjc@1716
  2170
///
gjc@1716
  2171
/// \param tuple the MPR selector tuple to be removed.
gjc@1716
  2172
///
gjc@1716
  2173
void
gjc@1801
  2174
AgentImpl::RemoveMprSelectorTuple (const MprSelectorTuple &tuple)
gjc@1716
  2175
{
gjc@1716
  2176
//   debug("%f: Node %d removes MPR selector tuple: nb_addr = %d\n",
gjc@1716
  2177
//         Simulator::Now (),
gjc@1716
  2178
//         OLSR::node_id(ra_addr()),
gjc@1716
  2179
//         OLSR::node_id(tuple->main_addr()));
gjc@1716
  2180
  
gjc@1716
  2181
  m_state.EraseMprSelectorTuple (tuple);
gjc@2328
  2182
  IncrementAnsn ();
gjc@1716
  2183
}
gjc@1716
  2184
gjc@1716
  2185
///
gjc@1716
  2186
/// \brief Adds a topology tuple to the Topology Set.
gjc@1716
  2187
///
gjc@1716
  2188
/// \param tuple the topology tuple to be added.
gjc@1716
  2189
///
gjc@1716
  2190
void
gjc@1801
  2191
AgentImpl::AddTopologyTuple (const TopologyTuple &tuple)
gjc@1716
  2192
{
gjc@1716
  2193
//   debug("%f: Node %d adds topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
gjc@1716
  2194
//         Simulator::Now (),
gjc@1716
  2195
//         OLSR::node_id(ra_addr()),
gjc@1716
  2196
//         OLSR::node_id(tuple->dest_addr()),
gjc@1716
  2197
//         OLSR::node_id(tuple->last_addr()),
gjc@1716
  2198
//         tuple->seq());
gjc@1716
  2199
gjc@1716
  2200
  m_state.InsertTopologyTuple(tuple);
gjc@1716
  2201
}
gjc@1716
  2202
gjc@1716
  2203
///
gjc@1716
  2204
/// \brief Removes a topology tuple from the Topology Set.
gjc@1716
  2205
///
gjc@1716
  2206
/// \param tuple the topology tuple to be removed.
gjc@1716
  2207
///
gjc@1716
  2208
void
gjc@1801
  2209
AgentImpl::RemoveTopologyTuple (const TopologyTuple &tuple)
gjc@1716
  2210
{
gjc@1716
  2211
//   debug("%f: Node %d removes topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
gjc@1716
  2212
//         Simulator::Now (),
gjc@1716
  2213
//         OLSR::node_id(ra_addr()),
gjc@1716
  2214
//         OLSR::node_id(tuple->dest_addr()),
gjc@1716
  2215
//         OLSR::node_id(tuple->last_addr()),
gjc@1716
  2216
//         tuple->seq());
gjc@1716
  2217
gjc@1716
  2218
  m_state.EraseTopologyTuple (tuple);
gjc@1716
  2219
}
gjc@1716
  2220
gjc@1716
  2221
///
gjc@1716
  2222
/// \brief Adds an interface association tuple to the Interface Association Set.
gjc@1716
  2223
///
gjc@1716
  2224
/// \param tuple the interface association tuple to be added.
gjc@1716
  2225
///
gjc@1716
  2226
void
gjc@1801
  2227
AgentImpl::AddIfaceAssocTuple (const IfaceAssocTuple &tuple)
gjc@1716
  2228
{
gjc@1716
  2229
//   debug("%f: Node %d adds iface association tuple: main_addr = %d iface_addr = %d\n",
gjc@1716
  2230
//         Simulator::Now (),
gjc@1716
  2231
//         OLSR::node_id(ra_addr()),
gjc@1716
  2232
//         OLSR::node_id(tuple->main_addr()),
gjc@1716
  2233
//         OLSR::node_id(tuple->iface_addr()));
gjc@1716
  2234
gjc@1716
  2235
  m_state.InsertIfaceAssocTuple (tuple);
gjc@1716
  2236
}
gjc@1716
  2237
gjc@1716
  2238
///
gjc@1716
  2239
/// \brief Removes an interface association tuple from the Interface Association Set.
gjc@1716
  2240
///
gjc@1716
  2241
/// \param tuple the interface association tuple to be removed.
gjc@1716
  2242
///
gjc@1716
  2243
void
gjc@1801
  2244
AgentImpl::RemoveIfaceAssocTuple (const IfaceAssocTuple &tuple)
gjc@1716
  2245
{
gjc@1716
  2246
//   debug("%f: Node %d removes iface association tuple: main_addr = %d iface_addr = %d\n",
gjc@1716
  2247
//         Simulator::Now (),
gjc@1716
  2248
//         OLSR::node_id(ra_addr()),
gjc@1716
  2249
//         OLSR::node_id(tuple->main_addr()),
gjc@1716
  2250
//         OLSR::node_id(tuple->iface_addr()));
gjc@1716
  2251
gjc@1716
  2252
  m_state.EraseIfaceAssocTuple (tuple);
gjc@1716
  2253
}
gjc@1716
  2254
gjc@1716
  2255
gjc@1801
  2256
uint16_t AgentImpl::GetPacketSequenceNumber ()
gjc@1716
  2257
{
gjc@1716
  2258
  m_packetSequenceNumber = (m_packetSequenceNumber + 1) % (OLSR_MAX_SEQ_NUM + 1);
gjc@1716
  2259
  return m_packetSequenceNumber;
gjc@1716
  2260
}
gjc@1716
  2261
gjc@1716
  2262
/// Increments message sequence number and returns the new value.
gjc@1801
  2263
uint16_t AgentImpl::GetMessageSequenceNumber ()
gjc@1716
  2264
{
gjc@1716
  2265
  m_messageSequenceNumber = (m_messageSequenceNumber + 1) % (OLSR_MAX_SEQ_NUM + 1);
gjc@1716
  2266
  return m_messageSequenceNumber;
gjc@1716
  2267
}
gjc@1716
  2268
gjc@1716
  2269
gjc@1716
  2270
///
gjc@1716
  2271
/// \brief Sends a HELLO message and reschedules the HELLO timer.
gjc@1716
  2272
/// \param e The event which has expired.
gjc@1716
  2273
///
gjc@1716
  2274
void
gjc@1801
  2275
AgentImpl::HelloTimerExpire ()
gjc@1716
  2276
{
gjc@1716
  2277
  SendHello ();
gjc@1765
  2278
  m_helloTimer.Schedule (m_helloInterval);
gjc@1716
  2279
}
gjc@1716
  2280
gjc@1716
  2281
///
gjc@1716
  2282
/// \brief Sends a TC message (if there exists any MPR selector) and reschedules the TC timer.
gjc@1716
  2283
/// \param e The event which has expired.
gjc@1716
  2284
///
gjc@1716
  2285
void
gjc@1801
  2286
AgentImpl::TcTimerExpire ()
gjc@1716
  2287
{
gjc@1716
  2288
  if (m_state.GetMprSelectors ().size () > 0)
gjc@1765
  2289
    {
gjc@1765
  2290
      SendTc ();
gjc@1765
  2291
    }
gjc@3970
  2292
  else
gjc@3970
  2293
    {
gjc@3970
  2294
      NS_LOG_DEBUG ("Not sending any TC, no one selected me as MPR.");
gjc@3970
  2295
    }
gjc@1765
  2296
  m_tcTimer.Schedule (m_tcInterval);
gjc@1716
  2297
}
gjc@1716
  2298
gjc@1716
  2299
///
gjc@1716
  2300
/// \brief Sends a MID message (if the node has more than one interface) and resets the MID timer.
gjc@1716
  2301
/// \warning Currently it does nothing because there is no support for multiple interfaces.
gjc@1716
  2302
/// \param e The event which has expired.
gjc@1716
  2303
///
gjc@1716
  2304
void
gjc@1801
  2305
AgentImpl::MidTimerExpire ()
gjc@1716
  2306
{
gjc@1716
  2307
  SendMid ();
gjc@1765
  2308
  m_midTimer.Schedule (m_midInterval);
gjc@1716
  2309
}
gjc@1716
  2310
gjc@1716
  2311
///
gjc@1765
  2312
/// \brief Removes tuple if expired. Else timer is rescheduled to expire at tuple.expirationTime.
gjc@1716
  2313
///
gjc@1716
  2314
/// The task of actually removing the tuple is left to the OLSR agent.
gjc@1716
  2315
///
gjc@1765
  2316
/// \param tuple The tuple which has expired.
gjc@1716
  2317
///
gjc@1716
  2318
void
gjc@2358
  2319
AgentImpl::DupTupleTimerExpire (Ipv4Address address, uint16_t sequenceNumber)
gjc@1716
  2320
{
gjc@2329
  2321
  DuplicateTuple *tuple =
gjc@2358
  2322
    m_state.FindDuplicateTuple (address, sequenceNumber);
gjc@2329
  2323
  if (tuple == NULL)
gjc@1716
  2324
    {
gjc@2329
  2325
      return;
gjc@2329
  2326
    }
gjc@2329
  2327
  if (tuple->expirationTime < Simulator::Now ())
gjc@2329
  2328
    {
gjc@2329
  2329
      RemoveDuplicateTuple (*tuple);
gjc@1716
  2330
    }
gjc@1716
  2331
  else
gjc@1765
  2332
    {
gjc@2329
  2333
      m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
gjc@1801
  2334
                                           &AgentImpl::DupTupleTimerExpire, this,
gjc@2358
  2335
                                           address, sequenceNumber));
gjc@1765
  2336
    }
gjc@1716
  2337
}
gjc@1716
  2338
gjc@1716
  2339
///
gjc@1716
  2340
/// \brief Removes tuple_ if expired. Else if symmetric time
gjc@1716
  2341
/// has expired then it is assumed a neighbor loss and agent_->nb_loss()
gjc@1716
  2342
/// is called. In this case the timer is rescheduled to expire at
gjc@1716
  2343
/// tuple_->time(). Otherwise the timer is rescheduled to expire at
gjc@1716
  2344
/// the minimum between tuple_->time() and tuple_->sym_time().
gjc@1716
  2345
///
gjc@1716
  2346
/// The task of actually removing the tuple is left to the OLSR agent.
gjc@1716
  2347
///
gjc@1716
  2348
/// \param e The event which has expired.
gjc@1716
  2349
///
gjc@1716
  2350
void
gjc@2358
  2351
AgentImpl::LinkTupleTimerExpire (Ipv4Address neighborIfaceAddr)
gjc@1716
  2352
{
gjc@1716
  2353
  Time now = Simulator::Now ();
gjc@2328
  2354
gjc@2328
  2355
  // the tuple parameter may be a stale copy; get a newer version from m_state
gjc@2358
  2356
  LinkTuple *tuple = m_state.FindLinkTuple (neighborIfaceAddr);
gjc@2329
  2357
  if (tuple == NULL)
gjc@2329
  2358
    {
gjc@2329
  2359
      return;
gjc@2329
  2360
    }
gjc@2329
  2361
  if (tuple->time < now)
gjc@1716
  2362
    {
gjc@2328
  2363
      RemoveLinkTuple (*tuple);
gjc@1716
  2364
    }
gjc@2328
  2365
  else if (tuple->symTime < now)
gjc@1716
  2366
    {
gjc@1716
  2367
      if (m_linkTupleTimerFirstTime)
gjc@1716
  2368
        m_linkTupleTimerFirstTime = false;
gjc@1716
  2369
      else
gjc@2328
  2370
        NeighborLoss (*tuple);
gjc@1716
  2371
gjc@2328
  2372
      m_events.Track (Simulator::Schedule (DELAY (tuple->time),
gjc@1801
  2373
                                           &AgentImpl::LinkTupleTimerExpire, this,
gjc@2358
  2374
                                           neighborIfaceAddr));
gjc@1716
  2375
    }
gjc@1716
  2376
  else
gjc@1765
  2377
    {
gjc@2328
  2378
      m_events.Track (Simulator::Schedule (DELAY (std::min (tuple->time, tuple->symTime)),
gjc@1801
  2379
                                           &AgentImpl::LinkTupleTimerExpire, this,
gjc@2358
  2380
                                           neighborIfaceAddr));
gjc@1765
  2381
    }
gjc@1716
  2382
}
gjc@1716
  2383
gjc@1716
  2384
///
gjc@1716
  2385
/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
gjc@1716
  2386
///
gjc@1716
  2387
/// The task of actually removing the tuple is left to the OLSR agent.
gjc@1716
  2388
///
gjc@1716
  2389
/// \param e The event which has expired.
gjc@1716
  2390
///
gjc@1716
  2391
void
gjc@2358
  2392
AgentImpl::Nb2hopTupleTimerExpire (Ipv4Address neighborMainAddr, Ipv4Address twoHopNeighborAddr)
gjc@1716
  2393
{
gjc@2328
  2394
  TwoHopNeighborTuple *tuple;
gjc@2358
  2395
  tuple = m_state.FindTwoHopNeighborTuple (neighborMainAddr, twoHopNeighborAddr);
gjc@2329
  2396
  if (tuple == NULL)
gjc@2329
  2397
    {
gjc@2329
  2398
      return;
gjc@2329
  2399
    }
gjc@2329
  2400
  if (tuple->expirationTime < Simulator::Now ())
gjc@1716
  2401
    {
gjc@2328
  2402
      RemoveTwoHopNeighborTuple (*tuple);
gjc@1716
  2403
    }
gjc@1716
  2404
  else
gjc@1765
  2405
    {
gjc@2328
  2406
      m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
gjc@1801
  2407
                                           &AgentImpl::Nb2hopTupleTimerExpire,
gjc@2358
  2408
                                           this, neighborMainAddr, twoHopNeighborAddr));
gjc@1765
  2409
    }
gjc@1716
  2410
}
gjc@1716
  2411
gjc@1716
  2412
///
gjc@1716
  2413
/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
gjc@1716
  2414
///
gjc@1716
  2415
/// The task of actually removing the tuple is left to the OLSR agent.
gjc@1716
  2416
///
gjc@1716
  2417
/// \param e The event which has expired.
gjc@1716
  2418
///
gjc@1716
  2419
void
gjc@2358
  2420
AgentImpl::MprSelTupleTimerExpire (Ipv4Address mainAddr)
gjc@1716
  2421
{
gjc@2358
  2422
  MprSelectorTuple *tuple = m_state.FindMprSelectorTuple (mainAddr);
gjc@2329
  2423
  if (tuple == NULL)
gjc@2329
  2424
    {
gjc@2329
  2425
      return;
gjc@2329
  2426
    }
gjc@2329
  2427
  if (tuple->expirationTime < Simulator::Now ())
gjc@1716
  2428
    {
gjc@2328
  2429
      RemoveMprSelectorTuple (*tuple);
gjc@1716
  2430
    }
gjc@1716
  2431
  else
gjc@1765
  2432
    {
gjc@2328
  2433
      m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
gjc@1801
  2434
                                           &AgentImpl::MprSelTupleTimerExpire,
gjc@2358
  2435
                                           this, mainAddr));
gjc@1765
  2436
    }
gjc@1716
  2437
}
gjc@1716
  2438
gjc@1716
  2439
///
gjc@1716
  2440
/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
gjc@1716
  2441
///
gjc@1716
  2442
/// The task of actually removing the tuple is left to the OLSR agent.
gjc@1716
  2443
///
gjc@1716
  2444
/// \param e The event which has expired.
gjc@1716
  2445
///
gjc@1716
  2446
void
gjc@2358
  2447
AgentImpl::TopologyTupleTimerExpire (Ipv4Address destAddr, Ipv4Address lastAddr)
gjc@1716
  2448
{
gjc@2358
  2449
  TopologyTuple *tuple = m_state.FindTopologyTuple (destAddr, lastAddr);
gjc@2329
  2450
  if (tuple == NULL)
gjc@2329
  2451
    {
gjc@2329
  2452
      return;
gjc@2329
  2453
    }
gjc@2329
  2454
  if (tuple->expirationTime < Simulator::Now ())
gjc@1716
  2455
    {
gjc@2328
  2456
      RemoveTopologyTuple (*tuple);
gjc@1716
  2457
    }
gjc@1716
  2458
  else
gjc@1765
  2459
    {
gjc@2328
  2460
      m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
gjc@1801
  2461
                                           &AgentImpl::TopologyTupleTimerExpire,
gjc@2358
  2462
                                           this, tuple->destAddr, tuple->lastAddr));
gjc@1765
  2463
    }
gjc@1716
  2464
}
gjc@1716
  2465
gjc@1716
  2466
///
gjc@1716
  2467
/// \brief Removes tuple_ if expired. Else timer is rescheduled to expire at tuple_->time().
gjc@1716
  2468
/// \warning Actually this is never invoked because there is no support for multiple interfaces.
gjc@1716
  2469
/// \param e The event which has expired.
gjc@1716
  2470
///
gjc@1716
  2471
void
gjc@2358
  2472
AgentImpl::IfaceAssocTupleTimerExpire (Ipv4Address ifaceAddr)
gjc@1716
  2473
{
gjc@2358
  2474
  IfaceAssocTuple *tuple = m_state.FindIfaceAssocTuple (ifaceAddr);
gjc@2329
  2475
  if (tuple == NULL)
gjc@2329
  2476
    {
gjc@2329
  2477
      return;
gjc@2329
  2478
    }
gjc@2329
  2479
  if (tuple->time < Simulator::Now ())
gjc@1716
  2480
    {
gjc@2328
  2481
      RemoveIfaceAssocTuple (*tuple);
gjc@1716
  2482
    }
gjc@1716
  2483
  else
gjc@1765
  2484
    {
gjc@2328
  2485
      m_events.Track (Simulator::Schedule (DELAY (tuple->time),
gjc@1801
  2486
                                           &AgentImpl::IfaceAssocTupleTimerExpire,
gjc@2358
  2487
                                           this, ifaceAddr));
gjc@1765
  2488
    }
gjc@1716
  2489
}
gjc@1716
  2490
gjc@3853
  2491
Ptr<const olsr::RoutingTable>
gjc@3853
  2492
AgentImpl::GetRoutingTable () const
gjc@3853
  2493
{
gjc@3853
  2494
  return m_routingTable;
gjc@3853
  2495
}
gjc@1716
  2496
gjc@1801
  2497
}} // namespace olsr, ns3
gjc@1716
  2498
gjc@1716
  2499