A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
arp-cache.cc
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 
28 #include "arp-cache.h"
29 #include "arp-header.h"
30 #include "ipv4-interface.h"
31 
32 NS_LOG_COMPONENT_DEFINE ("ArpCache");
33 
34 namespace ns3 {
35 
36 NS_OBJECT_ENSURE_REGISTERED (ArpCache);
37 
38 TypeId
39 ArpCache::GetTypeId (void)
40 {
41  static TypeId tid = TypeId ("ns3::ArpCache")
42  .SetParent<Object> ()
43  .AddAttribute ("AliveTimeout",
44  "When this timeout expires, the matching cache entry needs refreshing",
45  TimeValue (Seconds (120)),
46  MakeTimeAccessor (&ArpCache::m_aliveTimeout),
47  MakeTimeChecker ())
48  .AddAttribute ("DeadTimeout",
49  "When this timeout expires, a new attempt to resolve the matching entry is made",
50  TimeValue (Seconds (100)),
51  MakeTimeAccessor (&ArpCache::m_deadTimeout),
52  MakeTimeChecker ())
53  .AddAttribute ("WaitReplyTimeout",
54  "When this timeout expires, the cache entries will be scanned and entries in WaitReply state will resend ArpRequest unless MaxRetries has been exceeded, in which case the entry is marked dead",
55  TimeValue (Seconds (1)),
56  MakeTimeAccessor (&ArpCache::m_waitReplyTimeout),
57  MakeTimeChecker ())
58  .AddAttribute ("MaxRetries",
59  "Number of retransmissions of ArpRequest before marking dead",
60  UintegerValue (3),
61  MakeUintegerAccessor (&ArpCache::m_maxRetries),
62  MakeUintegerChecker<uint32_t> ())
63  .AddAttribute ("PendingQueueSize",
64  "The size of the queue for packets pending an arp reply.",
65  UintegerValue (3),
66  MakeUintegerAccessor (&ArpCache::m_pendingQueueSize),
67  MakeUintegerChecker<uint32_t> ())
68  .AddTraceSource ("Drop",
69  "Packet dropped due to ArpCache entry in WaitReply expiring.",
70  MakeTraceSourceAccessor (&ArpCache::m_dropTrace))
71  ;
72  return tid;
73 }
74 
75 ArpCache::ArpCache ()
76  : m_device (0),
77  m_interface (0)
78 {
79  NS_LOG_FUNCTION (this);
80 }
81 
82 ArpCache::~ArpCache ()
83 {
84  NS_LOG_FUNCTION (this);
85 }
86 
87 void
89 {
90  NS_LOG_FUNCTION (this);
91  Flush ();
92  m_device = 0;
93  m_interface = 0;
94  if (!m_waitReplyTimer.IsRunning ())
95  {
96  Simulator::Remove (m_waitReplyTimer);
97  }
99 }
100 
101 void
103 {
104  NS_LOG_FUNCTION (this << device << interface);
105  m_device = device;
106  m_interface = interface;
107 }
108 
111 {
112  NS_LOG_FUNCTION (this);
113  return m_device;
114 }
115 
118 {
119  NS_LOG_FUNCTION (this);
120  return m_interface;
121 }
122 
123 void
124 ArpCache::SetAliveTimeout (Time aliveTimeout)
125 {
126  NS_LOG_FUNCTION (this << aliveTimeout);
127  m_aliveTimeout = aliveTimeout;
128 }
129 void
130 ArpCache::SetDeadTimeout (Time deadTimeout)
131 {
132  NS_LOG_FUNCTION (this << deadTimeout);
133  m_deadTimeout = deadTimeout;
134 }
135 void
136 ArpCache::SetWaitReplyTimeout (Time waitReplyTimeout)
137 {
138  NS_LOG_FUNCTION (this << waitReplyTimeout);
139  m_waitReplyTimeout = waitReplyTimeout;
140 }
141 
142 Time
143 ArpCache::GetAliveTimeout (void) const
144 {
145  NS_LOG_FUNCTION (this);
146  return m_aliveTimeout;
147 }
148 Time
149 ArpCache::GetDeadTimeout (void) const
150 {
151  NS_LOG_FUNCTION (this);
152  return m_deadTimeout;
153 }
154 Time
155 ArpCache::GetWaitReplyTimeout (void) const
156 {
157  NS_LOG_FUNCTION (this);
158  return m_waitReplyTimeout;
159 }
160 
161 void
163  Ipv4Address> arpRequestCallback)
164 {
165  NS_LOG_FUNCTION (this << &arpRequestCallback);
166  m_arpRequestCallback = arpRequestCallback;
167 }
168 
169 void
171 {
172  NS_LOG_FUNCTION (this);
173  if (!m_waitReplyTimer.IsRunning ())
174  {
175  NS_LOG_LOGIC ("Starting WaitReplyTimer at " << Simulator::Now () << " for " <<
176  m_waitReplyTimeout);
177  m_waitReplyTimer = Simulator::Schedule (m_waitReplyTimeout,
179  }
180 }
181 
182 void
184 {
185  NS_LOG_FUNCTION (this);
186  ArpCache::Entry* entry;
187  bool restartWaitReplyTimer = false;
188  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
189  {
190  entry = (*i).second;
191  if (entry != 0 && entry->IsWaitReply ())
192  {
193  if (entry->GetRetries () < m_maxRetries)
194  {
195  NS_LOG_LOGIC ("node="<< m_device->GetNode ()->GetId () <<
196  ", ArpWaitTimeout for " << entry->GetIpv4Address () <<
197  " expired -- retransmitting arp request since retries = " <<
198  entry->GetRetries ());
199  m_arpRequestCallback (this, entry->GetIpv4Address ());
200  restartWaitReplyTimer = true;
201  entry->IncrementRetries ();
202  }
203  else
204  {
205  NS_LOG_LOGIC ("node="<<m_device->GetNode ()->GetId () <<
206  ", wait reply for " << entry->GetIpv4Address () <<
207  " expired -- drop since max retries exceeded: " <<
208  entry->GetRetries ());
209  entry->MarkDead ();
210  entry->ClearRetries ();
211  Ptr<Packet> pending = entry->DequeuePending ();
212  while (pending != 0)
213  {
214  m_dropTrace (pending);
215  pending = entry->DequeuePending ();
216  }
217  }
218  }
219 
220  }
221  if (restartWaitReplyTimer)
222  {
223  NS_LOG_LOGIC ("Restarting WaitReplyTimer at " << Simulator::Now ().GetSeconds ());
224  m_waitReplyTimer = Simulator::Schedule (m_waitReplyTimeout,
226  }
227 }
228 
229 void
231 {
232  NS_LOG_FUNCTION (this);
233  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++)
234  {
235  delete (*i).second;
236  }
237  m_arpCache.erase (m_arpCache.begin (), m_arpCache.end ());
238  if (m_waitReplyTimer.IsRunning ())
239  {
240  NS_LOG_LOGIC ("Stopping WaitReplyTimer at " << Simulator::Now ().GetSeconds () << " due to ArpCache flush");
241  m_waitReplyTimer.Cancel ();
242  }
243 }
244 
247 {
248  NS_LOG_FUNCTION (this << to);
249  if (m_arpCache.find (to) != m_arpCache.end ())
250  {
251  ArpCache::Entry *entry = m_arpCache[to];
252  return entry;
253  }
254  return 0;
255 }
256 
259 {
260  NS_LOG_FUNCTION (this << to);
261  NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ());
262 
263  ArpCache::Entry *entry = new ArpCache::Entry (this);
264  m_arpCache[to] = entry;
265  entry->SetIpv4Address (to);
266  return entry;
267 }
268 
270  : m_arp (arp),
271  m_state (ALIVE),
272  m_retries (0)
273 {
274  NS_LOG_FUNCTION (this << arp);
275 }
276 
277 
278 bool
280 {
281  NS_LOG_FUNCTION (this);
282  return (m_state == DEAD) ? true : false;
283 }
284 bool
286 {
287  NS_LOG_FUNCTION (this);
288  return (m_state == ALIVE) ? true : false;
289 }
290 bool
292 {
293  NS_LOG_FUNCTION (this);
294  return (m_state == WAIT_REPLY) ? true : false;
295 }
296 
297 
298 void
300 {
301  NS_LOG_FUNCTION (this);
302  m_state = DEAD;
303  ClearRetries ();
304  UpdateSeen ();
305 }
306 void
308 {
309  NS_LOG_FUNCTION (this << macAddress);
310  NS_ASSERT (m_state == WAIT_REPLY);
311  m_macAddress = macAddress;
312  m_state = ALIVE;
313  ClearRetries ();
314  UpdateSeen ();
315 }
316 
317 bool
319 {
320  NS_LOG_FUNCTION (this << waiting);
321  NS_ASSERT (m_state == WAIT_REPLY);
322  /* We are already waiting for an answer so
323  * we dump the previously waiting packet and
324  * replace it with this one.
325  */
326  if (m_pending.size () >= m_arp->m_pendingQueueSize)
327  {
328  return false;
329  }
330  m_pending.push_back (waiting);
331  return true;
332 }
333 void
335 {
336  NS_LOG_FUNCTION (this << waiting);
337  NS_ASSERT (m_state == ALIVE || m_state == DEAD);
338  NS_ASSERT (m_pending.empty ());
339  m_state = WAIT_REPLY;
340  m_pending.push_back (waiting);
341  UpdateSeen ();
342  m_arp->StartWaitReplyTimer ();
343 }
344 
345 Address
347 {
348  NS_LOG_FUNCTION (this);
349  NS_ASSERT (m_state == ALIVE);
350  return m_macAddress;
351 }
354 {
355  NS_LOG_FUNCTION (this);
356  return m_ipv4Address;
357 }
358 void
360 {
361  NS_LOG_FUNCTION (this << destination);
362  m_ipv4Address = destination;
363 }
364 Time
365 ArpCache::Entry::GetTimeout (void) const
366 {
367  NS_LOG_FUNCTION (this);
368  switch (m_state) {
369  case ArpCache::Entry::WAIT_REPLY:
370  return m_arp->GetWaitReplyTimeout ();
371  case ArpCache::Entry::DEAD:
372  return m_arp->GetDeadTimeout ();
373  case ArpCache::Entry::ALIVE:
374  return m_arp->GetAliveTimeout ();
375  default:
376  NS_ASSERT (false);
377  return Seconds (0);
378  /* NOTREACHED */
379  }
380 }
381 bool
383 {
384  NS_LOG_FUNCTION (this);
385  Time timeout = GetTimeout ();
386  Time delta = Simulator::Now () - m_lastSeen;
387  NS_LOG_DEBUG ("delta=" << delta.GetSeconds () << "s");
388  if (delta > timeout)
389  {
390  return true;
391  }
392  return false;
393 }
396 {
397  NS_LOG_FUNCTION (this);
398  if (m_pending.empty ())
399  {
400  return 0;
401  }
402  else
403  {
404  Ptr<Packet> p = m_pending.front ();
405  m_pending.pop_front ();
406  return p;
407  }
408 }
409 void
410 ArpCache::Entry::UpdateSeen (void)
411 {
412  NS_LOG_FUNCTION (this);
413  m_lastSeen = Simulator::Now ();
414 }
415 uint32_t
417 {
418  NS_LOG_FUNCTION (this);
419  return m_retries;
420 }
421 void
423 {
424  NS_LOG_FUNCTION (this);
425  m_retries++;
426  UpdateSeen ();
427 }
428 void
430 {
431  NS_LOG_FUNCTION (this);
432  m_retries = 0;
433 }
434 
435 } // namespace ns3
436 
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv4Interface > interface)
Definition: arp-cache.cc:102
void StartWaitReplyTimer(void)
Definition: arp-cache.cc:170
keep track of time unit.
Definition: nstime.h:149
void SetArpRequestCallback(Callback< void, Ptr< const ArpCache >, Ipv4Address > arpRequestCallback)
Definition: arp-cache.cc:162
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Callback template class.
Definition: callback.h:369
ArpCache::Entry * Add(Ipv4Address to)
Add an Ipv4Address to this ARP cache.
Definition: arp-cache.cc:258
virtual void DoDispose(void)
Definition: arp-cache.cc:88
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition: arp-cache.cc:246
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
Ptr< NetDevice > GetDevice(void) const
Definition: arp-cache.cc:110
virtual void DoDispose(void)
Definition: object.cc:335
bool IsRunning(void) const
Definition: event-id.cc:59
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
bool IsAlive(void)
Definition: arp-cache.cc:285
a polymophic address class
Definition: address.h:86
double GetSeconds(void) const
Definition: nstime.h:262
void SetIpv4Address(Ipv4Address destination)
Definition: arp-cache.cc:359
void HandleWaitReplyTimeout(void)
Definition: arp-cache.cc:183
void MarkWaitReply(Ptr< Packet > waiting)
Definition: arp-cache.cc:334
uint32_t GetRetries(void) const
Definition: arp-cache.cc:416
bool IsDead(void)
Definition: arp-cache.cc:279
bool IsExpired(void) const
Definition: arp-cache.cc:382
Ipv4Address GetIpv4Address(void) const
Definition: arp-cache.cc:353
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
Address GetMacAddress(void) const
Definition: arp-cache.cc:346
Ptr< Ipv4Interface > GetInterface(void) const
Definition: arp-cache.cc:117
static void Remove(const EventId &id)
Definition: simulator.cc:257
void IncrementRetries(void)
Increment the counter of number of retries for an entry.
Definition: arp-cache.cc:422
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
void MarkAlive(Address macAddress)
Definition: arp-cache.cc:307
A record that that holds information about an ArpCache entry.
Definition: arp-cache.h:116
static Time Now(void)
Definition: simulator.cc:179
void Flush(void)
Clear the ArpCache of all entries.
Definition: arp-cache.cc:230
Entry(ArpCache *arp)
Constructor.
Definition: arp-cache.cc:269
bool UpdateWaitReply(Ptr< Packet > waiting)
Definition: arp-cache.cc:318
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
bool IsWaitReply(void)
Definition: arp-cache.cc:291
An ARP cache.
Definition: arp-cache.h:49
Ptr< Packet > DequeuePending(void)
Definition: arp-cache.cc:395
void Cancel(void)
Definition: event-id.cc:47
void ClearRetries(void)
Zero the counter of number of retries for an entry.
Definition: arp-cache.cc:429
void MarkDead(void)
Changes the state of this entry to dead.
Definition: arp-cache.cc:299