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 "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 
33 namespace ns3
34 {
35 
36 NS_LOG_COMPONENT_DEFINE("ArpCache");
37 
39 
40 TypeId
42 {
43  static TypeId tid = TypeId("ns3::ArpCache")
44  .SetParent<Object>()
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",
64  TimeValue(Seconds(1)),
67  .AddAttribute("MaxRetries",
68  "Number of retransmissions of ArpRequest "
69  "before marking dead",
70  UintegerValue(3),
72  MakeUintegerChecker<uint32_t>())
73  .AddAttribute("PendingQueueSize",
74  "The size of the queue for packets pending an arp reply.",
75  UintegerValue(3),
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 
98 void
100 {
101  NS_LOG_FUNCTION(this);
102  Flush();
103  m_device = nullptr;
104  m_interface = nullptr;
106  {
108  }
110 }
111 
112 void
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 
134 void
136 {
137  NS_LOG_FUNCTION(this << aliveTimeout);
138  m_aliveTimeout = aliveTimeout;
139 }
140 
141 void
143 {
144  NS_LOG_FUNCTION(this << deadTimeout);
145  m_deadTimeout = deadTimeout;
146 }
147 
148 void
150 {
151  NS_LOG_FUNCTION(this << waitReplyTimeout);
152  m_waitReplyTimeout = waitReplyTimeout;
153 }
154 
155 Time
157 {
158  NS_LOG_FUNCTION(this);
159  return m_aliveTimeout;
160 }
161 
162 Time
164 {
165  NS_LOG_FUNCTION(this);
166  return m_deadTimeout;
167 }
168 
169 Time
171 {
172  NS_LOG_FUNCTION(this);
173  return m_waitReplyTimeout;
174 }
175 
176 void
178 {
179  NS_LOG_FUNCTION(this << &arpRequestCallback);
180  m_arpRequestCallback = arpRequestCallback;
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION(this);
188  {
189  NS_LOG_LOGIC("Starting WaitReplyTimer at " << Simulator::Now() << " for "
190  << m_waitReplyTimeout);
193  }
194 }
195 
196 void
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 
244 void
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 
261 void
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 
305 void
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 
322 std::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 
363 void
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 
389 bool
391 {
392  NS_LOG_FUNCTION(this);
393  return (m_state == DEAD);
394 }
395 
396 bool
398 {
399  NS_LOG_FUNCTION(this);
400  return (m_state == ALIVE);
401 }
402 
403 bool
405 {
406  NS_LOG_FUNCTION(this);
407  return (m_state == WAIT_REPLY);
408 }
409 
410 bool
412 {
413  NS_LOG_FUNCTION(this);
414  return (m_state == PERMANENT);
415 }
416 
417 bool
419 {
420  NS_LOG_FUNCTION(this);
421  return (m_state == STATIC_AUTOGENERATED);
422 }
423 
424 void
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 
434 void
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 
445 void
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 
456 void
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 
467 bool
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 
484 void
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 
498 Address
500 {
501  NS_LOG_FUNCTION(this);
502  return m_macAddress;
503 }
504 
505 void
507 {
508  NS_LOG_FUNCTION(this);
509  m_macAddress = macAddress;
510 }
511 
514 {
515  NS_LOG_FUNCTION(this);
516  return m_ipv4Address;
517 }
518 
519 void
521 {
522  NS_LOG_FUNCTION(this << destination);
523  m_ipv4Address = destination;
524 }
525 
526 Time
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 
546 bool
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 
573 void
575 {
576  NS_LOG_FUNCTION(this);
577  m_pending.clear();
578 }
579 
580 void
582 {
583  NS_LOG_FUNCTION(this);
584  m_lastSeen = Simulator::Now();
585 }
586 
587 uint32_t
589 {
590  NS_LOG_FUNCTION(this);
591  return m_retries;
592 }
593 
594 void
596 {
597  NS_LOG_FUNCTION(this);
598  m_retries++;
599  UpdateSeen();
600 }
601 
602 void
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:352
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: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
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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
#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.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:839
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
ns3::Time timeout