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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
7 * David Gross <gdavid.devel@gmail.com>
8 * Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
9 * Tommaso Pecorella <tommaso.pecorella@unifi.it>
10 */
11
12#include "icmpv6-l4-protocol.h"
13
14#include "ipv4-interface.h"
15#include "ipv6-interface.h"
16#include "ipv6-l3-protocol.h"
17#include "ipv6-route.h"
19
20#include "ns3/assert.h"
21#include "ns3/boolean.h"
22#include "ns3/double.h"
23#include "ns3/integer.h"
24#include "ns3/log.h"
25#include "ns3/node.h"
26#include "ns3/packet.h"
27#include "ns3/pointer.h"
28#include "ns3/string.h"
29#include "ns3/uinteger.h"
30
31namespace ns3
32{
33
34NS_LOG_COMPONENT_DEFINE("Icmpv6L4Protocol");
35
36NS_OBJECT_ENSURE_REGISTERED(Icmpv6L4Protocol);
37
38const uint8_t Icmpv6L4Protocol::PROT_NUMBER = 58;
39
40// const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERT_INTERVAL = 16; // max initial RA initial
41// interval. const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERTISEMENTS = 3; // max initial RA
42// transmission. const uint8_t Icmpv6L4Protocol::MAX_FINAL_RTR_ADVERTISEMENTS = 3; // max final
43// RA transmission. const uint8_t Icmpv6L4Protocol::MIN_DELAY_BETWEEN_RAS = 3; // min
44// delay between RA. const uint32_t Icmpv6L4Protocol::MAX_RA_DELAY_TIME = 500; //
45// millisecond - max delay between RA.
46
47// const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATION_DELAY = 1; // max RS delay.
48// const uint8_t Icmpv6L4Protocol::RTR_SOLICITATION_INTERVAL = 4; // RS interval.
49// const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATIONS = 3; // max RS transmission.
50
51// const uint8_t Icmpv6L4Protocol::MAX_ANYCAST_DELAY_TIME = 1; // max anycast delay.
52// const uint8_t Icmpv6L4Protocol::MAX_NEIGHBOR_ADVERTISEMENT = 3; // max NA transmission.
53
54// const double Icmpv6L4Protocol::MIN_RANDOM_FACTOR = 0.5; // min random factor.
55// const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5; // max random factor.
56
57TypeId
59{
60 static TypeId tid =
61 TypeId("ns3::Icmpv6L4Protocol")
63 .SetGroupName("Internet")
64 .AddConstructor<Icmpv6L4Protocol>()
65 .AddAttribute("DAD",
66 "Always do DAD check.",
67 BooleanValue(true),
70 .AddAttribute(
71 "SolicitationJitter",
72 "The jitter in ms a node is allowed to wait before sending any solicitation. Some "
73 "jitter aims to prevent collisions. By default, the model will wait for a duration "
74 "in ms defined by a uniform random-variable between 0 and SolicitationJitter",
75 StringValue("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
78 .AddAttribute("MaxMulticastSolicit",
79 "Neighbor Discovery node constants: max multicast solicitations.",
80 IntegerValue(3),
83 .AddAttribute("MaxUnicastSolicit",
84 "Neighbor Discovery node constants: max unicast solicitations.",
85 IntegerValue(3),
88 .AddAttribute("ReachableTime",
89 "Neighbor Discovery node constants: reachable time.",
90 TimeValue(Seconds(30)),
93 .AddAttribute("RetransmissionTime",
94 "Neighbor Discovery node constants: retransmission timer.",
98 .AddAttribute("DelayFirstProbe",
99 "Neighbor Discovery node constants: delay for the first probe.",
100 TimeValue(Seconds(5)),
103 .AddAttribute("DadTimeout",
104 "Duplicate Address Detection (DAD) timeout",
105 TimeValue(Seconds(1)),
108 .AddAttribute("RsRetransmissionJitter",
109 "Multicast RS retransmission randomization quantity",
110 StringValue("ns3::UniformRandomVariable[Min=-0.1|Max=0.1]"),
113 .AddAttribute("RsInitialRetransmissionTime",
114 "Multicast RS initial retransmission time.",
115 TimeValue(Seconds(4)),
118 .AddAttribute("RsMaxRetransmissionTime",
119 "Multicast RS maximum retransmission time (0 means unbound).",
120 TimeValue(Seconds(3600)),
123 .AddAttribute(
124 "RsMaxRetransmissionCount",
125 "Multicast RS maximum retransmission count (0 means unbound). "
126 "Note: RFC 7559 suggest a zero value (infinite). The default is 4 to avoid "
127 "non-terminating simulations.",
128 UintegerValue(4),
131 .AddAttribute("RsMaxRetransmissionDuration",
132 "Multicast RS maximum retransmission duration (0 means unbound).",
133 TimeValue(Seconds(0)),
136 .AddTraceSource("DadFailure",
137 "Duplicate Address detected during DAD, the address is now INVALID",
139 "ns3::Ipv6Address::TracedCallback")
140 .AddTraceSource(
141 "DadSuccess",
142 "Duplicate Address not detected during DAD, the address is now PREFERRED",
144 "ns3::Ipv6Address::TracedCallback");
145 return tid;
146}
147
149 : m_node(nullptr)
150{
151 NS_LOG_FUNCTION(this);
152}
153
158
159void
161{
162 NS_LOG_FUNCTION(this);
163 for (auto it = m_cacheList.begin(); it != m_cacheList.end(); it++)
164 {
165 Ptr<NdiscCache> cache = *it;
166 cache->Dispose();
167 cache = nullptr;
168 }
169 m_cacheList.clear();
172
173 m_node = nullptr;
175}
176
177int64_t
179{
180 NS_LOG_FUNCTION(this << stream);
182 m_rsRetransmissionJitter->SetStream(stream + 1);
183 return 2;
184}
185
186void
188{
189 NS_LOG_FUNCTION(this);
190 if (!m_node)
191 {
192 Ptr<Node> node = this->GetObject<Node>();
193 if (node)
194 {
195 Ptr<Ipv6> ipv6 = this->GetObject<Ipv6>();
196 if (ipv6 && m_downTarget.IsNull())
197 {
198 SetNode(node);
199 ipv6->Insert(this);
201 }
202 }
203 }
205}
206
207void
209{
210 NS_LOG_FUNCTION(this << node);
211 m_node = node;
212}
213
216{
217 NS_LOG_FUNCTION(this);
218 return m_node;
219}
220
221uint16_t
227
228int
230{
231 NS_LOG_FUNCTION(this);
232 return PROT_NUMBER;
233}
234
235int
237{
238 NS_LOG_FUNCTION(this);
239 return 1;
240}
241
242bool
244{
245 NS_LOG_FUNCTION(this);
246 return m_alwaysDad;
247}
248
249void
251{
252 NS_LOG_FUNCTION(this << target << interface);
253 Ipv6Address addr;
255
256 NS_ASSERT(ipv6);
257
258 if (!m_alwaysDad)
259 {
260 return;
261 }
262
263 /** @todo disable multicast loopback to prevent NS probing to be received by the sender */
264
267 target,
268 interface->GetDevice()->GetAddress());
269
270 /* update last packet UID */
271 interface->SetNsDadUid(target, p.first->GetUid());
274 interface,
275 p.first,
276 p.second,
278}
279
282 const Ipv4Header& header,
283 Ptr<Ipv4Interface> interface)
284{
285 NS_LOG_FUNCTION(this << packet << header);
287}
288
291 const Ipv6Header& header,
292 Ptr<Ipv6Interface> interface)
293{
294 NS_LOG_FUNCTION(this << packet << header.GetSource() << header.GetDestination() << interface);
295 Ptr<Packet> p = packet->Copy();
296 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
297
298 /* very ugly! try to find something better in the future */
299 uint8_t type;
300 p->CopyData(&type, sizeof(type));
301
302 switch (type)
303 {
305 if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
306 {
307 HandleRS(p, header.GetSource(), header.GetDestination(), interface);
308 }
309 break;
311 if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
312 {
313 HandleRA(p, header.GetSource(), header.GetDestination(), interface);
314 }
315 break;
317 HandleNS(p, header.GetSource(), header.GetDestination(), interface);
318 break;
320 HandleNA(p, header.GetSource(), header.GetDestination(), interface);
321 break;
323 HandleRedirection(p, header.GetSource(), header.GetDestination(), interface);
324 break;
326 HandleEchoRequest(p, header.GetSource(), header.GetDestination(), interface);
327 break;
329 // EchoReply does not contain any info about L4
330 // so we can not forward it up.
331 /// @todo implement request / reply consistency check.
332 break;
334 HandleDestinationUnreachable(p, header.GetSource(), header.GetDestination(), interface);
335 break;
337 HandlePacketTooBig(p, header.GetSource(), header.GetDestination(), interface);
338 break;
340 HandleTimeExceeded(p, header.GetSource(), header.GetDestination(), interface);
341 break;
343 HandleParameterError(p, header.GetSource(), header.GetDestination(), interface);
344 break;
345 default:
346 NS_LOG_LOGIC("Unknown ICMPv6 message type=" << type);
347 break;
348 }
349
350 return IpL4Protocol::RX_OK;
351}
352
353void
355 Icmpv6Header icmp,
356 uint32_t info,
357 Ipv6Header ipHeader,
358 const uint8_t payload[8])
359{
360 NS_LOG_FUNCTION(this << source << icmp << info << ipHeader << payload);
361
363
364 /// @todo assuming the ICMP is carrying a extensionless IP packet
365
366 uint8_t nextHeader = ipHeader.GetNextHeader();
367
368 if (nextHeader != Icmpv6L4Protocol::PROT_NUMBER)
369 {
370 Ptr<IpL4Protocol> l4 = ipv6->GetProtocol(nextHeader);
371 if (l4)
372 {
373 l4->ReceiveIcmp(source,
374 ipHeader.GetHopLimit(),
375 icmp.GetType(),
376 icmp.GetCode(),
377 info,
378 ipHeader.GetSource(),
379 ipHeader.GetDestination(),
380 payload);
381 }
382 }
383}
384
385void
387 const Ipv6Address& src,
388 const Ipv6Address& dst,
389 Ptr<Ipv6Interface> interface)
390{
391 NS_LOG_FUNCTION(this << packet << src << dst << interface);
392 Icmpv6Echo request;
393 auto buf = new uint8_t[packet->GetSize()];
394
395 packet->RemoveHeader(request);
396 /* XXX IPv6 extension: obtain a fresh copy of data otherwise it crash... */
397 packet->CopyData(buf, packet->GetSize());
398 Ptr<Packet> p = Create<Packet>(buf, packet->GetSize());
399
400 /* if we send message from ff02::* (link-local multicast), we use our link-local address */
401 SendEchoReply(dst.IsMulticast() ? interface->GetLinkLocalAddress().GetAddress() : dst,
402 src,
403 request.GetId(),
404 request.GetSeq(),
405 p);
406 delete[] buf;
407}
408
409void
411 const Ipv6Address& src,
412 const Ipv6Address& dst,
413 Ptr<Ipv6Interface> interface)
414{
415 NS_LOG_FUNCTION(this << packet << src << dst << interface);
416
418 {
420 // We need to update this in case we need to restart RS retransmissions.
422 }
423
424 Ptr<Packet> p = packet->Copy();
425 Icmpv6RA raHeader;
428 Icmpv6OptionMtu mtuHdr;
430 bool next = true;
431 bool hasLla = false;
432 bool hasMtu = false;
433 Ipv6Address defaultRouter = Ipv6Address::GetZero();
434
435 p->RemoveHeader(raHeader);
436
437 // If 'M' flag is set, we need to start DHCPv6.
438 if (raHeader.GetFlagM())
439 {
440 if (!m_startDhcpv6.IsNull())
441 {
442 m_startDhcpv6(ipv6->GetInterfaceForDevice(interface->GetDevice()));
443 }
444 }
445
446 if (raHeader.GetLifeTime())
447 {
448 defaultRouter = src;
449 }
450
451 while (next)
452 {
453 uint8_t type = 0;
454 p->CopyData(&type, sizeof(type));
455
456 switch (type)
457 {
459 p->RemoveHeader(prefixHdr);
460 ipv6->AddAutoconfiguredAddress(ipv6->GetInterfaceForDevice(interface->GetDevice()),
461 prefixHdr.GetPrefix(),
462 prefixHdr.GetPrefixLength(),
463 prefixHdr.GetFlags(),
464 prefixHdr.GetValidTime(),
465 prefixHdr.GetPreferredTime(),
466 defaultRouter);
467 break;
469 /* take in account the first MTU option */
470 if (!hasMtu)
471 {
472 p->RemoveHeader(mtuHdr);
473 hasMtu = true;
474 /** @todo case of multiple prefix on single interface */
475 /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
476 }
477 break;
479 /* take in account the first LLA option */
480 if (!hasLla)
481 {
482 p->RemoveHeader(llaHdr);
483 ReceiveLLA(llaHdr, src, dst, interface);
484 hasLla = true;
485 }
486 break;
487 default:
488 /* unknown option, quit */
489 next = false;
490 }
491 }
492}
493
494void
496 const Ipv6Address& src,
497 const Ipv6Address& dst,
498 Ptr<Ipv6Interface> interface)
499{
500 NS_LOG_FUNCTION(this << lla << src << dst << interface);
501 Address hardwareAddress;
502 NdiscCache::Entry* entry = nullptr;
503 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
504
505 /* check if we have this address in our cache */
506 entry = cache->Lookup(src);
507
508 if (!entry)
509 {
510 entry = cache->Add(src);
511 entry->SetRouter(true);
512 entry->SetMacAddress(lla.GetAddress());
513 entry->MarkReachable();
514 entry->StartReachableTimer();
515 }
516 else
517 {
518 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
519 switch (entry->m_state)
520 {
522 entry->StopNudTimer();
523 // mark it to reachable
524 waiting = entry->MarkReachable(lla.GetAddress());
525 entry->StartReachableTimer();
526 // send out waiting packet
527 for (auto it = waiting.begin(); it != waiting.end(); 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 (auto it = waiting.begin(); it != waiting.end(); it++)
562 {
563 cache->GetInterface()->Send(it->first, it->second, src);
564 }
565 entry->StartReachableTimer();
566 }
567 return;
568 }
570 if (entry->GetMacAddress() != lla.GetAddress())
571 {
572 entry->SetMacAddress(lla.GetAddress());
573 entry->MarkStale();
574 entry->SetRouter(true);
575 }
576 entry->StartReachableTimer();
577 return;
578 }
581 if (entry->GetMacAddress() != lla.GetAddress())
582 {
583 entry->SetMacAddress(lla.GetAddress());
584 entry->MarkStale();
585 entry->SetRouter(true);
586 }
587 return;
588 }
589 }
590 return; // Silence compiler warning
591 }
592}
593
594void
596 const Ipv6Address& src,
597 const Ipv6Address& dst,
598 Ptr<Ipv6Interface> interface)
599{
600 NS_LOG_FUNCTION(this << packet << src << dst << interface);
602 Icmpv6RS rsHeader;
603 packet->RemoveHeader(rsHeader);
604 Address hardwareAddress;
606 NdiscCache::Entry* entry = nullptr;
607 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
608
609 if (src != Ipv6Address::GetAny())
610 {
611 /* XXX search all options following the RS header */
612 /* test if the next option is SourceLinkLayerAddress */
613 uint8_t type;
614 packet->CopyData(&type, sizeof(type));
615
617 {
618 return;
619 }
620 packet->RemoveHeader(lla);
621 NS_LOG_LOGIC("Cache updated by RS");
622
623 entry = cache->Lookup(src);
624 if (!entry)
625 {
626 entry = cache->Add(src);
627 entry->SetRouter(false);
628 entry->MarkStale(lla.GetAddress());
629 }
630 else if (entry->GetMacAddress() != lla.GetAddress())
631 {
632 entry->MarkStale(lla.GetAddress());
633 }
634 }
635}
636
637void
639 const Ipv6Address& src,
640 const Ipv6Address& dst,
641 Ptr<Ipv6Interface> interface)
642{
643 NS_LOG_FUNCTION(this << packet << src << dst << interface);
644 Icmpv6NS nsHeader("::");
646 uint32_t nb = interface->GetNAddresses();
647 uint32_t i = 0;
648 bool found = false;
649
650 packet->RemoveHeader(nsHeader);
651
652 Ipv6Address target = nsHeader.GetIpv6Target();
653
654 for (i = 0; i < nb; i++)
655 {
656 ifaddr = interface->GetAddress(i);
657
658 if (ifaddr.GetAddress() == target)
659 {
660 found = true;
661 break;
662 }
663 }
664
665 if (!found)
666 {
667 NS_LOG_LOGIC("Not a NS for us");
668 return;
669 }
670
671 if (packet->GetUid() == ifaddr.GetNsDadUid())
672 {
673 /* don't process our own DAD probe */
674 NS_LOG_LOGIC("Hey we receive our DAD probe!");
675 return;
676 }
677
678 NdiscCache::Entry* entry = nullptr;
679 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
680 uint8_t flags = 0;
681
682 /* search all options following the NS header */
683 Icmpv6OptionLinkLayerAddress sllaoHdr(true);
684
685 bool next = true;
686 bool hasSllao = false;
687
688 while (next)
689 {
690 uint8_t type;
691 packet->CopyData(&type, sizeof(type));
692
693 switch (type)
694 {
696 if (!hasSllao)
697 {
698 packet->RemoveHeader(sllaoHdr);
699 hasSllao = true;
700 }
701 break;
702 default:
703 /* unknown option, quit */
704 next = false;
705 }
706 if (packet->GetSize() == 0)
707 {
708 next = false;
709 }
710 }
711
712 Address replyMacAddress;
713
714 if (src != Ipv6Address::GetAny())
715 {
716 entry = cache->Lookup(src);
717 if (!entry)
718 {
719 if (!hasSllao)
720 {
721 NS_LOG_LOGIC("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a "
722 "NCE, discarding.");
723 return;
724 }
725 entry = cache->Add(src);
726 entry->SetRouter(false);
727 entry->MarkStale(sllaoHdr.GetAddress());
728 replyMacAddress = sllaoHdr.GetAddress();
729 }
730 else if (hasSllao && (entry->GetMacAddress() != sllaoHdr.GetAddress()))
731 {
732 entry->MarkStale(sllaoHdr.GetAddress());
733 replyMacAddress = sllaoHdr.GetAddress();
734 }
735 else
736 {
737 replyMacAddress = entry->GetMacAddress();
738 }
739
740 flags = 3; /* S + O flags */
741 }
742 else
743 {
744 /* it's a DAD */
745 flags = 1; /* O flag */
746 replyMacAddress = interface->GetDevice()->GetMulticast(dst);
747 }
748
749 /* send a NA to src */
751
752 if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
753 {
754 flags += 4; /* R flag */
755 }
756
757 Address hardwareAddress = interface->GetDevice()->GetAddress();
759 target.IsLinkLocal() ? interface->GetLinkLocalAddress().GetAddress() : ifaddr.GetAddress(),
760 src.IsAny() ? dst : src, // DAD replies must go to the multicast group it was sent to.
761 &hardwareAddress,
762 flags);
763
764 // We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not
765 // change it beyond what we did already).
766 Ptr<Packet> pkt = p.first;
767 pkt->AddHeader(p.second);
768 interface->GetDevice()->Send(pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
769}
770
773{
774 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
776 Ipv6Header ipHeader;
777 Icmpv6RS rs;
778
779 NS_LOG_LOGIC("Forge RS (from " << src << " to " << dst << ")");
780 // RFC 4861:
781 // The link-layer address of the sender MUST NOT be included if the Source Address is the
782 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
783 if (!src.IsAny())
784 {
786 true,
787 hardwareAddress); /* we give our mac address in response */
788 p->AddHeader(llOption);
789 }
790
791 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
792 p->AddHeader(rs);
793
794 ipHeader.SetSource(src);
795 ipHeader.SetDestination(dst);
796 ipHeader.SetNextHeader(PROT_NUMBER);
797 ipHeader.SetPayloadLength(p->GetSize());
798 ipHeader.SetHopLimit(255);
799
800 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
801}
802
805 Ipv6Address dst,
806 uint16_t id,
807 uint16_t seq,
809{
810 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
811 Ptr<Packet> p = data->Copy();
812 Ipv6Header ipHeader;
813 Icmpv6Echo req(true);
814
815 req.SetId(id);
816 req.SetSeq(seq);
817
819 dst,
820 p->GetSize() + req.GetSerializedSize(),
822 p->AddHeader(req);
823
824 ipHeader.SetSource(src);
825 ipHeader.SetDestination(dst);
826 ipHeader.SetNextHeader(PROT_NUMBER);
827 ipHeader.SetPayloadLength(p->GetSize());
828 ipHeader.SetHopLimit(255);
829
830 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
831}
832
833void
835 const Ipv6Address& src,
836 const Ipv6Address& dst,
837 Ptr<Ipv6Interface> interface)
838{
839 NS_LOG_FUNCTION(this << packet << src << dst << interface);
840 Icmpv6NA naHeader;
842
843 packet->RemoveHeader(naHeader);
844 Ipv6Address target = naHeader.GetIpv6Target();
845
846 Address hardwareAddress;
847 NdiscCache::Entry* entry = nullptr;
848 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
849 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
850
851 /* check if we have something in our cache */
852 entry = cache->Lookup(target);
853
854 if (!entry)
855 {
856 /* ouch!! we might be victim of a DAD */
857
859 bool found = false;
860 uint32_t i = 0;
861 uint32_t nb = interface->GetNAddresses();
862
863 for (i = 0; i < nb; i++)
864 {
865 ifaddr = interface->GetAddress(i);
866 if (ifaddr.GetAddress() == target)
867 {
868 found = true;
869 break;
870 }
871 }
872
873 if (found)
874 {
877 {
879 interface->SetState(ifaddr.GetAddress(), Ipv6InterfaceAddress::INVALID);
880 }
881 }
882
883 /* we have not initiated any communication with the target so... discard the NA */
884 return;
885 }
886
887 /* XXX search all options following the NA header */
888 /* Get LLA */
889 uint8_t type;
890 packet->CopyData(&type, sizeof(type));
891
893 {
894 return;
895 }
896 packet->RemoveHeader(lla);
897
898 /* we receive a NA so stop the probe timer or delay timer if any */
899 entry->StopNudTimer();
900 switch (entry->m_state)
901 {
903 /* we receive a NA so stop the retransmission timer */
904 entry->StopNudTimer();
905
906 if (naHeader.GetFlagS())
907 {
908 /* mark it to reachable */
909 waiting = entry->MarkReachable(lla.GetAddress());
910 entry->StartReachableTimer();
911 /* send out waiting packet */
912 for (auto it = waiting.begin(); it != waiting.end(); it++)
913 {
914 cache->GetInterface()->Send(it->first, it->second, src);
915 }
916 entry->ClearWaitingPacket();
917 }
918 else
919 {
920 entry->MarkStale(lla.GetAddress());
921 }
922
923 if (naHeader.GetFlagR())
924 {
925 entry->SetRouter(true);
926 }
927 return;
928 }
930 /* if the Flag O is clear and mac address differs from the cache */
931 if (!naHeader.GetFlagO() && lla.GetAddress() != entry->GetMacAddress())
932 {
933 entry->MarkStale();
934 return;
935 }
936 else
937 {
938 entry->SetMacAddress(lla.GetAddress());
939 if (naHeader.GetFlagS())
940 {
941 entry->StartReachableTimer();
942 }
943 else if (lla.GetAddress() != entry->GetMacAddress())
944 {
945 entry->MarkStale();
946 }
947 entry->SetRouter(naHeader.GetFlagR());
948 }
949 break;
950 }
953 /* if the Flag O is clear and mac address differs from the cache */
954 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
955 {
956 entry->SetMacAddress(lla.GetAddress());
957 if (naHeader.GetFlagS())
958 {
959 entry->MarkReachable(lla.GetAddress());
960 entry->StartReachableTimer();
961 }
962 else if (lla.GetAddress() != entry->GetMacAddress())
963 {
964 entry->MarkStale();
965 }
966 entry->SetRouter(naHeader.GetFlagR());
967 }
968 return;
969 }
971 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
972 {
973 entry->SetMacAddress(lla.GetAddress());
974 if (naHeader.GetFlagS())
975 {
976 waiting = entry->MarkReachable(lla.GetAddress());
977 for (auto it = waiting.begin(); it != waiting.end(); it++)
978 {
979 cache->GetInterface()->Send(it->first, it->second, src);
980 }
981 entry->ClearWaitingPacket();
982 entry->StartReachableTimer();
983 }
984 else if (lla.GetAddress() != entry->GetMacAddress())
985 {
986 entry->MarkStale();
987 }
988 entry->SetRouter(naHeader.GetFlagR());
989 }
990 return;
991 }
994 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
995 {
996 entry->SetMacAddress(lla.GetAddress());
997 if (lla.GetAddress() != entry->GetMacAddress())
998 {
999 entry->MarkStale();
1000 }
1001 entry->SetRouter(naHeader.GetFlagR());
1002 }
1003 return;
1004 }
1005 }
1006 // Silence compiler warning
1007}
1008
1009void
1011 const Ipv6Address& src,
1012 const Ipv6Address& dst,
1013 Ptr<Ipv6Interface> interface)
1014{
1015 NS_LOG_FUNCTION(this << packet << src << dst << interface);
1016 bool hasLla = false;
1017 Ptr<Packet> p = packet->Copy();
1018 Icmpv6OptionLinkLayerAddress llOptionHeader(false);
1019
1020 Icmpv6Redirection redirectionHeader;
1021 p->RemoveHeader(redirectionHeader);
1022
1023 /* little ugly try to find a better way */
1024 uint8_t type;
1025 p->CopyData(&type, sizeof(type));
1027 {
1028 hasLla = true;
1029 p->RemoveHeader(llOptionHeader);
1030 }
1031
1032 Icmpv6OptionRedirected redirectedOptionHeader;
1033 p->RemoveHeader(redirectedOptionHeader);
1034
1035 Ipv6Address redirTarget = redirectionHeader.GetTarget();
1036 Ipv6Address redirDestination = redirectionHeader.GetDestination();
1037
1038 if (hasLla)
1039 {
1040 /* update the cache if needed */
1041 NdiscCache::Entry* entry = nullptr;
1042 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
1043
1044 entry = cache->Lookup(redirTarget);
1045 if (!entry)
1046 {
1047 entry = cache->Add(redirTarget);
1048 /* destination and target different => necessarily a router */
1049 entry->SetRouter(redirTarget != redirDestination);
1050 entry->SetMacAddress(llOptionHeader.GetAddress());
1051 entry->MarkStale();
1052 }
1053 else
1054 {
1055 if (entry->IsIncomplete() || entry->GetMacAddress() != llOptionHeader.GetAddress())
1056 {
1057 /* update entry to STALE */
1058 if (entry->GetMacAddress() != llOptionHeader.GetAddress())
1059 {
1060 entry->SetMacAddress(llOptionHeader.GetAddress());
1061 entry->MarkStale();
1062 }
1063 }
1064 else
1065 {
1066 /* stay unchanged */
1067 }
1068 }
1069 }
1070
1071 /* add redirection in routing table */
1072 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1073
1074 if (redirTarget == redirDestination)
1075 {
1076 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1077 Ipv6Prefix(128),
1078 Ipv6Address("::"),
1079 ipv6->GetInterfaceForAddress(dst));
1080 }
1081 else
1082 {
1083 uint32_t ifIndex = ipv6->GetInterfaceForAddress(dst);
1084 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1085 Ipv6Prefix(128),
1086 redirTarget,
1087 ifIndex);
1088 }
1089}
1090
1091void
1093 const Ipv6Address& src,
1094 const Ipv6Address& dst,
1095 Ptr<Ipv6Interface> interface)
1096{
1097 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1098 Ptr<Packet> pkt = p->Copy();
1099
1101 pkt->RemoveHeader(unreach);
1102
1103 Ipv6Header ipHeader;
1104 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1105 {
1106 pkt->RemoveHeader(ipHeader);
1107 uint8_t payload[8];
1108 pkt->CopyData(payload, 8);
1109 Forward(src, unreach, unreach.GetCode(), ipHeader, payload);
1110 }
1111}
1112
1113void
1115 const Ipv6Address& src,
1116 const Ipv6Address& dst,
1117 Ptr<Ipv6Interface> interface)
1118{
1119 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1120 Ptr<Packet> pkt = p->Copy();
1121
1122 Icmpv6TimeExceeded timeexceeded;
1123 pkt->RemoveHeader(timeexceeded);
1124
1125 Ipv6Header ipHeader;
1126 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1127 {
1128 Ipv6Header ipHeader;
1129 pkt->RemoveHeader(ipHeader);
1130 uint8_t payload[8];
1131 pkt->CopyData(payload, 8);
1132 Forward(src, timeexceeded, timeexceeded.GetCode(), ipHeader, payload);
1133 }
1134}
1135
1136void
1138 const Ipv6Address& src,
1139 const Ipv6Address& dst,
1140 Ptr<Ipv6Interface> interface)
1141{
1142 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1143 Ptr<Packet> pkt = p->Copy();
1144
1145 Icmpv6TooBig tooBig;
1146 pkt->RemoveHeader(tooBig);
1147
1148 Ipv6Header ipHeader;
1149 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1150 {
1151 pkt->RemoveHeader(ipHeader);
1152 uint8_t payload[8];
1153 pkt->CopyData(payload, 8);
1154
1156 ipv6->SetPmtu(ipHeader.GetDestination(), tooBig.GetMtu());
1157
1158 Forward(src, tooBig, tooBig.GetMtu(), ipHeader, payload);
1159 }
1160}
1161
1162void
1164 const Ipv6Address& src,
1165 const Ipv6Address& dst,
1166 Ptr<Ipv6Interface> interface)
1167{
1168 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1169 Ptr<Packet> pkt = p->Copy();
1170
1171 Icmpv6ParameterError paramErr;
1172 pkt->RemoveHeader(paramErr);
1173
1174 Ipv6Header ipHeader;
1175 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1176 {
1177 pkt->RemoveHeader(ipHeader);
1178 uint8_t payload[8];
1179 pkt->CopyData(payload, 8);
1180 Forward(src, paramErr, paramErr.GetCode(), ipHeader, payload);
1181 }
1182}
1183
1184void
1186{
1187 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1190 NS_ASSERT(ipv6);
1191
1192 tag.SetHopLimit(ttl);
1193 packet->AddPacketTag(tag);
1194 m_downTarget(packet, src, dst, PROT_NUMBER, nullptr);
1195}
1196
1197void
1199 Ipv6Address src,
1200 Ipv6Address dst,
1201 uint8_t ttl)
1202{
1203 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1204 SendMessage(packet, src, dst, ttl);
1205}
1206
1207void
1209 Ipv6Address dst,
1210 Icmpv6Header& icmpv6Hdr,
1211 uint8_t ttl)
1212{
1213 NS_LOG_FUNCTION(this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
1215 NS_ASSERT(ipv6 && ipv6->GetRoutingProtocol());
1216 Ipv6Header header;
1219 Ptr<Ipv6Route> route;
1220 Ptr<NetDevice> oif(nullptr); // specify non-zero if bound to a source address
1221
1222 header.SetDestination(dst);
1223 route = ipv6->GetRoutingProtocol()->RouteOutput(packet, header, oif, err);
1224
1225 if (route)
1226 {
1227 NS_LOG_LOGIC("Route exists");
1228 tag.SetHopLimit(ttl);
1229 packet->AddPacketTag(tag);
1230 Ipv6Address src = route->GetSource();
1231
1232 icmpv6Hdr.CalculatePseudoHeaderChecksum(src,
1233 dst,
1234 packet->GetSize() + icmpv6Hdr.GetSerializedSize(),
1235 PROT_NUMBER);
1236 packet->AddHeader(icmpv6Hdr);
1237 m_downTarget(packet, src, dst, PROT_NUMBER, route);
1238 }
1239 else
1240 {
1241 NS_LOG_WARN("drop icmp message");
1242 }
1243}
1244
1245void
1246Icmpv6L4Protocol::SendNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1247{
1248 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << static_cast<uint32_t>(flags));
1250 Icmpv6NA na;
1251 Icmpv6OptionLinkLayerAddress llOption(false, *hardwareAddress); /* not a source link layer */
1252
1253 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1254 na.SetIpv6Target(src);
1255
1256 if (flags & 1)
1257 {
1258 na.SetFlagO(true);
1259 }
1260 if ((flags & 2) && src != Ipv6Address::GetAny())
1261 {
1262 na.SetFlagS(true);
1263 }
1264 if (flags & 4)
1265 {
1266 na.SetFlagR(true);
1267 }
1268
1269 p->AddHeader(llOption);
1270 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1271 p->AddHeader(na);
1272
1273 SendMessage(p, src, dst, 255);
1274}
1275
1276void
1278 Ipv6Address dst,
1279 uint16_t id,
1280 uint16_t seq,
1282{
1283 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
1284 Ptr<Packet> p = data->Copy();
1285 Icmpv6Echo reply(false); /* echo reply */
1286
1287 reply.SetId(id);
1288 reply.SetSeq(seq);
1289
1291 dst,
1292 p->GetSize() + reply.GetSerializedSize(),
1293 PROT_NUMBER);
1294 p->AddHeader(reply);
1295 SendMessage(p, src, dst, 64);
1296}
1297
1298void
1300 Ipv6Address dst,
1301 Ipv6Address target,
1302 Address hardwareAddress)
1303{
1304 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1306 /* Ipv6Header ipHeader; */
1307 Icmpv6NS ns(target);
1309 true,
1310 hardwareAddress); /* we give our mac address in response */
1311
1312 /* if the source is unspec, multicast the NA to all-nodes multicast */
1313 if (src == Ipv6Address::GetAny())
1314 {
1316 }
1317
1318 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1319
1320 p->AddHeader(llOption);
1321 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1322 p->AddHeader(ns);
1323 if (!dst.IsMulticast())
1324 {
1325 SendMessage(p, src, dst, 255);
1326 }
1327 else
1328 {
1329 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1332 this,
1333 p,
1334 src,
1335 dst,
1336 255);
1337 }
1338}
1339
1340void
1342{
1343 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1345 Icmpv6RS rs;
1346
1347 // RFC 4861:
1348 // The link-layer address of the sender MUST NOT be included if the Source Address is the
1349 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
1350 if (!src.IsAny())
1351 {
1352 Icmpv6OptionLinkLayerAddress llOption(true, hardwareAddress);
1353 p->AddHeader(llOption);
1354 }
1355
1356 if (!src.IsAny())
1357 {
1359 if (ipv6->GetInterfaceForAddress(src) == -1)
1360 {
1361 NS_LOG_INFO("Preventing RS from being sent or rescheduled because the source address "
1362 << src << " has been removed");
1363 return;
1364 }
1365 }
1366
1367 NS_LOG_LOGIC("Send RS (from " << src << " to " << dst << ")");
1368
1369 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
1370 p->AddHeader(rs);
1371 if (!dst.IsMulticast())
1372 {
1373 SendMessage(p, src, dst, 255);
1374 }
1375 else
1376 {
1377 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1378 Time rsDelay = Time(0);
1379 Time rsTimeout = Time(0);
1380
1381 if (m_rsRetransmissionCount == 0)
1382 {
1383 // First RS transmission - also add some jitter to desynchronize nodes.
1385 rsTimeout = m_rsInitialRetransmissionTime * (1 + m_rsRetransmissionJitter->GetValue());
1387 }
1388 else
1389 {
1390 // Following RS transmission - adding further jitter is unnecessary.
1391 rsTimeout = m_rsPrevRetransmissionTimeout * (2 + m_rsRetransmissionJitter->GetValue());
1392 if (rsTimeout > m_rsMaxRetransmissionTime)
1393 {
1394 rsTimeout = m_rsMaxRetransmissionTime * (1 + m_rsRetransmissionJitter->GetValue());
1395 }
1396 }
1398 Simulator::Schedule(rsDelay, &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
1401 this,
1402 src,
1403 dst,
1404 hardwareAddress);
1405 }
1406}
1407
1408void
1410{
1411 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1412
1414 {
1415 // Unbound number of retransmissions - just add one to signal that we're in retransmission
1416 // mode.
1418 }
1419 else
1420 {
1423 {
1424 NS_LOG_LOGIC("Maximum number of multicast RS reached, giving up.");
1425 return;
1426 }
1427 }
1428
1431 {
1432 NS_LOG_LOGIC("Maximum RS retransmission time reached, giving up.");
1433 return;
1434 }
1435
1436 SendRS(src, dst, hardwareAddress);
1437}
1438
1439void
1441 Ipv6Address dst,
1442 uint8_t code)
1443{
1444 NS_LOG_FUNCTION(this << malformedPacket << dst << (uint32_t)code);
1445 uint32_t malformedPacketSize = malformedPacket->GetSize();
1447 header.SetCode(code);
1448
1449 NS_LOG_LOGIC("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1450
1451 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1452 if (malformedPacketSize <= 1280 - 48)
1453 {
1454 header.SetPacket(malformedPacket);
1455 SendMessage(malformedPacket, dst, header, 255);
1456 }
1457 else
1458 {
1459 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1460 header.SetPacket(fragment);
1461 SendMessage(fragment, dst, header, 255);
1462 }
1463}
1464
1465void
1467{
1468 NS_LOG_FUNCTION(this << malformedPacket << dst << mtu);
1469 uint32_t malformedPacketSize = malformedPacket->GetSize();
1470 Icmpv6TooBig header;
1471 header.SetCode(0);
1472 header.SetMtu(mtu);
1473
1474 NS_LOG_LOGIC("Send Too Big ( to " << dst << " )");
1475
1476 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1477 if (malformedPacketSize <= 1280 - 48)
1478 {
1479 header.SetPacket(malformedPacket);
1480 SendMessage(malformedPacket, dst, header, 255);
1481 }
1482 else
1483 {
1484 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1485 header.SetPacket(fragment);
1486 SendMessage(fragment, dst, header, 255);
1487 }
1488}
1489
1490void
1492{
1493 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code));
1494 uint32_t malformedPacketSize = malformedPacket->GetSize();
1495 Icmpv6TimeExceeded header;
1496 header.SetCode(code);
1497
1498 NS_LOG_LOGIC("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1499
1500 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1501 if (malformedPacketSize <= 1280 - 48)
1502 {
1503 header.SetPacket(malformedPacket);
1504 SendMessage(malformedPacket, dst, header, 255);
1505 }
1506 else
1507 {
1508 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1509 header.SetPacket(fragment);
1510 SendMessage(fragment, dst, header, 255);
1511 }
1512}
1513
1514void
1516 Ipv6Address dst,
1517 uint8_t code,
1518 uint32_t ptr)
1519{
1520 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code) << ptr);
1521 uint32_t malformedPacketSize = malformedPacket->GetSize();
1522 Icmpv6ParameterError header;
1523 header.SetCode(code);
1524 header.SetPtr(ptr);
1525
1526 NS_LOG_LOGIC("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1527
1528 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1529 if (malformedPacketSize <= 1280 - 48)
1530 {
1531 header.SetPacket(malformedPacket);
1532 SendMessage(malformedPacket, dst, header, 255);
1533 }
1534 else
1535 {
1536 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1537 header.SetPacket(fragment);
1538 SendMessage(fragment, dst, header, 255);
1539 }
1540}
1541
1542void
1544 Ipv6Address src,
1545 Ipv6Address dst,
1546 Ipv6Address redirTarget,
1547 Ipv6Address redirDestination,
1548 Address redirHardwareTarget)
1549{
1550 NS_LOG_FUNCTION(this << redirectedPacket << dst << redirTarget << redirDestination
1551 << redirHardwareTarget);
1552 uint32_t llaSize = 0;
1554 uint32_t redirectedPacketSize = redirectedPacket->GetSize();
1555 Icmpv6OptionLinkLayerAddress llOption(false);
1556
1557 NS_LOG_LOGIC("Send Redirection ( to " << dst << " target " << redirTarget << " destination "
1558 << redirDestination << " )");
1559
1560 Icmpv6OptionRedirected redirectedOptionHeader;
1561
1562 if ((redirectedPacketSize % 8) != 0)
1563 {
1564 Ptr<Packet> pad = Create<Packet>(8 - (redirectedPacketSize % 8));
1565 redirectedPacket->AddAtEnd(pad);
1566 }
1567
1568 if (redirHardwareTarget.GetLength())
1569 {
1570 llOption.SetAddress(redirHardwareTarget);
1571 llaSize = llOption.GetSerializedSize();
1572 }
1573
1574 /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1575 if (redirectedPacketSize <= (1280 - 56 - llaSize))
1576 {
1577 redirectedOptionHeader.SetPacket(redirectedPacket);
1578 }
1579 else
1580 {
1581 Ptr<Packet> fragment = redirectedPacket->CreateFragment(0, 1280 - 56 - llaSize);
1582 redirectedOptionHeader.SetPacket(fragment);
1583 }
1584
1585 p->AddHeader(redirectedOptionHeader);
1586
1587 if (llaSize)
1588 {
1589 p->AddHeader(llOption);
1590 }
1591
1592 Icmpv6Redirection redirectionHeader;
1593 redirectionHeader.SetTarget(redirTarget);
1594 redirectionHeader.SetDestination(redirDestination);
1595 redirectionHeader.CalculatePseudoHeaderChecksum(src,
1596 dst,
1597 p->GetSize() +
1598 redirectionHeader.GetSerializedSize(),
1599 PROT_NUMBER);
1600 p->AddHeader(redirectionHeader);
1601
1602 SendMessage(p, src, dst, 64);
1603}
1604
1606Icmpv6L4Protocol::ForgeNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1607{
1608 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << (uint32_t)flags);
1610 Ipv6Header ipHeader;
1611 Icmpv6NA na;
1613 false,
1614 *hardwareAddress); /* we give our mac address in response */
1615
1616 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << ")");
1617
1618 /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet
1619 * does not pass by Icmpv6L4Protocol::Lookup again */
1620
1621 p->AddHeader(llOption);
1622 na.SetIpv6Target(src);
1623
1624 if (flags & 1)
1625 {
1626 na.SetFlagO(true);
1627 }
1628 if ((flags & 2) && src != Ipv6Address::GetAny())
1629 {
1630 na.SetFlagS(true);
1631 }
1632 if (flags & 4)
1633 {
1634 na.SetFlagR(true);
1635 }
1636
1637 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1638 p->AddHeader(na);
1639
1640 ipHeader.SetSource(src);
1641 ipHeader.SetDestination(dst);
1642 ipHeader.SetNextHeader(PROT_NUMBER);
1643 ipHeader.SetPayloadLength(p->GetSize());
1644 ipHeader.SetHopLimit(255);
1645
1646 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1647}
1648
1651 Ipv6Address dst,
1652 Ipv6Address target,
1653 Address hardwareAddress)
1654{
1655 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1657 Ipv6Header ipHeader;
1658 Icmpv6NS ns(target);
1660 true,
1661 hardwareAddress); /* we give our mac address in response */
1662
1663 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1664
1665 p->AddHeader(llOption);
1666 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1667 p->AddHeader(ns);
1668
1669 ipHeader.SetSource(src);
1670 ipHeader.SetDestination(dst);
1671 ipHeader.SetNextHeader(PROT_NUMBER);
1672 ipHeader.SetPayloadLength(p->GetSize());
1673 ipHeader.SetHopLimit(255);
1674
1675 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1676}
1677
1680{
1681 NS_LOG_FUNCTION(this << device);
1682
1683 for (auto i = m_cacheList.begin(); i != m_cacheList.end(); i++)
1684 {
1685 if ((*i)->GetDevice() == device)
1686 {
1687 return *i;
1688 }
1689 }
1690
1691 NS_ASSERT_MSG(false, "Icmpv6L4Protocol can not find a NDIS Cache for device " << device);
1692 /* quiet compiler */
1693 return nullptr;
1694}
1695
1698{
1699 NS_LOG_FUNCTION(this << device << interface);
1700
1702
1703 cache->SetDevice(device, interface, this);
1704 device->AddLinkChangeCallback(MakeCallback(&NdiscCache::Flush, cache));
1705 m_cacheList.push_back(cache);
1706 return cache;
1707}
1708
1709bool
1711 Ptr<NetDevice> device,
1712 Ptr<NdiscCache> cache,
1713 Address* hardwareDestination)
1714{
1715 NS_LOG_FUNCTION(this << dst << device << cache << hardwareDestination);
1716
1717 if (!cache)
1718 {
1719 /* try to find the cache */
1720 cache = FindCache(device);
1721 }
1722 if (cache)
1723 {
1724 NdiscCache::Entry* entry = cache->Lookup(dst);
1725 if (entry)
1726 {
1727 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1728 entry->IsAutoGenerated())
1729 {
1730 *hardwareDestination = entry->GetMacAddress();
1731 return true;
1732 }
1733 else if (entry->IsStale())
1734 {
1735 entry->StartDelayTimer();
1736 entry->MarkDelay();
1737 *hardwareDestination = entry->GetMacAddress();
1738 return true;
1739 }
1740 }
1741 }
1742 return false;
1743}
1744
1745bool
1747 const Ipv6Header& ipHeader,
1748 Ipv6Address dst,
1749 Ptr<NetDevice> device,
1750 Ptr<NdiscCache> cache,
1751 Address* hardwareDestination)
1752{
1753 NS_LOG_FUNCTION(this << p << ipHeader << dst << device << cache << hardwareDestination);
1754
1755 if (!cache)
1756 {
1757 /* try to find the cache */
1758 cache = FindCache(device);
1759 }
1760 if (!cache)
1761 {
1762 return false;
1763 }
1764
1765 NdiscCache::Entry* entry = cache->Lookup(dst);
1766 if (entry)
1767 {
1768 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1769 entry->IsAutoGenerated())
1770 {
1771 /* XXX check reachability time */
1772 /* send packet */
1773 *hardwareDestination = entry->GetMacAddress();
1774 return true;
1775 }
1776 else if (entry->IsStale())
1777 {
1778 /* start delay timer */
1779 entry->StartDelayTimer();
1780 entry->MarkDelay();
1781 *hardwareDestination = entry->GetMacAddress();
1782 return true;
1783 }
1784 else /* INCOMPLETE or PROBE */
1785 {
1786 /* queue packet */
1788 return false;
1789 }
1790 }
1791 else
1792 {
1793 /* we contact this node for the first time
1794 * add it to the cache and send an NS
1795 */
1796 Ipv6Address addr;
1797 NdiscCache::Entry* entry = cache->Add(dst);
1799 entry->SetRouter(false);
1800
1801 if (dst.IsLinkLocal())
1802 {
1803 addr = cache->GetInterface()->GetLinkLocalAddress().GetAddress();
1804 }
1805 else if (cache->GetInterface()->GetNAddresses() ==
1806 1) /* an interface have at least one address (link-local) */
1807 {
1808 /* try to resolve global address without having global address so return! */
1809 cache->Remove(entry);
1810 return false;
1811 }
1812 else
1813 {
1814 /* find source address that match destination */
1815 addr = cache->GetInterface()->GetAddressMatchingDestination(dst).GetAddress();
1816 }
1817
1818 SendNS(addr, Ipv6Address::MakeSolicitedAddress(dst), dst, cache->GetDevice()->GetAddress());
1819
1820 /* start retransmit timer */
1821 entry->StartRetransmitTimer();
1822 return false;
1823 }
1824
1825 return false;
1826}
1827
1828void
1830{
1831 NS_LOG_FUNCTION(this << interface << addr);
1832
1833 Ipv6InterfaceAddress ifaddr;
1834 bool found = false;
1835 uint32_t i = 0;
1836 uint32_t nb = interface->GetNAddresses();
1837
1838 for (i = 0; i < nb; i++)
1839 {
1840 ifaddr = interface->GetAddress(i);
1841
1842 if (ifaddr.GetAddress() == addr)
1843 {
1844 found = true;
1845 break;
1846 }
1847 }
1848
1849 if (!found)
1850 {
1851 NS_LOG_LOGIC("Can not find the address in the interface.");
1852 }
1853
1854 /* for the moment, this function is always called, if we was victim of a DAD the address is
1855 * INVALID and we do not set it to PREFERRED
1856 */
1857 if (found && ifaddr.GetState() != Ipv6InterfaceAddress::INVALID)
1858 {
1861 NS_LOG_LOGIC("DAD OK, interface in state PREFERRED");
1862
1863 /* send an RS if our interface is not forwarding (router) and if address is a link-local
1864 * ones (because we will send RS with it)
1865 */
1866 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1867
1868 if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())) &&
1869 addr.IsLinkLocal())
1870 {
1871 /* \todo Add random delays before sending RS
1872 * because all nodes start at the same time, there will be many of RS around 1 second of
1873 * simulation time
1874 */
1875 NS_LOG_LOGIC("Scheduled a first Router Solicitation");
1879 this,
1880 ifaddr.GetAddress(),
1882 interface->GetDevice()->GetAddress());
1883 }
1884 else
1885 {
1886 NS_LOG_LOGIC("Did not schedule a Router Solicitation because the interface is in "
1887 "forwarding mode");
1888 }
1889 }
1890}
1891
1892void
1897
1898void
1900{
1901 NS_LOG_FUNCTION(this << &callback);
1902 m_downTarget = callback;
1903}
1904
1911
1914{
1915 NS_LOG_FUNCTION(this);
1916 return m_downTarget;
1917}
1918
1919uint8_t
1924
1925uint8_t
1930
1931Time
1936
1937Time
1942
1943Time
1948
1949Time
1951{
1952 return m_dadTimeout;
1953}
1954
1955} /* namespace ns3 */
a polymophic address class
Definition address.h:90
uint8_t GetLength() const
Get the length of the underlying address.
Definition address.cc:67
AttributeValue implementation for Boolean.
Definition boolean.h:26
void Nullify()
Discard the implementation, set it to null.
Definition callback.h:561
bool IsNull() const
Check for null implementation.
Definition callback.h:555
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
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.
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_ERROR_DESTINATION_UNREACHABLE
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 ].
ns3::TracedCallback< const Ipv6Address & > m_dadSuccessAddressTrace
The trace fired when a DAD completes and no duplicate address has been detected.
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.
Callback< void, uint32_t > m_startDhcpv6
The DHCPv6 callback when the M flag is set in a Router Advertisement.
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).
ns3::TracedCallback< const Ipv6Address & > m_dadFailureAddressTrace
The trace fired when a DAD fails, changing the address state to INVALID.
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.
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.
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).
bool GetFlagM() const
Get the M flag.
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:34
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:23
Describes an IPv6 address.
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:24
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
void SetSource(Ipv6Address src)
Set the "Source address" field.
uint8_t GetHopLimit() const
Get the "Hop limit" field (TTL).
uint8_t GetNextHeader() const
Get the next header.
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Ipv6Address GetDestination() const
Get the "Destination address" field.
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Ipv6Address GetSource() const
Get the "Source address" field.
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition ipv6.h:71
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 constexpr uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
Describes an IPv6 prefix.
A record that holds information about a NdiscCache entry.
bool IsPermanent() const
Is the entry PERMANENT.
NdiscCacheEntryState_e m_state
The state of the entry.
@ PROBE
Try to contact IPv6 address to know again its L2 address.
@ STALE
Mapping is stale.
@ REACHABLE
Mapping exists between IPv6 and L2 addresses.
@ PERMANENT
Permanent Mapping exists between IPv6 and L2 addresses.
@ DELAY
Try to wait contact from remote host.
@ INCOMPLETE
No mapping between IPv6 and L2 addresses.
@ STATIC_AUTOGENERATED
Permanent entries generate by NeighborCacheHelper.
void ClearWaitingPacket()
Clear the waiting packet list.
std::list< Ipv6PayloadHeaderPair > MarkStale(Address mac)
Changes the state to this entry to STALE.
void StartReachableTimer()
Start the reachable timer.
Address GetMacAddress() const
Get the MAC address of this entry.
void StartDelayTimer()
Start delay timer.
std::list< Ipv6PayloadHeaderPair > MarkReachable(Address mac)
Changes the state to this entry to REACHABLE.
bool IsIncomplete() const
Is the entry INCOMPLETE.
bool IsDelay() const
Is the entry DELAY.
void StartRetransmitTimer()
Start retransmit timer.
void MarkIncomplete(Ipv6PayloadHeaderPair p)
Changes the state to this entry to INCOMPLETE.
bool IsStale() const
Is the entry STALE.
void SetMacAddress(Address mac)
Set the MAC address of this entry.
void MarkDelay()
Change the state to this entry to DELAY.
void SetRouter(bool router)
Set the node type.
bool IsAutoGenerated() const
Is the entry STATIC_AUTOGENERATED.
void AddWaitingPacket(Ipv6PayloadHeaderPair p)
Add a packet (or replace old value) in the queue.
bool IsReachable() const
Is the entry REACHABLE.
void StopNudTimer()
Stop NUD timer and reset the NUD retransmission counter.
std::pair< Ptr< Packet >, Ipv6Header > Ipv6PayloadHeaderPair
Pair of a packet and an Ipv4 header.
void Flush()
Flush the cache.
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition object.cc:412
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
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:561
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition socket.h:73
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition socket.h:1161
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition socket.cc:657
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
bool IsZero() const
Exactly equivalent to t == 0.
Definition nstime.h:304
AttributeValue implementation for Time.
Definition nstime.h:1432
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#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:75
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeIntegerChecker()
Definition integer.h:99
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition integer.h:35
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1433
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1453
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION_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:250
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
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:684
uint8_t data[writeSize]