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 (auto 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 auto 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 (auto it = waiting.begin(); it != waiting.end(); it++)
526 {
527 cache->GetInterface()->Send(it->first, it->second, src);
528 }
529 entry->ClearWaitingPacket();
530 return;
531 }
534 if (entry->GetMacAddress() != lla.GetAddress())
535 {
536 entry->SetMacAddress(lla.GetAddress());
537 entry->MarkStale();
538 entry->SetRouter(true);
539 }
540 else
541 {
542 entry->StopNudTimer();
543 waiting = entry->MarkReachable(lla.GetAddress());
544 entry->StartReachableTimer();
545 }
546 return;
547 }
549 if (entry->GetMacAddress() != lla.GetAddress())
550 {
551 entry->SetMacAddress(lla.GetAddress());
552 entry->MarkStale();
553 entry->SetRouter(true);
554 }
555 else
556 {
557 entry->StopNudTimer();
558 waiting = entry->MarkReachable(lla.GetAddress());
559 for (auto it = waiting.begin(); it != waiting.end(); it++)
560 {
561 cache->GetInterface()->Send(it->first, it->second, src);
562 }
563 entry->StartReachableTimer();
564 }
565 return;
566 }
568 if (entry->GetMacAddress() != lla.GetAddress())
569 {
570 entry->SetMacAddress(lla.GetAddress());
571 entry->MarkStale();
572 entry->SetRouter(true);
573 }
574 entry->StartReachableTimer();
575 return;
576 }
579 if (entry->GetMacAddress() != lla.GetAddress())
580 {
581 entry->SetMacAddress(lla.GetAddress());
582 entry->MarkStale();
583 entry->SetRouter(true);
584 }
585 return;
586 }
587 }
588 return; // Silence compiler warning
589 }
590}
591
592void
594 const Ipv6Address& src,
595 const Ipv6Address& dst,
596 Ptr<Ipv6Interface> interface)
597{
598 NS_LOG_FUNCTION(this << packet << src << dst << interface);
600 Icmpv6RS rsHeader;
601 packet->RemoveHeader(rsHeader);
602 Address hardwareAddress;
604 NdiscCache::Entry* entry = nullptr;
605 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
606
607 if (src != Ipv6Address::GetAny())
608 {
609 /* XXX search all options following the RS header */
610 /* test if the next option is SourceLinkLayerAddress */
611 uint8_t type;
612 packet->CopyData(&type, sizeof(type));
613
615 {
616 return;
617 }
618 packet->RemoveHeader(lla);
619 NS_LOG_LOGIC("Cache updated by RS");
620
621 entry = cache->Lookup(src);
622 if (!entry)
623 {
624 entry = cache->Add(src);
625 entry->SetRouter(false);
626 entry->MarkStale(lla.GetAddress());
627 }
628 else if (entry->GetMacAddress() != lla.GetAddress())
629 {
630 entry->MarkStale(lla.GetAddress());
631 }
632 }
633}
634
635void
637 const Ipv6Address& src,
638 const Ipv6Address& dst,
639 Ptr<Ipv6Interface> interface)
640{
641 NS_LOG_FUNCTION(this << packet << src << dst << interface);
642 Icmpv6NS nsHeader("::");
644 uint32_t nb = interface->GetNAddresses();
645 uint32_t i = 0;
646 bool found = false;
647
648 packet->RemoveHeader(nsHeader);
649
650 Ipv6Address target = nsHeader.GetIpv6Target();
651
652 for (i = 0; i < nb; i++)
653 {
654 ifaddr = interface->GetAddress(i);
655
656 if (ifaddr.GetAddress() == target)
657 {
658 found = true;
659 break;
660 }
661 }
662
663 if (!found)
664 {
665 NS_LOG_LOGIC("Not a NS for us");
666 return;
667 }
668
669 if (packet->GetUid() == ifaddr.GetNsDadUid())
670 {
671 /* don't process our own DAD probe */
672 NS_LOG_LOGIC("Hey we receive our DAD probe!");
673 return;
674 }
675
676 NdiscCache::Entry* entry = nullptr;
677 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
678 uint8_t flags = 0;
679
680 /* search all options following the NS header */
681 Icmpv6OptionLinkLayerAddress sllaoHdr(true);
682
683 bool next = true;
684 bool hasSllao = false;
685
686 while (next)
687 {
688 uint8_t type;
689 packet->CopyData(&type, sizeof(type));
690
691 switch (type)
692 {
694 if (!hasSllao)
695 {
696 packet->RemoveHeader(sllaoHdr);
697 hasSllao = true;
698 }
699 break;
700 default:
701 /* unknown option, quit */
702 next = false;
703 }
704 if (packet->GetSize() == 0)
705 {
706 next = false;
707 }
708 }
709
710 Address replyMacAddress;
711
712 if (src != Ipv6Address::GetAny())
713 {
714 entry = cache->Lookup(src);
715 if (!entry)
716 {
717 if (!hasSllao)
718 {
719 NS_LOG_LOGIC("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a "
720 "NCE, discarding.");
721 return;
722 }
723 entry = cache->Add(src);
724 entry->SetRouter(false);
725 entry->MarkStale(sllaoHdr.GetAddress());
726 replyMacAddress = sllaoHdr.GetAddress();
727 }
728 else if (hasSllao && (entry->GetMacAddress() != sllaoHdr.GetAddress()))
729 {
730 entry->MarkStale(sllaoHdr.GetAddress());
731 replyMacAddress = sllaoHdr.GetAddress();
732 }
733 else
734 {
735 replyMacAddress = entry->GetMacAddress();
736 }
737
738 flags = 3; /* S + O flags */
739 }
740 else
741 {
742 /* it's a DAD */
743 flags = 1; /* O flag */
744 replyMacAddress = interface->GetDevice()->GetMulticast(dst);
745 }
746
747 /* send a NA to src */
749
750 if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
751 {
752 flags += 4; /* R flag */
753 }
754
755 Address hardwareAddress = interface->GetDevice()->GetAddress();
757 target.IsLinkLocal() ? interface->GetLinkLocalAddress().GetAddress() : ifaddr.GetAddress(),
758 src.IsAny() ? dst : src, // DAD replies must go to the multicast group it was sent to.
759 &hardwareAddress,
760 flags);
761
762 // We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not
763 // change it beyond what we did already).
764 Ptr<Packet> pkt = p.first;
765 pkt->AddHeader(p.second);
766 interface->GetDevice()->Send(pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
767}
768
771{
772 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
773 Ptr<Packet> p = Create<Packet>();
774 Ipv6Header ipHeader;
775 Icmpv6RS rs;
776
777 NS_LOG_LOGIC("Forge RS (from " << src << " to " << dst << ")");
778 // RFC 4861:
779 // The link-layer address of the sender MUST NOT be included if the Source Address is the
780 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
781 if (!src.IsAny())
782 {
784 true,
785 hardwareAddress); /* we give our mac address in response */
786 p->AddHeader(llOption);
787 }
788
789 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
790 p->AddHeader(rs);
791
792 ipHeader.SetSource(src);
793 ipHeader.SetDestination(dst);
794 ipHeader.SetNextHeader(PROT_NUMBER);
795 ipHeader.SetPayloadLength(p->GetSize());
796 ipHeader.SetHopLimit(255);
797
798 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
799}
800
803 Ipv6Address dst,
804 uint16_t id,
805 uint16_t seq,
807{
808 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
809 Ptr<Packet> p = data->Copy();
810 Ipv6Header ipHeader;
811 Icmpv6Echo req(true);
812
813 req.SetId(id);
814 req.SetSeq(seq);
815
817 dst,
818 p->GetSize() + req.GetSerializedSize(),
820 p->AddHeader(req);
821
822 ipHeader.SetSource(src);
823 ipHeader.SetDestination(dst);
824 ipHeader.SetNextHeader(PROT_NUMBER);
825 ipHeader.SetPayloadLength(p->GetSize());
826 ipHeader.SetHopLimit(255);
827
828 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
829}
830
831void
833 const Ipv6Address& src,
834 const Ipv6Address& dst,
835 Ptr<Ipv6Interface> interface)
836{
837 NS_LOG_FUNCTION(this << packet << src << dst << interface);
838 Icmpv6NA naHeader;
840
841 packet->RemoveHeader(naHeader);
842 Ipv6Address target = naHeader.GetIpv6Target();
843
844 Address hardwareAddress;
845 NdiscCache::Entry* entry = nullptr;
846 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
847 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
848
849 /* check if we have something in our cache */
850 entry = cache->Lookup(target);
851
852 if (!entry)
853 {
854 /* ouch!! we might be victim of a DAD */
855
857 bool found = false;
858 uint32_t i = 0;
859 uint32_t nb = interface->GetNAddresses();
860
861 for (i = 0; i < nb; i++)
862 {
863 ifaddr = interface->GetAddress(i);
864 if (ifaddr.GetAddress() == target)
865 {
866 found = true;
867 break;
868 }
869 }
870
871 if (found)
872 {
875 {
876 interface->SetState(ifaddr.GetAddress(), Ipv6InterfaceAddress::INVALID);
877 }
878 }
879
880 /* we have not initiated any communication with the target so... discard the NA */
881 return;
882 }
883
884 /* XXX search all options following the NA header */
885 /* Get LLA */
886 uint8_t type;
887 packet->CopyData(&type, sizeof(type));
888
890 {
891 return;
892 }
893 packet->RemoveHeader(lla);
894
895 /* we receive a NA so stop the probe timer or delay timer if any */
896 entry->StopNudTimer();
897 switch (entry->m_state)
898 {
900 /* we receive a NA so stop the retransmission timer */
901 entry->StopNudTimer();
902
903 if (naHeader.GetFlagS())
904 {
905 /* mark it to reachable */
906 waiting = entry->MarkReachable(lla.GetAddress());
907 entry->StartReachableTimer();
908 /* send out waiting packet */
909 for (auto it = waiting.begin(); it != waiting.end(); it++)
910 {
911 cache->GetInterface()->Send(it->first, it->second, src);
912 }
913 entry->ClearWaitingPacket();
914 }
915 else
916 {
917 entry->MarkStale(lla.GetAddress());
918 }
919
920 if (naHeader.GetFlagR())
921 {
922 entry->SetRouter(true);
923 }
924 return;
925 }
927 /* if the Flag O is clear and mac address differs from the cache */
928 if (!naHeader.GetFlagO() && lla.GetAddress() != entry->GetMacAddress())
929 {
930 entry->MarkStale();
931 return;
932 }
933 else
934 {
935 entry->SetMacAddress(lla.GetAddress());
936 if (naHeader.GetFlagS())
937 {
938 entry->StartReachableTimer();
939 }
940 else if (lla.GetAddress() != entry->GetMacAddress())
941 {
942 entry->MarkStale();
943 }
944 entry->SetRouter(naHeader.GetFlagR());
945 }
946 break;
947 }
950 /* if the Flag O is clear and mac address differs from the cache */
951 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
952 {
953 entry->SetMacAddress(lla.GetAddress());
954 if (naHeader.GetFlagS())
955 {
956 entry->MarkReachable(lla.GetAddress());
957 entry->StartReachableTimer();
958 }
959 else if (lla.GetAddress() != entry->GetMacAddress())
960 {
961 entry->MarkStale();
962 }
963 entry->SetRouter(naHeader.GetFlagR());
964 }
965 return;
966 }
968 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
969 {
970 entry->SetMacAddress(lla.GetAddress());
971 if (naHeader.GetFlagS())
972 {
973 waiting = entry->MarkReachable(lla.GetAddress());
974 for (auto it = waiting.begin(); it != waiting.end(); it++)
975 {
976 cache->GetInterface()->Send(it->first, it->second, src);
977 }
978 entry->ClearWaitingPacket();
979 entry->StartReachableTimer();
980 }
981 else if (lla.GetAddress() != entry->GetMacAddress())
982 {
983 entry->MarkStale();
984 }
985 entry->SetRouter(naHeader.GetFlagR());
986 }
987 return;
988 }
991 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
992 {
993 entry->SetMacAddress(lla.GetAddress());
994 if (lla.GetAddress() != entry->GetMacAddress())
995 {
996 entry->MarkStale();
997 }
998 entry->SetRouter(naHeader.GetFlagR());
999 }
1000 return;
1001 }
1002 }
1003 // Silence compiler warning
1004}
1005
1006void
1008 const Ipv6Address& src,
1009 const Ipv6Address& dst,
1010 Ptr<Ipv6Interface> interface)
1011{
1012 NS_LOG_FUNCTION(this << packet << src << dst << interface);
1013 bool hasLla = false;
1014 Ptr<Packet> p = packet->Copy();
1015 Icmpv6OptionLinkLayerAddress llOptionHeader(false);
1016
1017 Icmpv6Redirection redirectionHeader;
1018 p->RemoveHeader(redirectionHeader);
1019
1020 /* little ugly try to find a better way */
1021 uint8_t type;
1022 p->CopyData(&type, sizeof(type));
1024 {
1025 hasLla = true;
1026 p->RemoveHeader(llOptionHeader);
1027 }
1028
1029 Icmpv6OptionRedirected redirectedOptionHeader;
1030 p->RemoveHeader(redirectedOptionHeader);
1031
1032 Ipv6Address redirTarget = redirectionHeader.GetTarget();
1033 Ipv6Address redirDestination = redirectionHeader.GetDestination();
1034
1035 if (hasLla)
1036 {
1037 /* update the cache if needed */
1038 NdiscCache::Entry* entry = nullptr;
1039 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
1040
1041 entry = cache->Lookup(redirTarget);
1042 if (!entry)
1043 {
1044 entry = cache->Add(redirTarget);
1045 /* destination and target different => necessarily a router */
1046 entry->SetRouter(redirTarget != redirDestination);
1047 entry->SetMacAddress(llOptionHeader.GetAddress());
1048 entry->MarkStale();
1049 }
1050 else
1051 {
1052 if (entry->IsIncomplete() || entry->GetMacAddress() != llOptionHeader.GetAddress())
1053 {
1054 /* update entry to STALE */
1055 if (entry->GetMacAddress() != llOptionHeader.GetAddress())
1056 {
1057 entry->SetMacAddress(llOptionHeader.GetAddress());
1058 entry->MarkStale();
1059 }
1060 }
1061 else
1062 {
1063 /* stay unchanged */
1064 }
1065 }
1066 }
1067
1068 /* add redirection in routing table */
1069 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1070
1071 if (redirTarget == redirDestination)
1072 {
1073 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1074 Ipv6Prefix(128),
1075 Ipv6Address("::"),
1076 ipv6->GetInterfaceForAddress(dst));
1077 }
1078 else
1079 {
1080 uint32_t ifIndex = ipv6->GetInterfaceForAddress(dst);
1081 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1082 Ipv6Prefix(128),
1083 redirTarget,
1084 ifIndex);
1085 }
1086}
1087
1088void
1090 const Ipv6Address& src,
1091 const Ipv6Address& dst,
1092 Ptr<Ipv6Interface> interface)
1093{
1094 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1095 Ptr<Packet> pkt = p->Copy();
1096
1098 pkt->RemoveHeader(unreach);
1099
1100 Ipv6Header ipHeader;
1101 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1102 {
1103 pkt->RemoveHeader(ipHeader);
1104 uint8_t payload[8];
1105 pkt->CopyData(payload, 8);
1106 Forward(src, unreach, unreach.GetCode(), ipHeader, payload);
1107 }
1108}
1109
1110void
1112 const Ipv6Address& src,
1113 const Ipv6Address& dst,
1114 Ptr<Ipv6Interface> interface)
1115{
1116 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1117 Ptr<Packet> pkt = p->Copy();
1118
1119 Icmpv6TimeExceeded timeexceeded;
1120 pkt->RemoveHeader(timeexceeded);
1121
1122 Ipv6Header ipHeader;
1123 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1124 {
1125 Ipv6Header ipHeader;
1126 pkt->RemoveHeader(ipHeader);
1127 uint8_t payload[8];
1128 pkt->CopyData(payload, 8);
1129 Forward(src, timeexceeded, timeexceeded.GetCode(), ipHeader, payload);
1130 }
1131}
1132
1133void
1135 const Ipv6Address& src,
1136 const Ipv6Address& dst,
1137 Ptr<Ipv6Interface> interface)
1138{
1139 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1140 Ptr<Packet> pkt = p->Copy();
1141
1142 Icmpv6TooBig tooBig;
1143 pkt->RemoveHeader(tooBig);
1144
1145 Ipv6Header ipHeader;
1146 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1147 {
1148 pkt->RemoveHeader(ipHeader);
1149 uint8_t payload[8];
1150 pkt->CopyData(payload, 8);
1151
1153 ipv6->SetPmtu(ipHeader.GetDestination(), tooBig.GetMtu());
1154
1155 Forward(src, tooBig, tooBig.GetMtu(), ipHeader, payload);
1156 }
1157}
1158
1159void
1161 const Ipv6Address& src,
1162 const Ipv6Address& dst,
1163 Ptr<Ipv6Interface> interface)
1164{
1165 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1166 Ptr<Packet> pkt = p->Copy();
1167
1168 Icmpv6ParameterError paramErr;
1169 pkt->RemoveHeader(paramErr);
1170
1171 Ipv6Header ipHeader;
1172 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1173 {
1174 pkt->RemoveHeader(ipHeader);
1175 uint8_t payload[8];
1176 pkt->CopyData(payload, 8);
1177 Forward(src, paramErr, paramErr.GetCode(), ipHeader, payload);
1178 }
1179}
1180
1181void
1183{
1184 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1187 NS_ASSERT(ipv6);
1188
1189 tag.SetHopLimit(ttl);
1190 packet->AddPacketTag(tag);
1191 m_downTarget(packet, src, dst, PROT_NUMBER, nullptr);
1192}
1193
1194void
1196 Ipv6Address src,
1197 Ipv6Address dst,
1198 uint8_t ttl)
1199{
1200 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1201 SendMessage(packet, src, dst, ttl);
1202}
1203
1204void
1206 Ipv6Address dst,
1207 Icmpv6Header& icmpv6Hdr,
1208 uint8_t ttl)
1209{
1210 NS_LOG_FUNCTION(this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
1212 NS_ASSERT(ipv6 && ipv6->GetRoutingProtocol());
1213 Ipv6Header header;
1216 Ptr<Ipv6Route> route;
1217 Ptr<NetDevice> oif(nullptr); // specify non-zero if bound to a source address
1218
1219 header.SetDestination(dst);
1220 route = ipv6->GetRoutingProtocol()->RouteOutput(packet, header, oif, err);
1221
1222 if (route)
1223 {
1224 NS_LOG_LOGIC("Route exists");
1225 tag.SetHopLimit(ttl);
1226 packet->AddPacketTag(tag);
1227 Ipv6Address src = route->GetSource();
1228
1229 icmpv6Hdr.CalculatePseudoHeaderChecksum(src,
1230 dst,
1231 packet->GetSize() + icmpv6Hdr.GetSerializedSize(),
1232 PROT_NUMBER);
1233 packet->AddHeader(icmpv6Hdr);
1234 m_downTarget(packet, src, dst, PROT_NUMBER, route);
1235 }
1236 else
1237 {
1238 NS_LOG_WARN("drop icmp message");
1239 }
1240}
1241
1242void
1243Icmpv6L4Protocol::SendNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1244{
1245 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << static_cast<uint32_t>(flags));
1246 Ptr<Packet> p = Create<Packet>();
1247 Icmpv6NA na;
1248 Icmpv6OptionLinkLayerAddress llOption(false, *hardwareAddress); /* not a source link layer */
1249
1250 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1251 na.SetIpv6Target(src);
1252
1253 if (flags & 1)
1254 {
1255 na.SetFlagO(true);
1256 }
1257 if ((flags & 2) && src != Ipv6Address::GetAny())
1258 {
1259 na.SetFlagS(true);
1260 }
1261 if (flags & 4)
1262 {
1263 na.SetFlagR(true);
1264 }
1265
1266 p->AddHeader(llOption);
1267 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1268 p->AddHeader(na);
1269
1270 SendMessage(p, src, dst, 255);
1271}
1272
1273void
1275 Ipv6Address dst,
1276 uint16_t id,
1277 uint16_t seq,
1279{
1280 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
1281 Ptr<Packet> p = data->Copy();
1282 Icmpv6Echo reply(false); /* echo reply */
1283
1284 reply.SetId(id);
1285 reply.SetSeq(seq);
1286
1288 dst,
1289 p->GetSize() + reply.GetSerializedSize(),
1290 PROT_NUMBER);
1291 p->AddHeader(reply);
1292 SendMessage(p, src, dst, 64);
1293}
1294
1295void
1297 Ipv6Address dst,
1298 Ipv6Address target,
1299 Address hardwareAddress)
1300{
1301 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1302 Ptr<Packet> p = Create<Packet>();
1303 /* Ipv6Header ipHeader; */
1304 Icmpv6NS ns(target);
1306 true,
1307 hardwareAddress); /* we give our mac address in response */
1308
1309 /* if the source is unspec, multicast the NA to all-nodes multicast */
1310 if (src == Ipv6Address::GetAny())
1311 {
1313 }
1314
1315 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1316
1317 p->AddHeader(llOption);
1318 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1319 p->AddHeader(ns);
1320 if (!dst.IsMulticast())
1321 {
1322 SendMessage(p, src, dst, 255);
1323 }
1324 else
1325 {
1326 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1329 this,
1330 p,
1331 src,
1332 dst,
1333 255);
1334 }
1335}
1336
1337void
1339{
1340 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1341 Ptr<Packet> p = Create<Packet>();
1342 Icmpv6RS rs;
1343
1344 // RFC 4861:
1345 // The link-layer address of the sender MUST NOT be included if the Source Address is the
1346 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
1347 if (!src.IsAny())
1348 {
1349 Icmpv6OptionLinkLayerAddress llOption(true, hardwareAddress);
1350 p->AddHeader(llOption);
1351 }
1352
1353 if (!src.IsAny())
1354 {
1356 if (ipv6->GetInterfaceForAddress(src) == -1)
1357 {
1358 NS_LOG_INFO("Preventing RS from being sent or rescheduled because the source address "
1359 << src << " has been removed");
1360 return;
1361 }
1362 }
1363
1364 NS_LOG_LOGIC("Send RS (from " << src << " to " << dst << ")");
1365
1366 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
1367 p->AddHeader(rs);
1368 if (!dst.IsMulticast())
1369 {
1370 SendMessage(p, src, dst, 255);
1371 }
1372 else
1373 {
1374 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1375 Time rsDelay = Time(0);
1376 Time rsTimeout = Time(0);
1377
1378 if (m_rsRetransmissionCount == 0)
1379 {
1380 // First RS transmission - also add some jitter to desynchronize nodes.
1384 }
1385 else
1386 {
1387 // Following RS transmission - adding further jitter is unnecessary.
1389 if (rsTimeout > m_rsMaxRetransmissionTime)
1390 {
1392 }
1393 }
1395 Simulator::Schedule(rsDelay, &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
1398 this,
1399 src,
1400 dst,
1401 hardwareAddress);
1402 }
1403}
1404
1405void
1407{
1408 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1409
1411 {
1412 // Unbound number of retransmissions - just add one to signal that we're in retransmission
1413 // mode.
1415 }
1416 else
1417 {
1420 {
1421 NS_LOG_LOGIC("Maximum number of multicast RS reached, giving up.");
1422 return;
1423 }
1424 }
1425
1428 {
1429 NS_LOG_LOGIC("Maximum RS retransmission time reached, giving up.");
1430 return;
1431 }
1432
1433 SendRS(src, dst, hardwareAddress);
1434}
1435
1436void
1438 Ipv6Address dst,
1439 uint8_t code)
1440{
1441 NS_LOG_FUNCTION(this << malformedPacket << dst << (uint32_t)code);
1442 uint32_t malformedPacketSize = malformedPacket->GetSize();
1444 header.SetCode(code);
1445
1446 NS_LOG_LOGIC("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1447
1448 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1449 if (malformedPacketSize <= 1280 - 48)
1450 {
1451 header.SetPacket(malformedPacket);
1452 SendMessage(malformedPacket, dst, header, 255);
1453 }
1454 else
1455 {
1456 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1457 header.SetPacket(fragment);
1458 SendMessage(fragment, dst, header, 255);
1459 }
1460}
1461
1462void
1464{
1465 NS_LOG_FUNCTION(this << malformedPacket << dst << mtu);
1466 uint32_t malformedPacketSize = malformedPacket->GetSize();
1467 Icmpv6TooBig header;
1468 header.SetCode(0);
1469 header.SetMtu(mtu);
1470
1471 NS_LOG_LOGIC("Send Too Big ( to " << dst << " )");
1472
1473 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1474 if (malformedPacketSize <= 1280 - 48)
1475 {
1476 header.SetPacket(malformedPacket);
1477 SendMessage(malformedPacket, dst, header, 255);
1478 }
1479 else
1480 {
1481 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1482 header.SetPacket(fragment);
1483 SendMessage(fragment, dst, header, 255);
1484 }
1485}
1486
1487void
1489{
1490 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code));
1491 uint32_t malformedPacketSize = malformedPacket->GetSize();
1492 Icmpv6TimeExceeded header;
1493 header.SetCode(code);
1494
1495 NS_LOG_LOGIC("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1496
1497 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1498 if (malformedPacketSize <= 1280 - 48)
1499 {
1500 header.SetPacket(malformedPacket);
1501 SendMessage(malformedPacket, dst, header, 255);
1502 }
1503 else
1504 {
1505 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1506 header.SetPacket(fragment);
1507 SendMessage(fragment, dst, header, 255);
1508 }
1509}
1510
1511void
1513 Ipv6Address dst,
1514 uint8_t code,
1515 uint32_t ptr)
1516{
1517 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code) << ptr);
1518 uint32_t malformedPacketSize = malformedPacket->GetSize();
1519 Icmpv6ParameterError header;
1520 header.SetCode(code);
1521 header.SetPtr(ptr);
1522
1523 NS_LOG_LOGIC("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1524
1525 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1526 if (malformedPacketSize <= 1280 - 48)
1527 {
1528 header.SetPacket(malformedPacket);
1529 SendMessage(malformedPacket, dst, header, 255);
1530 }
1531 else
1532 {
1533 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1534 header.SetPacket(fragment);
1535 SendMessage(fragment, dst, header, 255);
1536 }
1537}
1538
1539void
1541 Ipv6Address src,
1542 Ipv6Address dst,
1543 Ipv6Address redirTarget,
1544 Ipv6Address redirDestination,
1545 Address redirHardwareTarget)
1546{
1547 NS_LOG_FUNCTION(this << redirectedPacket << dst << redirTarget << redirDestination
1548 << redirHardwareTarget);
1549 uint32_t llaSize = 0;
1550 Ptr<Packet> p = Create<Packet>();
1551 uint32_t redirectedPacketSize = redirectedPacket->GetSize();
1552 Icmpv6OptionLinkLayerAddress llOption(false);
1553
1554 NS_LOG_LOGIC("Send Redirection ( to " << dst << " target " << redirTarget << " destination "
1555 << redirDestination << " )");
1556
1557 Icmpv6OptionRedirected redirectedOptionHeader;
1558
1559 if ((redirectedPacketSize % 8) != 0)
1560 {
1561 Ptr<Packet> pad = Create<Packet>(8 - (redirectedPacketSize % 8));
1562 redirectedPacket->AddAtEnd(pad);
1563 }
1564
1565 if (redirHardwareTarget.GetLength())
1566 {
1567 llOption.SetAddress(redirHardwareTarget);
1568 llaSize = llOption.GetSerializedSize();
1569 }
1570
1571 /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1572 if (redirectedPacketSize <= (1280 - 56 - llaSize))
1573 {
1574 redirectedOptionHeader.SetPacket(redirectedPacket);
1575 }
1576 else
1577 {
1578 Ptr<Packet> fragment = redirectedPacket->CreateFragment(0, 1280 - 56 - llaSize);
1579 redirectedOptionHeader.SetPacket(fragment);
1580 }
1581
1582 p->AddHeader(redirectedOptionHeader);
1583
1584 if (llaSize)
1585 {
1586 p->AddHeader(llOption);
1587 }
1588
1589 Icmpv6Redirection redirectionHeader;
1590 redirectionHeader.SetTarget(redirTarget);
1591 redirectionHeader.SetDestination(redirDestination);
1592 redirectionHeader.CalculatePseudoHeaderChecksum(src,
1593 dst,
1594 p->GetSize() +
1595 redirectionHeader.GetSerializedSize(),
1596 PROT_NUMBER);
1597 p->AddHeader(redirectionHeader);
1598
1599 SendMessage(p, src, dst, 64);
1600}
1601
1603Icmpv6L4Protocol::ForgeNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1604{
1605 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << (uint32_t)flags);
1606 Ptr<Packet> p = Create<Packet>();
1607 Ipv6Header ipHeader;
1608 Icmpv6NA na;
1610 false,
1611 *hardwareAddress); /* we give our mac address in response */
1612
1613 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << ")");
1614
1615 /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet
1616 * does not pass by Icmpv6L4Protocol::Lookup again */
1617
1618 p->AddHeader(llOption);
1619 na.SetIpv6Target(src);
1620
1621 if (flags & 1)
1622 {
1623 na.SetFlagO(true);
1624 }
1625 if ((flags & 2) && src != Ipv6Address::GetAny())
1626 {
1627 na.SetFlagS(true);
1628 }
1629 if (flags & 4)
1630 {
1631 na.SetFlagR(true);
1632 }
1633
1634 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1635 p->AddHeader(na);
1636
1637 ipHeader.SetSource(src);
1638 ipHeader.SetDestination(dst);
1639 ipHeader.SetNextHeader(PROT_NUMBER);
1640 ipHeader.SetPayloadLength(p->GetSize());
1641 ipHeader.SetHopLimit(255);
1642
1643 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1644}
1645
1648 Ipv6Address dst,
1649 Ipv6Address target,
1650 Address hardwareAddress)
1651{
1652 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1653 Ptr<Packet> p = Create<Packet>();
1654 Ipv6Header ipHeader;
1655 Icmpv6NS ns(target);
1657 true,
1658 hardwareAddress); /* we give our mac address in response */
1659
1660 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1661
1662 p->AddHeader(llOption);
1663 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1664 p->AddHeader(ns);
1665
1666 ipHeader.SetSource(src);
1667 ipHeader.SetDestination(dst);
1668 ipHeader.SetNextHeader(PROT_NUMBER);
1669 ipHeader.SetPayloadLength(p->GetSize());
1670 ipHeader.SetHopLimit(255);
1671
1672 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1673}
1674
1677{
1678 NS_LOG_FUNCTION(this << device);
1679
1680 for (auto i = m_cacheList.begin(); i != m_cacheList.end(); i++)
1681 {
1682 if ((*i)->GetDevice() == device)
1683 {
1684 return *i;
1685 }
1686 }
1687
1688 NS_ASSERT_MSG(false, "Icmpv6L4Protocol can not find a NDIS Cache for device " << device);
1689 /* quiet compiler */
1690 return nullptr;
1691}
1692
1695{
1696 NS_LOG_FUNCTION(this << device << interface);
1697
1698 Ptr<NdiscCache> cache = CreateObject<NdiscCache>();
1699
1700 cache->SetDevice(device, interface, this);
1701 device->AddLinkChangeCallback(MakeCallback(&NdiscCache::Flush, cache));
1702 m_cacheList.push_back(cache);
1703 return cache;
1704}
1705
1706bool
1708 Ptr<NetDevice> device,
1709 Ptr<NdiscCache> cache,
1710 Address* hardwareDestination)
1711{
1712 NS_LOG_FUNCTION(this << dst << device << cache << hardwareDestination);
1713
1714 if (!cache)
1715 {
1716 /* try to find the cache */
1717 cache = FindCache(device);
1718 }
1719 if (cache)
1720 {
1721 NdiscCache::Entry* entry = cache->Lookup(dst);
1722 if (entry)
1723 {
1724 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1725 entry->IsAutoGenerated())
1726 {
1727 *hardwareDestination = entry->GetMacAddress();
1728 return true;
1729 }
1730 else if (entry->IsStale())
1731 {
1732 entry->StartDelayTimer();
1733 entry->MarkDelay();
1734 *hardwareDestination = entry->GetMacAddress();
1735 return true;
1736 }
1737 }
1738 }
1739 return false;
1740}
1741
1742bool
1744 const Ipv6Header& ipHeader,
1745 Ipv6Address dst,
1746 Ptr<NetDevice> device,
1747 Ptr<NdiscCache> cache,
1748 Address* hardwareDestination)
1749{
1750 NS_LOG_FUNCTION(this << p << ipHeader << dst << device << cache << hardwareDestination);
1751
1752 if (!cache)
1753 {
1754 /* try to find the cache */
1755 cache = FindCache(device);
1756 }
1757 if (!cache)
1758 {
1759 return false;
1760 }
1761
1762 NdiscCache::Entry* entry = cache->Lookup(dst);
1763 if (entry)
1764 {
1765 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1766 entry->IsAutoGenerated())
1767 {
1768 /* XXX check reachability time */
1769 /* send packet */
1770 *hardwareDestination = entry->GetMacAddress();
1771 return true;
1772 }
1773 else if (entry->IsStale())
1774 {
1775 /* start delay timer */
1776 entry->StartDelayTimer();
1777 entry->MarkDelay();
1778 *hardwareDestination = entry->GetMacAddress();
1779 return true;
1780 }
1781 else /* INCOMPLETE or PROBE */
1782 {
1783 /* queue packet */
1785 return false;
1786 }
1787 }
1788 else
1789 {
1790 /* we contact this node for the first time
1791 * add it to the cache and send an NS
1792 */
1793 Ipv6Address addr;
1794 NdiscCache::Entry* entry = cache->Add(dst);
1796 entry->SetRouter(false);
1797
1798 if (dst.IsLinkLocal())
1799 {
1800 addr = cache->GetInterface()->GetLinkLocalAddress().GetAddress();
1801 }
1802 else if (cache->GetInterface()->GetNAddresses() ==
1803 1) /* an interface have at least one address (link-local) */
1804 {
1805 /* try to resolve global address without having global address so return! */
1806 cache->Remove(entry);
1807 return false;
1808 }
1809 else
1810 {
1811 /* find source address that match destination */
1812 addr = cache->GetInterface()->GetAddressMatchingDestination(dst).GetAddress();
1813 }
1814
1815 SendNS(addr, Ipv6Address::MakeSolicitedAddress(dst), dst, cache->GetDevice()->GetAddress());
1816
1817 /* start retransmit timer */
1818 entry->StartRetransmitTimer();
1819 return false;
1820 }
1821
1822 return false;
1823}
1824
1825void
1827{
1828 NS_LOG_FUNCTION(this << interface << addr);
1829
1830 Ipv6InterfaceAddress ifaddr;
1831 bool found = false;
1832 uint32_t i = 0;
1833 uint32_t nb = interface->GetNAddresses();
1834
1835 for (i = 0; i < nb; i++)
1836 {
1837 ifaddr = interface->GetAddress(i);
1838
1839 if (ifaddr.GetAddress() == addr)
1840 {
1841 found = true;
1842 break;
1843 }
1844 }
1845
1846 if (!found)
1847 {
1848 NS_LOG_LOGIC("Can not find the address in the interface.");
1849 }
1850
1851 /* for the moment, this function is always called, if we was victim of a DAD the address is
1852 * INVALID and we do not set it to PREFERRED
1853 */
1854 if (found && ifaddr.GetState() != Ipv6InterfaceAddress::INVALID)
1855 {
1857 NS_LOG_LOGIC("DAD OK, interface in state PREFERRED");
1858
1859 /* send an RS if our interface is not forwarding (router) and if address is a link-local
1860 * ones (because we will send RS with it)
1861 */
1862 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1863
1864 if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())) &&
1865 addr.IsLinkLocal())
1866 {
1867 /* \todo Add random delays before sending RS
1868 * because all nodes start at the same time, there will be many of RS around 1 second of
1869 * simulation time
1870 */
1871 NS_LOG_LOGIC("Scheduled a first Router Solicitation");
1875 this,
1876 ifaddr.GetAddress(),
1878 interface->GetDevice()->GetAddress());
1879 }
1880 else
1881 {
1882 NS_LOG_LOGIC("Did not schedule a Router Solicitation because the interface is in "
1883 "forwarding mode");
1884 }
1885 }
1886}
1887
1888void
1890{
1891 NS_LOG_FUNCTION(this << &callback);
1892}
1893
1894void
1896{
1897 NS_LOG_FUNCTION(this << &callback);
1898 m_downTarget = callback;
1899}
1900
1903{
1904 NS_LOG_FUNCTION(this);
1906}
1907
1910{
1911 NS_LOG_FUNCTION(this);
1912 return m_downTarget;
1913}
1914
1915uint8_t
1917{
1918 return m_maxMulticastSolicit;
1919}
1920
1921uint8_t
1923{
1924 return m_maxUnicastSolicit;
1925}
1926
1927Time
1929{
1930 return m_reachableTime;
1931}
1932
1933Time
1935{
1936 return m_retransmissionTime;
1937}
1938
1939Time
1941{
1942 return m_delayFirstProbe;
1943}
1944
1945Time
1947{
1948 return m_dadTimeout;
1949}
1950
1951} /* namespace ns3 */
a polymophic address class
Definition: address.h:101
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:575
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
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:423
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:522
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:444
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
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:1172
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:668
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:1413
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
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:81
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:259
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1434
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
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_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#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:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
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:704
uint8_t data[writeSize]