A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ndisc-cache.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007-2009 Strasbourg University
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
7 */
8
9#include "ndisc-cache.h"
10
11#include "icmpv6-l4-protocol.h"
12#include "ipv6-interface.h"
13#include "ipv6-l3-protocol.h"
14
15#include "ns3/log.h"
16#include "ns3/names.h"
17#include "ns3/node.h"
18#include "ns3/uinteger.h"
19
20namespace ns3
21{
22
23NS_LOG_COMPONENT_DEFINE("NdiscCache");
24
26
29{
30 static TypeId tid = TypeId("ns3::NdiscCache")
32 .SetGroupName("Internet")
33 .AddAttribute("UnresolvedQueueSize",
34 "Size of the queue for packets pending an NA reply.",
38 return tid;
39}
40
45
51
52void
54{
55 NS_LOG_FUNCTION(this);
56 for (auto& iter : m_ndCache)
57 {
58 delete iter.second; /* delete the pointer NdiscCache::Entry */
59 }
60 m_ndCache.clear();
61 m_device = nullptr;
62 m_interface = nullptr;
63 m_icmpv6 = nullptr;
65}
66
67void
69 Ptr<Ipv6Interface> interface,
71{
72 NS_LOG_FUNCTION(this << device << interface);
73 m_device = device;
74 m_interface = interface;
75 m_icmpv6 = icmpv6;
76}
77
80{
81 NS_LOG_FUNCTION(this);
82 return m_interface;
83}
84
87{
88 NS_LOG_FUNCTION(this);
89 return m_device;
90}
91
94{
95 NS_LOG_FUNCTION(this << dst);
96
97 if (m_ndCache.find(dst) != m_ndCache.end())
98 {
99 NdiscCache::Entry* entry = m_ndCache[dst];
100 NS_LOG_LOGIC("Found an entry: " << *entry);
101
102 return entry;
103 }
104 NS_LOG_LOGIC("Nothing found");
105 return nullptr;
106}
107
108std::list<NdiscCache::Entry*>
110{
111 NS_LOG_FUNCTION(this << dst);
112
113 std::list<NdiscCache::Entry*> entryList;
114 for (auto i = m_ndCache.begin(); i != m_ndCache.end(); i++)
115 {
116 NdiscCache::Entry* entry = (*i).second;
117 if (entry->GetMacAddress() == dst)
118 {
119 NS_LOG_LOGIC("Found an entry:" << (*entry));
120 entryList.push_back(entry);
121 }
122 }
123 return entryList;
124}
125
128{
129 NS_LOG_FUNCTION(this << to);
130 NS_ASSERT(m_ndCache.find(to) == m_ndCache.end());
131
132 auto entry = new NdiscCache::Entry(this);
133 entry->SetIpv6Address(to);
134 m_ndCache[to] = entry;
135 return entry;
136}
137
138void
140{
141 NS_LOG_FUNCTION(this << entry);
142
143 for (auto i = m_ndCache.begin(); i != m_ndCache.end(); i++)
144 {
145 if ((*i).second == entry)
146 {
147 m_ndCache.erase(i);
148 entry->ClearWaitingPacket();
149 delete entry;
150 return;
151 }
152 }
153}
154
155void
157{
158 NS_LOG_FUNCTION(this);
159
160 for (auto i = m_ndCache.begin(); i != m_ndCache.end();)
161 {
162 if (!i->second->IsAutoGenerated())
163 {
164 i->second->ClearWaitingPacket();
165 delete i->second;
166 i = m_ndCache.erase(i);
167 }
168 else
169 {
170 i++;
171 }
172 }
173}
174
175void
177{
178 NS_LOG_FUNCTION(this << unresQlen);
179 m_unresQlen = unresQlen;
180}
181
184{
185 NS_LOG_FUNCTION(this);
186 return m_unresQlen;
187}
188
189void
191{
192 NS_LOG_FUNCTION(this << stream);
193 std::ostream* os = stream->GetStream();
194
195 for (auto i = m_ndCache.begin(); i != m_ndCache.end(); i++)
196 {
197 *os << i->first << " dev ";
198 std::string found = Names::FindName(m_device);
199 if (!Names::FindName(m_device).empty())
200 {
201 *os << found;
202 }
203 else
204 {
205 *os << static_cast<int>(m_device->GetIfIndex());
206 }
207
208 *os << " lladdr " << i->second->GetMacAddress();
209
210 if (i->second->IsReachable())
211 {
212 *os << " REACHABLE\n";
213 }
214 else if (i->second->IsDelay())
215 {
216 *os << " DELAY\n";
217 }
218 else if (i->second->IsIncomplete())
219 {
220 *os << " INCOMPLETE\n";
221 }
222 else if (i->second->IsProbe())
223 {
224 *os << " PROBE\n";
225 }
226 else if (i->second->IsStale())
227 {
228 *os << " STALE\n";
229 }
230 else if (i->second->IsPermanent())
231 {
232 *os << " PERMANENT\n";
233 }
234 else if (i->second->IsAutoGenerated())
235 {
236 *os << " STATIC_AUTOGENERATED\n";
237 }
238 else
239 {
240 NS_FATAL_ERROR("Test for possibly unreachable code-- please file a bug report, with a "
241 "test case, if this is ever hit");
242 }
243 }
244}
245
247 : m_ndCache(nd),
248 m_waiting(),
249 m_router(false),
250 m_nudTimer(Timer::CANCEL_ON_DESTROY),
253{
254 NS_LOG_FUNCTION(this);
255}
256
257void
259{
260 NS_LOG_FUNCTION(this << router);
261 m_router = router;
262}
263
264bool
266{
267 NS_LOG_FUNCTION(this);
268 return m_router;
269}
270
271void
273{
274 NS_LOG_FUNCTION(this << p.second << p.first);
275
276 if (m_waiting.size() >= m_ndCache->GetUnresQlen())
277 {
278 /* we store only m_unresQlen packet => first packet in first packet remove */
279 /** @todo report packet as 'dropped' */
280 m_waiting.pop_front();
281 }
282 m_waiting.push_back(p);
283}
284
285void
287{
288 NS_LOG_FUNCTION(this);
289 /** @todo report packets as 'dropped' */
290 m_waiting.clear();
291}
292
293void
299
300void
302{
303 NS_LOG_FUNCTION(this);
304 Ipv6Address addr;
305
306 /* determine source address */
307 if (m_ipv6Address.IsLinkLocal())
308 {
309 addr = m_ndCache->GetInterface()->GetLinkLocalAddress().GetAddress();
310 }
311 else if (!m_ipv6Address.IsAny())
312 {
313 addr = m_ndCache->GetInterface()->GetAddressMatchingDestination(m_ipv6Address).GetAddress();
314
315 if (addr.IsAny()) /* maybe address has expired */
316 {
317 /* delete the entry */
318 m_ndCache->Remove(this);
319 return;
320 }
321 }
322
323 if (m_nsRetransmit < m_ndCache->m_icmpv6->GetMaxMulticastSolicit())
324 {
326
327 m_ndCache->m_icmpv6->SendNS(addr,
330 m_ndCache->GetDevice()->GetAddress());
331 /* arm the timer again */
333 }
334 else
335 {
336 Ipv6PayloadHeaderPair malformedPacket = m_waiting.front();
337 if (!malformedPacket.first)
338 {
339 malformedPacket.first = Create<Packet>();
340 }
341 else
342 {
343 malformedPacket.first->AddHeader(malformedPacket.second);
344 }
345
346 m_ndCache->m_icmpv6->SendErrorDestinationUnreachable(malformedPacket.first,
347 addr,
349
350 /* delete the entry */
351 m_ndCache->Remove(this);
352 }
353}
354
355void
357{
358 NS_LOG_FUNCTION(this);
359 Ipv6Address addr;
360
361 this->MarkProbe();
362
363 if (m_ipv6Address.IsLinkLocal())
364 {
365 addr = m_ndCache->GetInterface()->GetLinkLocalAddress().GetAddress();
366 }
367 else if (!m_ipv6Address.IsAny())
368 {
369 addr = m_ndCache->GetInterface()->GetAddressMatchingDestination(m_ipv6Address).GetAddress();
370 if (addr.IsAny()) /* maybe address has expired */
371 {
372 /* delete the entry */
373 m_ndCache->Remove(this);
374 return;
375 }
376 }
377 else
378 {
379 /* should not happen */
380 return;
381 }
382
383 Ipv6PayloadHeaderPair p = m_ndCache->m_icmpv6->ForgeNS(addr,
386 m_ndCache->GetDevice()->GetAddress());
387 p.first->AddHeader(p.second);
388 m_ndCache->GetDevice()->Send(p.first, this->GetMacAddress(), Ipv6L3Protocol::PROT_NUMBER);
389
390 m_nsRetransmit = 1;
392}
393
394void
396{
397 NS_LOG_FUNCTION(this);
398
399 if (m_nsRetransmit < m_ndCache->m_icmpv6->GetMaxUnicastSolicit())
400 {
402
403 Ipv6Address addr;
404
405 if (m_ipv6Address.IsLinkLocal())
406 {
407 addr = m_ndCache->GetInterface()->GetLinkLocalAddress().GetAddress();
408 }
409 else if (!m_ipv6Address.IsAny())
410 {
411 addr = m_ndCache->GetInterface()
412 ->GetAddressMatchingDestination(m_ipv6Address)
413 .GetAddress();
414 if (addr.IsAny()) /* maybe address has expired */
415 {
416 /* delete the entry */
417 m_ndCache->Remove(this);
418 return;
419 }
420 }
421 else
422 {
423 /* should not happen */
424 return;
425 }
426
427 /* icmpv6->SendNS (m_ndCache->GetInterface ()->GetLinkLocalAddress (), m_ipv6Address,
428 * m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ()); */
430 m_ndCache->m_icmpv6->ForgeNS(addr,
433 m_ndCache->GetDevice()->GetAddress());
434 p.first->AddHeader(p.second);
435 m_ndCache->GetDevice()->Send(p.first, this->GetMacAddress(), Ipv6L3Protocol::PROT_NUMBER);
436
437 /* arm the timer again */
439 }
440 else
441 {
442 /* delete the entry */
443 m_ndCache->Remove(this);
444 }
445}
446
447void
449{
450 NS_LOG_FUNCTION(this << ipv6Address);
451 m_ipv6Address = ipv6Address;
452}
453
456{
457 NS_LOG_FUNCTION(this);
458 return m_ipv6Address;
459}
460
461Time
467
468void
470{
471 NS_LOG_FUNCTION(this);
472 if (m_nudTimer.IsRunning())
473 {
474 m_nudTimer.Cancel();
475 }
476
479 m_nudTimer.SetDelay(m_ndCache->m_icmpv6->GetReachableTime());
480 m_nudTimer.Schedule();
481}
482
483void
485{
486 NS_LOG_FUNCTION(this);
487
488 if (m_state == REACHABLE)
489 {
491 if (m_nudTimer.IsRunning())
492 {
493 m_nudTimer.Cancel();
494 }
495 m_nudTimer.Schedule();
496 }
497}
498
499void
501{
502 NS_LOG_FUNCTION(this);
503 if (m_nudTimer.IsRunning())
504 {
505 m_nudTimer.Cancel();
506 }
507
509 m_nudTimer.SetDelay(m_ndCache->m_icmpv6->GetRetransmissionTime());
510 m_nudTimer.Schedule();
511}
512
513void
515{
516 NS_LOG_FUNCTION(this);
517 if (m_nudTimer.IsRunning())
518 {
519 m_nudTimer.Cancel();
520 }
521
523 m_nudTimer.SetDelay(m_ndCache->m_icmpv6->GetDelayFirstProbe());
524 m_nudTimer.Schedule();
525}
526
527void
529{
530 NS_LOG_FUNCTION(this);
531 if (m_nudTimer.IsRunning())
532 {
533 m_nudTimer.Cancel();
534 }
535
537 m_nudTimer.SetDelay(m_ndCache->m_icmpv6->GetRetransmissionTime());
538 m_nudTimer.Schedule();
539}
540
541void
543{
544 NS_LOG_FUNCTION(this);
545 m_nudTimer.Cancel();
546 m_nsRetransmit = 0;
547}
548
549void
551{
552 NS_LOG_FUNCTION(this << p.second << p.first);
554
555 if (p.first)
556 {
557 m_waiting.push_back(p);
558 }
559}
560
561std::list<NdiscCache::Ipv6PayloadHeaderPair>
563{
564 NS_LOG_FUNCTION(this << mac);
566 m_macAddress = mac;
567 return m_waiting;
568}
569
570void
576
577void
583
584void
590
591std::list<NdiscCache::Ipv6PayloadHeaderPair>
593{
594 NS_LOG_FUNCTION(this << mac);
595 m_state = STALE;
596 m_macAddress = mac;
597 return m_waiting;
598}
599
600void
606
607void
614
615void
622
623bool
625{
626 NS_LOG_FUNCTION(this);
627 return (m_state == STALE);
628}
629
630bool
632{
633 NS_LOG_FUNCTION(this);
634 return (m_state == REACHABLE);
635}
636
637bool
639{
640 NS_LOG_FUNCTION(this);
641 return (m_state == DELAY);
642}
643
644bool
646{
647 NS_LOG_FUNCTION(this);
648 return (m_state == INCOMPLETE);
649}
650
651bool
653{
654 NS_LOG_FUNCTION(this);
655 return (m_state == PROBE);
656}
657
658bool
660{
661 NS_LOG_FUNCTION(this);
662 return (m_state == PERMANENT);
663}
664
665bool
671
674{
675 NS_LOG_FUNCTION(this);
676 return m_macAddress;
677}
678
679void
681{
682 NS_LOG_FUNCTION(this << mac << int(m_state));
683 m_macAddress = mac;
684}
685
686void
687NdiscCache::Entry::Print(std::ostream& os) const
688{
689 os << m_ipv6Address << " lladdr " << m_macAddress << " state ";
690 switch (m_state)
691 {
692 case INCOMPLETE:
693 os << "INCOMPLETE";
694 break;
695 case REACHABLE:
696 os << "REACHABLE";
697 break;
698 case STALE:
699 os << "STALE";
700 break;
701 case DELAY:
702 os << "DELAY";
703 break;
704 case PROBE:
705 os << "PROBE";
706 break;
707 case PERMANENT:
708 os << "PERMANENT";
709 break;
711 os << "STATIC_AUTOGENERATED";
712 break;
713 }
714}
715
716void
718{
719 NS_LOG_FUNCTION(this);
720 for (auto i = m_ndCache.begin(); i != m_ndCache.end();)
721 {
722 if (i->second->IsAutoGenerated())
723 {
724 i->second->ClearWaitingPacket();
725 delete i->second;
726 i = m_ndCache.erase(i);
727 }
728 else
729 {
730 i++;
731 }
732 }
733}
734
735std::ostream&
736operator<<(std::ostream& os, const NdiscCache::Entry& entry)
737{
738 entry.Print(os);
739 return os;
740}
741
742} /* namespace ns3 */
a polymophic address class
Definition address.h:90
Describes an IPv6 address.
static Ipv6Address MakeSolicitedAddress(Ipv6Address addr)
Make the solicited IPv6 address.
bool IsAny() const
If the IPv6 address is the "Any" address.
static constexpr uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
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:818
A record that holds information about a NdiscCache entry.
bool m_router
Type of node (router or host).
void MarkProbe()
Changes the state to this entry to PROBE.
bool IsPermanent() const
Is the entry PERMANENT.
void MarkPermanent()
Change the state to this entry to PERMANENT.
NdiscCacheEntryState_e m_state
The state of the entry.
@ PROBE
Try to contact IPv6 address to know again its L2 address.
@ STALE
Mapping is stale.
@ REACHABLE
Mapping exists between IPv6 and L2 addresses.
@ PERMANENT
Permanent Mapping exists between IPv6 and L2 addresses.
@ DELAY
Try to wait contact from remote host.
@ INCOMPLETE
No mapping between IPv6 and L2 addresses.
@ STATIC_AUTOGENERATED
Permanent entries generate by NeighborCacheHelper.
void ClearWaitingPacket()
Clear the waiting packet list.
std::list< Ipv6PayloadHeaderPair > MarkStale(Address mac)
Changes the state to this entry to STALE.
void StartProbeTimer()
Start probe timer.
Ipv6Address m_ipv6Address
The IPv6 address.
void MarkReachable()
Changes the state to this entry to REACHABLE.
void StartReachableTimer()
Start the reachable timer.
void Print(std::ostream &os) const
Print this entry to the given output stream.
void UpdateReachableTimer()
Update the reachable timer.
uint8_t m_nsRetransmit
Number of NS retransmission.
void FunctionProbeTimeout()
Function called when probe timer timeout.
void MarkStale()
Changes the state to this entry to STALE.
std::list< Ipv6PayloadHeaderPair > m_waiting
The list of packet waiting.
Time m_lastReachabilityConfirmation
Last time we see a reachability confirmation.
Address GetMacAddress() const
Get the MAC address of this entry.
Ipv6Address GetIpv6Address() const
Get the IPv6 address.
void StartDelayTimer()
Start delay timer.
void MarkAutoGenerated()
Changes the state of this entry to auto-generated.
bool IsIncomplete() const
Is the entry INCOMPLETE.
Address m_macAddress
The MAC address.
void FunctionDelayTimeout()
Function called when delay timer timeout.
bool IsDelay() const
Is the entry DELAY.
void StartRetransmitTimer()
Start retransmit timer.
void SetIpv6Address(Ipv6Address ipv6Address)
Set the IPv6 address.
void MarkIncomplete(Ipv6PayloadHeaderPair p)
Changes the state to this entry to INCOMPLETE.
bool IsStale() const
Is the entry STALE.
void SetMacAddress(Address mac)
Set the MAC address of this entry.
bool IsProbe() const
Is the entry PROBE.
Time GetLastReachabilityConfirmation() const
Get the time of last reachability confirmation.
void FunctionRetransmitTimeout()
Function called when retransmit timer timeout.
NdiscCache * m_ndCache
the NdiscCache associated.
void MarkDelay()
Change the state to this entry to DELAY.
Entry(NdiscCache *nd)
Constructor.
bool IsRouter() const
If the entry is a host or a router.
void SetRouter(bool router)
Set the node type.
Timer m_nudTimer
Timer (used for NUD).
void FunctionReachableTimeout()
Function called when reachable timer timeout.
bool IsAutoGenerated() const
Is the entry STATIC_AUTOGENERATED.
void AddWaitingPacket(Ipv6PayloadHeaderPair p)
Add a packet (or replace old value) in the queue.
bool IsReachable() const
Is the entry REACHABLE.
void StopNudTimer()
Stop NUD timer and reset the NUD retransmission counter.
IPv6 Neighbor Discovery cache.
Definition ndisc-cache.h:38
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface, Ptr< Icmpv6L4Protocol > icmpv6)
Set the device and interface.
std::pair< Ptr< Packet >, Ipv6Header > Ipv6PayloadHeaderPair
Pair of a packet and an Ipv4 header.
virtual NdiscCache::Entry * Add(Ipv6Address to)
Add an entry.
void Flush()
Clear the cache of all entries except auto-generated entries.
Ptr< Ipv6Interface > m_interface
the interface.
void Remove(NdiscCache::Entry *entry)
Delete an entry.
NdiscCache()
Constructor.
void PrintNdiscCache(Ptr< OutputStreamWrapper > stream)
Print the NDISC cache entries.
~NdiscCache() override
Destructor.
Ptr< NetDevice > m_device
The NetDevice.
uint32_t GetUnresQlen()
Get the max number of waiting packet.
virtual NdiscCache::Entry * Lookup(Ipv6Address dst)
Lookup in the cache.
void RemoveAutoGeneratedEntries()
Clear the NDISC cache of all Auto-Generated entries.
void DoDispose() override
Dispose this object.
Ptr< NetDevice > GetDevice() const
Get the NetDevice associated with this cache.
static const uint32_t DEFAULT_UNRES_QLEN
Default value for unres qlen.
Definition ndisc-cache.h:51
static TypeId GetTypeId()
Get the type ID.
Cache m_ndCache
A list of Entry.
std::list< NdiscCache::Entry * > LookupInverse(Address dst)
Lookup in the cache for a MAC address.
void SetUnresQlen(uint32_t unresQlen)
Set the max number of waiting packet.
Ptr< Icmpv6L4Protocol > m_icmpv6
the icmpv6 L4 protocol for this cache.
Ptr< Ipv6Interface > GetInterface() const
Get the Ipv6Interface associated with this cache.
uint32_t m_unresQlen
Max number of packet stored in m_waiting.
Object()
Constructor.
Definition object.cc:96
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
A simple virtual Timer class.
Definition timer.h:67
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
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:35
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:439
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148