A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ndisc-cache.cc
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 NS_OBJECT_ENSURE_REGISTERED (NdiscCache);
36 
38 {
39  static TypeId tid = TypeId ("ns3::NdiscCache")
40  .SetParent<Object> ()
41  .AddAttribute ("UnresolvedQueueSize",
42  "Size of the queue for packets pending an NA reply.",
44  MakeUintegerAccessor (&NdiscCache::m_unresQlen),
45  MakeUintegerChecker<uint32_t> ())
46  ;
47  return tid;
48 }
49 
51 {
53 }
54 
56 {
58  Flush ();
59 }
60 
62 {
64  Flush ();
65  m_device = 0;
66  m_interface = 0;
68 }
69 
71 {
72  NS_LOG_FUNCTION (this << device << interface);
73  m_device = device;
74  m_interface = interface;
75 }
76 
78 {
80  return m_interface;
81 }
82 
84 {
86  return m_device;
87 }
88 
90 {
91  NS_LOG_FUNCTION (this << dst);
92 
93  if (m_ndCache.find (dst) != m_ndCache.end ())
94  {
95  NdiscCache::Entry* entry = m_ndCache[dst];
96  return entry;
97  }
98  return 0;
99 }
100 
102 {
103  NS_LOG_FUNCTION (this << to);
104  NS_ASSERT (m_ndCache.find (to) == m_ndCache.end ());
105 
106  NdiscCache::Entry* entry = new NdiscCache::Entry (this);
107  entry->SetIpv6Address (to);
108  m_ndCache[to] = entry;
109  return entry;
110 }
111 
113 {
115 
116  for (CacheI i = m_ndCache.begin (); i != m_ndCache.end (); i++)
117  {
118  if ((*i).second == entry)
119  {
120  m_ndCache.erase (i);
121  entry->ClearWaitingPacket ();
122  delete entry;
123  return;
124  }
125  }
126 }
127 
129 {
131 
132  for (CacheI i = m_ndCache.begin (); i != m_ndCache.end (); i++)
133  {
134  delete (*i).second; /* delete the pointer NdiscCache::Entry */
135  }
136 
137  m_ndCache.erase (m_ndCache.begin (), m_ndCache.end ());
138 }
139 
140 void NdiscCache::SetUnresQlen (uint32_t unresQlen)
141 {
142  NS_LOG_FUNCTION (this << unresQlen);
143  m_unresQlen = unresQlen;
144 }
145 
147 {
149  return m_unresQlen;
150 }
151 
153  : m_ndCache (nd),
154  m_waiting (),
155  m_router (false),
156  m_reachableTimer (Timer::CANCEL_ON_DESTROY),
157  m_retransTimer (Timer::CANCEL_ON_DESTROY),
158  m_probeTimer (Timer::CANCEL_ON_DESTROY),
159  m_delayTimer (Timer::CANCEL_ON_DESTROY),
160  m_lastReachabilityConfirmation (Seconds (0.0)),
161  m_nsRetransmit (0)
162 {
164 }
165 
167 {
168  NS_LOG_FUNCTION (this << router);
169  m_router = router;
170 }
171 
173 {
175  return m_router;
176 }
177 
179 {
180  NS_LOG_FUNCTION (this << p);
181 
182  if (m_waiting.size () >= m_ndCache->GetUnresQlen ())
183  {
184  /* we store only m_unresQlen packet => first packet in first packet remove */
185  /* XXX report packet as 'dropped' */
186  m_waiting.remove (0);
187  }
188  m_waiting.push_back (p);
189 }
190 
192 {
194  /* XXX report packets as 'dropped' */
195  m_waiting.clear ();
196 }
197 
199 {
201  this->MarkStale ();
202 }
203 
205 {
207  Ptr<Icmpv6L4Protocol> icmpv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
208  Ipv6Address addr;
209 
210  /* determine source address */
211  if (m_ipv6Address.IsLinkLocal ())
212  {
213  addr = m_ndCache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();;
214  }
215  else if (!m_ipv6Address.IsAny ())
216  {
217  addr = m_ndCache->GetInterface ()->GetAddressMatchingDestination (m_ipv6Address).GetAddress ();
218 
219  if (addr.IsAny ()) /* maybe address has expired */
220  {
221  /* delete the entry */
222  m_ndCache->Remove (this);
223  return;
224  }
225  }
226 
227  if (GetNSRetransmit () < icmpv6->MAX_MULTICAST_SOLICIT)
228  {
229  IncNSRetransmit ();
230 
231  icmpv6->SendNS (addr, Ipv6Address::MakeSolicitedAddress (m_ipv6Address), m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ());
232  /* arm the timer again */
233  StartRetransmitTimer ();
234  }
235  else
236  {
237  Ptr<Packet> malformedPacket = m_waiting.front ();
238  if (malformedPacket == 0)
239  {
240  malformedPacket = Create<Packet> ();
241  }
242 
243  icmpv6->SendErrorDestinationUnreachable (malformedPacket, addr, Icmpv6Header::ICMPV6_ADDR_UNREACHABLE);
244 
245  /* delete the entry */
246  m_ndCache->Remove (this);
247  }
248 }
249 
251 {
253  Ptr<Ipv6L3Protocol> ipv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject<Ipv6L3Protocol> ();
254  Ptr<Icmpv6L4Protocol> icmpv6 = ipv6->GetIcmpv6 ();
255  Ipv6Address addr;
256 
257  this->MarkProbe ();
258 
259  if (m_ipv6Address.IsLinkLocal ())
260  {
261  addr = m_ndCache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
262  }
263  else if (!m_ipv6Address.IsAny ())
264  {
265  addr = m_ndCache->GetInterface ()->GetAddressMatchingDestination (m_ipv6Address).GetAddress ();
266  if (addr.IsAny ()) /* maybe address has expired */
267  {
268  /* delete the entry */
269  m_ndCache->Remove (this);
270  return;
271  }
272  }
273  else
274  {
275  /* should not happen */
276  return;
277  }
278 
279  Ptr<Packet> p = icmpv6->ForgeNS (addr, m_ipv6Address, m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ());
280  m_ndCache->GetDevice ()->Send (p, this->GetMacAddress (), Ipv6L3Protocol::PROT_NUMBER);
281 
282  ResetNSRetransmit ();
283  IncNSRetransmit ();
284  StartProbeTimer ();
285 }
286 
288 {
290  Ptr<Ipv6L3Protocol> ipv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject<Ipv6L3Protocol> ();
291  Ptr<Icmpv6L4Protocol> icmpv6 = ipv6->GetIcmpv6 ();
292 
293  if (GetNSRetransmit () < icmpv6->MAX_UNICAST_SOLICIT)
294  {
295  Ipv6Address addr;
296 
297  if (m_ipv6Address.IsLinkLocal ())
298  {
299  addr = m_ndCache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
300  }
301  else if (!m_ipv6Address.IsAny ())
302  {
303  addr = m_ndCache->GetInterface ()->GetAddressMatchingDestination (m_ipv6Address).GetAddress ();
304  if (addr.IsAny ()) /* maybe address has expired */
305  {
306  /* delete the entry */
307  m_ndCache->Remove (this);
308  return;
309  }
310  }
311  else
312  {
313  /* should not happen */
314  return;
315  }
316 
317  IncNSRetransmit ();
318  /* icmpv6->SendNS (m_ndCache->GetInterface ()->GetLinkLocalAddress (), m_ipv6Address, m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ()); */
319  Ptr<Packet> p = icmpv6->ForgeNS (addr, m_ipv6Address, m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ());
320  m_ndCache->GetDevice ()->Send (p, this->GetMacAddress (), Ipv6L3Protocol::PROT_NUMBER);
321 
322  /* arm the timer again */
323  StartProbeTimer ();
324  }
325  else
326  {
327  /* delete the entry */
328  m_ndCache->Remove (this);
329  }
330 }
331 
333 {
334  NS_LOG_FUNCTION (this << ipv6Address);
335  m_ipv6Address = ipv6Address;
336 }
337 
339 {
341  return m_nsRetransmit;
342 }
343 
345 {
347  m_nsRetransmit++;
348 }
349 
351 {
353  m_nsRetransmit = 0;
354 }
355 
357 {
359  return m_lastReachabilityConfirmation;
360 }
361 
363 {
365 }
366 
368 {
370  m_reachableTimer.SetFunction (&NdiscCache::Entry::FunctionReachableTimeout, this);
371  m_reachableTimer.SetDelay (MilliSeconds (Icmpv6L4Protocol::REACHABLE_TIME));
372  m_reachableTimer.Schedule ();
373 }
374 
376 {
378  m_reachableTimer.Cancel ();
379 }
380 
382 {
384  m_probeTimer.SetFunction (&NdiscCache::Entry::FunctionProbeTimeout, this);
385  m_probeTimer.SetDelay (MilliSeconds (Icmpv6L4Protocol::RETRANS_TIMER));
386  m_probeTimer.Schedule ();
387 }
388 
390 {
392  m_probeTimer.Cancel ();
393  ResetNSRetransmit ();
394 }
395 
396 
398 {
400  m_delayTimer.SetFunction (&NdiscCache::Entry::FunctionDelayTimeout, this);
401  m_delayTimer.SetDelay (Seconds (Icmpv6L4Protocol::DELAY_FIRST_PROBE_TIME));
402  m_delayTimer.Schedule ();
403 }
404 
406 {
408  m_delayTimer.Cancel ();
409  ResetNSRetransmit ();
410 }
411 
413 {
415  m_retransTimer.SetFunction (&NdiscCache::Entry::FunctionRetransmitTimeout, this);
416  m_retransTimer.SetDelay (MilliSeconds (Icmpv6L4Protocol::RETRANS_TIMER));
417  m_retransTimer.Schedule ();
418 }
419 
421 {
423  m_retransTimer.Cancel ();
424  ResetNSRetransmit ();
425 }
426 
428 {
429  NS_LOG_FUNCTION (this << p);
430  m_state = INCOMPLETE;
431 
432  if (p)
433  {
434  m_waiting.push_back (p);
435  }
436 }
437 
438 std::list<Ptr<Packet> > NdiscCache::Entry::MarkReachable (Address mac)
439 {
440  NS_LOG_FUNCTION (this << mac);
441  m_state = REACHABLE;
442  m_macAddress = mac;
443  return m_waiting;
444 }
445 
447 {
449  m_state = PROBE;
450 }
451 
453 {
455  m_state = STALE;
456 }
457 
459 {
461  m_state = REACHABLE;
462 }
463 
464 std::list<Ptr<Packet> > NdiscCache::Entry::MarkStale (Address mac)
465 {
466  NS_LOG_FUNCTION (this << mac);
467  m_state = STALE;
468  m_macAddress = mac;
469  return m_waiting;
470 }
471 
473 {
475  m_state = DELAY;
476 }
477 
479 {
481  return (m_state == STALE);
482 }
483 
485 {
487  return (m_state == REACHABLE);
488 }
489 
491 {
493  return (m_state == DELAY);
494 }
495 
497 {
499  return (m_state == INCOMPLETE);
500 }
501 
503 {
505  return (m_state == PROBE);
506 }
507 
509 {
511  return m_macAddress;
512 }
513 
515 {
516  NS_LOG_FUNCTION (this << mac);
517  m_macAddress = mac;
518 }
519 
520 } /* namespace ns3 */
521 
bool IsAny() const
If the IPv6 address is the "Any" address.
void FunctionDelayTimeout()
Function called when delay timer timeout.
Definition: ndisc-cache.cc:250
static TypeId GetTypeId()
Get the type ID.
Definition: ndisc-cache.cc:37
keep track of time unit.
Definition: nstime.h:149
Time GetLastReachabilityConfirmation() const
Get the time of last reachability confirmation.
Definition: ndisc-cache.cc:356
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void MarkIncomplete(Ptr< Packet > p)
Changes the state to this entry to INCOMPLETE.
Definition: ndisc-cache.cc:427
~NdiscCache()
Destructor.
Definition: ndisc-cache.cc:55
a simple Timer class
Definition: timer.h:45
Address GetMacAddress() const
Get the MAC address of this entry.
Definition: ndisc-cache.cc:508
NdiscCache::Entry * Add(Ipv6Address to)
Add an entry.
Definition: ndisc-cache.cc:101
void SetUnresQlen(uint32_t unresQlen)
Set the max number of waiting packet.
Definition: ndisc-cache.cc:140
IPv6 layer implementation.
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
void StopReachableTimer()
Stop the reachable timer.
Definition: ndisc-cache.cc:375
virtual void DoDispose(void)
Definition: object.cc:335
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
a polymophic address class
Definition: address.h:86
uint32_t GetUnresQlen()
Get the max number of waiting packet.
Definition: ndisc-cache.cc:146
Ptr< Ipv6Interface > GetInterface() const
Get the Ipv6Interface associated with this cache.
Definition: ndisc-cache.cc:77
bool IsDelay() const
Is the entry DELAY.
Definition: ndisc-cache.cc:490
Ptr< Ipv6Interface > m_interface
the interface.
Definition: ndisc-cache.h:443
void FunctionRetransmitTimeout()
Function called when retransmit timer timeout. It verify that the NS retransmit has reached the max s...
Definition: ndisc-cache.cc:204
void MarkReachable()
Changes the state to this entry to REACHABLE.
Definition: ndisc-cache.cc:458
void Flush()
Flush the cache.
Definition: ndisc-cache.cc:128
Hold an unsigned integer type.
Definition: uinteger.h:46
IPv6 Neighbor Discovery cache.
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:389
NdiscCache()
Constructor.
Definition: ndisc-cache.cc:50
void StartRetransmitTimer()
Start retransmit timer.
Definition: ndisc-cache.cc:412
void ClearWaitingPacket()
Clear the waiting packet list.
Definition: ndisc-cache.cc:191
Entry(NdiscCache *nd)
Constructor.
Definition: ndisc-cache.cc:152
bool IsProbe() const
Is the entry PROBE.
Definition: ndisc-cache.cc:502
void AddWaitingPacket(Ptr< Packet > p)
Add a packet (or replace old value) in the queue.
Definition: ndisc-cache.cc:178
void StartDelayTimer()
Start delay timer.
Definition: ndisc-cache.cc:397
void StartReachableTimer()
Start the reachable timer.
Definition: ndisc-cache.cc:367
bool IsIncomplete() const
Is the entry INCOMPLETE.
Definition: ndisc-cache.cc:496
void FunctionReachableTimeout()
Function called when reachable timer timeout.
Definition: ndisc-cache.cc:198
void StartProbeTimer()
Start probe timer.
Definition: ndisc-cache.cc:381
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:112
void FunctionProbeTimeout()
Function called when probe timer timeout.
Definition: ndisc-cache.cc:287
uint32_t m_unresQlen
Max number of packet stored in m_waiting.
Definition: ndisc-cache.h:453
void SetMacAddress(Address mac)
Set the MAC address of this entry.
Definition: ndisc-cache.cc:514
Describes an IPv6 address.
Definition: ipv6-address.h:44
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
NdiscCache::Entry * Lookup(Ipv6Address dst)
Lookup in the cache.
Definition: ndisc-cache.cc:89
void MarkStale()
Changes the state to this entry to STALE.
Definition: ndisc-cache.cc:452
void IncNSRetransmit()
Increment NS retransmit.
Definition: ndisc-cache.cc:344
void DoDispose()
Dispose this object.
Definition: ndisc-cache.cc:61
void SetIpv6Address(Ipv6Address ipv6Address)
Set the IPv6 address.
Definition: ndisc-cache.cc:332
void MarkDelay()
Change the state to this entry to DELAY.
Definition: ndisc-cache.cc:472
static const uint32_t RETRANS_TIMER
Neighbor Discovery node constants : retransmission timer.
void StopRetransmitTimer()
Stop retransmit timer.
Definition: ndisc-cache.cc:420
void UpdateLastReachabilityconfirmation()
Update the time of last reachability confirmation.
Definition: ndisc-cache.cc:362
void StopDelayTimer()
Stop delay timer.
Definition: ndisc-cache.cc:405
bool IsRouter() const
If the entry is a host or a router.
Definition: ndisc-cache.cc:172
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface)
Set the device and interface.
Definition: ndisc-cache.cc:70
Cache m_ndCache
A list of Entry.
Definition: ndisc-cache.h:448
A record that holds information about an NdiscCache entry.
Definition: ndisc-cache.h:131
Time MilliSeconds(uint64_t ms)
create ns3::Time instances in units of milliseconds.
Definition: nstime.h:601
void SetRouter(bool router)
Set the node type.
Definition: ndisc-cache.cc:166
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
bool IsReachable() const
Is the entry REACHABLE.
Definition: ndisc-cache.cc:484
a unique identifier for an interface.
Definition: type-id.h:44
void ResetNSRetransmit()
Reset NS retransmit (=0).
Definition: ndisc-cache.cc:350
Ptr< NetDevice > GetDevice() const
Get the NetDevice associated with this cache.
Definition: ndisc-cache.cc:83
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
void MarkProbe()
Changes the state to this entry to PROBE.
Definition: ndisc-cache.cc:446
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
bool IsStale() const
Is the entry STALE.
Definition: ndisc-cache.cc:478
static Ipv6Address MakeSolicitedAddress(Ipv6Address addr)
Make the solicited IPv6 address.
Ptr< NetDevice > m_device
The NetDevice.
Definition: ndisc-cache.h:438
uint8_t GetNSRetransmit() const
Get the number of NS retransmit.
Definition: ndisc-cache.cc:338