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