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