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 "ipv6-interface.h"
15#include "ipv6-l3-protocol.h"
16#include "ipv6-route.h"
18
19#include "ns3/assert.h"
20#include "ns3/boolean.h"
21#include "ns3/double.h"
22#include "ns3/integer.h"
23#include "ns3/log.h"
24#include "ns3/node.h"
25#include "ns3/packet.h"
26#include "ns3/pointer.h"
27#include "ns3/string.h"
28#include "ns3/uinteger.h"
29
30namespace ns3
31{
32
33NS_LOG_COMPONENT_DEFINE("Icmpv6L4Protocol");
34
35NS_OBJECT_ENSURE_REGISTERED(Icmpv6L4Protocol);
36
37const uint8_t Icmpv6L4Protocol::PROT_NUMBER = 58;
38
39// const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERT_INTERVAL = 16; // max initial RA initial
40// interval. const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERTISEMENTS = 3; // max initial RA
41// transmission. const uint8_t Icmpv6L4Protocol::MAX_FINAL_RTR_ADVERTISEMENTS = 3; // max final
42// RA transmission. const uint8_t Icmpv6L4Protocol::MIN_DELAY_BETWEEN_RAS = 3; // min
43// delay between RA. const uint32_t Icmpv6L4Protocol::MAX_RA_DELAY_TIME = 500; //
44// millisecond - max delay between RA.
45
46// const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATION_DELAY = 1; // max RS delay.
47// const uint8_t Icmpv6L4Protocol::RTR_SOLICITATION_INTERVAL = 4; // RS interval.
48// const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATIONS = 3; // max RS transmission.
49
50// const uint8_t Icmpv6L4Protocol::MAX_ANYCAST_DELAY_TIME = 1; // max anycast delay.
51// const uint8_t Icmpv6L4Protocol::MAX_NEIGHBOR_ADVERTISEMENT = 3; // max NA transmission.
52
53// const double Icmpv6L4Protocol::MIN_RANDOM_FACTOR = 0.5; // min random factor.
54// const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5; // max random factor.
55
56TypeId
58{
59 static TypeId tid =
60 TypeId("ns3::Icmpv6L4Protocol")
62 .SetGroupName("Internet")
63 .AddConstructor<Icmpv6L4Protocol>()
64 .AddAttribute("DAD",
65 "Always do DAD check.",
66 BooleanValue(true),
69 .AddAttribute(
70 "SolicitationJitter",
71 "The jitter in ms a node is allowed to wait before sending any solicitation. Some "
72 "jitter aims to prevent collisions. By default, the model will wait for a duration "
73 "in ms defined by a uniform random-variable between 0 and SolicitationJitter",
74 StringValue("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
77 .AddAttribute("MaxMulticastSolicit",
78 "Neighbor Discovery node constants: max multicast solicitations.",
79 IntegerValue(3),
82 .AddAttribute("MaxUnicastSolicit",
83 "Neighbor Discovery node constants: max unicast solicitations.",
84 IntegerValue(3),
87 .AddAttribute("ReachableTime",
88 "Neighbor Discovery node constants: reachable time.",
89 TimeValue(Seconds(30)),
92 .AddAttribute("RetransmissionTime",
93 "Neighbor Discovery node constants: retransmission timer.",
97 .AddAttribute("DelayFirstProbe",
98 "Neighbor Discovery node constants: delay for the first probe.",
102 .AddAttribute("DadTimeout",
103 "Duplicate Address Detection (DAD) timeout",
104 TimeValue(Seconds(1)),
107 .AddAttribute("RsRetransmissionJitter",
108 "Multicast RS retransmission randomization quantity",
109 StringValue("ns3::UniformRandomVariable[Min=-0.1|Max=0.1]"),
112 .AddAttribute("RsInitialRetransmissionTime",
113 "Multicast RS initial retransmission time.",
114 TimeValue(Seconds(4)),
117 .AddAttribute("RsMaxRetransmissionTime",
118 "Multicast RS maximum retransmission time (0 means unbound).",
119 TimeValue(Seconds(3600)),
122 .AddAttribute(
123 "RsMaxRetransmissionCount",
124 "Multicast RS maximum retransmission count (0 means unbound). "
125 "Note: RFC 7559 suggest a zero value (infinite). The default is 4 to avoid "
126 "non-terminating simulations.",
127 UintegerValue(4),
130 .AddAttribute("RsMaxRetransmissionDuration",
131 "Multicast RS maximum retransmission duration (0 means unbound).",
132 TimeValue(Seconds(0)),
135 .AddTraceSource("DadFailure",
136 "Duplicate Address detected during DAD, the address is now INVALID",
138 "ns3::Ipv6Address::TracedCallback")
139 .AddTraceSource(
140 "DadSuccess",
141 "Duplicate Address not detected during DAD, the address is now PREFERRED",
143 "ns3::Ipv6Address::TracedCallback");
144 return tid;
145}
146
147TypeId
153
155 : m_node(nullptr)
156{
157 NS_LOG_FUNCTION(this);
158}
159
164
165void
167{
168 NS_LOG_FUNCTION(this);
169 for (auto it = m_cacheList.begin(); it != m_cacheList.end(); it++)
170 {
171 Ptr<NdiscCache> cache = *it;
172 cache->Dispose();
173 cache = nullptr;
174 }
175 m_cacheList.clear();
177
178 m_node = nullptr;
180}
181
182int64_t
184{
185 NS_LOG_FUNCTION(this << stream);
187 m_rsRetransmissionJitter->SetStream(stream + 1);
188 return 2;
189}
190
191void
193{
194 NS_LOG_FUNCTION(this);
195 if (!m_node)
196 {
197 Ptr<Node> node = this->GetObject<Node>();
198 if (node)
199 {
200 Ptr<Ipv6> ipv6 = this->GetObject<Ipv6>();
201 if (ipv6 && m_downTarget.IsNull())
202 {
203 SetNode(node);
204 ipv6->Insert(this);
206 }
207 }
208 }
210}
211
212void
214{
215 NS_LOG_FUNCTION(this << node);
216 m_node = node;
217}
218
221{
222 NS_LOG_FUNCTION(this);
223 return m_node;
224}
225
226uint16_t
232
233int
235{
236 NS_LOG_FUNCTION(this);
237 return PROT_NUMBER;
238}
239
240int
242{
243 NS_LOG_FUNCTION(this);
244 return 1;
245}
246
247bool
249{
250 NS_LOG_FUNCTION(this);
251 return m_alwaysDad;
252}
253
254void
256{
257 NS_LOG_FUNCTION(this << target << interface);
258 Ipv6Address addr;
260
261 NS_ASSERT(ipv6);
262
263 if (!m_alwaysDad)
264 {
265 return;
266 }
267
268 /** \todo disable multicast loopback to prevent NS probing to be received by the sender */
269
272 target,
273 interface->GetDevice()->GetAddress());
274
275 /* update last packet UID */
276 interface->SetNsDadUid(target, p.first->GetUid());
279 interface,
280 p.first,
281 p.second,
283}
284
287 const Ipv4Header& header,
288 Ptr<Ipv4Interface> interface)
289{
290 NS_LOG_FUNCTION(this << packet << header);
292}
293
296 const Ipv6Header& header,
297 Ptr<Ipv6Interface> interface)
298{
299 NS_LOG_FUNCTION(this << packet << header.GetSource() << header.GetDestination() << interface);
300 Ptr<Packet> p = packet->Copy();
301 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
302
303 /* very ugly! try to find something better in the future */
304 uint8_t type;
305 p->CopyData(&type, sizeof(type));
306
307 switch (type)
308 {
310 if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
311 {
312 HandleRS(p, header.GetSource(), header.GetDestination(), interface);
313 }
314 break;
316 if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
317 {
318 HandleRA(p, header.GetSource(), header.GetDestination(), interface);
319 }
320 break;
322 HandleNS(p, header.GetSource(), header.GetDestination(), interface);
323 break;
325 HandleNA(p, header.GetSource(), header.GetDestination(), interface);
326 break;
328 HandleRedirection(p, header.GetSource(), header.GetDestination(), interface);
329 break;
331 HandleEchoRequest(p, header.GetSource(), header.GetDestination(), interface);
332 break;
334 // EchoReply does not contain any info about L4
335 // so we can not forward it up.
336 /// \todo implement request / reply consistency check.
337 break;
339 HandleDestinationUnreachable(p, header.GetSource(), header.GetDestination(), interface);
340 break;
342 HandlePacketTooBig(p, header.GetSource(), header.GetDestination(), interface);
343 break;
345 HandleTimeExceeded(p, header.GetSource(), header.GetDestination(), interface);
346 break;
348 HandleParameterError(p, header.GetSource(), header.GetDestination(), interface);
349 break;
350 default:
351 NS_LOG_LOGIC("Unknown ICMPv6 message type=" << type);
352 break;
353 }
354
355 return IpL4Protocol::RX_OK;
356}
357
358void
360 Icmpv6Header icmp,
361 uint32_t info,
362 Ipv6Header ipHeader,
363 const uint8_t payload[8])
364{
365 NS_LOG_FUNCTION(this << source << icmp << info << ipHeader << payload);
366
368
369 /// \todo assuming the ICMP is carrying a extensionless IP packet
370
371 uint8_t nextHeader = ipHeader.GetNextHeader();
372
373 if (nextHeader != Icmpv6L4Protocol::PROT_NUMBER)
374 {
375 Ptr<IpL4Protocol> l4 = ipv6->GetProtocol(nextHeader);
376 if (l4)
377 {
378 l4->ReceiveIcmp(source,
379 ipHeader.GetHopLimit(),
380 icmp.GetType(),
381 icmp.GetCode(),
382 info,
383 ipHeader.GetSource(),
384 ipHeader.GetDestination(),
385 payload);
386 }
387 }
388}
389
390void
392 const Ipv6Address& src,
393 const Ipv6Address& dst,
394 Ptr<Ipv6Interface> interface)
395{
396 NS_LOG_FUNCTION(this << packet << src << dst << interface);
397 Icmpv6Echo request;
398 auto buf = new uint8_t[packet->GetSize()];
399
400 packet->RemoveHeader(request);
401 /* XXX IPv6 extension: obtain a fresh copy of data otherwise it crash... */
402 packet->CopyData(buf, packet->GetSize());
403 Ptr<Packet> p = Create<Packet>(buf, packet->GetSize());
404
405 /* if we send message from ff02::* (link-local multicast), we use our link-local address */
406 SendEchoReply(dst.IsMulticast() ? interface->GetLinkLocalAddress().GetAddress() : dst,
407 src,
408 request.GetId(),
409 request.GetSeq(),
410 p);
411 delete[] buf;
412}
413
414void
416 const Ipv6Address& src,
417 const Ipv6Address& dst,
418 Ptr<Ipv6Interface> interface)
419{
420 NS_LOG_FUNCTION(this << packet << src << dst << interface);
421
423 {
425 // We need to update this in case we need to restart RS retransmissions.
427 }
428
429 Ptr<Packet> p = packet->Copy();
430 Icmpv6RA raHeader;
433 Icmpv6OptionMtu mtuHdr;
435 bool next = true;
436 bool hasLla = false;
437 bool hasMtu = false;
438 Ipv6Address defaultRouter = Ipv6Address::GetZero();
439
440 p->RemoveHeader(raHeader);
441
442 // If 'M' flag is set, we need to start DHCPv6.
443 if (raHeader.GetFlagM())
444 {
445 if (!m_startDhcpv6.IsNull())
446 {
447 m_startDhcpv6(ipv6->GetInterfaceForDevice(interface->GetDevice()));
448 }
449 }
450
451 if (raHeader.GetLifeTime())
452 {
453 defaultRouter = src;
454 }
455
456 while (next)
457 {
458 uint8_t type = 0;
459 p->CopyData(&type, sizeof(type));
460
461 switch (type)
462 {
464 p->RemoveHeader(prefixHdr);
465 ipv6->AddAutoconfiguredAddress(ipv6->GetInterfaceForDevice(interface->GetDevice()),
466 prefixHdr.GetPrefix(),
467 prefixHdr.GetPrefixLength(),
468 prefixHdr.GetFlags(),
469 prefixHdr.GetValidTime(),
470 prefixHdr.GetPreferredTime(),
471 defaultRouter);
472 break;
474 /* take in account the first MTU option */
475 if (!hasMtu)
476 {
477 p->RemoveHeader(mtuHdr);
478 hasMtu = true;
479 /** \todo case of multiple prefix on single interface */
480 /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
481 }
482 break;
484 /* take in account the first LLA option */
485 if (!hasLla)
486 {
487 p->RemoveHeader(llaHdr);
488 ReceiveLLA(llaHdr, src, dst, interface);
489 hasLla = true;
490 }
491 break;
492 default:
493 /* unknown option, quit */
494 next = false;
495 }
496 }
497}
498
499void
501 const Ipv6Address& src,
502 const Ipv6Address& dst,
503 Ptr<Ipv6Interface> interface)
504{
505 NS_LOG_FUNCTION(this << lla << src << dst << interface);
506 Address hardwareAddress;
507 NdiscCache::Entry* entry = nullptr;
508 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
509
510 /* check if we have this address in our cache */
511 entry = cache->Lookup(src);
512
513 if (!entry)
514 {
515 entry = cache->Add(src);
516 entry->SetRouter(true);
517 entry->SetMacAddress(lla.GetAddress());
518 entry->MarkReachable();
519 entry->StartReachableTimer();
520 }
521 else
522 {
523 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
524 switch (entry->m_state)
525 {
527 entry->StopNudTimer();
528 // mark it to reachable
529 waiting = entry->MarkReachable(lla.GetAddress());
530 entry->StartReachableTimer();
531 // send out waiting packet
532 for (auto it = waiting.begin(); it != waiting.end(); it++)
533 {
534 cache->GetInterface()->Send(it->first, it->second, src);
535 }
536 entry->ClearWaitingPacket();
537 return;
538 }
541 if (entry->GetMacAddress() != lla.GetAddress())
542 {
543 entry->SetMacAddress(lla.GetAddress());
544 entry->MarkStale();
545 entry->SetRouter(true);
546 }
547 else
548 {
549 entry->StopNudTimer();
550 waiting = entry->MarkReachable(lla.GetAddress());
551 entry->StartReachableTimer();
552 }
553 return;
554 }
556 if (entry->GetMacAddress() != lla.GetAddress())
557 {
558 entry->SetMacAddress(lla.GetAddress());
559 entry->MarkStale();
560 entry->SetRouter(true);
561 }
562 else
563 {
564 entry->StopNudTimer();
565 waiting = entry->MarkReachable(lla.GetAddress());
566 for (auto it = waiting.begin(); it != waiting.end(); it++)
567 {
568 cache->GetInterface()->Send(it->first, it->second, src);
569 }
570 entry->StartReachableTimer();
571 }
572 return;
573 }
575 if (entry->GetMacAddress() != lla.GetAddress())
576 {
577 entry->SetMacAddress(lla.GetAddress());
578 entry->MarkStale();
579 entry->SetRouter(true);
580 }
581 entry->StartReachableTimer();
582 return;
583 }
586 if (entry->GetMacAddress() != lla.GetAddress())
587 {
588 entry->SetMacAddress(lla.GetAddress());
589 entry->MarkStale();
590 entry->SetRouter(true);
591 }
592 return;
593 }
594 }
595 return; // Silence compiler warning
596 }
597}
598
599void
601 const Ipv6Address& src,
602 const Ipv6Address& dst,
603 Ptr<Ipv6Interface> interface)
604{
605 NS_LOG_FUNCTION(this << packet << src << dst << interface);
607 Icmpv6RS rsHeader;
608 packet->RemoveHeader(rsHeader);
609 Address hardwareAddress;
611 NdiscCache::Entry* entry = nullptr;
612 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
613
614 if (src != Ipv6Address::GetAny())
615 {
616 /* XXX search all options following the RS header */
617 /* test if the next option is SourceLinkLayerAddress */
618 uint8_t type;
619 packet->CopyData(&type, sizeof(type));
620
622 {
623 return;
624 }
625 packet->RemoveHeader(lla);
626 NS_LOG_LOGIC("Cache updated by RS");
627
628 entry = cache->Lookup(src);
629 if (!entry)
630 {
631 entry = cache->Add(src);
632 entry->SetRouter(false);
633 entry->MarkStale(lla.GetAddress());
634 }
635 else if (entry->GetMacAddress() != lla.GetAddress())
636 {
637 entry->MarkStale(lla.GetAddress());
638 }
639 }
640}
641
642void
644 const Ipv6Address& src,
645 const Ipv6Address& dst,
646 Ptr<Ipv6Interface> interface)
647{
648 NS_LOG_FUNCTION(this << packet << src << dst << interface);
649 Icmpv6NS nsHeader("::");
651 uint32_t nb = interface->GetNAddresses();
652 uint32_t i = 0;
653 bool found = false;
654
655 packet->RemoveHeader(nsHeader);
656
657 Ipv6Address target = nsHeader.GetIpv6Target();
658
659 for (i = 0; i < nb; i++)
660 {
661 ifaddr = interface->GetAddress(i);
662
663 if (ifaddr.GetAddress() == target)
664 {
665 found = true;
666 break;
667 }
668 }
669
670 if (!found)
671 {
672 NS_LOG_LOGIC("Not a NS for us");
673 return;
674 }
675
676 if (packet->GetUid() == ifaddr.GetNsDadUid())
677 {
678 /* don't process our own DAD probe */
679 NS_LOG_LOGIC("Hey we receive our DAD probe!");
680 return;
681 }
682
683 NdiscCache::Entry* entry = nullptr;
684 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
685 uint8_t flags = 0;
686
687 /* search all options following the NS header */
688 Icmpv6OptionLinkLayerAddress sllaoHdr(true);
689
690 bool next = true;
691 bool hasSllao = false;
692
693 while (next)
694 {
695 uint8_t type;
696 packet->CopyData(&type, sizeof(type));
697
698 switch (type)
699 {
701 if (!hasSllao)
702 {
703 packet->RemoveHeader(sllaoHdr);
704 hasSllao = true;
705 }
706 break;
707 default:
708 /* unknown option, quit */
709 next = false;
710 }
711 if (packet->GetSize() == 0)
712 {
713 next = false;
714 }
715 }
716
717 Address replyMacAddress;
718
719 if (src != Ipv6Address::GetAny())
720 {
721 entry = cache->Lookup(src);
722 if (!entry)
723 {
724 if (!hasSllao)
725 {
726 NS_LOG_LOGIC("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a "
727 "NCE, discarding.");
728 return;
729 }
730 entry = cache->Add(src);
731 entry->SetRouter(false);
732 entry->MarkStale(sllaoHdr.GetAddress());
733 replyMacAddress = sllaoHdr.GetAddress();
734 }
735 else if (hasSllao && (entry->GetMacAddress() != sllaoHdr.GetAddress()))
736 {
737 entry->MarkStale(sllaoHdr.GetAddress());
738 replyMacAddress = sllaoHdr.GetAddress();
739 }
740 else
741 {
742 replyMacAddress = entry->GetMacAddress();
743 }
744
745 flags = 3; /* S + O flags */
746 }
747 else
748 {
749 /* it's a DAD */
750 flags = 1; /* O flag */
751 replyMacAddress = interface->GetDevice()->GetMulticast(dst);
752 }
753
754 /* send a NA to src */
756
757 if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
758 {
759 flags += 4; /* R flag */
760 }
761
762 Address hardwareAddress = interface->GetDevice()->GetAddress();
764 target.IsLinkLocal() ? interface->GetLinkLocalAddress().GetAddress() : ifaddr.GetAddress(),
765 src.IsAny() ? dst : src, // DAD replies must go to the multicast group it was sent to.
766 &hardwareAddress,
767 flags);
768
769 // We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not
770 // change it beyond what we did already).
771 Ptr<Packet> pkt = p.first;
772 pkt->AddHeader(p.second);
773 interface->GetDevice()->Send(pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
774}
775
778{
779 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
781 Ipv6Header ipHeader;
782 Icmpv6RS rs;
783
784 NS_LOG_LOGIC("Forge RS (from " << src << " to " << dst << ")");
785 // RFC 4861:
786 // The link-layer address of the sender MUST NOT be included if the Source Address is the
787 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
788 if (!src.IsAny())
789 {
791 true,
792 hardwareAddress); /* we give our mac address in response */
793 p->AddHeader(llOption);
794 }
795
796 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
797 p->AddHeader(rs);
798
799 ipHeader.SetSource(src);
800 ipHeader.SetDestination(dst);
801 ipHeader.SetNextHeader(PROT_NUMBER);
802 ipHeader.SetPayloadLength(p->GetSize());
803 ipHeader.SetHopLimit(255);
804
805 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
806}
807
810 Ipv6Address dst,
811 uint16_t id,
812 uint16_t seq,
814{
815 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
816 Ptr<Packet> p = data->Copy();
817 Ipv6Header ipHeader;
818 Icmpv6Echo req(true);
819
820 req.SetId(id);
821 req.SetSeq(seq);
822
824 dst,
825 p->GetSize() + req.GetSerializedSize(),
827 p->AddHeader(req);
828
829 ipHeader.SetSource(src);
830 ipHeader.SetDestination(dst);
831 ipHeader.SetNextHeader(PROT_NUMBER);
832 ipHeader.SetPayloadLength(p->GetSize());
833 ipHeader.SetHopLimit(255);
834
835 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
836}
837
838void
840 const Ipv6Address& src,
841 const Ipv6Address& dst,
842 Ptr<Ipv6Interface> interface)
843{
844 NS_LOG_FUNCTION(this << packet << src << dst << interface);
845 Icmpv6NA naHeader;
847
848 packet->RemoveHeader(naHeader);
849 Ipv6Address target = naHeader.GetIpv6Target();
850
851 Address hardwareAddress;
852 NdiscCache::Entry* entry = nullptr;
853 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
854 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
855
856 /* check if we have something in our cache */
857 entry = cache->Lookup(target);
858
859 if (!entry)
860 {
861 /* ouch!! we might be victim of a DAD */
862
864 bool found = false;
865 uint32_t i = 0;
866 uint32_t nb = interface->GetNAddresses();
867
868 for (i = 0; i < nb; i++)
869 {
870 ifaddr = interface->GetAddress(i);
871 if (ifaddr.GetAddress() == target)
872 {
873 found = true;
874 break;
875 }
876 }
877
878 if (found)
879 {
882 {
884 interface->SetState(ifaddr.GetAddress(), Ipv6InterfaceAddress::INVALID);
885 }
886 }
887
888 /* we have not initiated any communication with the target so... discard the NA */
889 return;
890 }
891
892 /* XXX search all options following the NA header */
893 /* Get LLA */
894 uint8_t type;
895 packet->CopyData(&type, sizeof(type));
896
898 {
899 return;
900 }
901 packet->RemoveHeader(lla);
902
903 /* we receive a NA so stop the probe timer or delay timer if any */
904 entry->StopNudTimer();
905 switch (entry->m_state)
906 {
908 /* we receive a NA so stop the retransmission timer */
909 entry->StopNudTimer();
910
911 if (naHeader.GetFlagS())
912 {
913 /* mark it to reachable */
914 waiting = entry->MarkReachable(lla.GetAddress());
915 entry->StartReachableTimer();
916 /* send out waiting packet */
917 for (auto it = waiting.begin(); it != waiting.end(); it++)
918 {
919 cache->GetInterface()->Send(it->first, it->second, src);
920 }
921 entry->ClearWaitingPacket();
922 }
923 else
924 {
925 entry->MarkStale(lla.GetAddress());
926 }
927
928 if (naHeader.GetFlagR())
929 {
930 entry->SetRouter(true);
931 }
932 return;
933 }
935 /* if the Flag O is clear and mac address differs from the cache */
936 if (!naHeader.GetFlagO() && lla.GetAddress() != entry->GetMacAddress())
937 {
938 entry->MarkStale();
939 return;
940 }
941 else
942 {
943 entry->SetMacAddress(lla.GetAddress());
944 if (naHeader.GetFlagS())
945 {
946 entry->StartReachableTimer();
947 }
948 else if (lla.GetAddress() != entry->GetMacAddress())
949 {
950 entry->MarkStale();
951 }
952 entry->SetRouter(naHeader.GetFlagR());
953 }
954 break;
955 }
958 /* if the Flag O is clear and mac address differs from the cache */
959 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
960 {
961 entry->SetMacAddress(lla.GetAddress());
962 if (naHeader.GetFlagS())
963 {
964 entry->MarkReachable(lla.GetAddress());
965 entry->StartReachableTimer();
966 }
967 else if (lla.GetAddress() != entry->GetMacAddress())
968 {
969 entry->MarkStale();
970 }
971 entry->SetRouter(naHeader.GetFlagR());
972 }
973 return;
974 }
976 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
977 {
978 entry->SetMacAddress(lla.GetAddress());
979 if (naHeader.GetFlagS())
980 {
981 waiting = entry->MarkReachable(lla.GetAddress());
982 for (auto it = waiting.begin(); it != waiting.end(); it++)
983 {
984 cache->GetInterface()->Send(it->first, it->second, src);
985 }
986 entry->ClearWaitingPacket();
987 entry->StartReachableTimer();
988 }
989 else if (lla.GetAddress() != entry->GetMacAddress())
990 {
991 entry->MarkStale();
992 }
993 entry->SetRouter(naHeader.GetFlagR());
994 }
995 return;
996 }
999 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
1000 {
1001 entry->SetMacAddress(lla.GetAddress());
1002 if (lla.GetAddress() != entry->GetMacAddress())
1003 {
1004 entry->MarkStale();
1005 }
1006 entry->SetRouter(naHeader.GetFlagR());
1007 }
1008 return;
1009 }
1010 }
1011 // Silence compiler warning
1012}
1013
1014void
1016 const Ipv6Address& src,
1017 const Ipv6Address& dst,
1018 Ptr<Ipv6Interface> interface)
1019{
1020 NS_LOG_FUNCTION(this << packet << src << dst << interface);
1021 bool hasLla = false;
1022 Ptr<Packet> p = packet->Copy();
1023 Icmpv6OptionLinkLayerAddress llOptionHeader(false);
1024
1025 Icmpv6Redirection redirectionHeader;
1026 p->RemoveHeader(redirectionHeader);
1027
1028 /* little ugly try to find a better way */
1029 uint8_t type;
1030 p->CopyData(&type, sizeof(type));
1032 {
1033 hasLla = true;
1034 p->RemoveHeader(llOptionHeader);
1035 }
1036
1037 Icmpv6OptionRedirected redirectedOptionHeader;
1038 p->RemoveHeader(redirectedOptionHeader);
1039
1040 Ipv6Address redirTarget = redirectionHeader.GetTarget();
1041 Ipv6Address redirDestination = redirectionHeader.GetDestination();
1042
1043 if (hasLla)
1044 {
1045 /* update the cache if needed */
1046 NdiscCache::Entry* entry = nullptr;
1047 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
1048
1049 entry = cache->Lookup(redirTarget);
1050 if (!entry)
1051 {
1052 entry = cache->Add(redirTarget);
1053 /* destination and target different => necessarily a router */
1054 entry->SetRouter(redirTarget != redirDestination);
1055 entry->SetMacAddress(llOptionHeader.GetAddress());
1056 entry->MarkStale();
1057 }
1058 else
1059 {
1060 if (entry->IsIncomplete() || entry->GetMacAddress() != llOptionHeader.GetAddress())
1061 {
1062 /* update entry to STALE */
1063 if (entry->GetMacAddress() != llOptionHeader.GetAddress())
1064 {
1065 entry->SetMacAddress(llOptionHeader.GetAddress());
1066 entry->MarkStale();
1067 }
1068 }
1069 else
1070 {
1071 /* stay unchanged */
1072 }
1073 }
1074 }
1075
1076 /* add redirection in routing table */
1077 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1078
1079 if (redirTarget == redirDestination)
1080 {
1081 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1082 Ipv6Prefix(128),
1083 Ipv6Address("::"),
1084 ipv6->GetInterfaceForAddress(dst));
1085 }
1086 else
1087 {
1088 uint32_t ifIndex = ipv6->GetInterfaceForAddress(dst);
1089 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1090 Ipv6Prefix(128),
1091 redirTarget,
1092 ifIndex);
1093 }
1094}
1095
1096void
1098 const Ipv6Address& src,
1099 const Ipv6Address& dst,
1100 Ptr<Ipv6Interface> interface)
1101{
1102 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1103 Ptr<Packet> pkt = p->Copy();
1104
1106 pkt->RemoveHeader(unreach);
1107
1108 Ipv6Header ipHeader;
1109 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1110 {
1111 pkt->RemoveHeader(ipHeader);
1112 uint8_t payload[8];
1113 pkt->CopyData(payload, 8);
1114 Forward(src, unreach, unreach.GetCode(), ipHeader, payload);
1115 }
1116}
1117
1118void
1120 const Ipv6Address& src,
1121 const Ipv6Address& dst,
1122 Ptr<Ipv6Interface> interface)
1123{
1124 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1125 Ptr<Packet> pkt = p->Copy();
1126
1127 Icmpv6TimeExceeded timeexceeded;
1128 pkt->RemoveHeader(timeexceeded);
1129
1130 Ipv6Header ipHeader;
1131 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1132 {
1133 Ipv6Header ipHeader;
1134 pkt->RemoveHeader(ipHeader);
1135 uint8_t payload[8];
1136 pkt->CopyData(payload, 8);
1137 Forward(src, timeexceeded, timeexceeded.GetCode(), ipHeader, payload);
1138 }
1139}
1140
1141void
1143 const Ipv6Address& src,
1144 const Ipv6Address& dst,
1145 Ptr<Ipv6Interface> interface)
1146{
1147 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1148 Ptr<Packet> pkt = p->Copy();
1149
1150 Icmpv6TooBig tooBig;
1151 pkt->RemoveHeader(tooBig);
1152
1153 Ipv6Header ipHeader;
1154 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1155 {
1156 pkt->RemoveHeader(ipHeader);
1157 uint8_t payload[8];
1158 pkt->CopyData(payload, 8);
1159
1161 ipv6->SetPmtu(ipHeader.GetDestination(), tooBig.GetMtu());
1162
1163 Forward(src, tooBig, tooBig.GetMtu(), ipHeader, payload);
1164 }
1165}
1166
1167void
1169 const Ipv6Address& src,
1170 const Ipv6Address& dst,
1171 Ptr<Ipv6Interface> interface)
1172{
1173 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1174 Ptr<Packet> pkt = p->Copy();
1175
1176 Icmpv6ParameterError paramErr;
1177 pkt->RemoveHeader(paramErr);
1178
1179 Ipv6Header ipHeader;
1180 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1181 {
1182 pkt->RemoveHeader(ipHeader);
1183 uint8_t payload[8];
1184 pkt->CopyData(payload, 8);
1185 Forward(src, paramErr, paramErr.GetCode(), ipHeader, payload);
1186 }
1187}
1188
1189void
1191{
1192 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1195 NS_ASSERT(ipv6);
1196
1197 tag.SetHopLimit(ttl);
1198 packet->AddPacketTag(tag);
1199 m_downTarget(packet, src, dst, PROT_NUMBER, nullptr);
1200}
1201
1202void
1204 Ipv6Address src,
1205 Ipv6Address dst,
1206 uint8_t ttl)
1207{
1208 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1209 SendMessage(packet, src, dst, ttl);
1210}
1211
1212void
1214 Ipv6Address dst,
1215 Icmpv6Header& icmpv6Hdr,
1216 uint8_t ttl)
1217{
1218 NS_LOG_FUNCTION(this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
1220 NS_ASSERT(ipv6 && ipv6->GetRoutingProtocol());
1221 Ipv6Header header;
1224 Ptr<Ipv6Route> route;
1225 Ptr<NetDevice> oif(nullptr); // specify non-zero if bound to a source address
1226
1227 header.SetDestination(dst);
1228 route = ipv6->GetRoutingProtocol()->RouteOutput(packet, header, oif, err);
1229
1230 if (route)
1231 {
1232 NS_LOG_LOGIC("Route exists");
1233 tag.SetHopLimit(ttl);
1234 packet->AddPacketTag(tag);
1235 Ipv6Address src = route->GetSource();
1236
1237 icmpv6Hdr.CalculatePseudoHeaderChecksum(src,
1238 dst,
1239 packet->GetSize() + icmpv6Hdr.GetSerializedSize(),
1240 PROT_NUMBER);
1241 packet->AddHeader(icmpv6Hdr);
1242 m_downTarget(packet, src, dst, PROT_NUMBER, route);
1243 }
1244 else
1245 {
1246 NS_LOG_WARN("drop icmp message");
1247 }
1248}
1249
1250void
1251Icmpv6L4Protocol::SendNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1252{
1253 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << static_cast<uint32_t>(flags));
1255 Icmpv6NA na;
1256 Icmpv6OptionLinkLayerAddress llOption(false, *hardwareAddress); /* not a source link layer */
1257
1258 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1259 na.SetIpv6Target(src);
1260
1261 if (flags & 1)
1262 {
1263 na.SetFlagO(true);
1264 }
1265 if ((flags & 2) && src != Ipv6Address::GetAny())
1266 {
1267 na.SetFlagS(true);
1268 }
1269 if (flags & 4)
1270 {
1271 na.SetFlagR(true);
1272 }
1273
1274 p->AddHeader(llOption);
1275 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1276 p->AddHeader(na);
1277
1278 SendMessage(p, src, dst, 255);
1279}
1280
1281void
1283 Ipv6Address dst,
1284 uint16_t id,
1285 uint16_t seq,
1287{
1288 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
1289 Ptr<Packet> p = data->Copy();
1290 Icmpv6Echo reply(false); /* echo reply */
1291
1292 reply.SetId(id);
1293 reply.SetSeq(seq);
1294
1296 dst,
1297 p->GetSize() + reply.GetSerializedSize(),
1298 PROT_NUMBER);
1299 p->AddHeader(reply);
1300 SendMessage(p, src, dst, 64);
1301}
1302
1303void
1305 Ipv6Address dst,
1306 Ipv6Address target,
1307 Address hardwareAddress)
1308{
1309 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1311 /* Ipv6Header ipHeader; */
1312 Icmpv6NS ns(target);
1314 true,
1315 hardwareAddress); /* we give our mac address in response */
1316
1317 /* if the source is unspec, multicast the NA to all-nodes multicast */
1318 if (src == Ipv6Address::GetAny())
1319 {
1321 }
1322
1323 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1324
1325 p->AddHeader(llOption);
1326 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1327 p->AddHeader(ns);
1328 if (!dst.IsMulticast())
1329 {
1330 SendMessage(p, src, dst, 255);
1331 }
1332 else
1333 {
1334 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1337 this,
1338 p,
1339 src,
1340 dst,
1341 255);
1342 }
1343}
1344
1345void
1347{
1348 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1350 Icmpv6RS rs;
1351
1352 // RFC 4861:
1353 // The link-layer address of the sender MUST NOT be included if the Source Address is the
1354 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
1355 if (!src.IsAny())
1356 {
1357 Icmpv6OptionLinkLayerAddress llOption(true, hardwareAddress);
1358 p->AddHeader(llOption);
1359 }
1360
1361 if (!src.IsAny())
1362 {
1364 if (ipv6->GetInterfaceForAddress(src) == -1)
1365 {
1366 NS_LOG_INFO("Preventing RS from being sent or rescheduled because the source address "
1367 << src << " has been removed");
1368 return;
1369 }
1370 }
1371
1372 NS_LOG_LOGIC("Send RS (from " << src << " to " << dst << ")");
1373
1374 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
1375 p->AddHeader(rs);
1376 if (!dst.IsMulticast())
1377 {
1378 SendMessage(p, src, dst, 255);
1379 }
1380 else
1381 {
1382 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1383 Time rsDelay = Time(0);
1384 Time rsTimeout = Time(0);
1385
1386 if (m_rsRetransmissionCount == 0)
1387 {
1388 // First RS transmission - also add some jitter to desynchronize nodes.
1390 rsTimeout = m_rsInitialRetransmissionTime * (1 + m_rsRetransmissionJitter->GetValue());
1392 }
1393 else
1394 {
1395 // Following RS transmission - adding further jitter is unnecessary.
1396 rsTimeout = m_rsPrevRetransmissionTimeout * (2 + m_rsRetransmissionJitter->GetValue());
1397 if (rsTimeout > m_rsMaxRetransmissionTime)
1398 {
1399 rsTimeout = m_rsMaxRetransmissionTime * (1 + m_rsRetransmissionJitter->GetValue());
1400 }
1401 }
1403 Simulator::Schedule(rsDelay, &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
1406 this,
1407 src,
1408 dst,
1409 hardwareAddress);
1410 }
1411}
1412
1413void
1415{
1416 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1417
1419 {
1420 // Unbound number of retransmissions - just add one to signal that we're in retransmission
1421 // mode.
1423 }
1424 else
1425 {
1428 {
1429 NS_LOG_LOGIC("Maximum number of multicast RS reached, giving up.");
1430 return;
1431 }
1432 }
1433
1436 {
1437 NS_LOG_LOGIC("Maximum RS retransmission time reached, giving up.");
1438 return;
1439 }
1440
1441 SendRS(src, dst, hardwareAddress);
1442}
1443
1444void
1446 Ipv6Address dst,
1447 uint8_t code)
1448{
1449 NS_LOG_FUNCTION(this << malformedPacket << dst << (uint32_t)code);
1450 uint32_t malformedPacketSize = malformedPacket->GetSize();
1452 header.SetCode(code);
1453
1454 NS_LOG_LOGIC("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1455
1456 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1457 if (malformedPacketSize <= 1280 - 48)
1458 {
1459 header.SetPacket(malformedPacket);
1460 SendMessage(malformedPacket, dst, header, 255);
1461 }
1462 else
1463 {
1464 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1465 header.SetPacket(fragment);
1466 SendMessage(fragment, dst, header, 255);
1467 }
1468}
1469
1470void
1472{
1473 NS_LOG_FUNCTION(this << malformedPacket << dst << mtu);
1474 uint32_t malformedPacketSize = malformedPacket->GetSize();
1475 Icmpv6TooBig header;
1476 header.SetCode(0);
1477 header.SetMtu(mtu);
1478
1479 NS_LOG_LOGIC("Send Too Big ( to " << dst << " )");
1480
1481 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1482 if (malformedPacketSize <= 1280 - 48)
1483 {
1484 header.SetPacket(malformedPacket);
1485 SendMessage(malformedPacket, dst, header, 255);
1486 }
1487 else
1488 {
1489 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1490 header.SetPacket(fragment);
1491 SendMessage(fragment, dst, header, 255);
1492 }
1493}
1494
1495void
1497{
1498 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code));
1499 uint32_t malformedPacketSize = malformedPacket->GetSize();
1500 Icmpv6TimeExceeded header;
1501 header.SetCode(code);
1502
1503 NS_LOG_LOGIC("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1504
1505 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1506 if (malformedPacketSize <= 1280 - 48)
1507 {
1508 header.SetPacket(malformedPacket);
1509 SendMessage(malformedPacket, dst, header, 255);
1510 }
1511 else
1512 {
1513 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1514 header.SetPacket(fragment);
1515 SendMessage(fragment, dst, header, 255);
1516 }
1517}
1518
1519void
1521 Ipv6Address dst,
1522 uint8_t code,
1523 uint32_t ptr)
1524{
1525 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code) << ptr);
1526 uint32_t malformedPacketSize = malformedPacket->GetSize();
1527 Icmpv6ParameterError header;
1528 header.SetCode(code);
1529 header.SetPtr(ptr);
1530
1531 NS_LOG_LOGIC("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1532
1533 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1534 if (malformedPacketSize <= 1280 - 48)
1535 {
1536 header.SetPacket(malformedPacket);
1537 SendMessage(malformedPacket, dst, header, 255);
1538 }
1539 else
1540 {
1541 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1542 header.SetPacket(fragment);
1543 SendMessage(fragment, dst, header, 255);
1544 }
1545}
1546
1547void
1549 Ipv6Address src,
1550 Ipv6Address dst,
1551 Ipv6Address redirTarget,
1552 Ipv6Address redirDestination,
1553 Address redirHardwareTarget)
1554{
1555 NS_LOG_FUNCTION(this << redirectedPacket << dst << redirTarget << redirDestination
1556 << redirHardwareTarget);
1557 uint32_t llaSize = 0;
1559 uint32_t redirectedPacketSize = redirectedPacket->GetSize();
1560 Icmpv6OptionLinkLayerAddress llOption(false);
1561
1562 NS_LOG_LOGIC("Send Redirection ( to " << dst << " target " << redirTarget << " destination "
1563 << redirDestination << " )");
1564
1565 Icmpv6OptionRedirected redirectedOptionHeader;
1566
1567 if ((redirectedPacketSize % 8) != 0)
1568 {
1569 Ptr<Packet> pad = Create<Packet>(8 - (redirectedPacketSize % 8));
1570 redirectedPacket->AddAtEnd(pad);
1571 }
1572
1573 if (redirHardwareTarget.GetLength())
1574 {
1575 llOption.SetAddress(redirHardwareTarget);
1576 llaSize = llOption.GetSerializedSize();
1577 }
1578
1579 /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1580 if (redirectedPacketSize <= (1280 - 56 - llaSize))
1581 {
1582 redirectedOptionHeader.SetPacket(redirectedPacket);
1583 }
1584 else
1585 {
1586 Ptr<Packet> fragment = redirectedPacket->CreateFragment(0, 1280 - 56 - llaSize);
1587 redirectedOptionHeader.SetPacket(fragment);
1588 }
1589
1590 p->AddHeader(redirectedOptionHeader);
1591
1592 if (llaSize)
1593 {
1594 p->AddHeader(llOption);
1595 }
1596
1597 Icmpv6Redirection redirectionHeader;
1598 redirectionHeader.SetTarget(redirTarget);
1599 redirectionHeader.SetDestination(redirDestination);
1600 redirectionHeader.CalculatePseudoHeaderChecksum(src,
1601 dst,
1602 p->GetSize() +
1603 redirectionHeader.GetSerializedSize(),
1604 PROT_NUMBER);
1605 p->AddHeader(redirectionHeader);
1606
1607 SendMessage(p, src, dst, 64);
1608}
1609
1611Icmpv6L4Protocol::ForgeNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1612{
1613 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << (uint32_t)flags);
1615 Ipv6Header ipHeader;
1616 Icmpv6NA na;
1618 false,
1619 *hardwareAddress); /* we give our mac address in response */
1620
1621 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << ")");
1622
1623 /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet
1624 * does not pass by Icmpv6L4Protocol::Lookup again */
1625
1626 p->AddHeader(llOption);
1627 na.SetIpv6Target(src);
1628
1629 if (flags & 1)
1630 {
1631 na.SetFlagO(true);
1632 }
1633 if ((flags & 2) && src != Ipv6Address::GetAny())
1634 {
1635 na.SetFlagS(true);
1636 }
1637 if (flags & 4)
1638 {
1639 na.SetFlagR(true);
1640 }
1641
1642 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1643 p->AddHeader(na);
1644
1645 ipHeader.SetSource(src);
1646 ipHeader.SetDestination(dst);
1647 ipHeader.SetNextHeader(PROT_NUMBER);
1648 ipHeader.SetPayloadLength(p->GetSize());
1649 ipHeader.SetHopLimit(255);
1650
1651 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1652}
1653
1656 Ipv6Address dst,
1657 Ipv6Address target,
1658 Address hardwareAddress)
1659{
1660 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1662 Ipv6Header ipHeader;
1663 Icmpv6NS ns(target);
1665 true,
1666 hardwareAddress); /* we give our mac address in response */
1667
1668 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1669
1670 p->AddHeader(llOption);
1671 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1672 p->AddHeader(ns);
1673
1674 ipHeader.SetSource(src);
1675 ipHeader.SetDestination(dst);
1676 ipHeader.SetNextHeader(PROT_NUMBER);
1677 ipHeader.SetPayloadLength(p->GetSize());
1678 ipHeader.SetHopLimit(255);
1679
1680 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1681}
1682
1685{
1686 NS_LOG_FUNCTION(this << device);
1687
1688 for (auto i = m_cacheList.begin(); i != m_cacheList.end(); i++)
1689 {
1690 if ((*i)->GetDevice() == device)
1691 {
1692 return *i;
1693 }
1694 }
1695
1696 NS_ASSERT_MSG(false, "Icmpv6L4Protocol can not find a NDIS Cache for device " << device);
1697 /* quiet compiler */
1698 return nullptr;
1699}
1700
1703{
1704 NS_LOG_FUNCTION(this << device << interface);
1705
1707
1708 cache->SetDevice(device, interface, this);
1709 device->AddLinkChangeCallback(MakeCallback(&NdiscCache::Flush, cache));
1710 m_cacheList.push_back(cache);
1711 return cache;
1712}
1713
1714bool
1716 Ptr<NetDevice> device,
1717 Ptr<NdiscCache> cache,
1718 Address* hardwareDestination)
1719{
1720 NS_LOG_FUNCTION(this << dst << device << cache << hardwareDestination);
1721
1722 if (!cache)
1723 {
1724 /* try to find the cache */
1725 cache = FindCache(device);
1726 }
1727 if (cache)
1728 {
1729 NdiscCache::Entry* entry = cache->Lookup(dst);
1730 if (entry)
1731 {
1732 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1733 entry->IsAutoGenerated())
1734 {
1735 *hardwareDestination = entry->GetMacAddress();
1736 return true;
1737 }
1738 else if (entry->IsStale())
1739 {
1740 entry->StartDelayTimer();
1741 entry->MarkDelay();
1742 *hardwareDestination = entry->GetMacAddress();
1743 return true;
1744 }
1745 }
1746 }
1747 return false;
1748}
1749
1750bool
1752 const Ipv6Header& ipHeader,
1753 Ipv6Address dst,
1754 Ptr<NetDevice> device,
1755 Ptr<NdiscCache> cache,
1756 Address* hardwareDestination)
1757{
1758 NS_LOG_FUNCTION(this << p << ipHeader << dst << device << cache << hardwareDestination);
1759
1760 if (!cache)
1761 {
1762 /* try to find the cache */
1763 cache = FindCache(device);
1764 }
1765 if (!cache)
1766 {
1767 return false;
1768 }
1769
1770 NdiscCache::Entry* entry = cache->Lookup(dst);
1771 if (entry)
1772 {
1773 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1774 entry->IsAutoGenerated())
1775 {
1776 /* XXX check reachability time */
1777 /* send packet */
1778 *hardwareDestination = entry->GetMacAddress();
1779 return true;
1780 }
1781 else if (entry->IsStale())
1782 {
1783 /* start delay timer */
1784 entry->StartDelayTimer();
1785 entry->MarkDelay();
1786 *hardwareDestination = entry->GetMacAddress();
1787 return true;
1788 }
1789 else /* INCOMPLETE or PROBE */
1790 {
1791 /* queue packet */
1793 return false;
1794 }
1795 }
1796 else
1797 {
1798 /* we contact this node for the first time
1799 * add it to the cache and send an NS
1800 */
1801 Ipv6Address addr;
1802 NdiscCache::Entry* entry = cache->Add(dst);
1804 entry->SetRouter(false);
1805
1806 if (dst.IsLinkLocal())
1807 {
1808 addr = cache->GetInterface()->GetLinkLocalAddress().GetAddress();
1809 }
1810 else if (cache->GetInterface()->GetNAddresses() ==
1811 1) /* an interface have at least one address (link-local) */
1812 {
1813 /* try to resolve global address without having global address so return! */
1814 cache->Remove(entry);
1815 return false;
1816 }
1817 else
1818 {
1819 /* find source address that match destination */
1820 addr = cache->GetInterface()->GetAddressMatchingDestination(dst).GetAddress();
1821 }
1822
1823 SendNS(addr, Ipv6Address::MakeSolicitedAddress(dst), dst, cache->GetDevice()->GetAddress());
1824
1825 /* start retransmit timer */
1826 entry->StartRetransmitTimer();
1827 return false;
1828 }
1829
1830 return false;
1831}
1832
1833void
1835{
1836 NS_LOG_FUNCTION(this << interface << addr);
1837
1838 Ipv6InterfaceAddress ifaddr;
1839 bool found = false;
1840 uint32_t i = 0;
1841 uint32_t nb = interface->GetNAddresses();
1842
1843 for (i = 0; i < nb; i++)
1844 {
1845 ifaddr = interface->GetAddress(i);
1846
1847 if (ifaddr.GetAddress() == addr)
1848 {
1849 found = true;
1850 break;
1851 }
1852 }
1853
1854 if (!found)
1855 {
1856 NS_LOG_LOGIC("Can not find the address in the interface.");
1857 }
1858
1859 /* for the moment, this function is always called, if we was victim of a DAD the address is
1860 * INVALID and we do not set it to PREFERRED
1861 */
1862 if (found && ifaddr.GetState() != Ipv6InterfaceAddress::INVALID)
1863 {
1866 NS_LOG_LOGIC("DAD OK, interface in state PREFERRED");
1867
1868 /* send an RS if our interface is not forwarding (router) and if address is a link-local
1869 * ones (because we will send RS with it)
1870 */
1871 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1872
1873 if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())) &&
1874 addr.IsLinkLocal())
1875 {
1876 /* \todo Add random delays before sending RS
1877 * because all nodes start at the same time, there will be many of RS around 1 second of
1878 * simulation time
1879 */
1880 NS_LOG_LOGIC("Scheduled a first Router Solicitation");
1884 this,
1885 ifaddr.GetAddress(),
1887 interface->GetDevice()->GetAddress());
1888 }
1889 else
1890 {
1891 NS_LOG_LOGIC("Did not schedule a Router Solicitation because the interface is in "
1892 "forwarding mode");
1893 }
1894 }
1895}
1896
1897void
1902
1903void
1905{
1906 NS_LOG_FUNCTION(this << &callback);
1907 m_downTarget = callback;
1908}
1909
1916
1919{
1920 NS_LOG_FUNCTION(this);
1921 return m_downTarget;
1922}
1923
1924uint8_t
1929
1930uint8_t
1935
1936Time
1941
1942Time
1947
1948Time
1953
1954Time
1956{
1957 return m_dadTimeout;
1958}
1959
1960} /* 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
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.
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.
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 const 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:560
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
a unique identifier for an interface.
Definition type-id.h:48
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 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
#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:1308
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
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.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeChecker > MakeIntegerChecker()
Definition integer.h:99
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Definition integer.h:35
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition nstime.h:1396
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
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition boolean.h:70
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1416
uint8_t data[writeSize]