A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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 "ipv4-header.h"
22#include "ipv4-interface.h"
23
24#include "ns3/assert.h"
25#include "ns3/log.h"
26#include "ns3/names.h"
27#include "ns3/node.h"
28#include "ns3/packet.h"
29#include "ns3/simulator.h"
30#include "ns3/trace-source-accessor.h"
31#include "ns3/uinteger.h"
32
33namespace ns3
34{
35
36NS_LOG_COMPONENT_DEFINE("ArpCache");
37
39
40TypeId
42{
43 static TypeId tid = TypeId("ns3::ArpCache")
45 .SetGroupName("Internet")
46 .AddAttribute("AliveTimeout",
47 "When this timeout expires, "
48 "the matching cache entry needs refreshing",
49 TimeValue(Seconds(120)),
52 .AddAttribute("DeadTimeout",
53 "When this timeout expires, "
54 "a new attempt to resolve the matching entry is made",
55 TimeValue(Seconds(100)),
58 .AddAttribute("WaitReplyTimeout",
59 "When this timeout expires, "
60 "the cache entries will be scanned and "
61 "entries in WaitReply state will resend ArpRequest "
62 "unless MaxRetries has been exceeded, "
63 "in which case the entry is marked dead",
67 .AddAttribute("MaxRetries",
68 "Number of retransmissions of ArpRequest "
69 "before marking dead",
72 MakeUintegerChecker<uint32_t>())
73 .AddAttribute("PendingQueueSize",
74 "The size of the queue for packets pending an arp reply.",
77 MakeUintegerChecker<uint32_t>())
78 .AddTraceSource("Drop",
79 "Packet dropped due to ArpCache entry "
80 "in WaitReply expiring.",
82 "ns3::Packet::TracedCallback");
83 return tid;
84}
85
87 : m_device(nullptr),
88 m_interface(nullptr)
89{
90 NS_LOG_FUNCTION(this);
91}
92
94{
95 NS_LOG_FUNCTION(this);
96}
97
98void
100{
101 NS_LOG_FUNCTION(this);
102 Flush();
103 m_device = nullptr;
104 m_interface = nullptr;
106 {
108 }
110}
111
112void
114{
115 NS_LOG_FUNCTION(this << device << interface);
116 m_device = device;
117 m_interface = interface;
118}
119
122{
123 NS_LOG_FUNCTION(this);
124 return m_device;
125}
126
129{
130 NS_LOG_FUNCTION(this);
131 return m_interface;
132}
133
134void
136{
137 NS_LOG_FUNCTION(this << aliveTimeout);
138 m_aliveTimeout = aliveTimeout;
139}
140
141void
143{
144 NS_LOG_FUNCTION(this << deadTimeout);
145 m_deadTimeout = deadTimeout;
146}
147
148void
150{
151 NS_LOG_FUNCTION(this << waitReplyTimeout);
152 m_waitReplyTimeout = waitReplyTimeout;
153}
154
155Time
157{
158 NS_LOG_FUNCTION(this);
159 return m_aliveTimeout;
160}
161
162Time
164{
165 NS_LOG_FUNCTION(this);
166 return m_deadTimeout;
167}
168
169Time
171{
172 NS_LOG_FUNCTION(this);
173 return m_waitReplyTimeout;
174}
175
176void
178{
179 NS_LOG_FUNCTION(this << &arpRequestCallback);
180 m_arpRequestCallback = arpRequestCallback;
181}
182
183void
185{
186 NS_LOG_FUNCTION(this);
188 {
189 NS_LOG_LOGIC("Starting WaitReplyTimer at " << Simulator::Now() << " for "
193 }
194}
195
196void
198{
199 NS_LOG_FUNCTION(this);
200 ArpCache::Entry* entry;
201 bool restartWaitReplyTimer = false;
202 for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++)
203 {
204 entry = (*i).second;
205 if (entry != nullptr && entry->IsWaitReply())
206 {
207 if (entry->GetRetries() < m_maxRetries)
208 {
209 NS_LOG_LOGIC("node=" << m_device->GetNode()->GetId() << ", ArpWaitTimeout for "
210 << entry->GetIpv4Address()
211 << " expired -- retransmitting arp request since retries = "
212 << entry->GetRetries());
213 m_arpRequestCallback(this, entry->GetIpv4Address());
214 restartWaitReplyTimer = true;
215 entry->IncrementRetries();
216 }
217 else
218 {
219 NS_LOG_LOGIC("node=" << m_device->GetNode()->GetId() << ", wait reply for "
220 << entry->GetIpv4Address()
221 << " expired -- drop since max retries exceeded: "
222 << entry->GetRetries());
223 entry->MarkDead();
224 entry->ClearRetries();
225 Ipv4PayloadHeaderPair pending = entry->DequeuePending();
226 while (pending.first)
227 {
228 // add the Ipv4 header for tracing purposes
229 pending.first->AddHeader(pending.second);
230 m_dropTrace(pending.first);
231 pending = entry->DequeuePending();
232 }
233 }
234 }
235 }
236 if (restartWaitReplyTimer)
237 {
238 NS_LOG_LOGIC("Restarting WaitReplyTimer at " << Simulator::Now().GetSeconds());
241 }
242}
243
244void
246{
247 NS_LOG_FUNCTION(this);
248 for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++)
249 {
250 delete (*i).second;
251 }
252 m_arpCache.erase(m_arpCache.begin(), m_arpCache.end());
254 {
255 NS_LOG_LOGIC("Stopping WaitReplyTimer at " << Simulator::Now().GetSeconds()
256 << " due to ArpCache flush");
258 }
259}
260
261void
263{
264 NS_LOG_FUNCTION(this << stream);
265 std::ostream* os = stream->GetStream();
266
267 for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++)
268 {
269 *os << i->first << " dev ";
270 std::string found = Names::FindName(m_device);
271 if (!Names::FindName(m_device).empty())
272 {
273 *os << found;
274 }
275 else
276 {
277 *os << static_cast<int>(m_device->GetIfIndex());
278 }
279
280 *os << " lladdr " << i->second->GetMacAddress();
281
282 if (i->second->IsAlive())
283 {
284 *os << " REACHABLE\n";
285 }
286 else if (i->second->IsWaitReply())
287 {
288 *os << " DELAY\n";
289 }
290 else if (i->second->IsPermanent())
291 {
292 *os << " PERMANENT\n";
293 }
294 else if (i->second->IsAutoGenerated())
295 {
296 *os << " STATIC_AUTOGENERATED\n";
297 }
298 else
299 {
300 *os << " STALE\n";
301 }
302 }
303}
304
305void
307{
308 NS_LOG_FUNCTION(this);
309 for (auto i = m_arpCache.begin(); i != m_arpCache.end();)
310 {
311 if (i->second->IsAutoGenerated())
312 {
313 i->second->ClearPendingPacket(); // clear the pending packets for entry's ipaddress
314 delete i->second;
315 m_arpCache.erase(i++);
316 continue;
317 }
318 i++;
319 }
320}
321
322std::list<ArpCache::Entry*>
324{
325 NS_LOG_FUNCTION(this << to);
326
327 std::list<ArpCache::Entry*> entryList;
328 for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++)
329 {
330 ArpCache::Entry* entry = (*i).second;
331 if (entry->GetMacAddress() == to)
332 {
333 entryList.push_back(entry);
334 }
335 }
336 return entryList;
337}
338
341{
342 NS_LOG_FUNCTION(this << to);
343 auto it = m_arpCache.find(to);
344 if (it != m_arpCache.end())
345 {
346 return it->second;
347 }
348 return nullptr;
349}
350
353{
354 NS_LOG_FUNCTION(this << to);
355 NS_ASSERT(m_arpCache.find(to) == m_arpCache.end());
356
357 auto entry = new ArpCache::Entry(this);
358 m_arpCache[to] = entry;
359 entry->SetIpv4Address(to);
360 return entry;
361}
362
363void
365{
366 NS_LOG_FUNCTION(this << entry);
367
368 for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++)
369 {
370 if ((*i).second == entry)
371 {
372 m_arpCache.erase(i);
373 entry->ClearPendingPacket(); // clear the pending packets for entry's ipaddress
374 delete entry;
375 return;
376 }
377 }
378 NS_LOG_WARN("Entry not found in this ARP Cache");
379}
380
382 : m_arp(arp),
383 m_state(ALIVE),
384 m_retries(0)
385{
386 NS_LOG_FUNCTION(this << arp);
387}
388
389bool
391{
392 NS_LOG_FUNCTION(this);
393 return (m_state == DEAD);
394}
395
396bool
398{
399 NS_LOG_FUNCTION(this);
400 return (m_state == ALIVE);
401}
402
403bool
405{
406 NS_LOG_FUNCTION(this);
407 return (m_state == WAIT_REPLY);
408}
409
410bool
412{
413 NS_LOG_FUNCTION(this);
414 return (m_state == PERMANENT);
415}
416
417bool
419{
420 NS_LOG_FUNCTION(this);
421 return (m_state == STATIC_AUTOGENERATED);
422}
423
424void
426{
427 NS_LOG_FUNCTION(this);
428 NS_ASSERT(m_state == ALIVE || m_state == WAIT_REPLY || m_state == DEAD);
429 m_state = DEAD;
430 ClearRetries();
431 UpdateSeen();
432}
433
434void
436{
437 NS_LOG_FUNCTION(this << macAddress);
438 NS_ASSERT(m_state == WAIT_REPLY);
439 m_macAddress = macAddress;
440 m_state = ALIVE;
441 ClearRetries();
442 UpdateSeen();
443}
444
445void
447{
448 NS_LOG_FUNCTION(this << m_macAddress);
449 NS_ASSERT(!m_macAddress.IsInvalid());
450
451 m_state = PERMANENT;
452 ClearRetries();
453 UpdateSeen();
454}
455
456void
458{
459 NS_LOG_FUNCTION(this << m_macAddress);
460 NS_ASSERT(!m_macAddress.IsInvalid());
461
462 m_state = STATIC_AUTOGENERATED;
463 ClearRetries();
464 UpdateSeen();
465}
466
467bool
469{
470 NS_LOG_FUNCTION(this << waiting.first);
471 NS_ASSERT(m_state == WAIT_REPLY);
472 /* We are already waiting for an answer so
473 * we dump the previously waiting packet and
474 * replace it with this one.
475 */
476 if (m_pending.size() >= m_arp->m_pendingQueueSize)
477 {
478 return false;
479 }
480 m_pending.push_back(waiting);
481 return true;
482}
483
484void
486{
487 NS_LOG_FUNCTION(this << waiting.first);
488 NS_ASSERT(m_state == ALIVE || m_state == DEAD);
489 NS_ASSERT(m_pending.empty());
490 NS_ASSERT_MSG(waiting.first, "Can not add a null packet to the ARP queue");
491
492 m_state = WAIT_REPLY;
493 m_pending.push_back(waiting);
494 UpdateSeen();
495 m_arp->StartWaitReplyTimer();
496}
497
500{
501 NS_LOG_FUNCTION(this);
502 return m_macAddress;
503}
504
505void
507{
508 NS_LOG_FUNCTION(this);
509 m_macAddress = macAddress;
510}
511
514{
515 NS_LOG_FUNCTION(this);
516 return m_ipv4Address;
517}
518
519void
521{
522 NS_LOG_FUNCTION(this << destination);
523 m_ipv4Address = destination;
524}
525
526Time
528{
529 NS_LOG_FUNCTION(this);
530 switch (m_state)
531 {
533 return m_arp->GetWaitReplyTimeout();
535 return m_arp->GetDeadTimeout();
537 return m_arp->GetAliveTimeout();
539 return Time::Max();
541 return Time::Max();
542 }
543 return Time(); // Silence compiler warning
544}
545
546bool
548{
549 NS_LOG_FUNCTION(this);
550 Time timeout = GetTimeout();
551 Time delta = Simulator::Now() - m_lastSeen;
552 NS_LOG_DEBUG("delta=" << delta.GetSeconds() << "s");
553 return delta > timeout;
554}
555
558{
559 NS_LOG_FUNCTION(this);
560 if (m_pending.empty())
561 {
562 Ipv4Header h;
563 return Ipv4PayloadHeaderPair(nullptr, h);
564 }
565 else
566 {
567 Ipv4PayloadHeaderPair p = m_pending.front();
568 m_pending.pop_front();
569 return p;
570 }
571}
572
573void
575{
576 NS_LOG_FUNCTION(this);
577 m_pending.clear();
578}
579
580void
582{
583 NS_LOG_FUNCTION(this);
584 m_lastSeen = Simulator::Now();
585}
586
589{
590 NS_LOG_FUNCTION(this);
591 return m_retries;
592}
593
594void
596{
597 NS_LOG_FUNCTION(this);
598 m_retries++;
599 UpdateSeen();
600}
601
602void
604{
605 NS_LOG_FUNCTION(this);
606 m_retries = 0;
607}
608
609} // namespace ns3
a polymophic address class
Definition: address.h:101
A record that that holds information about an ArpCache entry.
Definition: arp-cache.h:184
bool IsDead()
Definition: arp-cache.cc:390
void SetIpv4Address(Ipv4Address destination)
Definition: arp-cache.cc:520
void MarkAutoGenerated()
Changes the state of this entry to auto-generated.
Definition: arp-cache.cc:457
bool IsAlive()
Definition: arp-cache.cc:397
bool UpdateWaitReply(Ipv4PayloadHeaderPair waiting)
Definition: arp-cache.cc:468
Address GetMacAddress() const
Definition: arp-cache.cc:499
void ClearPendingPacket()
Clear the pending packet list.
Definition: arp-cache.cc:574
void MarkPermanent()
Changes the state of this entry to Permanent.
Definition: arp-cache.cc:446
bool IsExpired() const
Definition: arp-cache.cc:547
void ClearRetries()
Zero the counter of number of retries for an entry.
Definition: arp-cache.cc:603
@ 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:588
void UpdateSeen()
Update the entry when seeing a packet.
Definition: arp-cache.cc:581
bool IsWaitReply()
Definition: arp-cache.cc:404
void IncrementRetries()
Increment the counter of number of retries for an entry.
Definition: arp-cache.cc:595
void MarkAlive(Address macAddress)
Definition: arp-cache.cc:435
bool IsAutoGenerated()
Definition: arp-cache.cc:418
void MarkDead()
Changes the state of this entry to dead.
Definition: arp-cache.cc:425
void SetMacAddress(Address macAddress)
Definition: arp-cache.cc:506
void MarkWaitReply(Ipv4PayloadHeaderPair waiting)
Definition: arp-cache.cc:485
Ipv4PayloadHeaderPair DequeuePending()
Definition: arp-cache.cc:557
Ipv4Address GetIpv4Address() const
Definition: arp-cache.cc:513
bool IsPermanent()
Definition: arp-cache.cc:411
Time GetTimeout() const
Returns the entry timeout.
Definition: arp-cache.cc:527
Entry(ArpCache *arp)
Constructor.
Definition: arp-cache.cc:381
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:170
void Remove(ArpCache::Entry *entry)
Remove an entry.
Definition: arp-cache.cc:364
void SetWaitReplyTimeout(Time waitReplyTimeout)
Set the time the entry will be in WAIT_REPLY state.
Definition: arp-cache.cc:149
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:197
Time GetAliveTimeout() const
Get the time the entry will be in ALIVE state (unless refreshed)
Definition: arp-cache.cc:156
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:99
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:177
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:262
void Flush()
Clear the ArpCache of all entries.
Definition: arp-cache.cc:245
void SetAliveTimeout(Time aliveTimeout)
Set the time the entry will be in ALIVE state (unless refreshed)
Definition: arp-cache.cc:135
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:352
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv4Interface > interface)
Set the NetDevice and Ipv4Interface associated with the ArpCache.
Definition: arp-cache.cc:113
Ptr< Ipv4Interface > GetInterface() const
Returns the Ipv4Interface that this ARP cache is associated with.
Definition: arp-cache.cc:128
std::list< ArpCache::Entry * > LookupInverse(Address destination)
Do lookup in the ARP cache against a MAC address.
Definition: arp-cache.cc:323
Callback< void, Ptr< const ArpCache >, Ipv4Address > m_arpRequestCallback
reply timeout callback
Definition: arp-cache.h:339
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition: arp-cache.cc:340
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:306
~ArpCache() override
Definition: arp-cache.cc:93
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:184
Time GetDeadTimeout() const
Get the time the entry will be in DEAD state before being removed.
Definition: arp-cache.cc:163
static TypeId GetTypeId()
Get the type ID.
Definition: arp-cache.cc:41
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:142
Ptr< NetDevice > GetDevice() const
Returns the NetDevice that this ARP cache is associated with.
Definition: arp-cache.cc:121
Callback template class.
Definition: callback.h:438
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:42
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:829
A base class which provides memory management and object aggregation.
Definition: object.h:89
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:444
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition: nstime.h:297
AttributeValue implementation for Time.
Definition: nstime.h:1413
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
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 AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1434
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
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:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns3::Time timeout