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