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
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 for (auto& iter : m_arpCache)
92 {
93 delete iter.second; /* delete the pointer ArpCache::Entry */
94 }
95 m_arpCache.clear();
96 m_device = nullptr;
97 m_interface = nullptr;
98 if (!m_waitReplyTimer.IsPending())
99 {
100 m_waitReplyTimer.Cancel();
101 }
103}
104
105void
107{
108 NS_LOG_FUNCTION(this << device << interface);
109 m_device = device;
110 m_interface = interface;
111}
112
115{
116 NS_LOG_FUNCTION(this);
117 return m_device;
118}
119
122{
123 NS_LOG_FUNCTION(this);
124 return m_interface;
125}
126
127void
129{
130 NS_LOG_FUNCTION(this << aliveTimeout);
131 m_aliveTimeout = aliveTimeout;
132}
133
134void
136{
137 NS_LOG_FUNCTION(this << deadTimeout);
138 m_deadTimeout = deadTimeout;
139}
140
141void
143{
144 NS_LOG_FUNCTION(this << waitReplyTimeout);
145 m_waitReplyTimeout = waitReplyTimeout;
146}
147
148Time
150{
151 NS_LOG_FUNCTION(this);
152 return m_aliveTimeout;
153}
154
155Time
157{
158 NS_LOG_FUNCTION(this);
159 return m_deadTimeout;
160}
161
162Time
164{
165 NS_LOG_FUNCTION(this);
166 return m_waitReplyTimeout;
167}
168
169void
171{
172 NS_LOG_FUNCTION(this << &arpRequestCallback);
173 m_arpRequestCallback = arpRequestCallback;
174}
175
176void
178{
179 NS_LOG_FUNCTION(this);
180 if (!m_waitReplyTimer.IsPending())
181 {
182 NS_LOG_LOGIC("Starting WaitReplyTimer at " << Simulator::Now() << " for "
186 }
187}
188
189void
191{
192 NS_LOG_FUNCTION(this);
193 ArpCache::Entry* entry;
194 bool restartWaitReplyTimer = false;
195 for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++)
196 {
197 entry = (*i).second;
198 if (entry != nullptr && entry->IsWaitReply())
199 {
200 if (entry->GetRetries() < m_maxRetries)
201 {
202 NS_LOG_LOGIC("node=" << m_device->GetNode()->GetId() << ", ArpWaitTimeout for "
203 << entry->GetIpv4Address()
204 << " expired -- retransmitting arp request since retries = "
205 << entry->GetRetries());
206 m_arpRequestCallback(this, entry->GetIpv4Address());
207 restartWaitReplyTimer = true;
208 entry->IncrementRetries();
209 }
210 else
211 {
212 NS_LOG_LOGIC("node=" << m_device->GetNode()->GetId() << ", wait reply for "
213 << entry->GetIpv4Address()
214 << " expired -- drop since max retries exceeded: "
215 << entry->GetRetries());
216 entry->MarkDead();
217 entry->ClearRetries();
218 Ipv4PayloadHeaderPair pending = entry->DequeuePending();
219 while (pending.first)
220 {
221 // add the Ipv4 header for tracing purposes
222 pending.first->AddHeader(pending.second);
223 m_dropTrace(pending.first);
224 pending = entry->DequeuePending();
225 }
226 }
227 }
228 }
229 if (restartWaitReplyTimer)
230 {
231 NS_LOG_LOGIC("Restarting WaitReplyTimer at " << Simulator::Now().GetSeconds());
234 }
235}
236
237void
239{
240 NS_LOG_FUNCTION(this);
241 for (auto i = m_arpCache.begin(); i != m_arpCache.end();)
242 {
243 if (!i->second->IsAutoGenerated())
244 {
245 i->second->ClearPendingPacket(); // clear the pending packets for entry's ipaddress
246 delete i->second;
247 i = m_arpCache.erase(i);
248 }
249 else
250 {
251 i++;
252 }
253 }
254 if (m_waitReplyTimer.IsPending())
255 {
256 NS_LOG_LOGIC("Stopping WaitReplyTimer at " << Simulator::Now().GetSeconds()
257 << " due to ArpCache flush");
258 m_waitReplyTimer.Cancel();
259 }
260}
261
262void
264{
265 NS_LOG_FUNCTION(this << stream);
266 std::ostream* os = stream->GetStream();
267
268 for (auto 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).empty())
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 (auto 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 i = m_arpCache.erase(i);
317 }
318 else
319 {
320 i++;
321 }
322 }
323}
324
325std::list<ArpCache::Entry*>
327{
328 NS_LOG_FUNCTION(this << to);
329
330 std::list<ArpCache::Entry*> entryList;
331 for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++)
332 {
333 ArpCache::Entry* entry = (*i).second;
334 if (entry->GetMacAddress() == to)
335 {
336 entryList.push_back(entry);
337 }
338 }
339 return entryList;
340}
341
344{
345 NS_LOG_FUNCTION(this << to);
346 auto it = m_arpCache.find(to);
347 if (it != m_arpCache.end())
348 {
349 return it->second;
350 }
351 return nullptr;
352}
353
356{
357 NS_LOG_FUNCTION(this << to);
358 NS_ASSERT(m_arpCache.find(to) == m_arpCache.end());
359
360 auto entry = new ArpCache::Entry(this);
361 m_arpCache[to] = entry;
362 entry->SetIpv4Address(to);
363 return entry;
364}
365
366void
368{
369 NS_LOG_FUNCTION(this << entry);
370
371 for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++)
372 {
373 if ((*i).second == entry)
374 {
375 m_arpCache.erase(i);
376 entry->ClearPendingPacket(); // clear the pending packets for entry's ipaddress
377 delete entry;
378 return;
379 }
380 }
381 NS_LOG_WARN("Entry not found in this ARP Cache");
382}
383
385 : m_arp(arp),
386 m_state(ALIVE),
387 m_retries(0)
388{
389 NS_LOG_FUNCTION(this << arp);
390}
391
392bool
394{
395 NS_LOG_FUNCTION(this);
396 return (m_state == DEAD);
397}
398
399bool
401{
402 NS_LOG_FUNCTION(this);
403 return (m_state == ALIVE);
404}
405
406bool
408{
409 NS_LOG_FUNCTION(this);
410 return (m_state == WAIT_REPLY);
411}
412
413bool
415{
416 NS_LOG_FUNCTION(this);
417 return (m_state == PERMANENT);
418}
419
420bool
426
427void
436
437void
439{
440 NS_LOG_FUNCTION(this << macAddress);
442 m_macAddress = macAddress;
443 m_state = ALIVE;
444 ClearRetries();
445 UpdateSeen();
446}
447
448void
458
459void
469
470bool
472{
473 NS_LOG_FUNCTION(this << waiting.first);
475 /* We are already waiting for an answer so
476 * we dump the previously waiting packet and
477 * replace it with this one.
478 */
479 if (m_pending.size() >= m_arp->m_pendingQueueSize)
480 {
481 return false;
482 }
483 m_pending.push_back(waiting);
484 return true;
485}
486
487void
489{
490 NS_LOG_FUNCTION(this << waiting.first);
492 NS_ASSERT(m_pending.empty());
493 NS_ASSERT_MSG(waiting.first, "Can not add a null packet to the ARP queue");
494
496 m_pending.push_back(waiting);
497 UpdateSeen();
498 m_arp->StartWaitReplyTimer();
499}
500
503{
504 NS_LOG_FUNCTION(this);
505 return m_macAddress;
506}
507
508void
510{
511 NS_LOG_FUNCTION(this);
512 m_macAddress = macAddress;
513}
514
517{
518 NS_LOG_FUNCTION(this);
519 return m_ipv4Address;
520}
521
522void
524{
525 NS_LOG_FUNCTION(this << destination);
526 m_ipv4Address = destination;
527}
528
529Time
531{
532 NS_LOG_FUNCTION(this);
533 switch (m_state)
534 {
536 return m_arp->GetWaitReplyTimeout();
538 return m_arp->GetDeadTimeout();
540 return m_arp->GetAliveTimeout();
543 return Time::Max();
544 }
545 return Time(); // Silence compiler warning
546}
547
548bool
550{
551 NS_LOG_FUNCTION(this);
553 Time delta = Simulator::Now() - m_lastSeen;
554 NS_LOG_DEBUG("delta=" << delta.GetSeconds() << "s");
555 return delta > timeout;
556}
557
560{
561 NS_LOG_FUNCTION(this);
562 if (m_pending.empty())
563 {
564 Ipv4Header h;
565 return Ipv4PayloadHeaderPair(nullptr, h);
566 }
567 else
568 {
570 m_pending.pop_front();
571 return p;
572 }
573}
574
575void
581
582void
588
591{
592 NS_LOG_FUNCTION(this);
593 return m_retries;
594}
595
596void
603
604void
610
611void
612ArpCache::Entry::Print(std::ostream& os) const
613{
614 os << m_ipv4Address << " lladdr " << m_macAddress << " state ";
615
616 switch (m_state)
617 {
618 case ALIVE:
619 os << "ALIVE";
620 break;
621 case WAIT_REPLY:
622 os << "WAIT_REPLY";
623 break;
624 case DEAD:
625 os << "DEAD";
626 break;
627 case PERMANENT:
628 os << "PERMANENT";
629 break;
631 os << "STATIC_AUTOGENERATED";
632 }
633
634 os << " last seen " << m_lastSeen.As() << " timeout " << GetTimeout().As();
635}
636
637std::ostream&
638operator<<(std::ostream& os, const ArpCache::Entry& entry)
639{
640 entry.Print(os);
641 return os;
642}
643
644} // namespace ns3
a polymophic address class
Definition address.h:90
A record that that holds information about an ArpCache entry.
Definition arp-cache.h:178
bool IsDead()
Definition arp-cache.cc:393
void SetIpv4Address(Ipv4Address destination)
Definition arp-cache.cc:523
void MarkAutoGenerated()
Changes the state of this entry to auto-generated.
Definition arp-cache.cc:460
bool IsAlive()
Definition arp-cache.cc:400
std::list< Ipv4PayloadHeaderPair > m_pending
list of pending packets for the entry's IP
Definition arp-cache.h:317
ArpCache * m_arp
pointer to the ARP cache owning the entry
Definition arp-cache.h:312
Ipv4Address m_ipv4Address
entry's IP address
Definition arp-cache.h:316
Time m_lastSeen
last moment a packet from that address has been seen
Definition arp-cache.h:314
bool UpdateWaitReply(Ipv4PayloadHeaderPair waiting)
Definition arp-cache.cc:471
Address m_macAddress
entry's MAC address
Definition arp-cache.h:315
Address GetMacAddress() const
Definition arp-cache.cc:502
void ClearPendingPacket()
Clear the pending packet list.
Definition arp-cache.cc:576
void MarkPermanent()
Changes the state of this entry to Permanent.
Definition arp-cache.cc:449
bool IsExpired() const
Definition arp-cache.cc:549
void ClearRetries()
Zero the counter of number of retries for an entry.
Definition arp-cache.cc:605
@ WAIT_REPLY
Definition arp-cache.h:306
@ ALIVE
Definition arp-cache.h:305
@ STATIC_AUTOGENERATED
Definition arp-cache.h:309
@ PERMANENT
Definition arp-cache.h:308
@ DEAD
Definition arp-cache.h:307
uint32_t GetRetries() const
Definition arp-cache.cc:590
void UpdateSeen()
Update the entry when seeing a packet.
Definition arp-cache.cc:583
uint32_t m_retries
retry counter
Definition arp-cache.h:318
bool IsWaitReply()
Definition arp-cache.cc:407
void IncrementRetries()
Increment the counter of number of retries for an entry.
Definition arp-cache.cc:597
void MarkAlive(Address macAddress)
Definition arp-cache.cc:438
bool IsAutoGenerated()
Definition arp-cache.cc:421
void MarkDead()
Changes the state of this entry to dead.
Definition arp-cache.cc:428
void Print(std::ostream &os) const
Print this ARP entry to the given output stream.
Definition arp-cache.cc:612
void SetMacAddress(Address macAddress)
Definition arp-cache.cc:509
void MarkWaitReply(Ipv4PayloadHeaderPair waiting)
Definition arp-cache.cc:488
Ipv4PayloadHeaderPair DequeuePending()
Definition arp-cache.cc:559
ArpCacheEntryState_e m_state
state of the entry
Definition arp-cache.h:313
Ipv4Address GetIpv4Address() const
Definition arp-cache.cc:516
bool IsPermanent()
Definition arp-cache.cc:414
Time GetTimeout() const
Returns the entry timeout.
Definition arp-cache.cc:530
Entry(ArpCache *arp)
Constructor.
Definition arp-cache.cc:384
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:163
void Remove(ArpCache::Entry *entry)
Remove an entry.
Definition arp-cache.cc:367
void SetWaitReplyTimeout(Time waitReplyTimeout)
Set the time the entry will be in WAIT_REPLY state.
Definition arp-cache.cc:142
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:190
Time GetAliveTimeout() const
Get the time the entry will be in ALIVE state (unless refreshed)
Definition arp-cache.cc:149
uint32_t m_maxRetries
max retries for a resolution
Definition arp-cache.h:341
EventId m_waitReplyTimer
cache alive state timer
Definition arp-cache.h:338
Time m_aliveTimeout
cache alive state timeout
Definition arp-cache.h:335
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:170
Time m_deadTimeout
cache dead state timeout
Definition arp-cache.h:336
Time m_waitReplyTimeout
cache reply state timeout
Definition arp-cache.h:337
Ptr< Ipv4Interface > m_interface
Ipv4Interface associated with the cache.
Definition arp-cache.h:334
void PrintArpCache(Ptr< OutputStreamWrapper > stream)
Print the ARP cache entries.
Definition arp-cache.cc:263
void Flush()
Clear the ArpCache of all entries except auto-generated entries.
Definition arp-cache.cc:238
void SetAliveTimeout(Time aliveTimeout)
Set the time the entry will be in ALIVE state (unless refreshed)
Definition arp-cache.cc:128
uint32_t m_pendingQueueSize
number of packets waiting for a resolution
Definition arp-cache.h:349
TracedCallback< Ptr< const Packet > > m_dropTrace
trace for packets dropped by the ARP cache queue
Definition arp-cache.h:352
ArpCache::Entry * Add(Ipv4Address to)
Add an Ipv4Address to this ARP cache.
Definition arp-cache.cc:355
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv4Interface > interface)
Set the NetDevice and Ipv4Interface associated with the ArpCache.
Definition arp-cache.cc:106
Ptr< Ipv4Interface > GetInterface() const
Returns the Ipv4Interface that this ARP cache is associated with.
Definition arp-cache.cc:121
std::list< ArpCache::Entry * > LookupInverse(Address destination)
Do lookup in the ARP cache against a MAC address.
Definition arp-cache.cc:326
Callback< void, Ptr< const ArpCache >, Ipv4Address > m_arpRequestCallback
reply timeout callback
Definition arp-cache.h:340
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition arp-cache.cc:343
Cache m_arpCache
the ARP cache
Definition arp-cache.h:350
void RemoveAutoGeneratedEntries()
Clear the ArpCache of all Auto-Generated entries.
Definition arp-cache.cc:307
~ArpCache() override
Definition arp-cache.cc:82
Ptr< NetDevice > m_device
NetDevice associated with the cache.
Definition arp-cache.h:333
void StartWaitReplyTimer()
This method will schedule a timeout at WaitReplyTimeout interval in the future, unless a timer is alr...
Definition arp-cache.cc:177
Time GetDeadTimeout() const
Get the time the entry will be in DEAD state before being removed.
Definition arp-cache.cc:156
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:172
void SetDeadTimeout(Time deadTimeout)
Set the time the entry will be in DEAD state before being removed.
Definition arp-cache.cc:135
Ptr< NetDevice > GetDevice() const
Returns the NetDevice that this ARP cache is associated with.
Definition arp-cache.cc:114
Callback template class.
Definition callback.h:422
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
Object()
Constructor.
Definition object.cc:96
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition nstime.h:288
AttributeValue implementation for Time.
Definition nstime.h:1456
a unique identifier for an interface.
Definition type-id.h:49
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:1457
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1477
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:1369
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.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
ns3::Time timeout