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
NS_LOG_FUNCTION
(
this
);
113
return
m_device
;
114
}
115
116
Ptr<Ipv4Interface>
117
ArpCache::GetInterface
(
void
)
const
118
{
119
NS_LOG_FUNCTION
(
this
);
120
return
m_interface
;
121
}
122
123
void
124
ArpCache::SetAliveTimeout
(
Time
aliveTimeout)
125
{
126
NS_LOG_FUNCTION
(
this
<< aliveTimeout);
127
m_aliveTimeout
= aliveTimeout;
128
}
129
void
130
ArpCache::SetDeadTimeout
(
Time
deadTimeout)
131
{
132
NS_LOG_FUNCTION
(
this
<< deadTimeout);
133
m_deadTimeout
= deadTimeout;
134
}
135
void
136
ArpCache::SetWaitReplyTimeout
(
Time
waitReplyTimeout)
137
{
138
NS_LOG_FUNCTION
(
this
<< waitReplyTimeout);
139
m_waitReplyTimeout
= waitReplyTimeout;
140
}
141
142
Time
143
ArpCache::GetAliveTimeout
(
void
)
const
144
{
145
NS_LOG_FUNCTION
(
this
);
146
return
m_aliveTimeout
;
147
}
148
Time
149
ArpCache::GetDeadTimeout
(
void
)
const
150
{
151
NS_LOG_FUNCTION
(
this
);
152
return
m_deadTimeout
;
153
}
154
Time
155
ArpCache::GetWaitReplyTimeout
(
void
)
const
156
{
157
NS_LOG_FUNCTION
(
this
);
158
return
m_waitReplyTimeout
;
159
}
160
161
void
162
ArpCache::SetArpRequestCallback
(
Callback
<
void
,
Ptr<const ArpCache>
,
163
Ipv4Address
> arpRequestCallback)
164
{
165
NS_LOG_FUNCTION
(
this
<< &arpRequestCallback);
166
m_arpRequestCallback
= arpRequestCallback;
167
}
168
169
void
170
ArpCache::StartWaitReplyTimer
(
void
)
171
{
172
NS_LOG_FUNCTION
(
this
);
173
if
(!
m_waitReplyTimer
.
IsRunning
())
174
{
175
NS_LOG_LOGIC
(
"Starting WaitReplyTimer at "
<<
Simulator::Now
() <<
" for "
<<
176
m_waitReplyTimeout
);
177
m_waitReplyTimer
=
Simulator::Schedule
(
m_waitReplyTimeout
,
178
&
ArpCache::HandleWaitReplyTimeout
,
this
);
179
}
180
}
181
182
void
183
ArpCache::HandleWaitReplyTimeout
(
void
)
184
{
185
NS_LOG_FUNCTION
(
this
);
186
ArpCache::Entry
* entry;
187
bool
restartWaitReplyTimer =
false
;
188
for
(
CacheI
i =
m_arpCache
.begin (); i !=
m_arpCache
.end (); i++)
189
{
190
entry = (*i).second;
191
if
(entry != 0 && entry->
IsWaitReply
())
192
{
193
if
(entry->
GetRetries
() <
m_maxRetries
)
194
{
195
NS_LOG_LOGIC
(
"node="
<<
m_device
->
GetNode
()->
GetId
() <<
196
", ArpWaitTimeout for "
<< entry->
GetIpv4Address
() <<
197
" expired -- retransmitting arp request since retries = "
<<
198
entry->
GetRetries
());
199
m_arpRequestCallback
(
this
, entry->
GetIpv4Address
());
200
restartWaitReplyTimer =
true
;
201
entry->
IncrementRetries
();
202
}
203
else
204
{
205
NS_LOG_LOGIC
(
"node="
<<
m_device
->
GetNode
()->
GetId
() <<
206
", wait reply for "
<< entry->
GetIpv4Address
() <<
207
" expired -- drop since max retries exceeded: "
<<
208
entry->
GetRetries
());
209
entry->
MarkDead
();
210
entry->
ClearRetries
();
211
Ptr<Packet>
pending = entry->
DequeuePending
();
212
while
(pending != 0)
213
{
214
m_dropTrace
(pending);
215
pending = entry->
DequeuePending
();
216
}
217
}
218
}
219
220
}
221
if
(restartWaitReplyTimer)
222
{
223
NS_LOG_LOGIC
(
"Restarting WaitReplyTimer at "
<<
Simulator::Now
().GetSeconds ());
224
m_waitReplyTimer
=
Simulator::Schedule
(
m_waitReplyTimeout
,
225
&
ArpCache::HandleWaitReplyTimeout
,
this
);
226
}
227
}
228
229
void
230
ArpCache::Flush
(
void
)
231
{
232
NS_LOG_FUNCTION
(
this
);
233
for
(
CacheI
i =
m_arpCache
.begin (); i !=
m_arpCache
.end (); i++)
234
{
235
delete
(*i).second;
236
}
237
m_arpCache
.erase (
m_arpCache
.begin (),
m_arpCache
.end ());
238
if
(
m_waitReplyTimer
.
IsRunning
())
239
{
240
NS_LOG_LOGIC
(
"Stopping WaitReplyTimer at "
<<
Simulator::Now
().GetSeconds () <<
" due to ArpCache flush"
);
241
m_waitReplyTimer
.
Cancel
();
242
}
243
}
244
245
ArpCache::Entry
*
246
ArpCache::Lookup
(
Ipv4Address
to)
247
{
248
NS_LOG_FUNCTION
(
this
<< to);
249
if
(
m_arpCache
.find (to) !=
m_arpCache
.end ())
250
{
251
ArpCache::Entry
*entry =
m_arpCache
[to];
252
return
entry;
253
}
254
return
0;
255
}
256
257
ArpCache::Entry
*
258
ArpCache::Add
(
Ipv4Address
to)
259
{
260
NS_LOG_FUNCTION
(
this
<< to);
261
NS_ASSERT
(
m_arpCache
.find (to) ==
m_arpCache
.end ());
262
263
ArpCache::Entry
*entry =
new
ArpCache::Entry
(
this
);
264
m_arpCache
[to] = entry;
265
entry->SetIpv4Address (to);
266
return
entry;
267
}
268
269
ArpCache::Entry::Entry
(
ArpCache
*arp)
270
: m_arp (arp),
271
m_state (ALIVE),
272
m_retries (0)
273
{
274
NS_LOG_FUNCTION
(
this
<< arp);
275
}
276
277
278
bool
279
ArpCache::Entry::IsDead
(
void
)
280
{
281
NS_LOG_FUNCTION
(
this
);
282
return
(m_state == DEAD) ?
true
:
false
;
283
}
284
bool
285
ArpCache::Entry::IsAlive
(
void
)
286
{
287
NS_LOG_FUNCTION
(
this
);
288
return
(m_state == ALIVE) ?
true
:
false
;
289
}
290
bool
291
ArpCache::Entry::IsWaitReply
(
void
)
292
{
293
NS_LOG_FUNCTION
(
this
);
294
return
(m_state == WAIT_REPLY) ?
true
:
false
;
295
}
296
297
298
void
299
ArpCache::Entry::MarkDead
(
void
)
300
{
301
NS_LOG_FUNCTION
(
this
);
302
m_state = DEAD;
303
ClearRetries ();
304
UpdateSeen ();
305
}
306
void
307
ArpCache::Entry::MarkAlive
(
Address
macAddress)
308
{
309
NS_LOG_FUNCTION
(
this
<< macAddress);
310
NS_ASSERT
(m_state == WAIT_REPLY);
311
m_macAddress = macAddress;
312
m_state = ALIVE;
313
ClearRetries ();
314
UpdateSeen ();
315
}
316
317
bool
318
ArpCache::Entry::UpdateWaitReply
(
Ptr<Packet>
waiting)
319
{
320
NS_LOG_FUNCTION
(
this
<< waiting);
321
NS_ASSERT
(m_state == WAIT_REPLY);
322
/* We are already waiting for an answer so
323
* we dump the previously waiting packet and
324
* replace it with this one.
325
*/
326
if
(m_pending.size () >= m_arp->m_pendingQueueSize)
327
{
328
return
false
;
329
}
330
m_pending.push_back (waiting);
331
return
true
;
332
}
333
void
334
ArpCache::Entry::MarkWaitReply
(
Ptr<Packet>
waiting)
335
{
336
NS_LOG_FUNCTION
(
this
<< waiting);
337
NS_ASSERT
(m_state == ALIVE || m_state == DEAD);
338
NS_ASSERT
(m_pending.empty ());
339
m_state = WAIT_REPLY;
340
m_pending.push_back (waiting);
341
UpdateSeen ();
342
m_arp->StartWaitReplyTimer ();
343
}
344
345
Address
346
ArpCache::Entry::GetMacAddress
(
void
)
const
347
{
348
NS_LOG_FUNCTION
(
this
);
349
NS_ASSERT
(m_state == ALIVE);
350
return
m_macAddress;
351
}
352
Ipv4Address
353
ArpCache::Entry::GetIpv4Address
(
void
)
const
354
{
355
NS_LOG_FUNCTION
(
this
);
356
return
m_ipv4Address;
357
}
358
void
359
ArpCache::Entry::SetIpv4Address
(
Ipv4Address
destination)
360
{
361
NS_LOG_FUNCTION
(
this
<< destination);
362
m_ipv4Address = destination;
363
}
364
Time
365
ArpCache::Entry::GetTimeout
(
void
)
const
366
{
367
NS_LOG_FUNCTION
(
this
);
368
switch
(m_state) {
369
case
ArpCache::Entry::WAIT_REPLY
:
370
return
m_arp->GetWaitReplyTimeout ();
371
case
ArpCache::Entry::DEAD
:
372
return
m_arp->GetDeadTimeout ();
373
case
ArpCache::Entry::ALIVE
:
374
return
m_arp->GetAliveTimeout ();
375
default
:
376
NS_ASSERT
(
false
);
377
return
Seconds
(0);
378
/* NOTREACHED */
379
}
380
}
381
bool
382
ArpCache::Entry::IsExpired
(
void
)
const
383
{
384
NS_LOG_FUNCTION
(
this
);
385
Time
timeout
= GetTimeout ();
386
Time
delta =
Simulator::Now
() - m_lastSeen;
387
NS_LOG_DEBUG
(
"delta="
<< delta.
GetSeconds
() <<
"s"
);
388
if
(delta > timeout)
389
{
390
return
true
;
391
}
392
return
false
;
393
}
394
Ptr<Packet>
395
ArpCache::Entry::DequeuePending
(
void
)
396
{
397
NS_LOG_FUNCTION
(
this
);
398
if
(m_pending.empty ())
399
{
400
return
0;
401
}
402
else
403
{
404
Ptr<Packet>
p = m_pending.front ();
405
m_pending.pop_front ();
406
return
p;
407
}
408
}
409
void
410
ArpCache::Entry::UpdateSeen
(
void
)
411
{
412
NS_LOG_FUNCTION
(
this
);
413
m_lastSeen =
Simulator::Now
();
414
}
415
uint32_t
416
ArpCache::Entry::GetRetries
(
void
)
const
417
{
418
NS_LOG_FUNCTION
(
this
);
419
return
m_retries;
420
}
421
void
422
ArpCache::Entry::IncrementRetries
(
void
)
423
{
424
NS_LOG_FUNCTION
(
this
);
425
m_retries++;
426
UpdateSeen ();
427
}
428
void
429
ArpCache::Entry::ClearRetries
(
void
)
430
{
431
NS_LOG_FUNCTION
(
this
);
432
m_retries = 0;
433
}
434
435
}
// namespace ns3
436
src
internet
model
arp-cache.cc
Generated on Tue May 14 2013 11:08:21 for ns-3 by
1.8.1.2