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 
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  Ptr<Packet> pending = entry->DequeuePending ();
223  while (pending != 0)
224  {
225  m_dropTrace (pending);
226  pending = entry->DequeuePending ();
227  }
228  }
229  }
230 
231  }
232  if (restartWaitReplyTimer)
233  {
234  NS_LOG_LOGIC ("Restarting WaitReplyTimer at " << Simulator::Now ().GetSeconds ());
237  }
238 }
239 
240 void
242 {
243  NS_LOG_FUNCTION (this);
244  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
245  {
246  delete (*i).second;
247  }
248  m_arpCache.erase (m_arpCache.begin (), m_arpCache.end ());
250  {
251  NS_LOG_LOGIC ("Stopping WaitReplyTimer at " << Simulator::Now ().GetSeconds () << " due to ArpCache flush");
253  }
254 }
255 
256 void
258 {
259  NS_LOG_FUNCTION (this << stream);
260  std::ostream* os = stream->GetStream ();
261 
262  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
263  {
264  *os << i->first << " dev ";
265  std::string found = Names::FindName (m_device);
266  if (Names::FindName (m_device) != "")
267  {
268  *os << found;
269  }
270  else
271  {
272  *os << static_cast<int> (m_device->GetIfIndex ());
273  }
274 
275  *os << " lladdr " << i->second->GetMacAddress ();
276 
277  if (i->second->IsAlive ())
278  {
279  *os << " REACHABLE\n";
280  }
281  else if (i->second->IsWaitReply ())
282  {
283  *os << " DELAY\n";
284  }
285  else
286  {
287  *os << " STALE\n";
288  }
289  }
290 }
291 
294 {
295  NS_LOG_FUNCTION (this << to);
296  if (m_arpCache.find (to) != m_arpCache.end ())
297  {
298  ArpCache::Entry *entry = m_arpCache[to];
299  return entry;
300  }
301  return 0;
302 }
303 
306 {
307  NS_LOG_FUNCTION (this << to);
308  NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ());
309 
310  ArpCache::Entry *entry = new ArpCache::Entry (this);
311  m_arpCache[to] = entry;
312  entry->SetIpv4Address (to);
313  return entry;
314 }
315 
317  : m_arp (arp),
318  m_state (ALIVE),
319  m_retries (0)
320 {
321  NS_LOG_FUNCTION (this << arp);
322 }
323 
324 
325 bool
327 {
328  NS_LOG_FUNCTION (this);
329  return (m_state == DEAD) ? true : false;
330 }
331 bool
333 {
334  NS_LOG_FUNCTION (this);
335  return (m_state == ALIVE) ? true : false;
336 }
337 bool
339 {
340  NS_LOG_FUNCTION (this);
341  return (m_state == WAIT_REPLY) ? true : false;
342 }
343 
344 
345 void
347 {
348  NS_LOG_FUNCTION (this);
349  m_state = DEAD;
350  ClearRetries ();
351  UpdateSeen ();
352 }
353 void
355 {
356  NS_LOG_FUNCTION (this << macAddress);
357  NS_ASSERT (m_state == WAIT_REPLY);
358  m_macAddress = macAddress;
359  m_state = ALIVE;
360  ClearRetries ();
361  UpdateSeen ();
362 }
363 
364 bool
366 {
367  NS_LOG_FUNCTION (this << waiting);
368  NS_ASSERT (m_state == WAIT_REPLY);
369  /* We are already waiting for an answer so
370  * we dump the previously waiting packet and
371  * replace it with this one.
372  */
373  if (m_pending.size () >= m_arp->m_pendingQueueSize)
374  {
375  return false;
376  }
377  m_pending.push_back (waiting);
378  return true;
379 }
380 void
382 {
383  NS_LOG_FUNCTION (this << waiting);
384  NS_ASSERT (m_state == ALIVE || m_state == DEAD);
385  NS_ASSERT (m_pending.empty ());
386  m_state = WAIT_REPLY;
387  m_pending.push_back (waiting);
388  UpdateSeen ();
389  m_arp->StartWaitReplyTimer ();
390 }
391 
392 Address
394 {
395  NS_LOG_FUNCTION (this);
396  return m_macAddress;
397 }
400 {
401  NS_LOG_FUNCTION (this);
402  return m_ipv4Address;
403 }
404 void
406 {
407  NS_LOG_FUNCTION (this << destination);
408  m_ipv4Address = destination;
409 }
410 Time
412 {
413  NS_LOG_FUNCTION (this);
414  switch (m_state) {
416  return m_arp->GetWaitReplyTimeout ();
418  return m_arp->GetDeadTimeout ();
420  return m_arp->GetAliveTimeout ();
421  default:
422  NS_ASSERT (false);
423  return Seconds (0);
424  /* NOTREACHED */
425  }
426 }
427 bool
429 {
430  NS_LOG_FUNCTION (this);
431  Time timeout = GetTimeout ();
432  Time delta = Simulator::Now () - m_lastSeen;
433  NS_LOG_DEBUG ("delta=" << delta.GetSeconds () << "s");
434  if (delta > timeout)
435  {
436  return true;
437  }
438  return false;
439 }
442 {
443  NS_LOG_FUNCTION (this);
444  if (m_pending.empty ())
445  {
446  return 0;
447  }
448  else
449  {
450  Ptr<Packet> p = m_pending.front ();
451  m_pending.pop_front ();
452  return p;
453  }
454 }
455 void
457 {
458  NS_LOG_FUNCTION (this);
459  m_lastSeen = Simulator::Now ();
460 }
461 uint32_t
463 {
464  NS_LOG_FUNCTION (this);
465  return m_retries;
466 }
467 void
469 {
470  NS_LOG_FUNCTION (this);
471  m_retries++;
472  UpdateSeen ();
473 }
474 void
476 {
477  NS_LOG_FUNCTION (this);
478  m_retries = 0;
479 }
480 
481 } // namespace ns3
482 
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:293
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
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:984
ArpCache::Entry * Add(Ipv4Address to)
Add an Ipv4Address to this ARP cache.
Definition: arp-cache.cc:305
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:257
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition: arp-cache.cc:293
#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
Callback< void, Ptr< const ArpCache >, Ipv4Address > m_arpRequestCallback
reply timeout callback
Definition: arp-cache.h:292
#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
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:339
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:819
ns3::Time timeout
bool IsAlive(void)
Definition: arp-cache.cc:332
EventId m_waitReplyTimer
cache alive state timer
Definition: arp-cache.h:291
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
Cache m_arpCache
the ARP cache
Definition: arp-cache.h:302
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:334
void SetIpv4Address(Ipv4Address destination)
Definition: arp-cache.cc:405
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
AttributeValue implementation for Time.
Definition: nstime.h:928
void MarkWaitReply(Ptr< Packet > waiting)
Definition: arp-cache.cc:381
Hold an unsigned integer type.
Definition: uinteger.h:44
uint32_t GetRetries(void) const
Definition: arp-cache.cc:462
bool IsDead(void)
Definition: arp-cache.cc:326
Ptr< Ipv4Interface > m_interface
Ipv4Interface associated with the cache.
Definition: arp-cache.h:287
bool IsExpired(void) const
Definition: arp-cache.cc:428
Ipv4Address GetIpv4Address(void) const
Definition: arp-cache.cc:399
Time m_waitReplyTimeout
cache reply state timeout
Definition: arp-cache.h:290
#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:393
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:468
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void MarkAlive(Address macAddress)
Definition: arp-cache.cc:354
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:168
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:929
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:241
Entry(ArpCache *arp)
Constructor.
Definition: arp-cache.cc:316
Time GetTimeout(void) const
Returns the entry timeout.
Definition: arp-cache.cc:411
void UpdateSeen(void)
Update the entry when seeing a packet.
Definition: arp-cache.cc:456
TracedCallback< Ptr< const Packet > > m_dropTrace
trace for packets dropped by the ARP cache queue
Definition: arp-cache.h:303
bool UpdateWaitReply(Ptr< Packet > waiting)
Definition: arp-cache.cc:365
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:40
sgi::hash_map< Ipv4Address, ArpCache::Entry *, Ipv4AddressHash >::iterator CacheI
ARP Cache container iterator.
Definition: arp-cache.h:282
#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:866
bool IsWaitReply(void)
Definition: arp-cache.cc:338
An ARP cache.
Definition: arp-cache.h:50
Ptr< Packet > DequeuePending(void)
Definition: arp-cache.cc:441
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:671
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:475
Ptr< NetDevice > m_device
NetDevice associated with the cache.
Definition: arp-cache.h:286
void MarkDead(void)
Changes the state of this entry to dead.
Definition: arp-cache.cc:346
Time m_deadTimeout
cache dead state timeout
Definition: arp-cache.h:289
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:301
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:288
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:57
TypeId SetParent(TypeId tid)
Definition: type-id.cc:638
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.