A Discrete-Event Network Simulator
API
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 #include "ipv4-header.h"
33 
34 namespace ns3 {
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)),
51  MakeTimeChecker ())
52  .AddAttribute ("DeadTimeout",
53  "When this timeout expires, "
54  "a new attempt to resolve the matching entry is made",
55  TimeValue (Seconds (100)),
57  MakeTimeChecker ())
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)),
66  MakeTimeChecker ())
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  ;
84  return tid;
85 }
86 
88  : m_device (0),
89  m_interface (0)
90 {
91  NS_LOG_FUNCTION (this);
92 }
93 
95 {
96  NS_LOG_FUNCTION (this);
97 }
98 
99 void
101 {
102  NS_LOG_FUNCTION (this);
103  Flush ();
104  m_device = 0;
105  m_interface = 0;
106  if (!m_waitReplyTimer.IsRunning ())
107  {
109  }
111 }
112 
113 void
115 {
116  NS_LOG_FUNCTION (this << device << interface);
117  m_device = device;
118  m_interface = interface;
119 }
120 
123 {
124  NS_LOG_FUNCTION (this);
125  return m_device;
126 }
127 
130 {
131  NS_LOG_FUNCTION (this);
132  return m_interface;
133 }
134 
135 void
137 {
138  NS_LOG_FUNCTION (this << aliveTimeout);
139  m_aliveTimeout = aliveTimeout;
140 }
141 void
143 {
144  NS_LOG_FUNCTION (this << deadTimeout);
145  m_deadTimeout = deadTimeout;
146 }
147 void
149 {
150  NS_LOG_FUNCTION (this << waitReplyTimeout);
151  m_waitReplyTimeout = waitReplyTimeout;
152 }
153 
154 Time
156 {
157  NS_LOG_FUNCTION (this);
158  return m_aliveTimeout;
159 }
160 Time
162 {
163  NS_LOG_FUNCTION (this);
164  return m_deadTimeout;
165 }
166 Time
168 {
169  NS_LOG_FUNCTION (this);
170  return m_waitReplyTimeout;
171 }
172 
173 void
175  Ipv4Address> arpRequestCallback)
176 {
177  NS_LOG_FUNCTION (this << &arpRequestCallback);
178  m_arpRequestCallback = arpRequestCallback;
179 }
180 
181 void
183 {
184  NS_LOG_FUNCTION (this);
185  if (!m_waitReplyTimer.IsRunning ())
186  {
187  NS_LOG_LOGIC ("Starting WaitReplyTimer at " << Simulator::Now () << " for " <<
191  }
192 }
193 
194 void
196 {
197  NS_LOG_FUNCTION (this);
198  ArpCache::Entry* entry;
199  bool restartWaitReplyTimer = false;
200  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
201  {
202  entry = (*i).second;
203  if (entry != 0 && entry->IsWaitReply ())
204  {
205  if (entry->GetRetries () < m_maxRetries)
206  {
207  NS_LOG_LOGIC ("node="<< m_device->GetNode ()->GetId () <<
208  ", ArpWaitTimeout for " << entry->GetIpv4Address () <<
209  " expired -- retransmitting arp request since retries = " <<
210  entry->GetRetries ());
211  m_arpRequestCallback (this, entry->GetIpv4Address ());
212  restartWaitReplyTimer = true;
213  entry->IncrementRetries ();
214  }
215  else
216  {
217  NS_LOG_LOGIC ("node="<<m_device->GetNode ()->GetId () <<
218  ", wait reply for " << entry->GetIpv4Address () <<
219  " expired -- drop since max retries exceeded: " <<
220  entry->GetRetries ());
221  entry->MarkDead ();
222  entry->ClearRetries ();
223  Ipv4PayloadHeaderPair pending = entry->DequeuePending ();
224  while (pending.first != 0)
225  {
226  // add the Ipv4 header for tracing purposes
227  pending.first->AddHeader (pending.second);
228  m_dropTrace (pending.first);
229  pending = entry->DequeuePending ();
230  }
231  }
232  }
233 
234  }
235  if (restartWaitReplyTimer)
236  {
237  NS_LOG_LOGIC ("Restarting WaitReplyTimer at " << Simulator::Now ().GetSeconds ());
240  }
241 }
242 
243 void
245 {
246  NS_LOG_FUNCTION (this);
247  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
248  {
249  delete (*i).second;
250  }
251  m_arpCache.erase (m_arpCache.begin (), m_arpCache.end ());
253  {
254  NS_LOG_LOGIC ("Stopping WaitReplyTimer at " << Simulator::Now ().GetSeconds () << " due to ArpCache flush");
256  }
257 }
258 
259 void
261 {
262  NS_LOG_FUNCTION (this << stream);
263  std::ostream* os = stream->GetStream ();
264 
265  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
266  {
267  *os << i->first << " dev ";
268  std::string found = Names::FindName (m_device);
269  if (Names::FindName (m_device) != "")
270  {
271  *os << found;
272  }
273  else
274  {
275  *os << static_cast<int> (m_device->GetIfIndex ());
276  }
277 
278  *os << " lladdr " << i->second->GetMacAddress ();
279 
280  if (i->second->IsAlive ())
281  {
282  *os << " REACHABLE\n";
283  }
284  else if (i->second->IsWaitReply ())
285  {
286  *os << " DELAY\n";
287  }
288  else if (i->second->IsPermanent ())
289  {
290  *os << " PERMANENT\n";
291  }
292  else
293  {
294  *os << " STALE\n";
295  }
296  }
297 }
298 
299 std::list<ArpCache::Entry *>
301 {
302  NS_LOG_FUNCTION (this << to);
303 
304  std::list<ArpCache::Entry *> entryList;
305  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
306  {
307  ArpCache::Entry *entry = (*i).second;
308  if (entry->GetMacAddress () == to)
309  {
310  entryList.push_back (entry);
311  }
312  }
313  return entryList;
314 }
315 
316 
319 {
320  NS_LOG_FUNCTION (this << to);
321  if (m_arpCache.find (to) != m_arpCache.end ())
322  {
323  ArpCache::Entry *entry = m_arpCache[to];
324  return entry;
325  }
326  return 0;
327 }
328 
331 {
332  NS_LOG_FUNCTION (this << to);
333  NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ());
334 
335  ArpCache::Entry *entry = new ArpCache::Entry (this);
336  m_arpCache[to] = entry;
337  entry->SetIpv4Address (to);
338  return entry;
339 }
340 
341 void
343 {
344  NS_LOG_FUNCTION (this << entry);
345 
346  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
347  {
348  if ((*i).second == entry)
349  {
350  m_arpCache.erase (i);
351  entry->ClearPendingPacket (); //clear the pending packets for entry's ipaddress
352  delete entry;
353  return;
354  }
355  }
356  NS_LOG_WARN ("Entry not found in this ARP Cache");
357 }
358 
360  : m_arp (arp),
361  m_state (ALIVE),
362  m_retries (0)
363 {
364  NS_LOG_FUNCTION (this << arp);
365 }
366 
367 
368 bool
370 {
371  NS_LOG_FUNCTION (this);
372  return (m_state == DEAD) ? true : false;
373 }
374 bool
376 {
377  NS_LOG_FUNCTION (this);
378  return (m_state == ALIVE) ? true : false;
379 }
380 bool
382 {
383  NS_LOG_FUNCTION (this);
384  return (m_state == WAIT_REPLY) ? true : false;
385 }
386 bool
388 {
389  NS_LOG_FUNCTION (this);
390  return (m_state == PERMANENT) ? true : false;
391 }
392 
393 
394 void
396 {
397  NS_LOG_FUNCTION (this);
398  NS_ASSERT (m_state == ALIVE || m_state == WAIT_REPLY || m_state == DEAD);
399  m_state = DEAD;
400  ClearRetries ();
401  UpdateSeen ();
402 }
403 void
405 {
406  NS_LOG_FUNCTION (this << macAddress);
407  NS_ASSERT (m_state == WAIT_REPLY);
408  m_macAddress = macAddress;
409  m_state = ALIVE;
410  ClearRetries ();
411  UpdateSeen ();
412 }
413 void
415 {
416  NS_LOG_FUNCTION (this << m_macAddress);
417  NS_ASSERT (!m_macAddress.IsInvalid ());
418 
419  m_state = PERMANENT;
420  ClearRetries ();
421  UpdateSeen ();
422 }
423 bool
425 {
426  NS_LOG_FUNCTION (this << waiting.first);
427  NS_ASSERT (m_state == WAIT_REPLY);
428  /* We are already waiting for an answer so
429  * we dump the previously waiting packet and
430  * replace it with this one.
431  */
432  if (m_pending.size () >= m_arp->m_pendingQueueSize)
433  {
434  return false;
435  }
436  m_pending.push_back (waiting);
437  return true;
438 }
439 void
441 {
442  NS_LOG_FUNCTION (this << waiting.first);
443  NS_ASSERT (m_state == ALIVE || m_state == DEAD);
444  NS_ASSERT (m_pending.empty ());
445  NS_ASSERT_MSG (waiting.first, "Can not add a null packet to the ARP queue");
446 
447  m_state = WAIT_REPLY;
448  m_pending.push_back (waiting);
449  UpdateSeen ();
450  m_arp->StartWaitReplyTimer ();
451 }
452 
453 Address
455 {
456  NS_LOG_FUNCTION (this);
457  return m_macAddress;
458 }
459 void
461 {
462  NS_LOG_FUNCTION (this);
463  m_macAddress = macAddress;
464 }
467 {
468  NS_LOG_FUNCTION (this);
469  return m_ipv4Address;
470 }
471 void
473 {
474  NS_LOG_FUNCTION (this << destination);
475  m_ipv4Address = destination;
476 }
477 Time
479 {
480  NS_LOG_FUNCTION (this);
481  switch (m_state) {
483  return m_arp->GetWaitReplyTimeout ();
485  return m_arp->GetDeadTimeout ();
487  return m_arp->GetAliveTimeout ();
489  return Time::Max ();
490  default:
491  NS_ASSERT (false);
492  return Seconds (0);
493  /* NOTREACHED */
494  }
495 }
496 bool
498 {
499  NS_LOG_FUNCTION (this);
500  Time timeout = GetTimeout ();
501  Time delta = Simulator::Now () - m_lastSeen;
502  NS_LOG_DEBUG ("delta=" << delta.GetSeconds () << "s");
503  if (delta > timeout)
504  {
505  return true;
506  }
507  return false;
508 }
511 {
512  NS_LOG_FUNCTION (this);
513  if (m_pending.empty ())
514  {
515  Ipv4Header h;
516  return Ipv4PayloadHeaderPair (0, h);
517  }
518  else
519  {
520  Ipv4PayloadHeaderPair p = m_pending.front ();
521  m_pending.pop_front ();
522  return p;
523  }
524 }
525 void
527 {
528  NS_LOG_FUNCTION (this);
529  m_pending.clear ();
530 }
531 void
533 {
534  NS_LOG_FUNCTION (this);
535  m_lastSeen = Simulator::Now ();
536 }
537 uint32_t
539 {
540  NS_LOG_FUNCTION (this);
541  return m_retries;
542 }
543 void
545 {
546  NS_LOG_FUNCTION (this);
547  m_retries++;
548  UpdateSeen ();
549 }
550 void
552 {
553  NS_LOG_FUNCTION (this);
554  m_retries = 0;
555 }
556 
557 } // namespace ns3
558 
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv4Interface > interface)
Set the NetDevice and Ipv4Interface associated with the ArpCache.
Definition: arp-cache.cc:114
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:182
void MarkPermanent(void)
Changes the state of this entry to Permanent.
Definition: arp-cache.cc:414
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:174
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:330
virtual void DoDispose(void)
Destructor implementation.
Definition: arp-cache.cc:100
static TypeId GetTypeId(void)
Get the type ID.
Definition: arp-cache.cc:41
void PrintArpCache(Ptr< OutputStreamWrapper > stream)
Print the ARP cache entries.
Definition: arp-cache.cc:260
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
void SetMacAddresss(Address macAddress)
Definition: arp-cache.cc:460
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition: arp-cache.cc:318
#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:387
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:161
Ptr< NetDevice > GetDevice(void) const
Returns the NetDevice that this ARP cache is associated with.
Definition: arp-cache.cc:122
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:346
ns3::Time timeout
bool IsAlive(void)
Definition: arp-cache.cc:375
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:33
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:472
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:195
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1238
AttributeValue implementation for Time.
Definition: nstime.h:957
Hold an unsigned integer type.
Definition: uinteger.h:44
uint32_t GetRetries(void) const
Definition: arp-cache.cc:538
bool IsDead(void)
Definition: arp-cache.cc:369
Ptr< Ipv4Interface > m_interface
Ipv4Interface associated with the cache.
Definition: arp-cache.h:323
bool IsExpired(void) const
Definition: arp-cache.cc:497
Ipv4Address GetIpv4Address(void) const
Definition: arp-cache.cc:466
void MarkWaitReply(Ipv4PayloadHeaderPair waiting)
Definition: arp-cache.cc:440
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:454
void SetDeadTimeout(Time deadTimeout)
Set the time the entry will be in DEAD state before being removed.
Definition: arp-cache.cc:142
void SetAliveTimeout(Time aliveTimeout)
Set the time the entry will be in ALIVE state (unless refreshed)
Definition: arp-cache.cc:136
Ptr< Ipv4Interface > GetInterface(void) const
Returns the Ipv4Interface that this ARP cache is associated with.
Definition: arp-cache.cc:129
static void Remove(const EventId &id)
Remove an event from the event list.
Definition: simulator.cc:311
void IncrementRetries(void)
Increment the counter of number of retries for an entry.
Definition: arp-cache.cc:544
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void ClearPendingPacket(void)
Clear the pending packet list.
Definition: arp-cache.cc:526
void MarkAlive(Address macAddress)
Definition: arp-cache.cc:404
Time GetAliveTimeout(void) const
Get the time the entry will be in ALIVE state (unless refreshed)
Definition: arp-cache.cc:155
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:224
void Flush(void)
Clear the ArpCache of all entries.
Definition: arp-cache.cc:244
void Remove(ArpCache::Entry *entry)
Remove an entry.
Definition: arp-cache.cc:342
Entry(ArpCache *arp)
Constructor.
Definition: arp-cache.cc:359
Time GetTimeout(void) const
Returns the entry timeout.
Definition: arp-cache.cc:478
void UpdateSeen(void)
Update the entry when seeing a packet.
Definition: arp-cache.cc:532
#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:424
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
Ipv4PayloadHeaderPair DequeuePending(void)
Definition: arp-cache.cc:510
#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:381
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:167
void ClearRetries(void)
Zero the counter of number of retries for an entry.
Definition: arp-cache.cc:551
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:300
void MarkDead(void)
Changes the state of this entry to dead.
Definition: arp-cache.cc:395
Time m_deadTimeout
cache dead state timeout
Definition: arp-cache.h:325
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:148
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:904
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.