A Discrete-Event Network Simulator
API
arp-cache.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006 INRIA
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19#include "arp-cache.h"
20
21#include "arp-header.h"
22#include "ipv4-header.h"
23#include "ipv4-interface.h"
24
25#include "ns3/assert.h"
26#include "ns3/log.h"
27#include "ns3/names.h"
28#include "ns3/node.h"
29#include "ns3/packet.h"
30#include "ns3/simulator.h"
31#include "ns3/trace-source-accessor.h"
32#include "ns3/uinteger.h"
33
34namespace ns3
35{
36
37NS_LOG_COMPONENT_DEFINE("ArpCache");
38
40
41TypeId
43{
44 static TypeId tid = TypeId("ns3::ArpCache")
46 .SetGroupName("Internet")
47 .AddAttribute("AliveTimeout",
48 "When this timeout expires, "
49 "the matching cache entry needs refreshing",
50 TimeValue(Seconds(120)),
53 .AddAttribute("DeadTimeout",
54 "When this timeout expires, "
55 "a new attempt to resolve the matching entry is made",
56 TimeValue(Seconds(100)),
59 .AddAttribute("WaitReplyTimeout",
60 "When this timeout expires, "
61 "the cache entries will be scanned and "
62 "entries in WaitReply state will resend ArpRequest "
63 "unless MaxRetries has been exceeded, "
64 "in which case the entry is marked dead",
68 .AddAttribute("MaxRetries",
69 "Number of retransmissions of ArpRequest "
70 "before marking dead",
73 MakeUintegerChecker<uint32_t>())
74 .AddAttribute("PendingQueueSize",
75 "The size of the queue for packets pending an arp reply.",
78 MakeUintegerChecker<uint32_t>())
79 .AddTraceSource("Drop",
80 "Packet dropped due to ArpCache entry "
81 "in WaitReply expiring.",
83 "ns3::Packet::TracedCallback");
84 return tid;
85}
86
88 : m_device(nullptr),
89 m_interface(nullptr)
90{
91 NS_LOG_FUNCTION(this);
92}
93
95{
96 NS_LOG_FUNCTION(this);
97}
98
99void
101{
102 NS_LOG_FUNCTION(this);
103 Flush();
104 m_device = nullptr;
105 m_interface = nullptr;
107 {
109 }
111}
112
113void
115{
116 NS_LOG_FUNCTION(this << device << interface);
117 m_device = device;
118 m_interface = interface;
119}
120
123{
124 NS_LOG_FUNCTION(this);
125 return m_device;
126}
127
130{
131 NS_LOG_FUNCTION(this);
132 return m_interface;
133}
134
135void
137{
138 NS_LOG_FUNCTION(this << aliveTimeout);
139 m_aliveTimeout = aliveTimeout;
140}
141
142void
144{
145 NS_LOG_FUNCTION(this << deadTimeout);
146 m_deadTimeout = deadTimeout;
147}
148
149void
151{
152 NS_LOG_FUNCTION(this << waitReplyTimeout);
153 m_waitReplyTimeout = waitReplyTimeout;
154}
155
156Time
158{
159 NS_LOG_FUNCTION(this);
160 return m_aliveTimeout;
161}
162
163Time
165{
166 NS_LOG_FUNCTION(this);
167 return m_deadTimeout;
168}
169
170Time
172{
173 NS_LOG_FUNCTION(this);
174 return m_waitReplyTimeout;
175}
176
177void
179{
180 NS_LOG_FUNCTION(this << &arpRequestCallback);
181 m_arpRequestCallback = arpRequestCallback;
182}
183
184void
186{
187 NS_LOG_FUNCTION(this);
189 {
190 NS_LOG_LOGIC("Starting WaitReplyTimer at " << Simulator::Now() << " for "
194 }
195}
196
197void
199{
200 NS_LOG_FUNCTION(this);
201 ArpCache::Entry* entry;
202 bool restartWaitReplyTimer = false;
203 for (CacheI i = m_arpCache.begin(); i != m_arpCache.end(); i++)
204 {
205 entry = (*i).second;
206 if (entry != nullptr && entry->IsWaitReply())
207 {
208 if (entry->GetRetries() < m_maxRetries)
209 {
210 NS_LOG_LOGIC("node=" << m_device->GetNode()->GetId() << ", ArpWaitTimeout for "
211 << entry->GetIpv4Address()
212 << " expired -- retransmitting arp request since retries = "
213 << entry->GetRetries());
214 m_arpRequestCallback(this, entry->GetIpv4Address());
215 restartWaitReplyTimer = true;
216 entry->IncrementRetries();
217 }
218 else
219 {
220 NS_LOG_LOGIC("node=" << m_device->GetNode()->GetId() << ", wait reply for "
221 << entry->GetIpv4Address()
222 << " expired -- drop since max retries exceeded: "
223 << entry->GetRetries());
224 entry->MarkDead();
225 entry->ClearRetries();
226 Ipv4PayloadHeaderPair pending = entry->DequeuePending();
227 while (pending.first)
228 {
229 // add the Ipv4 header for tracing purposes
230 pending.first->AddHeader(pending.second);
231 m_dropTrace(pending.first);
232 pending = entry->DequeuePending();
233 }
234 }
235 }
236 }
237 if (restartWaitReplyTimer)
238 {
239 NS_LOG_LOGIC("Restarting WaitReplyTimer at " << Simulator::Now().GetSeconds());
242 }
243}
244
245void
247{
248 NS_LOG_FUNCTION(this);
249 for (CacheI i = m_arpCache.begin(); i != m_arpCache.end(); i++)
250 {
251 delete (*i).second;
252 }
253 m_arpCache.erase(m_arpCache.begin(), m_arpCache.end());
255 {
256 NS_LOG_LOGIC("Stopping WaitReplyTimer at " << Simulator::Now().GetSeconds()
257 << " due to ArpCache flush");
259 }
260}
261
262void
264{
265 NS_LOG_FUNCTION(this << stream);
266 std::ostream* os = stream->GetStream();
267
268 for (CacheI i = m_arpCache.begin(); i != m_arpCache.end(); i++)
269 {
270 *os << i->first << " dev ";
271 std::string found = Names::FindName(m_device);
272 if (Names::FindName(m_device) != "")
273 {
274 *os << found;
275 }
276 else
277 {
278 *os << static_cast<int>(m_device->GetIfIndex());
279 }
280
281 *os << " lladdr " << i->second->GetMacAddress();
282
283 if (i->second->IsAlive())
284 {
285 *os << " REACHABLE\n";
286 }
287 else if (i->second->IsWaitReply())
288 {
289 *os << " DELAY\n";
290 }
291 else if (i->second->IsPermanent())
292 {
293 *os << " PERMANENT\n";
294 }
295 else if (i->second->IsAutoGenerated())
296 {
297 *os << " STATIC_AUTOGENERATED\n";
298 }
299 else
300 {
301 *os << " STALE\n";
302 }
303 }
304}
305
306void
308{
309 NS_LOG_FUNCTION(this);
310 for (CacheI i = m_arpCache.begin(); i != m_arpCache.end();)
311 {
312 if (i->second->IsAutoGenerated())
313 {
314 i->second->ClearPendingPacket(); // clear the pending packets for entry's ipaddress
315 delete i->second;
316 m_arpCache.erase(i++);
317 continue;
318 }
319 i++;
320 }
321}
322
323std::list<ArpCache::Entry*>
325{
326 NS_LOG_FUNCTION(this << to);
327
328 std::list<ArpCache::Entry*> entryList;
329 for (CacheI i = m_arpCache.begin(); i != m_arpCache.end(); i++)
330 {
331 ArpCache::Entry* entry = (*i).second;
332 if (entry->GetMacAddress() == to)
333 {
334 entryList.push_back(entry);
335 }
336 }
337 return entryList;
338}
339
342{
343 NS_LOG_FUNCTION(this << to);
344 CacheI it = m_arpCache.find(to);
345 if (it != m_arpCache.end())
346 {
347 return it->second;
348 }
349 return nullptr;
350}
351
354{
355 NS_LOG_FUNCTION(this << to);
356 NS_ASSERT(m_arpCache.find(to) == m_arpCache.end());
357
358 ArpCache::Entry* entry = new ArpCache::Entry(this);
359 m_arpCache[to] = entry;
360 entry->SetIpv4Address(to);
361 return entry;
362}
363
364void
366{
367 NS_LOG_FUNCTION(this << entry);
368
369 for (CacheI i = m_arpCache.begin(); i != m_arpCache.end(); i++)
370 {
371 if ((*i).second == entry)
372 {
373 m_arpCache.erase(i);
374 entry->ClearPendingPacket(); // clear the pending packets for entry's ipaddress
375 delete entry;
376 return;
377 }
378 }
379 NS_LOG_WARN("Entry not found in this ARP Cache");
380}
381
383 : m_arp(arp),
384 m_state(ALIVE),
385 m_retries(0)
386{
387 NS_LOG_FUNCTION(this << arp);
388}
389
390bool
392{
393 NS_LOG_FUNCTION(this);
394 return (m_state == DEAD);
395}
396
397bool
399{
400 NS_LOG_FUNCTION(this);
401 return (m_state == ALIVE);
402}
403
404bool
406{
407 NS_LOG_FUNCTION(this);
408 return (m_state == WAIT_REPLY);
409}
410
411bool
413{
414 NS_LOG_FUNCTION(this);
415 return (m_state == PERMANENT);
416}
417
418bool
420{
421 NS_LOG_FUNCTION(this);
422 return (m_state == STATIC_AUTOGENERATED);
423}
424
425void
427{
428 NS_LOG_FUNCTION(this);
429 NS_ASSERT(m_state == ALIVE || m_state == WAIT_REPLY || m_state == DEAD);
430 m_state = DEAD;
431 ClearRetries();
432 UpdateSeen();
433}
434
435void
437{
438 NS_LOG_FUNCTION(this << macAddress);
439 NS_ASSERT(m_state == WAIT_REPLY);
440 m_macAddress = macAddress;
441 m_state = ALIVE;
442 ClearRetries();
443 UpdateSeen();
444}
445
446void
448{
449 NS_LOG_FUNCTION(this << m_macAddress);
450 NS_ASSERT(!m_macAddress.IsInvalid());
451
452 m_state = PERMANENT;
453 ClearRetries();
454 UpdateSeen();
455}
456
457void
459{
460 NS_LOG_FUNCTION(this << m_macAddress);
461 NS_ASSERT(!m_macAddress.IsInvalid());
462
463 m_state = STATIC_AUTOGENERATED;
464 ClearRetries();
465 UpdateSeen();
466}
467
468bool
470{
471 NS_LOG_FUNCTION(this << waiting.first);
472 NS_ASSERT(m_state == WAIT_REPLY);
473 /* We are already waiting for an answer so
474 * we dump the previously waiting packet and
475 * replace it with this one.
476 */
477 if (m_pending.size() >= m_arp->m_pendingQueueSize)
478 {
479 return false;
480 }
481 m_pending.push_back(waiting);
482 return true;
483}
484
485void
487{
488 NS_LOG_FUNCTION(this << waiting.first);
489 NS_ASSERT(m_state == ALIVE || m_state == DEAD);
490 NS_ASSERT(m_pending.empty());
491 NS_ASSERT_MSG(waiting.first, "Can not add a null packet to the ARP queue");
492
493 m_state = WAIT_REPLY;
494 m_pending.push_back(waiting);
495 UpdateSeen();
496 m_arp->StartWaitReplyTimer();
497}
498
501{
502 NS_LOG_FUNCTION(this);
503 return m_macAddress;
504}
505
506void
508{
509 NS_LOG_FUNCTION(this);
510 m_macAddress = macAddress;
511}
512
515{
516 NS_LOG_FUNCTION(this);
517 return m_ipv4Address;
518}
519
520void
522{
523 NS_LOG_FUNCTION(this << destination);
524 m_ipv4Address = destination;
525}
526
527Time
529{
530 NS_LOG_FUNCTION(this);
531 switch (m_state)
532 {
534 return m_arp->GetWaitReplyTimeout();
536 return m_arp->GetDeadTimeout();
538 return m_arp->GetAliveTimeout();
540 return Time::Max();
542 return Time::Max();
543 }
544 return Time(); // Silence compiler warning
545}
546
547bool
549{
550 NS_LOG_FUNCTION(this);
551 Time timeout = GetTimeout();
552 Time delta = Simulator::Now() - m_lastSeen;
553 NS_LOG_DEBUG("delta=" << delta.GetSeconds() << "s");
554 if (delta > timeout)
555 {
556 return true;
557 }
558 return false;
559}
560
563{
564 NS_LOG_FUNCTION(this);
565 if (m_pending.empty())
566 {
567 Ipv4Header h;
568 return Ipv4PayloadHeaderPair(nullptr, h);
569 }
570 else
571 {
572 Ipv4PayloadHeaderPair p = m_pending.front();
573 m_pending.pop_front();
574 return p;
575 }
576}
577
578void
580{
581 NS_LOG_FUNCTION(this);
582 m_pending.clear();
583}
584
585void
587{
588 NS_LOG_FUNCTION(this);
589 m_lastSeen = Simulator::Now();
590}
591
594{
595 NS_LOG_FUNCTION(this);
596 return m_retries;
597}
598
599void
601{
602 NS_LOG_FUNCTION(this);
603 m_retries++;
604 UpdateSeen();
605}
606
607void
609{
610 NS_LOG_FUNCTION(this);
611 m_retries = 0;
612}
613
614} // namespace ns3
a polymophic address class
Definition: address.h:92
A record that that holds information about an ArpCache entry.
Definition: arp-cache.h:184
bool IsDead()
Definition: arp-cache.cc:391
void SetIpv4Address(Ipv4Address destination)
Definition: arp-cache.cc:521
void MarkAutoGenerated()
Changes the state of this entry to auto-generated.
Definition: arp-cache.cc:458
bool IsAlive()
Definition: arp-cache.cc:398
bool UpdateWaitReply(Ipv4PayloadHeaderPair waiting)
Definition: arp-cache.cc:469
Address GetMacAddress() const
Definition: arp-cache.cc:500
void ClearPendingPacket()
Clear the pending packet list.
Definition: arp-cache.cc:579
void MarkPermanent()
Changes the state of this entry to Permanent.
Definition: arp-cache.cc:447
bool IsExpired() const
Definition: arp-cache.cc:548
void ClearRetries()
Zero the counter of number of retries for an entry.
Definition: arp-cache.cc:608
@ WAIT_REPLY
Definition: arp-cache.h:299
@ ALIVE
Definition: arp-cache.h:298
@ STATIC_AUTOGENERATED
Definition: arp-cache.h:302
@ PERMANENT
Definition: arp-cache.h:301
@ DEAD
Definition: arp-cache.h:300
uint32_t GetRetries() const
Definition: arp-cache.cc:593
void UpdateSeen()
Update the entry when seeing a packet.
Definition: arp-cache.cc:586
bool IsWaitReply()
Definition: arp-cache.cc:405
void IncrementRetries()
Increment the counter of number of retries for an entry.
Definition: arp-cache.cc:600
void MarkAlive(Address macAddress)
Definition: arp-cache.cc:436
bool IsAutoGenerated()
Definition: arp-cache.cc:419
void MarkDead()
Changes the state of this entry to dead.
Definition: arp-cache.cc:426
void SetMacAddress(Address macAddress)
Definition: arp-cache.cc:507
void MarkWaitReply(Ipv4PayloadHeaderPair waiting)
Definition: arp-cache.cc:486
Ipv4PayloadHeaderPair DequeuePending()
Definition: arp-cache.cc:562
Ipv4Address GetIpv4Address() const
Definition: arp-cache.cc:514
bool IsPermanent()
Definition: arp-cache.cc:412
Time GetTimeout() const
Returns the entry timeout.
Definition: arp-cache.cc:528
Entry(ArpCache *arp)
Constructor.
Definition: arp-cache.cc:382
An ARP cache.
Definition: arp-cache.h:53
Time GetWaitReplyTimeout() const
Get the time the entry will be in WAIT_REPLY state.
Definition: arp-cache.cc:171
void Remove(ArpCache::Entry *entry)
Remove an entry.
Definition: arp-cache.cc:365
void SetWaitReplyTimeout(Time waitReplyTimeout)
Set the time the entry will be in WAIT_REPLY state.
Definition: arp-cache.cc:150
void HandleWaitReplyTimeout()
This function is an event handler for the event that the ArpCache wants to check whether it must retr...
Definition: arp-cache.cc:198
Time GetAliveTimeout() const
Get the time the entry will be in ALIVE state (unless refreshed)
Definition: arp-cache.cc:157
uint32_t m_maxRetries
max retries for a resolution
Definition: arp-cache.h:340
EventId m_waitReplyTimer
cache alive state timer
Definition: arp-cache.h:337
Time m_aliveTimeout
cache alive state timeout
Definition: arp-cache.h:334
void DoDispose() override
Destructor implementation.
Definition: arp-cache.cc:100
void SetArpRequestCallback(Callback< void, Ptr< const ArpCache >, Ipv4Address > arpRequestCallback)
This callback is set when the ArpCache is set up and allows the cache to generate an Arp request when...
Definition: arp-cache.cc:178
Time m_deadTimeout
cache dead state timeout
Definition: arp-cache.h:335
Time m_waitReplyTimeout
cache reply state timeout
Definition: arp-cache.h:336
Ptr< Ipv4Interface > m_interface
Ipv4Interface associated with the cache.
Definition: arp-cache.h:333
void PrintArpCache(Ptr< OutputStreamWrapper > stream)
Print the ARP cache entries.
Definition: arp-cache.cc:263
void Flush()
Clear the ArpCache of all entries.
Definition: arp-cache.cc:246
void SetAliveTimeout(Time aliveTimeout)
Set the time the entry will be in ALIVE state (unless refreshed)
Definition: arp-cache.cc:136
uint32_t m_pendingQueueSize
number of packets waiting for a resolution
Definition: arp-cache.h:348
TracedCallback< Ptr< const Packet > > m_dropTrace
trace for packets dropped by the ARP cache queue
Definition: arp-cache.h:351
ArpCache::Entry * Add(Ipv4Address to)
Add an Ipv4Address to this ARP cache.
Definition: arp-cache.cc:353
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv4Interface > interface)
Set the NetDevice and Ipv4Interface associated with the ArpCache.
Definition: arp-cache.cc:114
Ptr< Ipv4Interface > GetInterface() const
Returns the Ipv4Interface that this ARP cache is associated with.
Definition: arp-cache.cc:129
std::list< ArpCache::Entry * > LookupInverse(Address destination)
Do lookup in the ARP cache against a MAC address.
Definition: arp-cache.cc:324
Callback< void, Ptr< const ArpCache >, Ipv4Address > m_arpRequestCallback
reply timeout callback
Definition: arp-cache.h:339
std::map< Ipv4Address, ArpCache::Entry * >::iterator CacheI
ARP Cache container iterator.
Definition: arp-cache.h:328
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition: arp-cache.cc:341
Cache m_arpCache
the ARP cache
Definition: arp-cache.h:349
void RemoveAutoGeneratedEntries()
Clear the ArpCache of all Auto-Generated entries.
Definition: arp-cache.cc:307
~ArpCache() override
Definition: arp-cache.cc:94
Ptr< NetDevice > m_device
NetDevice associated with the cache.
Definition: arp-cache.h:332
void StartWaitReplyTimer()
This method will schedule a timeout at WaitReplyTimeout interval in the future, unless a timer is alr...
Definition: arp-cache.cc:185
Time GetDeadTimeout() const
Get the time the entry will be in DEAD state before being removed.
Definition: arp-cache.cc:164
static TypeId GetTypeId()
Get the type ID.
Definition: arp-cache.cc:42
std::pair< Ptr< Packet >, Ipv4Header > Ipv4PayloadHeaderPair
Pair of a packet and an Ipv4 header.
Definition: arp-cache.h:178
void SetDeadTimeout(Time deadTimeout)
Set the time the entry will be in DEAD state before being removed.
Definition: arp-cache.cc:143
Ptr< NetDevice > GetDevice() const
Returns the NetDevice that this ARP cache is associated with.
Definition: arp-cache.cc:122
Callback template class.
Definition: callback.h:443
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
Packet header for IPv4.
Definition: ipv4-header.h:34
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
Definition: names.cc:830
A base class which provides memory management and object aggregation.
Definition: object.h:89
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
std::ostream * GetStream()
Return a pointer to an ostream previously set in the wrapper.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:402
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition: nstime.h:296
AttributeValue implementation for Time.
Definition: nstime.h:1425
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1426
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:850
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
ns3::Time timeout