A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Groups
Pages
arp-cache.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2006 INRIA
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation;
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
*
18
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
*/
20
#include "ns3/assert.h"
21
#include "ns3/packet.h"
22
#include "ns3/simulator.h"
23
#include "ns3/uinteger.h"
24
#include "ns3/log.h"
25
#include "ns3/node.h"
26
#include "ns3/trace-source-accessor.h"
27
28
#include "
arp-cache.h
"
29
#include "
arp-header.h
"
30
#include "
ipv4-interface.h
"
31
32
NS_LOG_COMPONENT_DEFINE
(
"ArpCache"
);
33
34
namespace
ns3 {
35
36
NS_OBJECT_ENSURE_REGISTERED
(ArpCache);
37
38
TypeId
39
ArpCache::GetTypeId
(
void
)
40
{
41
static
TypeId
tid =
TypeId
(
"ns3::ArpCache"
)
42
.
SetParent
<
Object
> ()
43
.AddAttribute (
"AliveTimeout"
,
44
"When this timeout expires, the matching cache entry needs refreshing"
,
45
TimeValue
(
Seconds
(120)),
46
MakeTimeAccessor (&
ArpCache::m_aliveTimeout
),
47
MakeTimeChecker ())
48
.AddAttribute (
"DeadTimeout"
,
49
"When this timeout expires, a new attempt to resolve the matching entry is made"
,
50
TimeValue
(
Seconds
(100)),
51
MakeTimeAccessor (&
ArpCache::m_deadTimeout
),
52
MakeTimeChecker ())
53
.AddAttribute (
"WaitReplyTimeout"
,
54
"When this timeout expires, the cache entries will be scanned and entries in WaitReply state will resend ArpRequest unless MaxRetries has been exceeded, in which case the entry is marked dead"
,
55
TimeValue
(
Seconds
(1)),
56
MakeTimeAccessor (&
ArpCache::m_waitReplyTimeout
),
57
MakeTimeChecker ())
58
.AddAttribute (
"MaxRetries"
,
59
"Number of retransmissions of ArpRequest before marking dead"
,
60
UintegerValue
(3),
61
MakeUintegerAccessor (&
ArpCache::m_maxRetries
),
62
MakeUintegerChecker<uint32_t> ())
63
.AddAttribute (
"PendingQueueSize"
,
64
"The size of the queue for packets pending an arp reply."
,
65
UintegerValue
(3),
66
MakeUintegerAccessor (&
ArpCache::m_pendingQueueSize
),
67
MakeUintegerChecker<uint32_t> ())
68
.AddTraceSource (
"Drop"
,
69
"Packet dropped due to ArpCache entry in WaitReply expiring."
,
70
MakeTraceSourceAccessor
(&
ArpCache::m_dropTrace
))
71
;
72
return
tid;
73
}
74
75
ArpCache::ArpCache
()
76
: m_device (0),
77
m_interface (0)
78
{
79
NS_LOG_FUNCTION
(
this
);
80
}
81
82
ArpCache::~ArpCache
()
83
{
84
NS_LOG_FUNCTION
(
this
);
85
}
86
87
void
88
ArpCache::DoDispose
(
void
)
89
{
90
NS_LOG_FUNCTION
(
this
);
91
Flush
();
92
m_device
= 0;
93
m_interface
= 0;
94
if
(!
m_waitReplyTimer
.
IsRunning
())
95
{
96
Simulator::Remove
(
m_waitReplyTimer
);
97
}
98
Object::DoDispose
();
99
}
100
101
void
102
ArpCache::SetDevice
(
Ptr<NetDevice>
device,
Ptr<Ipv4Interface>
interface)
103
{
104
NS_LOG_FUNCTION
(
this
<< device << interface);
105
m_device
= device;
106
m_interface
= interface;
107
}
108
109
Ptr<NetDevice>
110
ArpCache::GetDevice
(
void
)
const
111
{
112
return
m_device
;
113
}
114
115
Ptr<Ipv4Interface>
116
ArpCache::GetInterface
(
void
)
const
117
{
118
return
m_interface
;
119
}
120
121
void
122
ArpCache::SetAliveTimeout
(
Time
aliveTimeout)
123
{
124
NS_LOG_FUNCTION
(
this
<< aliveTimeout);
125
m_aliveTimeout
= aliveTimeout;
126
}
127
void
128
ArpCache::SetDeadTimeout
(
Time
deadTimeout)
129
{
130
NS_LOG_FUNCTION
(
this
<< deadTimeout);
131
m_deadTimeout
= deadTimeout;
132
}
133
void
134
ArpCache::SetWaitReplyTimeout
(
Time
waitReplyTimeout)
135
{
136
NS_LOG_FUNCTION
(
this
<< waitReplyTimeout);
137
m_waitReplyTimeout
= waitReplyTimeout;
138
}
139
140
Time
141
ArpCache::GetAliveTimeout
(
void
)
const
142
{
143
return
m_aliveTimeout
;
144
}
145
Time
146
ArpCache::GetDeadTimeout
(
void
)
const
147
{
148
return
m_deadTimeout
;
149
}
150
Time
151
ArpCache::GetWaitReplyTimeout
(
void
)
const
152
{
153
return
m_waitReplyTimeout
;
154
}
155
156
void
157
ArpCache::SetArpRequestCallback
(
Callback
<
void
,
Ptr<const ArpCache>
,
158
Ipv4Address
> arpRequestCallback)
159
{
160
NS_LOG_FUNCTION
(
this
);
161
m_arpRequestCallback
= arpRequestCallback;
162
}
163
164
void
165
ArpCache::StartWaitReplyTimer
(
void
)
166
{
167
NS_LOG_FUNCTION
(
this
);
168
if
(!
m_waitReplyTimer
.
IsRunning
())
169
{
170
NS_LOG_LOGIC
(
"Starting WaitReplyTimer at "
<<
Simulator::Now
() <<
" for "
<<
171
m_waitReplyTimeout
);
172
m_waitReplyTimer
=
Simulator::Schedule
(
m_waitReplyTimeout
,
173
&
ArpCache::HandleWaitReplyTimeout
,
this
);
174
}
175
}
176
177
void
178
ArpCache::HandleWaitReplyTimeout
(
void
)
179
{
180
NS_LOG_FUNCTION
(
this
);
181
ArpCache::Entry
* entry;
182
bool
restartWaitReplyTimer =
false
;
183
for
(
CacheI
i =
m_arpCache
.begin (); i !=
m_arpCache
.end (); i++)
184
{
185
entry = (*i).second;
186
if
(entry != 0 && entry->
IsWaitReply
())
187
{
188
if
(entry->
GetRetries
() <
m_maxRetries
)
189
{
190
NS_LOG_LOGIC
(
"node="
<<
m_device
->
GetNode
()->
GetId
() <<
191
", ArpWaitTimeout for "
<< entry->
GetIpv4Address
() <<
192
" expired -- retransmitting arp request since retries = "
<<
193
entry->
GetRetries
());
194
m_arpRequestCallback
(
this
, entry->
GetIpv4Address
());
195
restartWaitReplyTimer =
true
;
196
entry->
IncrementRetries
();
197
}
198
else
199
{
200
NS_LOG_LOGIC
(
"node="
<<
m_device
->
GetNode
()->
GetId
() <<
201
", wait reply for "
<< entry->
GetIpv4Address
() <<
202
" expired -- drop since max retries exceeded: "
<<
203
entry->
GetRetries
());
204
entry->
MarkDead
();
205
entry->
ClearRetries
();
206
Ptr<Packet>
pending = entry->
DequeuePending
();
207
while
(pending != 0)
208
{
209
m_dropTrace
(pending);
210
pending = entry->
DequeuePending
();
211
}
212
}
213
}
214
215
}
216
if
(restartWaitReplyTimer)
217
{
218
NS_LOG_LOGIC
(
"Restarting WaitReplyTimer at "
<<
Simulator::Now
().GetSeconds ());
219
m_waitReplyTimer
=
Simulator::Schedule
(
m_waitReplyTimeout
,
220
&
ArpCache::HandleWaitReplyTimeout
,
this
);
221
}
222
}
223
224
void
225
ArpCache::Flush
(
void
)
226
{
227
NS_LOG_FUNCTION
(
this
);
228
for
(
CacheI
i =
m_arpCache
.begin (); i !=
m_arpCache
.end (); i++)
229
{
230
delete
(*i).second;
231
}
232
m_arpCache
.erase (
m_arpCache
.begin (),
m_arpCache
.end ());
233
if
(
m_waitReplyTimer
.
IsRunning
())
234
{
235
NS_LOG_LOGIC
(
"Stopping WaitReplyTimer at "
<<
Simulator::Now
().GetSeconds () <<
" due to ArpCache flush"
);
236
m_waitReplyTimer
.
Cancel
();
237
}
238
}
239
240
ArpCache::Entry
*
241
ArpCache::Lookup
(
Ipv4Address
to)
242
{
243
if
(
m_arpCache
.find (to) !=
m_arpCache
.end ())
244
{
245
ArpCache::Entry
*entry =
m_arpCache
[to];
246
return
entry;
247
}
248
return
0;
249
}
250
251
ArpCache::Entry
*
252
ArpCache::Add
(
Ipv4Address
to)
253
{
254
NS_LOG_FUNCTION
(
this
<< to);
255
NS_ASSERT
(
m_arpCache
.find (to) ==
m_arpCache
.end ());
256
257
ArpCache::Entry
*entry =
new
ArpCache::Entry
(
this
);
258
m_arpCache
[to] = entry;
259
entry->SetIpv4Address (to);
260
return
entry;
261
}
262
263
ArpCache::Entry::Entry
(
ArpCache
*arp)
264
: m_arp (arp),
265
m_state (ALIVE),
266
m_retries (0)
267
{
268
NS_LOG_FUNCTION
(
this
<< arp);
269
}
270
271
272
bool
273
ArpCache::Entry::IsDead
(
void
)
274
{
275
return
(m_state == DEAD) ?
true
:
false
;
276
}
277
bool
278
ArpCache::Entry::IsAlive
(
void
)
279
{
280
return
(m_state == ALIVE) ?
true
:
false
;
281
}
282
bool
283
ArpCache::Entry::IsWaitReply
(
void
)
284
{
285
return
(m_state == WAIT_REPLY) ?
true
:
false
;
286
}
287
288
289
void
290
ArpCache::Entry::MarkDead
(
void
)
291
{
292
NS_LOG_FUNCTION
(
this
);
293
m_state = DEAD;
294
ClearRetries ();
295
UpdateSeen ();
296
}
297
void
298
ArpCache::Entry::MarkAlive
(
Address
macAddress)
299
{
300
NS_LOG_FUNCTION
(
this
<< macAddress);
301
NS_ASSERT
(m_state == WAIT_REPLY);
302
m_macAddress = macAddress;
303
m_state = ALIVE;
304
ClearRetries ();
305
UpdateSeen ();
306
}
307
308
bool
309
ArpCache::Entry::UpdateWaitReply
(
Ptr<Packet>
waiting)
310
{
311
NS_LOG_FUNCTION
(
this
<< waiting);
312
NS_ASSERT
(m_state == WAIT_REPLY);
313
/* We are already waiting for an answer so
314
* we dump the previously waiting packet and
315
* replace it with this one.
316
*/
317
if
(m_pending.size () >= m_arp->m_pendingQueueSize)
318
{
319
return
false
;
320
}
321
m_pending.push_back (waiting);
322
return
true
;
323
}
324
void
325
ArpCache::Entry::MarkWaitReply
(
Ptr<Packet>
waiting)
326
{
327
NS_LOG_FUNCTION
(
this
<< waiting);
328
NS_ASSERT
(m_state == ALIVE || m_state == DEAD);
329
NS_ASSERT
(m_pending.empty ());
330
m_state = WAIT_REPLY;
331
m_pending.push_back (waiting);
332
UpdateSeen ();
333
m_arp->StartWaitReplyTimer ();
334
}
335
336
Address
337
ArpCache::Entry::GetMacAddress
(
void
)
const
338
{
339
NS_ASSERT
(m_state == ALIVE);
340
return
m_macAddress;
341
}
342
Ipv4Address
343
ArpCache::Entry::GetIpv4Address
(
void
)
const
344
{
345
return
m_ipv4Address;
346
}
347
void
348
ArpCache::Entry::SetIpv4Address
(
Ipv4Address
destination)
349
{
350
NS_LOG_FUNCTION
(
this
<< destination);
351
m_ipv4Address = destination;
352
}
353
Time
354
ArpCache::Entry::GetTimeout
(
void
)
const
355
{
356
switch
(m_state) {
357
case
ArpCache::Entry::WAIT_REPLY
:
358
return
m_arp->GetWaitReplyTimeout ();
359
case
ArpCache::Entry::DEAD
:
360
return
m_arp->GetDeadTimeout ();
361
case
ArpCache::Entry::ALIVE
:
362
return
m_arp->GetAliveTimeout ();
363
default
:
364
NS_ASSERT
(
false
);
365
return
Seconds
(0);
366
/* NOTREACHED */
367
}
368
}
369
bool
370
ArpCache::Entry::IsExpired
(
void
)
const
371
{
372
Time
timeout
= GetTimeout ();
373
Time
delta =
Simulator::Now
() - m_lastSeen;
374
NS_LOG_DEBUG
(
"delta="
<< delta.
GetSeconds
() <<
"s"
);
375
if
(delta > timeout)
376
{
377
return
true
;
378
}
379
return
false
;
380
}
381
Ptr<Packet>
382
ArpCache::Entry::DequeuePending
(
void
)
383
{
384
NS_LOG_FUNCTION
(
this
);
385
if
(m_pending.empty ())
386
{
387
return
0;
388
}
389
else
390
{
391
Ptr<Packet>
p = m_pending.front ();
392
m_pending.pop_front ();
393
return
p;
394
}
395
}
396
void
397
ArpCache::Entry::UpdateSeen
(
void
)
398
{
399
NS_LOG_FUNCTION
(
this
<< m_macAddress << m_ipv4Address);
400
m_lastSeen =
Simulator::Now
();
401
}
402
uint32_t
403
ArpCache::Entry::GetRetries
(
void
)
const
404
{
405
return
m_retries;
406
}
407
void
408
ArpCache::Entry::IncrementRetries
(
void
)
409
{
410
NS_LOG_FUNCTION
(
this
);
411
m_retries++;
412
UpdateSeen ();
413
}
414
void
415
ArpCache::Entry::ClearRetries
(
void
)
416
{
417
NS_LOG_FUNCTION
(
this
);
418
m_retries = 0;
419
}
420
421
}
// namespace ns3
422
src
internet
model
arp-cache.cc
Generated on Tue Nov 13 2012 10:32:13 for ns-3 by
1.8.1.2