A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
icmpv6-l4-protocol.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007-2009 Strasbourg University
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
18 * David Gross <gdavid.devel@gmail.com>
19 * Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
20 * Tommaso Pecorella <tommaso.pecorella@unifi.it>
21 */
22
23#include "icmpv6-l4-protocol.h"
24
25#include "ipv6-interface.h"
26#include "ipv6-l3-protocol.h"
27#include "ipv6-route.h"
29
30#include "ns3/assert.h"
31#include "ns3/boolean.h"
32#include "ns3/double.h"
33#include "ns3/integer.h"
34#include "ns3/log.h"
35#include "ns3/node.h"
36#include "ns3/packet.h"
37#include "ns3/pointer.h"
38#include "ns3/string.h"
39#include "ns3/uinteger.h"
40
41namespace ns3
42{
43
44NS_LOG_COMPONENT_DEFINE("Icmpv6L4Protocol");
45
46NS_OBJECT_ENSURE_REGISTERED(Icmpv6L4Protocol);
47
48const uint8_t Icmpv6L4Protocol::PROT_NUMBER = 58;
49
50// const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERT_INTERVAL = 16; // max initial RA initial
51// interval. const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERTISEMENTS = 3; // max initial RA
52// transmission. const uint8_t Icmpv6L4Protocol::MAX_FINAL_RTR_ADVERTISEMENTS = 3; // max final
53// RA transmission. const uint8_t Icmpv6L4Protocol::MIN_DELAY_BETWEEN_RAS = 3; // min
54// delay between RA. const uint32_t Icmpv6L4Protocol::MAX_RA_DELAY_TIME = 500; //
55// millisecond - max delay between RA.
56
57// const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATION_DELAY = 1; // max RS delay.
58// const uint8_t Icmpv6L4Protocol::RTR_SOLICITATION_INTERVAL = 4; // RS interval.
59// const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATIONS = 3; // max RS transmission.
60
61// const uint8_t Icmpv6L4Protocol::MAX_ANYCAST_DELAY_TIME = 1; // max anycast delay.
62// const uint8_t Icmpv6L4Protocol::MAX_NEIGHBOR_ADVERTISEMENT = 3; // max NA transmission.
63
64// const double Icmpv6L4Protocol::MIN_RANDOM_FACTOR = 0.5; // min random factor.
65// const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5; // max random factor.
66
67TypeId
69{
70 static TypeId tid =
71 TypeId("ns3::Icmpv6L4Protocol")
73 .SetGroupName("Internet")
74 .AddConstructor<Icmpv6L4Protocol>()
75 .AddAttribute("DAD",
76 "Always do DAD check.",
77 BooleanValue(true),
80 .AddAttribute(
81 "SolicitationJitter",
82 "The jitter in ms a node is allowed to wait before sending any solicitation. Some "
83 "jitter aims to prevent collisions. By default, the model will wait for a duration "
84 "in ms defined by a uniform random-variable between 0 and SolicitationJitter",
85 StringValue("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
87 MakePointerChecker<RandomVariableStream>())
88 .AddAttribute("MaxMulticastSolicit",
89 "Neighbor Discovery node constants: max multicast solicitations.",
90 IntegerValue(3),
92 MakeIntegerChecker<uint8_t>())
93 .AddAttribute("MaxUnicastSolicit",
94 "Neighbor Discovery node constants: max unicast solicitations.",
95 IntegerValue(3),
97 MakeIntegerChecker<uint8_t>())
98 .AddAttribute("ReachableTime",
99 "Neighbor Discovery node constants: reachable time.",
100 TimeValue(Seconds(30)),
103 .AddAttribute("RetransmissionTime",
104 "Neighbor Discovery node constants: retransmission timer.",
105 TimeValue(Seconds(1)),
108 .AddAttribute("DelayFirstProbe",
109 "Neighbor Discovery node constants: delay for the first probe.",
110 TimeValue(Seconds(5)),
113 .AddAttribute("DadTimeout",
114 "Duplicate Address Detection (DAD) timeout",
115 TimeValue(Seconds(1)),
118 .AddAttribute("RsRetransmissionJitter",
119 "Multicast RS retransmission randomization quantity",
120 StringValue("ns3::UniformRandomVariable[Min=-0.1|Max=0.1]"),
122 MakePointerChecker<RandomVariableStream>())
123 .AddAttribute("RsInitialRetransmissionTime",
124 "Multicast RS initial retransmission time.",
125 TimeValue(Seconds(4)),
128 .AddAttribute("RsMaxRetransmissionTime",
129 "Multicast RS maximum retransmission time (0 means unbound).",
130 TimeValue(Seconds(3600)),
133 .AddAttribute(
134 "RsMaxRetransmissionCount",
135 "Multicast RS maximum retransmission count (0 means unbound). "
136 "Note: RFC 7559 suggest a zero value (infinite). The default is 4 to avoid "
137 "non-terminating simulations.",
138 UintegerValue(4),
140 MakeUintegerChecker<uint32_t>())
141 .AddAttribute("RsMaxRetransmissionDuration",
142 "Multicast RS maximum retransmission duration (0 means unbound).",
143 TimeValue(Seconds(0)),
146 return tid;
147}
148
149TypeId
151{
152 NS_LOG_FUNCTION(this);
154}
155
157 : m_node(nullptr)
158{
159 NS_LOG_FUNCTION(this);
160}
161
163{
164 NS_LOG_FUNCTION(this);
165}
166
167void
169{
170 NS_LOG_FUNCTION(this);
171 for (CacheList::const_iterator it = m_cacheList.begin(); it != m_cacheList.end(); it++)
172 {
173 Ptr<NdiscCache> cache = *it;
174 cache->Dispose();
175 cache = nullptr;
176 }
177 m_cacheList.clear();
179
180 m_node = nullptr;
182}
183
184int64_t
186{
187 NS_LOG_FUNCTION(this << stream);
190 return 2;
191}
192
193void
195{
196 NS_LOG_FUNCTION(this);
197 if (!m_node)
198 {
199 Ptr<Node> node = this->GetObject<Node>();
200 if (node)
201 {
202 Ptr<Ipv6> ipv6 = this->GetObject<Ipv6>();
203 if (ipv6 && m_downTarget.IsNull())
204 {
205 SetNode(node);
206 ipv6->Insert(this);
208 }
209 }
210 }
212}
213
214void
216{
217 NS_LOG_FUNCTION(this << node);
218 m_node = node;
219}
220
223{
224 NS_LOG_FUNCTION(this);
225 return m_node;
226}
227
228uint16_t
230{
232 return PROT_NUMBER;
233}
234
235int
237{
238 NS_LOG_FUNCTION(this);
239 return PROT_NUMBER;
240}
241
242int
244{
245 NS_LOG_FUNCTION(this);
246 return 1;
247}
248
249bool
251{
252 NS_LOG_FUNCTION(this);
253 return m_alwaysDad;
254}
255
256void
258{
259 NS_LOG_FUNCTION(this << target << interface);
260 Ipv6Address addr;
262
263 NS_ASSERT(ipv6);
264
265 if (!m_alwaysDad)
266 {
267 return;
268 }
269
274 target,
275 interface->GetDevice()->GetAddress());
276
277 /* update last packet UID */
278 interface->SetNsDadUid(target, p.first->GetUid());
281 interface,
282 p.first,
283 p.second,
285}
286
289 const Ipv4Header& header,
290 Ptr<Ipv4Interface> interface)
291{
292 NS_LOG_FUNCTION(this << packet << header);
294}
295
298 const Ipv6Header& header,
299 Ptr<Ipv6Interface> interface)
300{
301 NS_LOG_FUNCTION(this << packet << header.GetSource() << header.GetDestination() << interface);
302 Ptr<Packet> p = packet->Copy();
303 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
304
305 /* very ugly! try to find something better in the future */
306 uint8_t type;
307 p->CopyData(&type, sizeof(type));
308
309 switch (type)
310 {
312 if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
313 {
314 HandleRS(p, header.GetSource(), header.GetDestination(), interface);
315 }
316 break;
318 if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
319 {
320 HandleRA(p, header.GetSource(), header.GetDestination(), interface);
321 }
322 break;
324 HandleNS(p, header.GetSource(), header.GetDestination(), interface);
325 break;
327 HandleNA(p, header.GetSource(), header.GetDestination(), interface);
328 break;
330 HandleRedirection(p, header.GetSource(), header.GetDestination(), interface);
331 break;
333 HandleEchoRequest(p, header.GetSource(), header.GetDestination(), interface);
334 break;
336 // EchoReply does not contain any info about L4
337 // so we can not forward it up.
339 break;
341 HandleDestinationUnreachable(p, header.GetSource(), header.GetDestination(), interface);
342 break;
344 HandlePacketTooBig(p, header.GetSource(), header.GetDestination(), interface);
345 break;
347 HandleTimeExceeded(p, header.GetSource(), header.GetDestination(), interface);
348 break;
350 HandleParameterError(p, header.GetSource(), header.GetDestination(), interface);
351 break;
352 default:
353 NS_LOG_LOGIC("Unknown ICMPv6 message type=" << type);
354 break;
355 }
356
357 return IpL4Protocol::RX_OK;
358}
359
360void
362 Icmpv6Header icmp,
363 uint32_t info,
364 Ipv6Header ipHeader,
365 const uint8_t payload[8])
366{
367 NS_LOG_FUNCTION(this << source << icmp << info << ipHeader << payload);
368
370
372
373 uint8_t nextHeader = ipHeader.GetNextHeader();
374
375 if (nextHeader != Icmpv6L4Protocol::PROT_NUMBER)
376 {
377 Ptr<IpL4Protocol> l4 = ipv6->GetProtocol(nextHeader);
378 if (l4)
379 {
380 l4->ReceiveIcmp(source,
381 ipHeader.GetHopLimit(),
382 icmp.GetType(),
383 icmp.GetCode(),
384 info,
385 ipHeader.GetSource(),
386 ipHeader.GetDestination(),
387 payload);
388 }
389 }
390}
391
392void
394 const Ipv6Address& src,
395 const Ipv6Address& dst,
396 Ptr<Ipv6Interface> interface)
397{
398 NS_LOG_FUNCTION(this << packet << src << dst << interface);
399 Icmpv6Echo request;
400 uint8_t* buf = new uint8_t[packet->GetSize()];
401
402 packet->RemoveHeader(request);
403 /* XXX IPv6 extension: obtain a fresh copy of data otherwise it crash... */
404 packet->CopyData(buf, packet->GetSize());
405 Ptr<Packet> p = Create<Packet>(buf, packet->GetSize());
406
407 /* if we send message from ff02::* (link-local multicast), we use our link-local address */
408 SendEchoReply(dst.IsMulticast() ? interface->GetLinkLocalAddress().GetAddress() : dst,
409 src,
410 request.GetId(),
411 request.GetSeq(),
412 p);
413 delete[] buf;
414}
415
416void
418 const Ipv6Address& src,
419 const Ipv6Address& dst,
420 Ptr<Ipv6Interface> interface)
421{
422 NS_LOG_FUNCTION(this << packet << src << dst << interface);
423
425 {
427 // We need to update this in case we need to restart RS retransmissions.
429 }
430
431 Ptr<Packet> p = packet->Copy();
432 Icmpv6RA raHeader;
435 Icmpv6OptionMtu mtuHdr;
437 bool next = true;
438 bool hasLla = false;
439 bool hasMtu = false;
440 Ipv6Address defaultRouter = Ipv6Address::GetZero();
441
442 p->RemoveHeader(raHeader);
443
444 if (raHeader.GetLifeTime())
445 {
446 defaultRouter = src;
447 }
448
449 while (next)
450 {
451 uint8_t type = 0;
452 p->CopyData(&type, sizeof(type));
453
454 switch (type)
455 {
457 p->RemoveHeader(prefixHdr);
458 ipv6->AddAutoconfiguredAddress(ipv6->GetInterfaceForDevice(interface->GetDevice()),
459 prefixHdr.GetPrefix(),
460 prefixHdr.GetPrefixLength(),
461 prefixHdr.GetFlags(),
462 prefixHdr.GetValidTime(),
463 prefixHdr.GetPreferredTime(),
464 defaultRouter);
465 break;
467 /* take in account the first MTU option */
468 if (!hasMtu)
469 {
470 p->RemoveHeader(mtuHdr);
471 hasMtu = true;
473 /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
474 }
475 break;
477 /* take in account the first LLA option */
478 if (!hasLla)
479 {
480 p->RemoveHeader(llaHdr);
481 ReceiveLLA(llaHdr, src, dst, interface);
482 hasLla = true;
483 }
484 break;
485 default:
486 /* unknown option, quit */
487 next = false;
488 }
489 }
490}
491
492void
494 const Ipv6Address& src,
495 const Ipv6Address& dst,
496 Ptr<Ipv6Interface> interface)
497{
498 NS_LOG_FUNCTION(this << lla << src << dst << interface);
499 Address hardwareAddress;
500 NdiscCache::Entry* entry = nullptr;
501 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
502
503 /* check if we have this address in our cache */
504 entry = cache->Lookup(src);
505
506 if (!entry)
507 {
508 entry = cache->Add(src);
509 entry->SetRouter(true);
510 entry->SetMacAddress(lla.GetAddress());
511 entry->MarkReachable();
512 entry->StartReachableTimer();
513 }
514 else
515 {
516 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
517 switch (entry->m_state)
518 {
520 entry->StopNudTimer();
521 // mark it to reachable
522 waiting = entry->MarkReachable(lla.GetAddress());
523 entry->StartReachableTimer();
524 // send out waiting packet
525 for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin();
526 it != waiting.end();
527 it++)
528 {
529 cache->GetInterface()->Send(it->first, it->second, src);
530 }
531 entry->ClearWaitingPacket();
532 return;
533 }
536 if (entry->GetMacAddress() != lla.GetAddress())
537 {
538 entry->SetMacAddress(lla.GetAddress());
539 entry->MarkStale();
540 entry->SetRouter(true);
541 }
542 else
543 {
544 entry->StopNudTimer();
545 waiting = entry->MarkReachable(lla.GetAddress());
546 entry->StartReachableTimer();
547 }
548 return;
549 }
551 if (entry->GetMacAddress() != lla.GetAddress())
552 {
553 entry->SetMacAddress(lla.GetAddress());
554 entry->MarkStale();
555 entry->SetRouter(true);
556 }
557 else
558 {
559 entry->StopNudTimer();
560 waiting = entry->MarkReachable(lla.GetAddress());
561 for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it =
562 waiting.begin();
563 it != waiting.end();
564 it++)
565 {
566 cache->GetInterface()->Send(it->first, it->second, src);
567 }
568 entry->StartReachableTimer();
569 }
570 return;
571 }
573 if (entry->GetMacAddress() != lla.GetAddress())
574 {
575 entry->SetMacAddress(lla.GetAddress());
576 entry->MarkStale();
577 entry->SetRouter(true);
578 }
579 entry->StartReachableTimer();
580 return;
581 }
584 if (entry->GetMacAddress() != lla.GetAddress())
585 {
586 entry->SetMacAddress(lla.GetAddress());
587 entry->MarkStale();
588 entry->SetRouter(true);
589 }
590 return;
591 }
592 }
593 return; // Silence compiler warning
594 }
595}
596
597void
599 const Ipv6Address& src,
600 const Ipv6Address& dst,
601 Ptr<Ipv6Interface> interface)
602{
603 NS_LOG_FUNCTION(this << packet << src << dst << interface);
605 Icmpv6RS rsHeader;
606 packet->RemoveHeader(rsHeader);
607 Address hardwareAddress;
609 NdiscCache::Entry* entry = nullptr;
610 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
611
612 if (src != Ipv6Address::GetAny())
613 {
614 /* XXX search all options following the RS header */
615 /* test if the next option is SourceLinkLayerAddress */
616 uint8_t type;
617 packet->CopyData(&type, sizeof(type));
618
620 {
621 return;
622 }
623 packet->RemoveHeader(lla);
624 NS_LOG_LOGIC("Cache updated by RS");
625
626 entry = cache->Lookup(src);
627 if (!entry)
628 {
629 entry = cache->Add(src);
630 entry->SetRouter(false);
631 entry->MarkStale(lla.GetAddress());
632 }
633 else if (entry->GetMacAddress() != lla.GetAddress())
634 {
635 entry->MarkStale(lla.GetAddress());
636 }
637 }
638}
639
640void
642 const Ipv6Address& src,
643 const Ipv6Address& dst,
644 Ptr<Ipv6Interface> interface)
645{
646 NS_LOG_FUNCTION(this << packet << src << dst << interface);
647 Icmpv6NS nsHeader("::");
649 uint32_t nb = interface->GetNAddresses();
650 uint32_t i = 0;
651 bool found = false;
652
653 packet->RemoveHeader(nsHeader);
654
655 Ipv6Address target = nsHeader.GetIpv6Target();
656
657 for (i = 0; i < nb; i++)
658 {
659 ifaddr = interface->GetAddress(i);
660
661 if (ifaddr.GetAddress() == target)
662 {
663 found = true;
664 break;
665 }
666 }
667
668 if (!found)
669 {
670 NS_LOG_LOGIC("Not a NS for us");
671 return;
672 }
673
674 if (packet->GetUid() == ifaddr.GetNsDadUid())
675 {
676 /* don't process our own DAD probe */
677 NS_LOG_LOGIC("Hey we receive our DAD probe!");
678 return;
679 }
680
681 NdiscCache::Entry* entry = nullptr;
682 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
683 uint8_t flags = 0;
684
685 /* search all options following the NS header */
686 Icmpv6OptionLinkLayerAddress sllaoHdr(true);
687
688 bool next = true;
689 bool hasSllao = false;
690
691 while (next)
692 {
693 uint8_t type;
694 packet->CopyData(&type, sizeof(type));
695
696 switch (type)
697 {
699 if (!hasSllao)
700 {
701 packet->RemoveHeader(sllaoHdr);
702 hasSllao = true;
703 }
704 break;
705 default:
706 /* unknown option, quit */
707 next = false;
708 }
709 if (packet->GetSize() == 0)
710 {
711 next = false;
712 }
713 }
714
715 Address replyMacAddress;
716
717 if (src != Ipv6Address::GetAny())
718 {
719 entry = cache->Lookup(src);
720 if (!entry)
721 {
722 if (!hasSllao)
723 {
724 NS_LOG_LOGIC("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a "
725 "NCE, discarding.");
726 return;
727 }
728 entry = cache->Add(src);
729 entry->SetRouter(false);
730 entry->MarkStale(sllaoHdr.GetAddress());
731 replyMacAddress = sllaoHdr.GetAddress();
732 }
733 else if (hasSllao && (entry->GetMacAddress() != sllaoHdr.GetAddress()))
734 {
735 entry->MarkStale(sllaoHdr.GetAddress());
736 replyMacAddress = sllaoHdr.GetAddress();
737 }
738 else
739 {
740 replyMacAddress = entry->GetMacAddress();
741 }
742
743 flags = 3; /* S + O flags */
744 }
745 else
746 {
747 /* it's a DAD */
748 flags = 1; /* O flag */
749 replyMacAddress = interface->GetDevice()->GetMulticast(dst);
750 }
751
752 /* send a NA to src */
754
755 if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
756 {
757 flags += 4; /* R flag */
758 }
759
760 Address hardwareAddress = interface->GetDevice()->GetAddress();
762 target.IsLinkLocal() ? interface->GetLinkLocalAddress().GetAddress() : ifaddr.GetAddress(),
763 src.IsAny() ? dst : src, // DAD replies must go to the multicast group it was sent to.
764 &hardwareAddress,
765 flags);
766
767 // We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not
768 // change it beyond what we did already).
769 Ptr<Packet> pkt = p.first;
770 pkt->AddHeader(p.second);
771 interface->GetDevice()->Send(pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
772}
773
776{
777 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
778 Ptr<Packet> p = Create<Packet>();
779 Ipv6Header ipHeader;
780 Icmpv6RS rs;
781
782 NS_LOG_LOGIC("Forge RS (from " << src << " to " << dst << ")");
783 // RFC 4861:
784 // The link-layer address of the sender MUST NOT be included if the Source Address is the
785 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
786 if (!src.IsAny())
787 {
789 1,
790 hardwareAddress); /* we give our mac address in response */
791 p->AddHeader(llOption);
792 }
793
794 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
795 p->AddHeader(rs);
796
797 ipHeader.SetSource(src);
798 ipHeader.SetDestination(dst);
799 ipHeader.SetNextHeader(PROT_NUMBER);
800 ipHeader.SetPayloadLength(p->GetSize());
801 ipHeader.SetHopLimit(255);
802
803 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
804}
805
808 Ipv6Address dst,
809 uint16_t id,
810 uint16_t seq,
812{
813 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
814 Ptr<Packet> p = data->Copy();
815 Ipv6Header ipHeader;
816 Icmpv6Echo req(1);
817
818 req.SetId(id);
819 req.SetSeq(seq);
820
822 dst,
823 p->GetSize() + req.GetSerializedSize(),
825 p->AddHeader(req);
826
827 ipHeader.SetSource(src);
828 ipHeader.SetDestination(dst);
829 ipHeader.SetNextHeader(PROT_NUMBER);
830 ipHeader.SetPayloadLength(p->GetSize());
831 ipHeader.SetHopLimit(255);
832
833 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
834}
835
836void
838 const Ipv6Address& src,
839 const Ipv6Address& dst,
840 Ptr<Ipv6Interface> interface)
841{
842 NS_LOG_FUNCTION(this << packet << src << dst << interface);
843 Icmpv6NA naHeader;
845
846 packet->RemoveHeader(naHeader);
847 Ipv6Address target = naHeader.GetIpv6Target();
848
849 Address hardwareAddress;
850 NdiscCache::Entry* entry = nullptr;
851 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
852 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
853
854 /* check if we have something in our cache */
855 entry = cache->Lookup(target);
856
857 if (!entry)
858 {
859 /* ouch!! we might be victim of a DAD */
860
862 bool found = false;
863 uint32_t i = 0;
864 uint32_t nb = interface->GetNAddresses();
865
866 for (i = 0; i < nb; i++)
867 {
868 ifaddr = interface->GetAddress(i);
869 if (ifaddr.GetAddress() == target)
870 {
871 found = true;
872 break;
873 }
874 }
875
876 if (found)
877 {
880 {
881 interface->SetState(ifaddr.GetAddress(), Ipv6InterfaceAddress::INVALID);
882 }
883 }
884
885 /* we have not initiated any communication with the target so... discard the NA */
886 return;
887 }
888
889 /* XXX search all options following the NA header */
890 /* Get LLA */
891 uint8_t type;
892 packet->CopyData(&type, sizeof(type));
893
895 {
896 return;
897 }
898 packet->RemoveHeader(lla);
899
900 /* we receive a NA so stop the probe timer or delay timer if any */
901 entry->StopNudTimer();
902 switch (entry->m_state)
903 {
905 /* we receive a NA so stop the retransmission timer */
906 entry->StopNudTimer();
907
908 if (naHeader.GetFlagS())
909 {
910 /* mark it to reachable */
911 waiting = entry->MarkReachable(lla.GetAddress());
912 entry->StartReachableTimer();
913 /* send out waiting packet */
914 for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin();
915 it != waiting.end();
916 it++)
917 {
918 cache->GetInterface()->Send(it->first, it->second, src);
919 }
920 entry->ClearWaitingPacket();
921 }
922 else
923 {
924 entry->MarkStale(lla.GetAddress());
925 }
926
927 if (naHeader.GetFlagR())
928 {
929 entry->SetRouter(true);
930 }
931 return;
932 }
934 /* if the Flag O is clear and mac address differs from the cache */
935 if (!naHeader.GetFlagO() && lla.GetAddress() != entry->GetMacAddress())
936 {
937 entry->MarkStale();
938 return;
939 }
940 else
941 {
942 entry->SetMacAddress(lla.GetAddress());
943 if (naHeader.GetFlagS())
944 {
945 entry->StartReachableTimer();
946 }
947 else if (lla.GetAddress() != entry->GetMacAddress())
948 {
949 entry->MarkStale();
950 }
951 entry->SetRouter(naHeader.GetFlagR());
952 }
953 break;
954 }
957 /* if the Flag O is clear and mac address differs from the cache */
958 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
959 {
960 entry->SetMacAddress(lla.GetAddress());
961 if (naHeader.GetFlagS())
962 {
963 entry->MarkReachable(lla.GetAddress());
964 entry->StartReachableTimer();
965 }
966 else if (lla.GetAddress() != entry->GetMacAddress())
967 {
968 entry->MarkStale();
969 }
970 entry->SetRouter(naHeader.GetFlagR());
971 }
972 return;
973 }
975 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
976 {
977 entry->SetMacAddress(lla.GetAddress());
978 if (naHeader.GetFlagS())
979 {
980 waiting = entry->MarkReachable(lla.GetAddress());
981 for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it =
982 waiting.begin();
983 it != waiting.end();
984 it++)
985 {
986 cache->GetInterface()->Send(it->first, it->second, src);
987 }
988 entry->ClearWaitingPacket();
989 entry->StartReachableTimer();
990 }
991 else if (lla.GetAddress() != entry->GetMacAddress())
992 {
993 entry->MarkStale();
994 }
995 entry->SetRouter(naHeader.GetFlagR());
996 }
997 return;
998 }
1001 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
1002 {
1003 entry->SetMacAddress(lla.GetAddress());
1004 if (lla.GetAddress() != entry->GetMacAddress())
1005 {
1006 entry->MarkStale();
1007 }
1008 entry->SetRouter(naHeader.GetFlagR());
1009 }
1010 return;
1011 }
1012 }
1013 // Silence compiler warning
1014}
1015
1016void
1018 const Ipv6Address& src,
1019 const Ipv6Address& dst,
1020 Ptr<Ipv6Interface> interface)
1021{
1022 NS_LOG_FUNCTION(this << packet << src << dst << interface);
1023 bool hasLla = false;
1024 Ptr<Packet> p = packet->Copy();
1025 Icmpv6OptionLinkLayerAddress llOptionHeader(0);
1026
1027 Icmpv6Redirection redirectionHeader;
1028 p->RemoveHeader(redirectionHeader);
1029
1030 /* little ugly try to find a better way */
1031 uint8_t type;
1032 p->CopyData(&type, sizeof(type));
1034 {
1035 hasLla = true;
1036 p->RemoveHeader(llOptionHeader);
1037 }
1038
1039 Icmpv6OptionRedirected redirectedOptionHeader;
1040 p->RemoveHeader(redirectedOptionHeader);
1041
1042 Ipv6Address redirTarget = redirectionHeader.GetTarget();
1043 Ipv6Address redirDestination = redirectionHeader.GetDestination();
1044
1045 if (hasLla)
1046 {
1047 /* update the cache if needed */
1048 NdiscCache::Entry* entry = nullptr;
1049 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
1050
1051 entry = cache->Lookup(redirTarget);
1052 if (!entry)
1053 {
1054 entry = cache->Add(redirTarget);
1055 /* destination and target different => necessarily a router */
1056 entry->SetRouter(redirTarget != redirDestination);
1057 entry->SetMacAddress(llOptionHeader.GetAddress());
1058 entry->MarkStale();
1059 }
1060 else
1061 {
1062 if (entry->IsIncomplete() || entry->GetMacAddress() != llOptionHeader.GetAddress())
1063 {
1064 /* update entry to STALE */
1065 if (entry->GetMacAddress() != llOptionHeader.GetAddress())
1066 {
1067 entry->SetMacAddress(llOptionHeader.GetAddress());
1068 entry->MarkStale();
1069 }
1070 }
1071 else
1072 {
1073 /* stay unchanged */
1074 }
1075 }
1076 }
1077
1078 /* add redirection in routing table */
1079 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1080
1081 if (redirTarget == redirDestination)
1082 {
1083 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1084 Ipv6Prefix(128),
1085 Ipv6Address("::"),
1086 ipv6->GetInterfaceForAddress(dst));
1087 }
1088 else
1089 {
1090 uint32_t ifIndex = ipv6->GetInterfaceForAddress(dst);
1091 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1092 Ipv6Prefix(128),
1093 redirTarget,
1094 ifIndex);
1095 }
1096}
1097
1098void
1100 const Ipv6Address& src,
1101 const Ipv6Address& dst,
1102 Ptr<Ipv6Interface> interface)
1103{
1104 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1105 Ptr<Packet> pkt = p->Copy();
1106
1108 pkt->RemoveHeader(unreach);
1109
1110 Ipv6Header ipHeader;
1111 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1112 {
1113 pkt->RemoveHeader(ipHeader);
1114 uint8_t payload[8];
1115 pkt->CopyData(payload, 8);
1116 Forward(src, unreach, unreach.GetCode(), ipHeader, payload);
1117 }
1118}
1119
1120void
1122 const Ipv6Address& src,
1123 const Ipv6Address& dst,
1124 Ptr<Ipv6Interface> interface)
1125{
1126 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1127 Ptr<Packet> pkt = p->Copy();
1128
1129 Icmpv6TimeExceeded timeexceeded;
1130 pkt->RemoveHeader(timeexceeded);
1131
1132 Ipv6Header ipHeader;
1133 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1134 {
1135 Ipv6Header ipHeader;
1136 pkt->RemoveHeader(ipHeader);
1137 uint8_t payload[8];
1138 pkt->CopyData(payload, 8);
1139 Forward(src, timeexceeded, timeexceeded.GetCode(), ipHeader, payload);
1140 }
1141}
1142
1143void
1145 const Ipv6Address& src,
1146 const Ipv6Address& dst,
1147 Ptr<Ipv6Interface> interface)
1148{
1149 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1150 Ptr<Packet> pkt = p->Copy();
1151
1152 Icmpv6TooBig tooBig;
1153 pkt->RemoveHeader(tooBig);
1154
1155 Ipv6Header ipHeader;
1156 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1157 {
1158 pkt->RemoveHeader(ipHeader);
1159 uint8_t payload[8];
1160 pkt->CopyData(payload, 8);
1161
1163 ipv6->SetPmtu(ipHeader.GetDestination(), tooBig.GetMtu());
1164
1165 Forward(src, tooBig, tooBig.GetMtu(), ipHeader, payload);
1166 }
1167}
1168
1169void
1171 const Ipv6Address& src,
1172 const Ipv6Address& dst,
1173 Ptr<Ipv6Interface> interface)
1174{
1175 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1176 Ptr<Packet> pkt = p->Copy();
1177
1178 Icmpv6ParameterError paramErr;
1179 pkt->RemoveHeader(paramErr);
1180
1181 Ipv6Header ipHeader;
1182 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1183 {
1184 pkt->RemoveHeader(ipHeader);
1185 uint8_t payload[8];
1186 pkt->CopyData(payload, 8);
1187 Forward(src, paramErr, paramErr.GetCode(), ipHeader, payload);
1188 }
1189}
1190
1191void
1193{
1194 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1197 NS_ASSERT(ipv6);
1198
1199 tag.SetHopLimit(ttl);
1200 packet->AddPacketTag(tag);
1201 m_downTarget(packet, src, dst, PROT_NUMBER, nullptr);
1202}
1203
1204void
1206 Ipv6Address src,
1207 Ipv6Address dst,
1208 uint8_t ttl)
1209{
1210 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1211 SendMessage(packet, src, dst, ttl);
1212}
1213
1214void
1216 Ipv6Address dst,
1217 Icmpv6Header& icmpv6Hdr,
1218 uint8_t ttl)
1219{
1220 NS_LOG_FUNCTION(this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
1222 NS_ASSERT(ipv6 && ipv6->GetRoutingProtocol());
1223 Ipv6Header header;
1226 Ptr<Ipv6Route> route;
1227 Ptr<NetDevice> oif(nullptr); // specify non-zero if bound to a source address
1228
1229 header.SetDestination(dst);
1230 route = ipv6->GetRoutingProtocol()->RouteOutput(packet, header, oif, err);
1231
1232 if (route)
1233 {
1234 NS_LOG_LOGIC("Route exists");
1235 tag.SetHopLimit(ttl);
1236 packet->AddPacketTag(tag);
1237 Ipv6Address src = route->GetSource();
1238
1239 icmpv6Hdr.CalculatePseudoHeaderChecksum(src,
1240 dst,
1241 packet->GetSize() + icmpv6Hdr.GetSerializedSize(),
1242 PROT_NUMBER);
1243 packet->AddHeader(icmpv6Hdr);
1244 m_downTarget(packet, src, dst, PROT_NUMBER, route);
1245 }
1246 else
1247 {
1248 NS_LOG_WARN("drop icmp message");
1249 }
1250}
1251
1252void
1253Icmpv6L4Protocol::SendNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1254{
1255 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << static_cast<uint32_t>(flags));
1256 Ptr<Packet> p = Create<Packet>();
1257 Icmpv6NA na;
1258 Icmpv6OptionLinkLayerAddress llOption(0, *hardwareAddress); /* not a source link layer */
1259
1260 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1261 na.SetIpv6Target(src);
1262
1263 if ((flags & 1))
1264 {
1265 na.SetFlagO(true);
1266 }
1267 if ((flags & 2) && src != Ipv6Address::GetAny())
1268 {
1269 na.SetFlagS(true);
1270 }
1271 if ((flags & 4))
1272 {
1273 na.SetFlagR(true);
1274 }
1275
1276 p->AddHeader(llOption);
1277 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1278 p->AddHeader(na);
1279
1280 SendMessage(p, src, dst, 255);
1281}
1282
1283void
1285 Ipv6Address dst,
1286 uint16_t id,
1287 uint16_t seq,
1289{
1290 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
1291 Ptr<Packet> p = data->Copy();
1292 Icmpv6Echo reply(0); /* echo reply */
1293
1294 reply.SetId(id);
1295 reply.SetSeq(seq);
1296
1298 dst,
1299 p->GetSize() + reply.GetSerializedSize(),
1300 PROT_NUMBER);
1301 p->AddHeader(reply);
1302 SendMessage(p, src, dst, 64);
1303}
1304
1305void
1307 Ipv6Address dst,
1308 Ipv6Address target,
1309 Address hardwareAddress)
1310{
1311 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1312 Ptr<Packet> p = Create<Packet>();
1313 /* Ipv6Header ipHeader; */
1314 Icmpv6NS ns(target);
1316 1,
1317 hardwareAddress); /* we give our mac address in response */
1318
1319 /* if the source is unspec, multicast the NA to all-nodes multicast */
1320 if (src == Ipv6Address::GetAny())
1321 {
1323 }
1324
1325 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1326
1327 p->AddHeader(llOption);
1328 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1329 p->AddHeader(ns);
1330 if (!dst.IsMulticast())
1331 {
1332 SendMessage(p, src, dst, 255);
1333 }
1334 else
1335 {
1336 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1339 this,
1340 p,
1341 src,
1342 dst,
1343 255);
1344 }
1345}
1346
1347void
1349{
1350 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1351 Ptr<Packet> p = Create<Packet>();
1352 Icmpv6RS rs;
1353
1354 // RFC 4861:
1355 // The link-layer address of the sender MUST NOT be included if the Source Address is the
1356 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
1357 if (!src.IsAny())
1358 {
1359 Icmpv6OptionLinkLayerAddress llOption(1, hardwareAddress);
1360 p->AddHeader(llOption);
1361 }
1362
1363 NS_LOG_LOGIC("Send RS (from " << src << " to " << dst << ")");
1364
1365 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
1366 p->AddHeader(rs);
1367 if (!dst.IsMulticast())
1368 {
1369 SendMessage(p, src, dst, 255);
1370 }
1371 else
1372 {
1373 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1374 Time rsDelay = Time(0);
1375 Time rsTimeout = Time(0);
1376
1377 if (m_rsRetransmissionCount == 0)
1378 {
1379 // First RS transmission - also add some jitter to desynchronize nodes.
1383 }
1384 else
1385 {
1386 // Following RS transmission - adding further jitter is unnecessary.
1388 if (rsTimeout > m_rsMaxRetransmissionTime)
1389 {
1391 }
1392 }
1394 Simulator::Schedule(rsDelay, &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
1397 this,
1398 src,
1399 dst,
1400 hardwareAddress);
1401 }
1402}
1403
1404void
1406{
1407 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1408
1410 {
1411 // Unbound number of retransmissions - just add one to signal that we're in retransmission
1412 // mode.
1414 }
1415 else
1416 {
1419 {
1420 NS_LOG_LOGIC("Maximum number of multicast RS reached, giving up.");
1421 return;
1422 }
1423 }
1424
1427 {
1428 NS_LOG_LOGIC("Maximum RS retransmission time reached, giving up.");
1429 return;
1430 }
1431
1432 SendRS(src, dst, hardwareAddress);
1433}
1434
1435void
1437 Ipv6Address dst,
1438 uint8_t code)
1439{
1440 NS_LOG_FUNCTION(this << malformedPacket << dst << (uint32_t)code);
1441 uint32_t malformedPacketSize = malformedPacket->GetSize();
1443 header.SetCode(code);
1444
1445 NS_LOG_LOGIC("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1446
1447 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1448 if (malformedPacketSize <= 1280 - 48)
1449 {
1450 header.SetPacket(malformedPacket);
1451 SendMessage(malformedPacket, dst, header, 255);
1452 }
1453 else
1454 {
1455 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1456 header.SetPacket(fragment);
1457 SendMessage(fragment, dst, header, 255);
1458 }
1459}
1460
1461void
1463{
1464 NS_LOG_FUNCTION(this << malformedPacket << dst << mtu);
1465 uint32_t malformedPacketSize = malformedPacket->GetSize();
1466 Icmpv6TooBig header;
1467 header.SetCode(0);
1468 header.SetMtu(mtu);
1469
1470 NS_LOG_LOGIC("Send Too Big ( to " << dst << " )");
1471
1472 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1473 if (malformedPacketSize <= 1280 - 48)
1474 {
1475 header.SetPacket(malformedPacket);
1476 SendMessage(malformedPacket, dst, header, 255);
1477 }
1478 else
1479 {
1480 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1481 header.SetPacket(fragment);
1482 SendMessage(fragment, dst, header, 255);
1483 }
1484}
1485
1486void
1488{
1489 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code));
1490 uint32_t malformedPacketSize = malformedPacket->GetSize();
1491 Icmpv6TimeExceeded header;
1492 header.SetCode(code);
1493
1494 NS_LOG_LOGIC("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1495
1496 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1497 if (malformedPacketSize <= 1280 - 48)
1498 {
1499 header.SetPacket(malformedPacket);
1500 SendMessage(malformedPacket, dst, header, 255);
1501 }
1502 else
1503 {
1504 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1505 header.SetPacket(fragment);
1506 SendMessage(fragment, dst, header, 255);
1507 }
1508}
1509
1510void
1512 Ipv6Address dst,
1513 uint8_t code,
1514 uint32_t ptr)
1515{
1516 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code) << ptr);
1517 uint32_t malformedPacketSize = malformedPacket->GetSize();
1518 Icmpv6ParameterError header;
1519 header.SetCode(code);
1520 header.SetPtr(ptr);
1521
1522 NS_LOG_LOGIC("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1523
1524 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1525 if (malformedPacketSize <= 1280 - 48)
1526 {
1527 header.SetPacket(malformedPacket);
1528 SendMessage(malformedPacket, dst, header, 255);
1529 }
1530 else
1531 {
1532 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1533 header.SetPacket(fragment);
1534 SendMessage(fragment, dst, header, 255);
1535 }
1536}
1537
1538void
1540 Ipv6Address src,
1541 Ipv6Address dst,
1542 Ipv6Address redirTarget,
1543 Ipv6Address redirDestination,
1544 Address redirHardwareTarget)
1545{
1546 NS_LOG_FUNCTION(this << redirectedPacket << dst << redirTarget << redirDestination
1547 << redirHardwareTarget);
1548 uint32_t llaSize = 0;
1549 Ptr<Packet> p = Create<Packet>();
1550 uint32_t redirectedPacketSize = redirectedPacket->GetSize();
1551 Icmpv6OptionLinkLayerAddress llOption(0);
1552
1553 NS_LOG_LOGIC("Send Redirection ( to " << dst << " target " << redirTarget << " destination "
1554 << redirDestination << " )");
1555
1556 Icmpv6OptionRedirected redirectedOptionHeader;
1557
1558 if ((redirectedPacketSize % 8) != 0)
1559 {
1560 Ptr<Packet> pad = Create<Packet>(8 - (redirectedPacketSize % 8));
1561 redirectedPacket->AddAtEnd(pad);
1562 }
1563
1564 if (redirHardwareTarget.GetLength())
1565 {
1566 llOption.SetAddress(redirHardwareTarget);
1567 llaSize = llOption.GetSerializedSize();
1568 }
1569
1570 /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1571 if (redirectedPacketSize <= (1280 - 56 - llaSize))
1572 {
1573 redirectedOptionHeader.SetPacket(redirectedPacket);
1574 }
1575 else
1576 {
1577 Ptr<Packet> fragment = redirectedPacket->CreateFragment(0, 1280 - 56 - llaSize);
1578 redirectedOptionHeader.SetPacket(fragment);
1579 }
1580
1581 p->AddHeader(redirectedOptionHeader);
1582
1583 if (llaSize)
1584 {
1585 p->AddHeader(llOption);
1586 }
1587
1588 Icmpv6Redirection redirectionHeader;
1589 redirectionHeader.SetTarget(redirTarget);
1590 redirectionHeader.SetDestination(redirDestination);
1591 redirectionHeader.CalculatePseudoHeaderChecksum(src,
1592 dst,
1593 p->GetSize() +
1594 redirectionHeader.GetSerializedSize(),
1595 PROT_NUMBER);
1596 p->AddHeader(redirectionHeader);
1597
1598 SendMessage(p, src, dst, 64);
1599}
1600
1602Icmpv6L4Protocol::ForgeNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1603{
1604 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << (uint32_t)flags);
1605 Ptr<Packet> p = Create<Packet>();
1606 Ipv6Header ipHeader;
1607 Icmpv6NA na;
1609 0,
1610 *hardwareAddress); /* we give our mac address in response */
1611
1612 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << ")");
1613
1614 /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet
1615 * does not pass by Icmpv6L4Protocol::Lookup again */
1616
1617 p->AddHeader(llOption);
1618 na.SetIpv6Target(src);
1619
1620 if ((flags & 1))
1621 {
1622 na.SetFlagO(true);
1623 }
1624 if ((flags & 2) && src != Ipv6Address::GetAny())
1625 {
1626 na.SetFlagS(true);
1627 }
1628 if ((flags & 4))
1629 {
1630 na.SetFlagR(true);
1631 }
1632
1633 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1634 p->AddHeader(na);
1635
1636 ipHeader.SetSource(src);
1637 ipHeader.SetDestination(dst);
1638 ipHeader.SetNextHeader(PROT_NUMBER);
1639 ipHeader.SetPayloadLength(p->GetSize());
1640 ipHeader.SetHopLimit(255);
1641
1642 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1643}
1644
1647 Ipv6Address dst,
1648 Ipv6Address target,
1649 Address hardwareAddress)
1650{
1651 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1652 Ptr<Packet> p = Create<Packet>();
1653 Ipv6Header ipHeader;
1654 Icmpv6NS ns(target);
1656 1,
1657 hardwareAddress); /* we give our mac address in response */
1658
1659 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1660
1661 p->AddHeader(llOption);
1662 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1663 p->AddHeader(ns);
1664
1665 ipHeader.SetSource(src);
1666 ipHeader.SetDestination(dst);
1667 ipHeader.SetNextHeader(PROT_NUMBER);
1668 ipHeader.SetPayloadLength(p->GetSize());
1669 ipHeader.SetHopLimit(255);
1670
1671 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1672}
1673
1676{
1677 NS_LOG_FUNCTION(this << device);
1678
1679 for (CacheList::const_iterator i = m_cacheList.begin(); i != m_cacheList.end(); i++)
1680 {
1681 if ((*i)->GetDevice() == device)
1682 {
1683 return *i;
1684 }
1685 }
1686
1687 NS_ASSERT_MSG(false, "Icmpv6L4Protocol can not find a NDIS Cache for device " << device);
1688 /* quiet compiler */
1689 return nullptr;
1690}
1691
1694{
1695 NS_LOG_FUNCTION(this << device << interface);
1696
1697 Ptr<NdiscCache> cache = CreateObject<NdiscCache>();
1698
1699 cache->SetDevice(device, interface, this);
1700 device->AddLinkChangeCallback(MakeCallback(&NdiscCache::Flush, cache));
1701 m_cacheList.push_back(cache);
1702 return cache;
1703}
1704
1705bool
1707 Ptr<NetDevice> device,
1708 Ptr<NdiscCache> cache,
1709 Address* hardwareDestination)
1710{
1711 NS_LOG_FUNCTION(this << dst << device << cache << hardwareDestination);
1712
1713 if (!cache)
1714 {
1715 /* try to find the cache */
1716 cache = FindCache(device);
1717 }
1718 if (cache)
1719 {
1720 NdiscCache::Entry* entry = cache->Lookup(dst);
1721 if (entry)
1722 {
1723 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1724 entry->IsAutoGenerated())
1725 {
1726 *hardwareDestination = entry->GetMacAddress();
1727 return true;
1728 }
1729 else if (entry->IsStale())
1730 {
1731 entry->StartDelayTimer();
1732 entry->MarkDelay();
1733 *hardwareDestination = entry->GetMacAddress();
1734 return true;
1735 }
1736 }
1737 }
1738 return false;
1739}
1740
1741bool
1743 const Ipv6Header& ipHeader,
1744 Ipv6Address dst,
1745 Ptr<NetDevice> device,
1746 Ptr<NdiscCache> cache,
1747 Address* hardwareDestination)
1748{
1749 NS_LOG_FUNCTION(this << p << ipHeader << dst << device << cache << hardwareDestination);
1750
1751 if (!cache)
1752 {
1753 /* try to find the cache */
1754 cache = FindCache(device);
1755 }
1756 if (!cache)
1757 {
1758 return false;
1759 }
1760
1761 NdiscCache::Entry* entry = cache->Lookup(dst);
1762 if (entry)
1763 {
1764 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1765 entry->IsAutoGenerated())
1766 {
1767 /* XXX check reachability time */
1768 /* send packet */
1769 *hardwareDestination = entry->GetMacAddress();
1770 return true;
1771 }
1772 else if (entry->IsStale())
1773 {
1774 /* start delay timer */
1775 entry->StartDelayTimer();
1776 entry->MarkDelay();
1777 *hardwareDestination = entry->GetMacAddress();
1778 return true;
1779 }
1780 else /* INCOMPLETE or PROBE */
1781 {
1782 /* queue packet */
1784 return false;
1785 }
1786 }
1787 else
1788 {
1789 /* we contact this node for the first time
1790 * add it to the cache and send an NS
1791 */
1792 Ipv6Address addr;
1793 NdiscCache::Entry* entry = cache->Add(dst);
1795 entry->SetRouter(false);
1796
1797 if (dst.IsLinkLocal())
1798 {
1799 addr = cache->GetInterface()->GetLinkLocalAddress().GetAddress();
1800 }
1801 else if (cache->GetInterface()->GetNAddresses() ==
1802 1) /* an interface have at least one address (link-local) */
1803 {
1804 /* try to resolve global address without having global address so return! */
1805 cache->Remove(entry);
1806 return false;
1807 }
1808 else
1809 {
1810 /* find source address that match destination */
1811 addr = cache->GetInterface()->GetAddressMatchingDestination(dst).GetAddress();
1812 }
1813
1814 SendNS(addr, Ipv6Address::MakeSolicitedAddress(dst), dst, cache->GetDevice()->GetAddress());
1815
1816 /* start retransmit timer */
1817 entry->StartRetransmitTimer();
1818 return false;
1819 }
1820
1821 return false;
1822}
1823
1824void
1826{
1827 NS_LOG_FUNCTION(this << interface << addr);
1828
1829 Ipv6InterfaceAddress ifaddr;
1830 bool found = false;
1831 uint32_t i = 0;
1832 uint32_t nb = interface->GetNAddresses();
1833
1834 for (i = 0; i < nb; i++)
1835 {
1836 ifaddr = interface->GetAddress(i);
1837
1838 if (ifaddr.GetAddress() == addr)
1839 {
1840 found = true;
1841 break;
1842 }
1843 }
1844
1845 if (!found)
1846 {
1847 NS_LOG_LOGIC("Can not find the address in the interface.");
1848 }
1849
1850 /* for the moment, this function is always called, if we was victim of a DAD the address is
1851 * INVALID and we do not set it to PREFERRED
1852 */
1853 if (found && ifaddr.GetState() != Ipv6InterfaceAddress::INVALID)
1854 {
1856 NS_LOG_LOGIC("DAD OK, interface in state PREFERRED");
1857
1858 /* send an RS if our interface is not forwarding (router) and if address is a link-local
1859 * ones (because we will send RS with it)
1860 */
1861 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1862
1863 if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())) &&
1864 addr.IsLinkLocal())
1865 {
1866 /* \todo Add random delays before sending RS
1867 * because all nodes start at the same time, there will be many of RS around 1 second of
1868 * simulation time
1869 */
1870 NS_LOG_LOGIC("Scheduled a first Router Solicitation");
1874 this,
1875 ifaddr.GetAddress(),
1877 interface->GetDevice()->GetAddress());
1878 }
1879 else
1880 {
1881 NS_LOG_LOGIC("Did not schedule a Router Solicitation because the interface is in "
1882 "forwarding mode");
1883 }
1884 }
1885}
1886
1887void
1889{
1890 NS_LOG_FUNCTION(this << &callback);
1891}
1892
1893void
1895{
1896 NS_LOG_FUNCTION(this << &callback);
1897 m_downTarget = callback;
1898}
1899
1902{
1903 NS_LOG_FUNCTION(this);
1905}
1906
1909{
1910 NS_LOG_FUNCTION(this);
1911 return m_downTarget;
1912}
1913
1914uint8_t
1916{
1917 return m_maxMulticastSolicit;
1918}
1919
1920uint8_t
1922{
1923 return m_maxUnicastSolicit;
1924}
1925
1926Time
1928{
1929 return m_reachableTime;
1930}
1931
1932Time
1934{
1935 return m_retransmissionTime;
1936}
1937
1938Time
1940{
1941 return m_delayFirstProbe;
1942}
1943
1944Time
1946{
1947 return m_dadTimeout;
1948}
1949
1950} /* namespace ns3 */
a polymophic address class
Definition: address.h:100
uint8_t GetLength() const
Get the length of the underlying address.
Definition: address.cc:78
AttributeValue implementation for Boolean.
Definition: boolean.h:37
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:573
bool IsNull() const
Check for null implementation.
Definition: callback.h:567
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
ICMPv6 Error Destination Unreachable header.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
ICMPv6 Echo message.
void SetId(uint16_t id)
Set the ID of the packet.
uint16_t GetId() const
Get the ID of the packet.
void SetSeq(uint16_t seq)
Set the sequence number.
uint32_t GetSerializedSize() const override
Get the serialized size.
uint16_t GetSeq() const
Get the sequence number.
ICMPv6 header.
Definition: icmpv6-header.h:38
uint8_t GetCode() const
Get the code field.
uint8_t GetType() const
Get the type field.
void CalculatePseudoHeaderChecksum(Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
Calculate pseudo header checksum for IPv6.
void SetCode(uint8_t code)
Set the code field.
uint32_t GetSerializedSize() const override
Get the serialized size.
@ ICMPV6_ND_NEIGHBOR_ADVERTISEMENT
Definition: icmpv6-header.h:57
@ ICMPV6_ERROR_DESTINATION_UNREACHABLE
Definition: icmpv6-header.h:45
An implementation of the ICMPv6 protocol.
Time GetRetransmissionTime() const
Neighbor Discovery node constants: retransmission timer.
int GetProtocolNumber() const override
Get the protocol number.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
void Forward(Ipv6Address source, Icmpv6Header icmp, uint32_t info, Ipv6Header ipHeader, const uint8_t payload[8])
Notify an ICMPv6 reception to upper layers (if requested).
void ReceiveLLA(Icmpv6OptionLinkLayerAddress lla, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Link layer address option processing.
void SendErrorTimeExceeded(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code)
Send an error Time Exceeded.
IpL4Protocol::RxStatus Receive(Ptr< Packet > p, const Ipv4Header &header, Ptr< Ipv4Interface > interface) override
Receive method.
void DoDispose() override
Dispose this object.
void SendErrorTooBig(Ptr< Packet > malformedPacket, Ipv6Address dst, uint32_t mtu)
Send an error Too Big.
uint8_t m_maxMulticastSolicit
Neighbor Discovery node constants: max multicast solicitations.
void NotifyNewAggregate() override
This method is called by AggregateObject and completes the aggregation by setting the node in the ICM...
Time m_reachableTime
Neighbor Discovery node constants: reachable time.
NdiscCache::Ipv6PayloadHeaderPair ForgeEchoRequest(Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr< Packet > data)
Forge an Echo Request.
Time m_rsMaxRetransmissionTime
Maximum time between multicast RS retransmissions [RFC 7559].
uint32_t m_rsMaxRetransmissionCount
Maximum number of multicast RS retransmissions [RFC 7559].
virtual Ptr< NdiscCache > CreateCache(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface)
Create a neighbor cache.
~Icmpv6L4Protocol() override
Destructor.
IpL4Protocol::DownTargetCallback6 GetDownTarget6() const override
This method allows a caller to get the current down target callback set for this L4 protocol (IPv6 ca...
void SetDownTarget6(IpL4Protocol::DownTargetCallback6 cb) override
This method allows a caller to set the current down target callback set for this L4 protocol (IPv6 ca...
uint32_t m_rsRetransmissionCount
Multicast RS retransmissions counter [RFC 7559].
void DelayedSendMessage(Ptr< Packet > packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
Helper function used during delayed solicitation.
Ptr< Node > GetNode()
Get the node.
void HandleTimeExceeded(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Time Exceeded method.
void HandleDestinationUnreachable(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Destination Unreachable method.
void HandlePacketTooBig(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Packet Too Big method.
Ptr< UniformRandomVariable > m_rsRetransmissionJitter
Random jitter for RS retransmissions.
bool IsAlwaysDad() const
Is the node must do DAD.
void HandleRA(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Router Advertisement method.
void SetDownTarget(IpL4Protocol::DownTargetCallback cb) override
This method allows a caller to set the current down target callback set for this L4 protocol (IPv4 ca...
void SendErrorParameterError(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
Send an error Parameter Error.
Time GetDadTimeout() const
Get the DAD timeout.
Time GetDelayFirstProbe() const
Neighbor Discovery node constants : delay for the first probe.
NdiscCache::Ipv6PayloadHeaderPair ForgeNA(Ipv6Address src, Ipv6Address dst, Address *hardwareAddress, uint8_t flags)
Forge a Neighbor Advertisement.
void HandleRS(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Router Solicitation method.
virtual void FunctionDadTimeout(Ipv6Interface *interface, Ipv6Address addr)
Function called when DAD timeout.
uint8_t m_maxUnicastSolicit
Neighbor Discovery node constants: max unicast solicitations.
void SendRedirection(Ptr< Packet > redirectedPacket, Ipv6Address src, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget)
Send an ICMPv6 Redirection.
Time m_dadTimeout
DAD timeout.
Ptr< Node > m_node
The node.
IpL4Protocol::DownTargetCallback6 m_downTarget
callback to Ipv6::Send
Ptr< NdiscCache > FindCache(Ptr< NetDevice > device)
Get the cache corresponding to the device.
void DoDAD(Ipv6Address target, Ptr< Ipv6Interface > interface)
Do the Duplication Address Detection (DAD).
virtual void HandleRsTimeout(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Router Solicitation Timeout handler.
bool m_alwaysDad
Always do DAD ?
void SendErrorDestinationUnreachable(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code)
Send an error Destination Unreachable.
static const uint8_t PROT_NUMBER
ICMPv6 protocol number (58).
virtual void SendNS(Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
Send a Neighbor Solicitation.
void SendRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Send a Router Solicitation.
Time m_retransmissionTime
Neighbor Discovery node constants: retransmission timer.
uint8_t GetMaxUnicastSolicit() const
Neighbor Discovery node constants: max unicast solicitations.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
void HandleEchoRequest(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Echo Request method.
void HandleParameterError(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Parameter Error method.
void HandleNS(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Solicitation method.
Time m_rsMaxRetransmissionDuration
Maximum duration of multicast RS retransmissions [RFC 7559].
void HandleRedirection(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Redirection method.
virtual bool Lookup(Ipv6Address dst, Ptr< NetDevice > device, Ptr< NdiscCache > cache, Address *hardwareDestination)
Lookup in the ND cache for the IPv6 address.
Time m_rsPrevRetransmissionTimeout
Previous multicast RS retransmissions timeout [RFC 7559].
IpL4Protocol::DownTargetCallback GetDownTarget() const override
This method allows a caller to get the current down target callback set for this L4 protocol (IPv4 ca...
EventId m_handleRsTimeoutEvent
RS timeout handler event.
virtual int GetVersion() const
Get the version of the protocol.
Ptr< RandomVariableStream > m_solicitationJitter
Random jitter before sending solicitations.
void SendMessage(Ptr< Packet > packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
Send a packet via ICMPv6, note that packet already contains ICMPv6 header.
Time m_delayFirstProbe
Neighbor Discovery node constants: delay for the first probe.
void SendEchoReply(Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr< Packet > data)
Send a Echo Reply.
NdiscCache::Ipv6PayloadHeaderPair ForgeRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Forge a Router Solicitation.
NdiscCache::Ipv6PayloadHeaderPair ForgeNS(Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
Forge a Neighbor Solicitation.
void SendNA(Ipv6Address src, Ipv6Address dst, Address *hardwareAddress, uint8_t flags)
Send a Neighbor Advertisement.
Time m_rsInitialRetransmissionTime
Initial multicast RS retransmission time [RFC 7559].
static TypeId GetTypeId()
Get the type ID.
Time GetReachableTime() const
Neighbor Discovery node constants: reachable time.
CacheList m_cacheList
A list of cache by device.
uint8_t GetMaxMulticastSolicit() const
Neighbor Discovery node constants: max multicast solicitations.
void SetNode(Ptr< Node > node)
Set the node.
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
void HandleNA(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Advertisement method.
ICMPv6 Neighbor Advertisement header.
bool GetFlagS() const
Get the S flag.
void SetFlagS(bool s)
Set the S flag.
void SetIpv6Target(Ipv6Address target)
Set the IPv6 target field.
void SetFlagR(bool r)
Set the R flag.
Ipv6Address GetIpv6Target() const
Get the IPv6 target field.
bool GetFlagR() const
Get the R flag.
uint32_t GetSerializedSize() const override
Get the serialized size.
bool GetFlagO() const
Get the O flag.
void SetFlagO(bool o)
Set the O flag.
ICMPv6 Neighbor Solicitation header.
uint32_t GetSerializedSize() const override
Get the serialized size.
Ipv6Address GetIpv6Target() const
Get the IPv6 target field.
ICMPv6 MTU option.
ICMPv6 Option Prefix Information.
ICMPv6 redirected option.
void SetPacket(Ptr< Packet > packet)
Set the redirected packet.
ICMPv6 Error Parameter Error header.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
void SetPtr(uint32_t ptr)
Set the pointer field.
ICMPv6 Router Advertisement header.
uint16_t GetLifeTime() const
Get the node Life time (Neighbor Discovery).
ICMPv6 Router Solicitation header.
uint32_t GetSerializedSize() const override
Get the serialized size.
ICMPv6 Redirection header.
Ipv6Address GetTarget() const
Get the IPv6 target address.
uint32_t GetSerializedSize() const override
Get the serialized size.
void SetDestination(Ipv6Address destination)
Set the IPv6 destination address.
Ipv6Address GetDestination() const
Get the IPv6 destination address.
void SetTarget(Ipv6Address target)
Set the IPv6 target address.
ICMPv6 Error Time Exceeded header.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
ICMPv6 Error Too Big header.
void SetMtu(uint32_t mtu)
Set the MTU.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
uint32_t GetMtu() const
Get the MTU field.
Hold a signed integer type.
Definition: integer.h:45
L4 Protocol abstract base class.
Callback< void, Ptr< Packet >, Ipv4Address, Ipv4Address, uint8_t, Ptr< Ipv4Route > > DownTargetCallback
callback to send packets over IPv4
RxStatus
Rx status codes.
Packet header for IPv4.
Definition: ipv4-header.h:34
Describes an IPv6 address.
Definition: ipv6-address.h:49
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
static Ipv6Address GetAllNodesMulticast()
Get the "all nodes multicast" address.
static Ipv6Address MakeSolicitedAddress(Ipv6Address addr)
Make the solicited IPv6 address.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
bool IsAny() const
If the IPv6 address is the "Any" address.
static Ipv6Address GetAllRoutersMulticast()
Get the "all routers multicast" address.
Packet header for IPv6.
Definition: ipv6-header.h:35
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:118
void SetSource(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:106
uint8_t GetHopLimit() const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:100
uint8_t GetNextHeader() const
Get the next header.
Definition: ipv6-header.cc:88
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:94
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:124
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:70
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Definition: ipv6-header.cc:159
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:82
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:82
virtual void Send(Ptr< Packet > packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr< Ipv6Route > route)=0
Higher-level layers call this method to send a packet down the stack to the MAC and PHY layers.
IPv6 address associated with an interface.
Ipv6Address GetAddress() const
Get the IPv6 address.
uint32_t GetNsDadUid() const
Get the latest DAD probe packet UID.
Ipv6InterfaceAddress::State_e GetState() const
Get the address state.
@ TENTATIVE_OPTIMISTIC
Address is tentative but we are optimistic so we can send packet even if DAD is not yet finished.
@ INVALID
Invalid state (after a DAD failed)
@ TENTATIVE
Address is tentative, no packet can be sent unless DAD finished.
The IPv6 representation of a network interface.
uint32_t GetNAddresses() const
Get number of addresses on this IPv6 interface.
Ipv6InterfaceAddress GetAddress(uint32_t index) const
Get an address from IPv6 interface.
void Send(Ptr< Packet > p, const Ipv6Header &hdr, Ipv6Address dest)
Send a packet through this interface.
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
void SetState(Ipv6Address address, Ipv6InterfaceAddress::State_e state)
Update state of an interface address.
IPv6 layer implementation.
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
Describes an IPv6 prefix.
Definition: ipv6-address.h:455
A record that holds information about a NdiscCache entry.
Definition: ndisc-cache.h:167
bool IsPermanent() const
Is the entry PERMANENT.
Definition: ndisc-cache.cc:659
NdiscCacheEntryState_e m_state
The state of the entry.
Definition: ndisc-cache.h:194
@ PROBE
Try to contact IPv6 address to know again its L2 address.
Definition: ndisc-cache.h:186
@ STALE
Mapping is stale.
Definition: ndisc-cache.h:184
@ REACHABLE
Mapping exists between IPv6 and L2 addresses.
Definition: ndisc-cache.h:183
@ PERMANENT
Permanent Mapping exists between IPv6 and L2 addresses.
Definition: ndisc-cache.h:187
@ DELAY
Try to wait contact from remote host.
Definition: ndisc-cache.h:185
@ INCOMPLETE
No mapping between IPv6 and L2 addresses.
Definition: ndisc-cache.h:182
@ STATIC_AUTOGENERATED
Permanent entries generate by NeighborCacheHelper.
Definition: ndisc-cache.h:188
void ClearWaitingPacket()
Clear the waiting packet list.
Definition: ndisc-cache.cc:286
std::list< Ipv6PayloadHeaderPair > MarkStale(Address mac)
Changes the state to this entry to STALE.
Definition: ndisc-cache.cc:592
void StartReachableTimer()
Start the reachable timer.
Definition: ndisc-cache.cc:469
Address GetMacAddress() const
Get the MAC address of this entry.
Definition: ndisc-cache.cc:673
void StartDelayTimer()
Start delay timer.
Definition: ndisc-cache.cc:514
std::list< Ipv6PayloadHeaderPair > MarkReachable(Address mac)
Changes the state to this entry to REACHABLE.
Definition: ndisc-cache.cc:562
bool IsIncomplete() const
Is the entry INCOMPLETE.
Definition: ndisc-cache.cc:645
bool IsDelay() const
Is the entry DELAY.
Definition: ndisc-cache.cc:638
void StartRetransmitTimer()
Start retransmit timer.
Definition: ndisc-cache.cc:528
void MarkIncomplete(Ipv6PayloadHeaderPair p)
Changes the state to this entry to INCOMPLETE.
Definition: ndisc-cache.cc:550
bool IsStale() const
Is the entry STALE.
Definition: ndisc-cache.cc:624
void SetMacAddress(Address mac)
Set the MAC address of this entry.
Definition: ndisc-cache.cc:680
void MarkDelay()
Change the state to this entry to DELAY.
Definition: ndisc-cache.cc:601
void SetRouter(bool router)
Set the node type.
Definition: ndisc-cache.cc:258
bool IsAutoGenerated() const
Is the entry STATIC_AUTOGENERATED.
Definition: ndisc-cache.cc:666
void AddWaitingPacket(Ipv6PayloadHeaderPair p)
Add a packet (or replace old value) in the queue.
Definition: ndisc-cache.cc:272
bool IsReachable() const
Is the entry REACHABLE.
Definition: ndisc-cache.cc:631
void StopNudTimer()
Stop NUD timer and reset the NUD retransmission counter.
Definition: ndisc-cache.cc:542
std::pair< Ptr< Packet >, Ipv6Header > Ipv6PayloadHeaderPair
Pair of a packet and an Ipv4 header.
Definition: ndisc-cache.h:159
void Flush()
Flush the cache.
Definition: ndisc-cache.cc:163
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:332
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
virtual double GetValue()=0
Get the next random value drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition: socket.h:1170
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:666
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1423
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Definition: integer.h:46
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1444
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:702
uint8_t data[writeSize]