A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ndisc-cache.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007-2009 Strasbourg University
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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/uinteger.h"
23 #include "ns3/node.h"
24 
25 #include "ipv6-l3-protocol.h"
26 #include "icmpv6-l4-protocol.h"
27 #include "ndisc-cache.h"
28 #include "ipv6-interface.h"
29 
30 namespace ns3
31 {
32 
33 NS_LOG_COMPONENT_DEFINE ("NdiscCache")
34  ;
35 
36 NS_OBJECT_ENSURE_REGISTERED (NdiscCache)
37  ;
38 
40 {
41  static TypeId tid = TypeId ("ns3::NdiscCache")
42  .SetParent<Object> ()
43  .AddAttribute ("UnresolvedQueueSize",
44  "Size of the queue for packets pending an NA reply.",
46  MakeUintegerAccessor (&NdiscCache::m_unresQlen),
47  MakeUintegerChecker<uint32_t> ())
48  ;
49  return tid;
50 }
51 
53 {
55 }
56 
58 {
60  Flush ();
61 }
62 
64 {
66  Flush ();
67  m_device = 0;
68  m_interface = 0;
70 }
71 
73 {
74  NS_LOG_FUNCTION (this << device << interface);
75  m_device = device;
76  m_interface = interface;
77 }
78 
80 {
82  return m_interface;
83 }
84 
86 {
88  return m_device;
89 }
90 
92 {
93  NS_LOG_FUNCTION (this << dst);
94 
95  if (m_ndCache.find (dst) != m_ndCache.end ())
96  {
97  NdiscCache::Entry* entry = m_ndCache[dst];
98  return entry;
99  }
100  return 0;
101 }
102 
104 {
105  NS_LOG_FUNCTION (this << to);
106  NS_ASSERT (m_ndCache.find (to) == m_ndCache.end ());
107 
108  NdiscCache::Entry* entry = new NdiscCache::Entry (this);
109  entry->SetIpv6Address (to);
110  m_ndCache[to] = entry;
111  return entry;
112 }
113 
115 {
117 
118  for (CacheI i = m_ndCache.begin (); i != m_ndCache.end (); i++)
119  {
120  if ((*i).second == entry)
121  {
122  m_ndCache.erase (i);
123  entry->ClearWaitingPacket ();
124  delete entry;
125  return;
126  }
127  }
128 }
129 
131 {
133 
134  for (CacheI i = m_ndCache.begin (); i != m_ndCache.end (); i++)
135  {
136  delete (*i).second; /* delete the pointer NdiscCache::Entry */
137  }
138 
139  m_ndCache.erase (m_ndCache.begin (), m_ndCache.end ());
140 }
141 
142 void NdiscCache::SetUnresQlen (uint32_t unresQlen)
143 {
144  NS_LOG_FUNCTION (this << unresQlen);
145  m_unresQlen = unresQlen;
146 }
147 
149 {
151  return m_unresQlen;
152 }
153 
155  : m_ndCache (nd),
156  m_waiting (),
157  m_router (false),
158  m_reachableTimer (Timer::CANCEL_ON_DESTROY),
159  m_retransTimer (Timer::CANCEL_ON_DESTROY),
160  m_probeTimer (Timer::CANCEL_ON_DESTROY),
161  m_delayTimer (Timer::CANCEL_ON_DESTROY),
162  m_lastReachabilityConfirmation (Seconds (0.0)),
163  m_nsRetransmit (0)
164 {
166 }
167 
169 {
170  NS_LOG_FUNCTION (this << router);
171  m_router = router;
172 }
173 
175 {
177  return m_router;
178 }
179 
181 {
182  NS_LOG_FUNCTION (this << p);
183 
184  if (m_waiting.size () >= m_ndCache->GetUnresQlen ())
185  {
186  /* we store only m_unresQlen packet => first packet in first packet remove */
188  m_waiting.remove (0);
189  }
190  m_waiting.push_back (p);
191 }
192 
194 {
197  m_waiting.clear ();
198 }
199 
201 {
203  this->MarkStale ();
204 }
205 
207 {
209  Ptr<Icmpv6L4Protocol> icmpv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
210  Ipv6Address addr;
211 
212  /* determine source address */
213  if (m_ipv6Address.IsLinkLocal ())
214  {
215  addr = m_ndCache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();;
216  }
217  else if (!m_ipv6Address.IsAny ())
218  {
219  addr = m_ndCache->GetInterface ()->GetAddressMatchingDestination (m_ipv6Address).GetAddress ();
220 
221  if (addr.IsAny ()) /* maybe address has expired */
222  {
223  /* delete the entry */
224  m_ndCache->Remove (this);
225  return;
226  }
227  }
228 
229  if (GetNSRetransmit () < icmpv6->MAX_MULTICAST_SOLICIT)
230  {
231  IncNSRetransmit ();
232 
233  icmpv6->SendNS (addr, Ipv6Address::MakeSolicitedAddress (m_ipv6Address), m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ());
234  /* arm the timer again */
235  StartRetransmitTimer ();
236  }
237  else
238  {
239  Ptr<Packet> malformedPacket = m_waiting.front ();
240  if (malformedPacket == 0)
241  {
242  malformedPacket = Create<Packet> ();
243  }
244 
245  icmpv6->SendErrorDestinationUnreachable (malformedPacket, addr, Icmpv6Header::ICMPV6_ADDR_UNREACHABLE);
246 
247  /* delete the entry */
248  m_ndCache->Remove (this);
249  }
250 }
251 
253 {
255  Ptr<Ipv6L3Protocol> ipv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject<Ipv6L3Protocol> ();
256  Ptr<Icmpv6L4Protocol> icmpv6 = ipv6->GetIcmpv6 ();
257  Ipv6Address addr;
258 
259  this->MarkProbe ();
260 
261  if (m_ipv6Address.IsLinkLocal ())
262  {
263  addr = m_ndCache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
264  }
265  else if (!m_ipv6Address.IsAny ())
266  {
267  addr = m_ndCache->GetInterface ()->GetAddressMatchingDestination (m_ipv6Address).GetAddress ();
268  if (addr.IsAny ()) /* maybe address has expired */
269  {
270  /* delete the entry */
271  m_ndCache->Remove (this);
272  return;
273  }
274  }
275  else
276  {
277  /* should not happen */
278  return;
279  }
280 
281  Ptr<Packet> p = icmpv6->ForgeNS (addr, m_ipv6Address, m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ());
282  m_ndCache->GetDevice ()->Send (p, this->GetMacAddress (), Ipv6L3Protocol::PROT_NUMBER);
283 
284  ResetNSRetransmit ();
285  IncNSRetransmit ();
286  StartProbeTimer ();
287 }
288 
290 {
292  Ptr<Ipv6L3Protocol> ipv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject<Ipv6L3Protocol> ();
293  Ptr<Icmpv6L4Protocol> icmpv6 = ipv6->GetIcmpv6 ();
294 
295  if (GetNSRetransmit () < icmpv6->MAX_UNICAST_SOLICIT)
296  {
297  Ipv6Address addr;
298 
299  if (m_ipv6Address.IsLinkLocal ())
300  {
301  addr = m_ndCache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
302  }
303  else if (!m_ipv6Address.IsAny ())
304  {
305  addr = m_ndCache->GetInterface ()->GetAddressMatchingDestination (m_ipv6Address).GetAddress ();
306  if (addr.IsAny ()) /* maybe address has expired */
307  {
308  /* delete the entry */
309  m_ndCache->Remove (this);
310  return;
311  }
312  }
313  else
314  {
315  /* should not happen */
316  return;
317  }
318 
319  IncNSRetransmit ();
320  /* icmpv6->SendNS (m_ndCache->GetInterface ()->GetLinkLocalAddress (), m_ipv6Address, m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ()); */
321  Ptr<Packet> p = icmpv6->ForgeNS (addr, m_ipv6Address, m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ());
322  m_ndCache->GetDevice ()->Send (p, this->GetMacAddress (), Ipv6L3Protocol::PROT_NUMBER);
323 
324  /* arm the timer again */
325  StartProbeTimer ();
326  }
327  else
328  {
329  /* delete the entry */
330  m_ndCache->Remove (this);
331  }
332 }
333 
335 {
336  NS_LOG_FUNCTION (this << ipv6Address);
337  m_ipv6Address = ipv6Address;
338 }
339 
341 {
343  return m_nsRetransmit;
344 }
345 
347 {
349  m_nsRetransmit++;
350 }
351 
353 {
355  m_nsRetransmit = 0;
356 }
357 
359 {
361  return m_lastReachabilityConfirmation;
362 }
363 
365 {
367 }
368 
370 {
372  m_reachableTimer.SetFunction (&NdiscCache::Entry::FunctionReachableTimeout, this);
373  m_reachableTimer.SetDelay (MilliSeconds (Icmpv6L4Protocol::REACHABLE_TIME));
374  m_reachableTimer.Schedule ();
375 }
376 
378 {
380  m_reachableTimer.Cancel ();
381 }
382 
384 {
386  m_probeTimer.SetFunction (&NdiscCache::Entry::FunctionProbeTimeout, this);
387  m_probeTimer.SetDelay (MilliSeconds (Icmpv6L4Protocol::RETRANS_TIMER));
388  m_probeTimer.Schedule ();
389 }
390 
392 {
394  m_probeTimer.Cancel ();
395  ResetNSRetransmit ();
396 }
397 
398 
400 {
402  m_delayTimer.SetFunction (&NdiscCache::Entry::FunctionDelayTimeout, this);
403  m_delayTimer.SetDelay (Seconds (Icmpv6L4Protocol::DELAY_FIRST_PROBE_TIME));
404  m_delayTimer.Schedule ();
405 }
406 
408 {
410  m_delayTimer.Cancel ();
411  ResetNSRetransmit ();
412 }
413 
415 {
417  m_retransTimer.SetFunction (&NdiscCache::Entry::FunctionRetransmitTimeout, this);
418  m_retransTimer.SetDelay (MilliSeconds (Icmpv6L4Protocol::RETRANS_TIMER));
419  m_retransTimer.Schedule ();
420 }
421 
423 {
425  m_retransTimer.Cancel ();
426  ResetNSRetransmit ();
427 }
428 
430 {
431  NS_LOG_FUNCTION (this << p);
432  m_state = INCOMPLETE;
433 
434  if (p)
435  {
436  m_waiting.push_back (p);
437  }
438 }
439 
440 std::list<Ptr<Packet> > NdiscCache::Entry::MarkReachable (Address mac)
441 {
442  NS_LOG_FUNCTION (this << mac);
443  m_state = REACHABLE;
444  m_macAddress = mac;
445  return m_waiting;
446 }
447 
449 {
451  m_state = PROBE;
452 }
453 
455 {
457  m_state = STALE;
458 }
459 
461 {
463  m_state = REACHABLE;
464 }
465 
466 std::list<Ptr<Packet> > NdiscCache::Entry::MarkStale (Address mac)
467 {
468  NS_LOG_FUNCTION (this << mac);
469  m_state = STALE;
470  m_macAddress = mac;
471  return m_waiting;
472 }
473 
475 {
477  m_state = DELAY;
478 }
479 
481 {
483  return (m_state == STALE);
484 }
485 
487 {
489  return (m_state == REACHABLE);
490 }
491 
493 {
495  return (m_state == DELAY);
496 }
497 
499 {
501  return (m_state == INCOMPLETE);
502 }
503 
505 {
507  return (m_state == PROBE);
508 }
509 
511 {
513  return m_macAddress;
514 }
515 
517 {
518  NS_LOG_FUNCTION (this << mac);
519  m_macAddress = mac;
520 }
521 
522 } /* namespace ns3 */
523 
bool IsAny() const
If the IPv6 address is the "Any" address.
void FunctionDelayTimeout()
Function called when delay timer timeout.
Definition: ndisc-cache.cc:252
static TypeId GetTypeId()
Get the type ID.
Definition: ndisc-cache.cc:39
keep track of time values and allow control of global simulation resolution
Definition: nstime.h:81
Time GetLastReachabilityConfirmation() const
Get the time of last reachability confirmation.
Definition: ndisc-cache.cc:358
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
void MarkIncomplete(Ptr< Packet > p)
Changes the state to this entry to INCOMPLETE.
Definition: ndisc-cache.cc:429
~NdiscCache()
Destructor.
Definition: ndisc-cache.cc:57
a simple Timer class
Definition: timer.h:45
NS_LOG_COMPONENT_DEFINE("GrantedTimeWindowMpiInterface")
Address GetMacAddress() const
Get the MAC address of this entry.
Definition: ndisc-cache.cc:510
NdiscCache::Entry * Add(Ipv6Address to)
Add an entry.
Definition: ndisc-cache.cc:103
void SetUnresQlen(uint32_t unresQlen)
Set the max number of waiting packet.
Definition: ndisc-cache.cc:142
IPv6 layer implementation.
#define NS_ASSERT(condition)
Definition: assert.h:64
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
void StopReachableTimer()
Stop the reachable timer.
Definition: ndisc-cache.cc:377
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:336
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
Definition: log.h:309
a polymophic address class
Definition: address.h:86
uint32_t GetUnresQlen()
Get the max number of waiting packet.
Definition: ndisc-cache.cc:148
Ptr< Ipv6Interface > GetInterface() const
Get the Ipv6Interface associated with this cache.
Definition: ndisc-cache.cc:79
bool IsDelay() const
Is the entry DELAY.
Definition: ndisc-cache.cc:492
Ptr< Ipv6Interface > m_interface
the interface.
Definition: ndisc-cache.h:452
void FunctionRetransmitTimeout()
Function called when retransmit timer timeout.
Definition: ndisc-cache.cc:206
void MarkReachable()
Changes the state to this entry to REACHABLE.
Definition: ndisc-cache.cc:460
void Flush()
Flush the cache.
Definition: ndisc-cache.cc:130
Hold an unsigned integer type.
Definition: uinteger.h:46
#define DELAY(time)
Gets the delay between a given time and the current time.
Doxygen introspection did not find any typical Config paths.
Definition: ndisc-cache.h:46
static const uint32_t REACHABLE_TIME
Neighbor Discovery node constants : reachable time.
void StopProbeTimer()
Stop probe timer.
Definition: ndisc-cache.cc:391
NdiscCache()
Constructor.
Definition: ndisc-cache.cc:52
void StartRetransmitTimer()
Start retransmit timer.
Definition: ndisc-cache.cc:414
void ClearWaitingPacket()
Clear the waiting packet list.
Definition: ndisc-cache.cc:193
Entry(NdiscCache *nd)
Constructor.
Definition: ndisc-cache.cc:154
bool IsProbe() const
Is the entry PROBE.
Definition: ndisc-cache.cc:504
void AddWaitingPacket(Ptr< Packet > p)
Add a packet (or replace old value) in the queue.
Definition: ndisc-cache.cc:180
void StartDelayTimer()
Start delay timer.
Definition: ndisc-cache.cc:399
void StartReachableTimer()
Start the reachable timer.
Definition: ndisc-cache.cc:369
bool IsIncomplete() const
Is the entry INCOMPLETE.
Definition: ndisc-cache.cc:498
void FunctionReachableTimeout()
Function called when reachable timer timeout.
Definition: ndisc-cache.cc:200
void StartProbeTimer()
Start probe timer.
Definition: ndisc-cache.cc:383
static const uint32_t DEFAULT_UNRES_QLEN
Default value for unres qlen.
Definition: ndisc-cache.h:60
void Remove(NdiscCache::Entry *entry)
Delete an entry.
Definition: ndisc-cache.cc:114
void FunctionProbeTimeout()
Function called when probe timer timeout.
Definition: ndisc-cache.cc:289
uint32_t m_unresQlen
Max number of packet stored in m_waiting.
Definition: ndisc-cache.h:462
void SetMacAddress(Address mac)
Set the MAC address of this entry.
Definition: ndisc-cache.cc:516
Describes an IPv6 address.
Definition: ipv6-address.h:46
NdiscCache::Entry * Lookup(Ipv6Address dst)
Lookup in the cache.
Definition: ndisc-cache.cc:91
void MarkStale()
Changes the state to this entry to STALE.
Definition: ndisc-cache.cc:454
void IncNSRetransmit()
Increment NS retransmit.
Definition: ndisc-cache.cc:346
void DoDispose()
Dispose this object.
Definition: ndisc-cache.cc:63
void SetIpv6Address(Ipv6Address ipv6Address)
Set the IPv6 address.
Definition: ndisc-cache.cc:334
void MarkDelay()
Change the state to this entry to DELAY.
Definition: ndisc-cache.cc:474
static const uint32_t RETRANS_TIMER
Neighbor Discovery node constants : retransmission timer.
void StopRetransmitTimer()
Stop retransmit timer.
Definition: ndisc-cache.cc:422
void UpdateLastReachabilityconfirmation()
Update the time of last reachability confirmation.
Definition: ndisc-cache.cc:364
void StopDelayTimer()
Stop delay timer.
Definition: ndisc-cache.cc:407
bool IsRouter() const
If the entry is a host or a router.
Definition: ndisc-cache.cc:174
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface)
Set the device and interface.
Definition: ndisc-cache.cc:72
Cache m_ndCache
A list of Entry.
Definition: ndisc-cache.h:457
A record that holds information about an NdiscCache entry.
Definition: ndisc-cache.h:131
void SetRouter(bool router)
Set the node type.
Definition: ndisc-cache.cc:168
static const uint8_t DELAY_FIRST_PROBE_TIME
Neighbor Discovery node constants : delay for the first probe.
a base class which provides memory management and object aggregation
Definition: object.h:63
sgi::hash_map< Ipv6Address, NdiscCache::Entry *, Ipv6AddressHash >::iterator CacheI
Neighbor Discovery Cache container iterator.
Definition: ndisc-cache.h:422
bool IsReachable() const
Is the entry REACHABLE.
Definition: ndisc-cache.cc:486
a unique identifier for an interface.
Definition: type-id.h:49
void ResetNSRetransmit()
Reset NS retransmit (=0).
Definition: ndisc-cache.cc:352
Ptr< NetDevice > GetDevice() const
Get the NetDevice associated with this cache.
Definition: ndisc-cache.cc:85
TypeId SetParent(TypeId tid)
Definition: type-id.cc:611
void MarkProbe()
Changes the state to this entry to PROBE.
Definition: ndisc-cache.cc:448
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
bool IsStale() const
Is the entry STALE.
Definition: ndisc-cache.cc:480
static Ipv6Address MakeSolicitedAddress(Ipv6Address addr)
Make the solicited IPv6 address.
Ptr< NetDevice > m_device
The NetDevice.
Definition: ndisc-cache.h:447
uint8_t GetNSRetransmit() const
Get the number of NS retransmit.
Definition: ndisc-cache.cc:340