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