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