|
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 |
|