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 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
254
255 NS_ASSERT(ipv6);
256
257 if (!m_alwaysDad)
258 {
259 return;
260 }
261
262 /** @todo disable multicast loopback to prevent NS probing to be received by the sender */
263
266 target,
267 interface->GetDevice()->GetAddress());
268
269 /* update last packet UID */
270 interface->SetNsDadUid(target, p.first->GetUid());
273 interface,
274 p.first,
275 p.second,
277}
278
281 const Ipv4Header& header,
282 Ptr<Ipv4Interface> interface)
283{
284 NS_LOG_FUNCTION(this << packet << header);
286}
287
290 const Ipv6Header& header,
291 Ptr<Ipv6Interface> interface)
292{
293 NS_LOG_FUNCTION(this << packet << header.GetSource() << header.GetDestination() << interface);
294 Ptr<Packet> p = packet->Copy();
295 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
296
297 /* very ugly! try to find something better in the future */
298 uint8_t type;
299 p->CopyData(&type, sizeof(type));
300
301 switch (type)
302 {
304 if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
305 {
306 HandleRS(p, header.GetSource(), header.GetDestination(), interface);
307 }
308 break;
310 if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
311 {
312 HandleRA(p, header.GetSource(), header.GetDestination(), interface);
313 }
314 break;
316 HandleNS(p, header.GetSource(), header.GetDestination(), interface);
317 break;
319 HandleNA(p, header.GetSource(), header.GetDestination(), interface);
320 break;
322 HandleRedirection(p, header.GetSource(), header.GetDestination(), interface);
323 break;
325 HandleEchoRequest(p, header.GetSource(), header.GetDestination(), interface);
326 break;
328 // EchoReply does not contain any info about L4
329 // so we can not forward it up.
330 /// @todo implement request / reply consistency check.
331 break;
333 HandleDestinationUnreachable(p, header.GetSource(), header.GetDestination(), interface);
334 break;
336 HandlePacketTooBig(p, header.GetSource(), header.GetDestination(), interface);
337 break;
339 HandleTimeExceeded(p, header.GetSource(), header.GetDestination(), interface);
340 break;
342 HandleParameterError(p, header.GetSource(), header.GetDestination(), interface);
343 break;
344 default:
345 NS_LOG_LOGIC("Unknown ICMPv6 message type=" << type);
346 break;
347 }
348
349 return IpL4Protocol::RX_OK;
350}
351
352void
354 Icmpv6Header icmp,
355 uint32_t info,
356 Ipv6Header ipHeader,
357 const uint8_t payload[8])
358{
359 NS_LOG_FUNCTION(this << source << icmp << info << ipHeader << payload);
360
361 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
362
363 /// @todo assuming the ICMP is carrying a extensionless IP packet
364
365 uint8_t nextHeader = ipHeader.GetNextHeader();
366
367 if (nextHeader != Icmpv6L4Protocol::PROT_NUMBER)
368 {
369 Ptr<IpL4Protocol> l4 = ipv6->GetProtocol(nextHeader);
370 if (l4)
371 {
372 l4->ReceiveIcmp(source,
373 ipHeader.GetHopLimit(),
374 icmp.GetType(),
375 icmp.GetCode(),
376 info,
377 ipHeader.GetSource(),
378 ipHeader.GetDestination(),
379 payload);
380 }
381 }
382}
383
384void
386 const Ipv6Address& src,
387 const Ipv6Address& dst,
388 Ptr<Ipv6Interface> interface)
389{
390 NS_LOG_FUNCTION(this << packet << src << dst << interface);
391 Icmpv6Echo request;
392 auto buf = new uint8_t[packet->GetSize()];
393
394 packet->RemoveHeader(request);
395 /* XXX IPv6 extension: obtain a fresh copy of data otherwise it crash... */
396 packet->CopyData(buf, packet->GetSize());
397 Ptr<Packet> p = Create<Packet>(buf, packet->GetSize());
398
399 /* if we send message from ff02::* (link-local multicast), we use our link-local address */
400 SendEchoReply(dst.IsMulticast() ? interface->GetLinkLocalAddress().GetAddress() : dst,
401 src,
402 request.GetId(),
403 request.GetSeq(),
404 p);
405 delete[] buf;
406}
407
408void
410 const Ipv6Address& src,
411 const Ipv6Address& dst,
412 Ptr<Ipv6Interface> interface)
413{
414 NS_LOG_FUNCTION(this << packet << src << dst << interface);
415
416 if (m_handleRsTimeoutEvent.IsPending())
417 {
418 m_handleRsTimeoutEvent.Cancel();
419 // We need to update this in case we need to restart RS retransmissions.
421 }
422
423 Ptr<Packet> p = packet->Copy();
424 Icmpv6RA raHeader;
425 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
427 Icmpv6OptionMtu mtuHdr;
429 bool next = true;
430 bool hasLla = false;
431 bool hasMtu = false;
432 Ipv6Address defaultRouter = Ipv6Address::GetZero();
433
434 p->RemoveHeader(raHeader);
435
436 // If 'M' flag is set, we need to start DHCPv6.
437 if (raHeader.GetFlagM())
438 {
439 if (!m_startDhcpv6.IsNull())
440 {
441 m_startDhcpv6(ipv6->GetInterfaceForDevice(interface->GetDevice()));
442 }
443 }
444
445 if (raHeader.GetLifeTime())
446 {
447 defaultRouter = src;
448 }
449
450 while (next)
451 {
452 uint8_t type = 0;
453 p->CopyData(&type, sizeof(type));
454
455 switch (type)
456 {
458 p->RemoveHeader(prefixHdr);
459 ipv6->AddAutoconfiguredAddress(ipv6->GetInterfaceForDevice(interface->GetDevice()),
460 prefixHdr.GetPrefix(),
461 prefixHdr.GetPrefixLength(),
462 prefixHdr.GetFlags(),
463 prefixHdr.GetValidTime(),
464 prefixHdr.GetPreferredTime(),
465 defaultRouter);
466 break;
468 /* take in account the first MTU option */
469 if (!hasMtu)
470 {
471 p->RemoveHeader(mtuHdr);
472 hasMtu = true;
473 /** @todo case of multiple prefix on single interface */
474 /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
475 }
476 break;
478 /* take in account the first LLA option */
479 if (!hasLla)
480 {
481 p->RemoveHeader(llaHdr);
482 ReceiveLLA(llaHdr, src, dst, interface);
483 hasLla = true;
484 }
485 break;
486 default:
487 /* unknown option, quit */
488 next = false;
489 }
490 }
491}
492
493void
495 const Ipv6Address& src,
496 const Ipv6Address& dst,
497 Ptr<Ipv6Interface> interface)
498{
499 NS_LOG_FUNCTION(this << lla << src << dst << interface);
500 NdiscCache::Entry* entry = nullptr;
501 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
502
503 /* check if we have this address in our cache */
504 entry = cache->Lookup(src);
505
506 if (!entry)
507 {
508 entry = cache->Add(src);
509 entry->SetRouter(true);
510 entry->SetMacAddress(lla.GetAddress());
511 entry->MarkReachable();
512 entry->StartReachableTimer();
513 }
514 else
515 {
516 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
517 switch (entry->m_state)
518 {
520 entry->StopNudTimer();
521 // mark it to reachable
522 waiting = entry->MarkReachable(lla.GetAddress());
523 entry->StartReachableTimer();
524 // send out waiting packet
525 for (auto it = waiting.begin(); it != waiting.end(); it++)
526 {
527 cache->GetInterface()->Send(it->first, it->second, src);
528 }
529 entry->ClearWaitingPacket();
530 return;
531 }
534 if (entry->GetMacAddress() != lla.GetAddress())
535 {
536 entry->SetMacAddress(lla.GetAddress());
537 entry->MarkStale();
538 entry->SetRouter(true);
539 }
540 else
541 {
542 entry->StopNudTimer();
543 waiting = entry->MarkReachable(lla.GetAddress());
544 entry->StartReachableTimer();
545 }
546 return;
547 }
549 if (entry->GetMacAddress() != lla.GetAddress())
550 {
551 entry->SetMacAddress(lla.GetAddress());
552 entry->MarkStale();
553 entry->SetRouter(true);
554 }
555 else
556 {
557 entry->StopNudTimer();
558 waiting = entry->MarkReachable(lla.GetAddress());
559 for (auto it = waiting.begin(); it != waiting.end(); it++)
560 {
561 cache->GetInterface()->Send(it->first, it->second, src);
562 }
563 entry->StartReachableTimer();
564 }
565 return;
566 }
568 if (entry->GetMacAddress() != lla.GetAddress())
569 {
570 entry->SetMacAddress(lla.GetAddress());
571 entry->MarkStale();
572 entry->SetRouter(true);
573 }
574 entry->StartReachableTimer();
575 return;
576 }
579 if (entry->GetMacAddress() != lla.GetAddress())
580 {
581 entry->SetMacAddress(lla.GetAddress());
582 entry->MarkStale();
583 entry->SetRouter(true);
584 }
585 return;
586 }
587 }
588 return; // Silence compiler warning
589 }
590}
591
592void
594 const Ipv6Address& src,
595 const Ipv6Address& dst,
596 Ptr<Ipv6Interface> interface)
597{
598 NS_LOG_FUNCTION(this << packet << src << dst << interface);
599 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
600 Icmpv6RS rsHeader;
601 packet->RemoveHeader(rsHeader);
603 NdiscCache::Entry* entry = nullptr;
604 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
605
606 if (src != Ipv6Address::GetAny())
607 {
608 /* XXX search all options following the RS header */
609 /* test if the next option is SourceLinkLayerAddress */
610 uint8_t type;
611 packet->CopyData(&type, sizeof(type));
612
614 {
615 return;
616 }
617 packet->RemoveHeader(lla);
618 NS_LOG_LOGIC("Cache updated by RS");
619
620 entry = cache->Lookup(src);
621 if (!entry)
622 {
623 entry = cache->Add(src);
624 entry->SetRouter(false);
625 entry->MarkStale(lla.GetAddress());
626 }
627 else if (entry->GetMacAddress() != lla.GetAddress())
628 {
629 entry->MarkStale(lla.GetAddress());
630 }
631 }
632}
633
634void
636 const Ipv6Address& src,
637 const Ipv6Address& dst,
638 Ptr<Ipv6Interface> interface)
639{
640 NS_LOG_FUNCTION(this << packet << src << dst << interface);
641 Icmpv6NS nsHeader("::");
643 uint32_t nb = interface->GetNAddresses();
644 uint32_t i = 0;
645 bool found = false;
646
647 packet->RemoveHeader(nsHeader);
648
649 Ipv6Address target = nsHeader.GetIpv6Target();
650
651 for (i = 0; i < nb; i++)
652 {
653 ifaddr = interface->GetAddress(i);
654
655 if (ifaddr.GetAddress() == target)
656 {
657 found = true;
658 break;
659 }
660 }
661
662 if (!found)
663 {
664 NS_LOG_LOGIC("Not a NS for us");
665 return;
666 }
667
668 if (packet->GetUid() == ifaddr.GetNsDadUid())
669 {
670 /* don't process our own DAD probe */
671 NS_LOG_LOGIC("Hey we receive our DAD probe!");
672 return;
673 }
674
675 NdiscCache::Entry* entry = nullptr;
676 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
677 uint8_t flags = 0;
678
679 /* search all options following the NS header */
680 Icmpv6OptionLinkLayerAddress sllaoHdr(true);
681
682 bool next = true;
683 bool hasSllao = false;
684
685 while (next)
686 {
687 uint8_t type;
688 packet->CopyData(&type, sizeof(type));
689
690 switch (type)
691 {
693 if (!hasSllao)
694 {
695 packet->RemoveHeader(sllaoHdr);
696 hasSllao = true;
697 }
698 break;
699 default:
700 /* unknown option, quit */
701 next = false;
702 }
703 if (packet->GetSize() == 0)
704 {
705 next = false;
706 }
707 }
708
709 Address replyMacAddress;
710
711 if (src != Ipv6Address::GetAny())
712 {
713 entry = cache->Lookup(src);
714 if (!entry)
715 {
716 if (!hasSllao)
717 {
718 NS_LOG_LOGIC("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a "
719 "NCE, discarding.");
720 return;
721 }
722 entry = cache->Add(src);
723 entry->SetRouter(false);
724 entry->MarkStale(sllaoHdr.GetAddress());
725 replyMacAddress = sllaoHdr.GetAddress();
726 }
727 else if (hasSllao && (entry->GetMacAddress() != sllaoHdr.GetAddress()))
728 {
729 entry->MarkStale(sllaoHdr.GetAddress());
730 replyMacAddress = sllaoHdr.GetAddress();
731 }
732 else
733 {
734 replyMacAddress = entry->GetMacAddress();
735 }
736
737 flags = 3; /* S + O flags */
738 }
739 else
740 {
741 /* it's a DAD */
742 flags = 1; /* O flag */
743 replyMacAddress = interface->GetDevice()->GetMulticast(dst);
744 }
745
746 /* send a NA to src */
747 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
748
749 if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
750 {
751 flags += 4; /* R flag */
752 }
753
754 Address hardwareAddress = interface->GetDevice()->GetAddress();
756 target.IsLinkLocal() ? interface->GetLinkLocalAddress().GetAddress() : ifaddr.GetAddress(),
757 src.IsAny() ? dst : src, // DAD replies must go to the multicast group it was sent to.
758 &hardwareAddress,
759 flags);
760
761 // We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not
762 // change it beyond what we did already).
763 Ptr<Packet> pkt = p.first;
764 pkt->AddHeader(p.second);
765 interface->GetDevice()->Send(pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
766}
767
770{
771 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
773 Ipv6Header ipHeader;
774 Icmpv6RS rs;
775
776 NS_LOG_LOGIC("Forge RS (from " << src << " to " << dst << ")");
777 // RFC 4861:
778 // The link-layer address of the sender MUST NOT be included if the Source Address is the
779 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
780 if (!src.IsAny())
781 {
783 true,
784 hardwareAddress); /* we give our mac address in response */
785 p->AddHeader(llOption);
786 }
787
788 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
789 p->AddHeader(rs);
790
791 ipHeader.SetSource(src);
792 ipHeader.SetDestination(dst);
793 ipHeader.SetNextHeader(PROT_NUMBER);
794 ipHeader.SetPayloadLength(p->GetSize());
795 ipHeader.SetHopLimit(255);
796
797 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
798}
799
802 Ipv6Address dst,
803 uint16_t id,
804 uint16_t seq,
806{
807 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
808 Ptr<Packet> p = data->Copy();
809 Ipv6Header ipHeader;
810 Icmpv6Echo req(true);
811
812 req.SetId(id);
813 req.SetSeq(seq);
814
816 dst,
817 p->GetSize() + req.GetSerializedSize(),
819 p->AddHeader(req);
820
821 ipHeader.SetSource(src);
822 ipHeader.SetDestination(dst);
823 ipHeader.SetNextHeader(PROT_NUMBER);
824 ipHeader.SetPayloadLength(p->GetSize());
825 ipHeader.SetHopLimit(255);
826
827 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
828}
829
830void
832 const Ipv6Address& src,
833 const Ipv6Address& dst,
834 Ptr<Ipv6Interface> interface)
835{
836 NS_LOG_FUNCTION(this << packet << src << dst << interface);
837 Icmpv6NA naHeader;
839
840 packet->RemoveHeader(naHeader);
841 Ipv6Address target = naHeader.GetIpv6Target();
842
843 NdiscCache::Entry* entry = nullptr;
844 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
845 std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
846
847 /* check if we have something in our cache */
848 entry = cache->Lookup(target);
849
850 if (!entry)
851 {
852 /* ouch!! we might be victim of a DAD */
853
855 bool found = false;
856 uint32_t i = 0;
857 uint32_t nb = interface->GetNAddresses();
858
859 for (i = 0; i < nb; i++)
860 {
861 ifaddr = interface->GetAddress(i);
862 if (ifaddr.GetAddress() == target)
863 {
864 found = true;
865 break;
866 }
867 }
868
869 if (found)
870 {
873 {
875 interface->SetState(ifaddr.GetAddress(), Ipv6InterfaceAddress::INVALID);
876 }
877 }
878
879 /* we have not initiated any communication with the target so... discard the NA */
880 return;
881 }
882
883 /* XXX search all options following the NA header */
884 /* Get LLA */
885 uint8_t type;
886 packet->CopyData(&type, sizeof(type));
887
889 {
890 return;
891 }
892 packet->RemoveHeader(lla);
893
894 /* we receive a NA so stop the probe timer or delay timer if any */
895 entry->StopNudTimer();
896 switch (entry->m_state)
897 {
899 /* we receive a NA so stop the retransmission timer */
900 entry->StopNudTimer();
901
902 if (naHeader.GetFlagS())
903 {
904 /* mark it to reachable */
905 waiting = entry->MarkReachable(lla.GetAddress());
906 entry->StartReachableTimer();
907 /* send out waiting packet */
908 for (auto it = waiting.begin(); it != waiting.end(); it++)
909 {
910 cache->GetInterface()->Send(it->first, it->second, src);
911 }
912 entry->ClearWaitingPacket();
913 }
914 else
915 {
916 entry->MarkStale(lla.GetAddress());
917 }
918
919 if (naHeader.GetFlagR())
920 {
921 entry->SetRouter(true);
922 }
923 return;
924 }
926 /* if the Flag O is clear and mac address differs from the cache */
927 if (!naHeader.GetFlagO() && lla.GetAddress() != entry->GetMacAddress())
928 {
929 entry->MarkStale();
930 return;
931 }
932 else
933 {
934 entry->SetMacAddress(lla.GetAddress());
935 if (naHeader.GetFlagS())
936 {
937 entry->StartReachableTimer();
938 }
939 else if (lla.GetAddress() != entry->GetMacAddress())
940 {
941 entry->MarkStale();
942 }
943 entry->SetRouter(naHeader.GetFlagR());
944 }
945 break;
946 }
949 /* if the Flag O is clear and mac address differs from the cache */
950 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
951 {
952 entry->SetMacAddress(lla.GetAddress());
953 if (naHeader.GetFlagS())
954 {
955 entry->MarkReachable(lla.GetAddress());
956 entry->StartReachableTimer();
957 }
958 else if (lla.GetAddress() != entry->GetMacAddress())
959 {
960 entry->MarkStale();
961 }
962 entry->SetRouter(naHeader.GetFlagR());
963 }
964 return;
965 }
967 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
968 {
969 entry->SetMacAddress(lla.GetAddress());
970 if (naHeader.GetFlagS())
971 {
972 waiting = entry->MarkReachable(lla.GetAddress());
973 for (auto it = waiting.begin(); it != waiting.end(); it++)
974 {
975 cache->GetInterface()->Send(it->first, it->second, src);
976 }
977 entry->ClearWaitingPacket();
978 entry->StartReachableTimer();
979 }
980 else if (lla.GetAddress() != entry->GetMacAddress())
981 {
982 entry->MarkStale();
983 }
984 entry->SetRouter(naHeader.GetFlagR());
985 }
986 return;
987 }
990 if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
991 {
992 entry->SetMacAddress(lla.GetAddress());
993 if (lla.GetAddress() != entry->GetMacAddress())
994 {
995 entry->MarkStale();
996 }
997 entry->SetRouter(naHeader.GetFlagR());
998 }
999 return;
1000 }
1001 }
1002 // Silence compiler warning
1003}
1004
1005void
1007 const Ipv6Address& src,
1008 const Ipv6Address& dst,
1009 Ptr<Ipv6Interface> interface)
1010{
1011 NS_LOG_FUNCTION(this << packet << src << dst << interface);
1012 bool hasLla = false;
1013 Ptr<Packet> p = packet->Copy();
1014 Icmpv6OptionLinkLayerAddress llOptionHeader(false);
1015
1016 Icmpv6Redirection redirectionHeader;
1017 p->RemoveHeader(redirectionHeader);
1018
1019 /* little ugly try to find a better way */
1020 uint8_t type;
1021 p->CopyData(&type, sizeof(type));
1023 {
1024 hasLla = true;
1025 p->RemoveHeader(llOptionHeader);
1026 }
1027
1028 Icmpv6OptionRedirected redirectedOptionHeader;
1029 p->RemoveHeader(redirectedOptionHeader);
1030
1031 Ipv6Address redirTarget = redirectionHeader.GetTarget();
1032 Ipv6Address redirDestination = redirectionHeader.GetDestination();
1033
1034 if (hasLla)
1035 {
1036 /* update the cache if needed */
1037 NdiscCache::Entry* entry = nullptr;
1038 Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
1039
1040 entry = cache->Lookup(redirTarget);
1041 if (!entry)
1042 {
1043 entry = cache->Add(redirTarget);
1044 /* destination and target different => necessarily a router */
1045 entry->SetRouter(redirTarget != redirDestination);
1046 entry->SetMacAddress(llOptionHeader.GetAddress());
1047 entry->MarkStale();
1048 }
1049 else
1050 {
1051 if (entry->IsIncomplete() || entry->GetMacAddress() != llOptionHeader.GetAddress())
1052 {
1053 /* update entry to STALE */
1054 if (entry->GetMacAddress() != llOptionHeader.GetAddress())
1055 {
1056 entry->SetMacAddress(llOptionHeader.GetAddress());
1057 entry->MarkStale();
1058 }
1059 }
1060 else
1061 {
1062 /* stay unchanged */
1063 }
1064 }
1065 }
1066
1067 /* add redirection in routing table */
1068 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1069
1070 if (redirTarget == redirDestination)
1071 {
1072 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1073 Ipv6Prefix(128),
1074 Ipv6Address("::"),
1075 ipv6->GetInterfaceForAddress(dst));
1076 }
1077 else
1078 {
1079 uint32_t ifIndex = ipv6->GetInterfaceForAddress(dst);
1080 ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1081 Ipv6Prefix(128),
1082 redirTarget,
1083 ifIndex);
1084 }
1085}
1086
1087void
1089 const Ipv6Address& src,
1090 const Ipv6Address& dst,
1091 Ptr<Ipv6Interface> interface)
1092{
1093 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1094 Ptr<Packet> pkt = p->Copy();
1095
1097 pkt->RemoveHeader(unreach);
1098
1099 Ipv6Header ipHeader;
1100 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1101 {
1102 pkt->RemoveHeader(ipHeader);
1103 uint8_t payload[8];
1104 pkt->CopyData(payload, 8);
1105 Forward(src, unreach, unreach.GetCode(), ipHeader, payload);
1106 }
1107}
1108
1109void
1111 const Ipv6Address& src,
1112 const Ipv6Address& dst,
1113 Ptr<Ipv6Interface> interface)
1114{
1115 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1116 Ptr<Packet> pkt = p->Copy();
1117
1118 Icmpv6TimeExceeded timeexceeded;
1119 pkt->RemoveHeader(timeexceeded);
1120
1121 Ipv6Header ipHeader;
1122 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1123 {
1124 Ipv6Header ipHeader;
1125 pkt->RemoveHeader(ipHeader);
1126 uint8_t payload[8];
1127 pkt->CopyData(payload, 8);
1128 Forward(src, timeexceeded, timeexceeded.GetCode(), ipHeader, payload);
1129 }
1130}
1131
1132void
1134 const Ipv6Address& src,
1135 const Ipv6Address& dst,
1136 Ptr<Ipv6Interface> interface)
1137{
1138 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1139 Ptr<Packet> pkt = p->Copy();
1140
1141 Icmpv6TooBig tooBig;
1142 pkt->RemoveHeader(tooBig);
1143
1144 Ipv6Header ipHeader;
1145 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1146 {
1147 pkt->RemoveHeader(ipHeader);
1148 uint8_t payload[8];
1149 pkt->CopyData(payload, 8);
1150
1151 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
1152 ipv6->SetPmtu(ipHeader.GetDestination(), tooBig.GetMtu());
1153
1154 Forward(src, tooBig, tooBig.GetMtu(), ipHeader, payload);
1155 }
1156}
1157
1158void
1160 const Ipv6Address& src,
1161 const Ipv6Address& dst,
1162 Ptr<Ipv6Interface> interface)
1163{
1164 NS_LOG_FUNCTION(this << *p << src << dst << interface);
1165 Ptr<Packet> pkt = p->Copy();
1166
1167 Icmpv6ParameterError paramErr;
1168 pkt->RemoveHeader(paramErr);
1169
1170 Ipv6Header ipHeader;
1171 if (pkt->GetSize() > ipHeader.GetSerializedSize())
1172 {
1173 pkt->RemoveHeader(ipHeader);
1174 uint8_t payload[8];
1175 pkt->CopyData(payload, 8);
1176 Forward(src, paramErr, paramErr.GetCode(), ipHeader, payload);
1177 }
1178}
1179
1180void
1182{
1183 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1184 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
1186 NS_ASSERT(ipv6);
1187
1188 tag.SetHopLimit(ttl);
1189 packet->AddPacketTag(tag);
1190 m_downTarget(packet, src, dst, PROT_NUMBER, nullptr);
1191}
1192
1193void
1195 Ipv6Address src,
1196 Ipv6Address dst,
1197 uint8_t ttl)
1198{
1199 NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1200 SendMessage(packet, src, dst, ttl);
1201}
1202
1203void
1205 Ipv6Address dst,
1206 Icmpv6Header& icmpv6Hdr,
1207 uint8_t ttl)
1208{
1209 NS_LOG_FUNCTION(this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
1210 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
1211 NS_ASSERT(ipv6 && ipv6->GetRoutingProtocol());
1212 Ipv6Header header;
1215 Ptr<Ipv6Route> route;
1216 Ptr<NetDevice> oif(nullptr); // specify non-zero if bound to a source address
1217
1218 header.SetDestination(dst);
1219 route = ipv6->GetRoutingProtocol()->RouteOutput(packet, header, oif, err);
1220
1221 if (route)
1222 {
1223 NS_LOG_LOGIC("Route exists");
1224 tag.SetHopLimit(ttl);
1225 packet->AddPacketTag(tag);
1226 Ipv6Address src = route->GetSource();
1227
1228 icmpv6Hdr.CalculatePseudoHeaderChecksum(src,
1229 dst,
1230 packet->GetSize() + icmpv6Hdr.GetSerializedSize(),
1231 PROT_NUMBER);
1232 packet->AddHeader(icmpv6Hdr);
1233 m_downTarget(packet, src, dst, PROT_NUMBER, route);
1234 }
1235 else
1236 {
1237 NS_LOG_WARN("drop icmp message");
1238 }
1239}
1240
1241void
1242Icmpv6L4Protocol::SendNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1243{
1244 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << static_cast<uint32_t>(flags));
1246 Icmpv6NA na;
1247 Icmpv6OptionLinkLayerAddress llOption(false, *hardwareAddress); /* not a source link layer */
1248
1249 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1250 na.SetIpv6Target(src);
1251
1252 if (flags & 1)
1253 {
1254 na.SetFlagO(true);
1255 }
1256 if ((flags & 2) && src != Ipv6Address::GetAny())
1257 {
1258 na.SetFlagS(true);
1259 }
1260 if (flags & 4)
1261 {
1262 na.SetFlagR(true);
1263 }
1264
1265 p->AddHeader(llOption);
1266 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1267 p->AddHeader(na);
1268
1269 SendMessage(p, src, dst, 255);
1270}
1271
1272void
1274 Ipv6Address dst,
1275 uint16_t id,
1276 uint16_t seq,
1278{
1279 NS_LOG_FUNCTION(this << src << dst << id << seq << data);
1280 Ptr<Packet> p = data->Copy();
1281 Icmpv6Echo reply(false); /* echo reply */
1282
1283 reply.SetId(id);
1284 reply.SetSeq(seq);
1285
1287 dst,
1288 p->GetSize() + reply.GetSerializedSize(),
1289 PROT_NUMBER);
1290 p->AddHeader(reply);
1291 SendMessage(p, src, dst, 64);
1292}
1293
1294void
1296 Ipv6Address dst,
1297 Ipv6Address target,
1298 Address hardwareAddress)
1299{
1300 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1302 /* Ipv6Header ipHeader; */
1303 Icmpv6NS ns(target);
1305 true,
1306 hardwareAddress); /* we give our mac address in response */
1307
1308 /* if the source is unspec, multicast the NA to all-nodes multicast */
1309 if (src == Ipv6Address::GetAny())
1310 {
1312 }
1313
1314 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1315
1316 p->AddHeader(llOption);
1317 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1318 p->AddHeader(ns);
1319 if (!dst.IsMulticast())
1320 {
1321 SendMessage(p, src, dst, 255);
1322 }
1323 else
1324 {
1325 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1328 this,
1329 p,
1330 src,
1331 dst,
1332 255);
1333 }
1334}
1335
1336void
1338{
1339 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1341 Icmpv6RS rs;
1342
1343 // RFC 4861:
1344 // The link-layer address of the sender MUST NOT be included if the Source Address is the
1345 // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
1346 if (!src.IsAny())
1347 {
1348 Icmpv6OptionLinkLayerAddress llOption(true, hardwareAddress);
1349 p->AddHeader(llOption);
1350 }
1351
1352 if (!src.IsAny())
1353 {
1354 Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol>();
1355 if (ipv6->GetInterfaceForAddress(src) == -1)
1356 {
1357 NS_LOG_INFO("Preventing RS from being sent or rescheduled because the source address "
1358 << src << " has been removed");
1359 return;
1360 }
1361 }
1362
1363 NS_LOG_LOGIC("Send RS (from " << src << " to " << dst << ")");
1364
1365 rs.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + rs.GetSerializedSize(), PROT_NUMBER);
1366 p->AddHeader(rs);
1367 if (!dst.IsMulticast())
1368 {
1369 SendMessage(p, src, dst, 255);
1370 }
1371 else
1372 {
1373 NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1374 Time rsDelay = Time(0);
1375 Time rsTimeout = Time(0);
1376
1377 if (m_rsRetransmissionCount == 0)
1378 {
1379 // First RS transmission - also add some jitter to desynchronize nodes.
1381 rsTimeout = m_rsInitialRetransmissionTime * (1 + m_rsRetransmissionJitter->GetValue());
1382 rsDelay = MilliSeconds(m_solicitationJitter->GetValue());
1383 }
1384 else
1385 {
1386 // Following RS transmission - adding further jitter is unnecessary.
1387 rsTimeout = m_rsPrevRetransmissionTimeout * (2 + m_rsRetransmissionJitter->GetValue());
1388 if (rsTimeout > m_rsMaxRetransmissionTime)
1389 {
1390 rsTimeout = m_rsMaxRetransmissionTime * (1 + m_rsRetransmissionJitter->GetValue());
1391 }
1392 }
1394 Simulator::Schedule(rsDelay, &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
1397 this,
1398 src,
1399 dst,
1400 hardwareAddress);
1401 }
1402}
1403
1404void
1406{
1407 NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1408
1410 {
1411 // Unbound number of retransmissions - just add one to signal that we're in retransmission
1412 // mode.
1414 }
1415 else
1416 {
1419 {
1420 NS_LOG_LOGIC("Maximum number of multicast RS reached, giving up.");
1421 return;
1422 }
1423 }
1424
1425 if (!m_rsMaxRetransmissionDuration.IsZero() &&
1427 {
1428 NS_LOG_LOGIC("Maximum RS retransmission time reached, giving up.");
1429 return;
1430 }
1431
1432 SendRS(src, dst, hardwareAddress);
1433}
1434
1435void
1437 Ipv6Address dst,
1438 uint8_t code)
1439{
1440 NS_LOG_FUNCTION(this << malformedPacket << dst << (uint32_t)code);
1441 uint32_t malformedPacketSize = malformedPacket->GetSize();
1443 header.SetCode(code);
1444
1445 NS_LOG_LOGIC("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1446
1447 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1448 if (malformedPacketSize <= 1280 - 48)
1449 {
1450 header.SetPacket(malformedPacket);
1451 SendMessage(malformedPacket, dst, header, 255);
1452 }
1453 else
1454 {
1455 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1456 header.SetPacket(fragment);
1457 SendMessage(fragment, dst, header, 255);
1458 }
1459}
1460
1461void
1463{
1464 NS_LOG_FUNCTION(this << malformedPacket << dst << mtu);
1465 uint32_t malformedPacketSize = malformedPacket->GetSize();
1466 Icmpv6TooBig header;
1467 header.SetCode(0);
1468 header.SetMtu(mtu);
1469
1470 NS_LOG_LOGIC("Send Too Big ( to " << dst << " )");
1471
1472 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1473 if (malformedPacketSize <= 1280 - 48)
1474 {
1475 header.SetPacket(malformedPacket);
1476 SendMessage(malformedPacket, dst, header, 255);
1477 }
1478 else
1479 {
1480 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1481 header.SetPacket(fragment);
1482 SendMessage(fragment, dst, header, 255);
1483 }
1484}
1485
1486void
1488{
1489 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code));
1490 uint32_t malformedPacketSize = malformedPacket->GetSize();
1491 Icmpv6TimeExceeded header;
1492 header.SetCode(code);
1493
1494 NS_LOG_LOGIC("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1495
1496 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1497 if (malformedPacketSize <= 1280 - 48)
1498 {
1499 header.SetPacket(malformedPacket);
1500 SendMessage(malformedPacket, dst, header, 255);
1501 }
1502 else
1503 {
1504 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1505 header.SetPacket(fragment);
1506 SendMessage(fragment, dst, header, 255);
1507 }
1508}
1509
1510void
1512 Ipv6Address dst,
1513 uint8_t code,
1514 uint32_t ptr)
1515{
1516 NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code) << ptr);
1517 uint32_t malformedPacketSize = malformedPacket->GetSize();
1518 Icmpv6ParameterError header;
1519 header.SetCode(code);
1520 header.SetPtr(ptr);
1521
1522 NS_LOG_LOGIC("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1523
1524 /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1525 if (malformedPacketSize <= 1280 - 48)
1526 {
1527 header.SetPacket(malformedPacket);
1528 SendMessage(malformedPacket, dst, header, 255);
1529 }
1530 else
1531 {
1532 Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1533 header.SetPacket(fragment);
1534 SendMessage(fragment, dst, header, 255);
1535 }
1536}
1537
1538void
1540 Ipv6Address src,
1541 Ipv6Address dst,
1542 Ipv6Address redirTarget,
1543 Ipv6Address redirDestination,
1544 Address redirHardwareTarget)
1545{
1546 NS_LOG_FUNCTION(this << redirectedPacket << dst << redirTarget << redirDestination
1547 << redirHardwareTarget);
1548 uint32_t llaSize = 0;
1550 uint32_t redirectedPacketSize = redirectedPacket->GetSize();
1551 Icmpv6OptionLinkLayerAddress llOption(false);
1552
1553 NS_LOG_LOGIC("Send Redirection ( to " << dst << " target " << redirTarget << " destination "
1554 << redirDestination << " )");
1555
1556 Icmpv6OptionRedirected redirectedOptionHeader;
1557
1558 if ((redirectedPacketSize % 8) != 0)
1559 {
1560 Ptr<Packet> pad = Create<Packet>(8 - (redirectedPacketSize % 8));
1561 redirectedPacket->AddAtEnd(pad);
1562 }
1563
1564 if (redirHardwareTarget.GetLength())
1565 {
1566 llOption.SetAddress(redirHardwareTarget);
1567 llaSize = llOption.GetSerializedSize();
1568 }
1569
1570 /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1571 if (redirectedPacketSize <= (1280 - 56 - llaSize))
1572 {
1573 redirectedOptionHeader.SetPacket(redirectedPacket);
1574 }
1575 else
1576 {
1577 Ptr<Packet> fragment = redirectedPacket->CreateFragment(0, 1280 - 56 - llaSize);
1578 redirectedOptionHeader.SetPacket(fragment);
1579 }
1580
1581 p->AddHeader(redirectedOptionHeader);
1582
1583 if (llaSize)
1584 {
1585 p->AddHeader(llOption);
1586 }
1587
1588 Icmpv6Redirection redirectionHeader;
1589 redirectionHeader.SetTarget(redirTarget);
1590 redirectionHeader.SetDestination(redirDestination);
1591 redirectionHeader.CalculatePseudoHeaderChecksum(src,
1592 dst,
1593 p->GetSize() +
1594 redirectionHeader.GetSerializedSize(),
1595 PROT_NUMBER);
1596 p->AddHeader(redirectionHeader);
1597
1598 SendMessage(p, src, dst, 64);
1599}
1600
1602Icmpv6L4Protocol::ForgeNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1603{
1604 NS_LOG_FUNCTION(this << src << dst << hardwareAddress << (uint32_t)flags);
1606 Ipv6Header ipHeader;
1607 Icmpv6NA na;
1609 false,
1610 *hardwareAddress); /* we give our mac address in response */
1611
1612 NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << ")");
1613
1614 /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet
1615 * does not pass by Icmpv6L4Protocol::Lookup again */
1616
1617 p->AddHeader(llOption);
1618 na.SetIpv6Target(src);
1619
1620 if (flags & 1)
1621 {
1622 na.SetFlagO(true);
1623 }
1624 if ((flags & 2) && src != Ipv6Address::GetAny())
1625 {
1626 na.SetFlagS(true);
1627 }
1628 if (flags & 4)
1629 {
1630 na.SetFlagR(true);
1631 }
1632
1633 na.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + na.GetSerializedSize(), PROT_NUMBER);
1634 p->AddHeader(na);
1635
1636 ipHeader.SetSource(src);
1637 ipHeader.SetDestination(dst);
1638 ipHeader.SetNextHeader(PROT_NUMBER);
1639 ipHeader.SetPayloadLength(p->GetSize());
1640 ipHeader.SetHopLimit(255);
1641
1642 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1643}
1644
1647 Ipv6Address dst,
1648 Ipv6Address target,
1649 Address hardwareAddress)
1650{
1651 NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1653 Ipv6Header ipHeader;
1654 Icmpv6NS ns(target);
1656 true,
1657 hardwareAddress); /* we give our mac address in response */
1658
1659 NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1660
1661 p->AddHeader(llOption);
1662 ns.CalculatePseudoHeaderChecksum(src, dst, p->GetSize() + ns.GetSerializedSize(), PROT_NUMBER);
1663 p->AddHeader(ns);
1664
1665 ipHeader.SetSource(src);
1666 ipHeader.SetDestination(dst);
1667 ipHeader.SetNextHeader(PROT_NUMBER);
1668 ipHeader.SetPayloadLength(p->GetSize());
1669 ipHeader.SetHopLimit(255);
1670
1671 return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1672}
1673
1676{
1677 NS_LOG_FUNCTION(this << device);
1678
1679 for (auto i = m_cacheList.begin(); i != m_cacheList.end(); i++)
1680 {
1681 if ((*i)->GetDevice() == device)
1682 {
1683 return *i;
1684 }
1685 }
1686
1687 NS_ASSERT_MSG(false, "Icmpv6L4Protocol can not find a NDIS Cache for device " << device);
1688 /* quiet compiler */
1689 return nullptr;
1690}
1691
1694{
1695 NS_LOG_FUNCTION(this << device << interface);
1696
1698
1699 cache->SetDevice(device, interface, this);
1700 device->AddLinkChangeCallback(MakeCallback(&NdiscCache::Flush, cache));
1701 m_cacheList.push_back(cache);
1702 return cache;
1703}
1704
1705bool
1707 Ptr<NetDevice> device,
1708 Ptr<NdiscCache> cache,
1709 Address* hardwareDestination)
1710{
1711 NS_LOG_FUNCTION(this << dst << device << cache << hardwareDestination);
1712
1713 if (!cache)
1714 {
1715 /* try to find the cache */
1716 cache = FindCache(device);
1717 }
1718 if (cache)
1719 {
1720 NdiscCache::Entry* entry = cache->Lookup(dst);
1721 if (entry)
1722 {
1723 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1724 entry->IsAutoGenerated())
1725 {
1726 *hardwareDestination = entry->GetMacAddress();
1727 return true;
1728 }
1729 else if (entry->IsStale())
1730 {
1731 entry->StartDelayTimer();
1732 entry->MarkDelay();
1733 *hardwareDestination = entry->GetMacAddress();
1734 return true;
1735 }
1736 }
1737 }
1738 return false;
1739}
1740
1741bool
1743 const Ipv6Header& ipHeader,
1744 Ipv6Address dst,
1745 Ptr<NetDevice> device,
1746 Ptr<NdiscCache> cache,
1747 Address* hardwareDestination)
1748{
1749 NS_LOG_FUNCTION(this << p << ipHeader << dst << device << cache << hardwareDestination);
1750
1751 if (!cache)
1752 {
1753 /* try to find the cache */
1754 cache = FindCache(device);
1755 }
1756 if (!cache)
1757 {
1758 return false;
1759 }
1760
1761 NdiscCache::Entry* entry = cache->Lookup(dst);
1762 if (entry)
1763 {
1764 if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1765 entry->IsAutoGenerated())
1766 {
1767 /* XXX check reachability time */
1768 /* send packet */
1769 *hardwareDestination = entry->GetMacAddress();
1770 return true;
1771 }
1772 else if (entry->IsStale())
1773 {
1774 /* start delay timer */
1775 entry->StartDelayTimer();
1776 entry->MarkDelay();
1777 *hardwareDestination = entry->GetMacAddress();
1778 return true;
1779 }
1780 else /* INCOMPLETE or PROBE */
1781 {
1782 /* queue packet */
1784 return false;
1785 }
1786 }
1787 else
1788 {
1789 /* we contact this node for the first time
1790 * add it to the cache and send an NS
1791 */
1792 Ipv6Address addr;
1793 NdiscCache::Entry* entry = cache->Add(dst);
1795 entry->SetRouter(false);
1796
1797 if (dst.IsLinkLocal())
1798 {
1799 addr = cache->GetInterface()->GetLinkLocalAddress().GetAddress();
1800 }
1801 else if (cache->GetInterface()->GetNAddresses() ==
1802 1) /* an interface have at least one address (link-local) */
1803 {
1804 /* try to resolve global address without having global address so return! */
1805 cache->Remove(entry);
1806 return false;
1807 }
1808 else
1809 {
1810 /* find source address that match destination */
1811 addr = cache->GetInterface()->GetAddressMatchingDestination(dst).GetAddress();
1812 }
1813
1814 SendNS(addr, Ipv6Address::MakeSolicitedAddress(dst), dst, cache->GetDevice()->GetAddress());
1815
1816 /* start retransmit timer */
1817 entry->StartRetransmitTimer();
1818 return false;
1819 }
1820
1821 return false;
1822}
1823
1824void
1826{
1827 NS_LOG_FUNCTION(this << interface << addr);
1828
1829 Ipv6InterfaceAddress ifaddr;
1830 bool found = false;
1831 uint32_t i = 0;
1832 uint32_t nb = interface->GetNAddresses();
1833
1834 for (i = 0; i < nb; i++)
1835 {
1836 ifaddr = interface->GetAddress(i);
1837
1838 if (ifaddr.GetAddress() == addr)
1839 {
1840 found = true;
1841 break;
1842 }
1843 }
1844
1845 if (!found)
1846 {
1847 NS_LOG_LOGIC("Can not find the address in the interface.");
1848 }
1849
1850 /* for the moment, this function is always called, if we was victim of a DAD the address is
1851 * INVALID and we do not set it to PREFERRED
1852 */
1853 if (found && ifaddr.GetState() != Ipv6InterfaceAddress::INVALID)
1854 {
1857 NS_LOG_LOGIC("DAD OK, interface in state PREFERRED");
1858
1859 /* send an RS if our interface is not forwarding (router) and if address is a link-local
1860 * ones (because we will send RS with it)
1861 */
1862 Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1863
1864 if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())) &&
1865 addr.IsLinkLocal())
1866 {
1867 /* \todo Add random delays before sending RS
1868 * because all nodes start at the same time, there will be many of RS around 1 second of
1869 * simulation time
1870 */
1871 NS_LOG_LOGIC("Scheduled a first Router Solicitation");
1875 this,
1876 ifaddr.GetAddress(),
1878 interface->GetDevice()->GetAddress());
1879 }
1880 else
1881 {
1882 NS_LOG_LOGIC("Did not schedule a Router Solicitation because the interface is in "
1883 "forwarding mode");
1884 }
1885 }
1886}
1887
1888void
1893
1894void
1896{
1897 NS_LOG_FUNCTION(this << &callback);
1898 m_downTarget = callback;
1899}
1900
1907
1910{
1911 NS_LOG_FUNCTION(this);
1912 return m_downTarget;
1913}
1914
1915uint8_t
1920
1921uint8_t
1926
1927Time
1932
1933Time
1938
1939Time
1944
1945Time
1947{
1948 return m_dadTimeout;
1949}
1950
1951} /* namespace ns3 */
a polymophic address class
Definition address.h:114
uint8_t GetLength() const
Get the length of the underlying address.
Definition address.cc:62
AttributeValue implementation for Boolean.
Definition boolean.h:26
ICMPv6 Error Destination Unreachable header.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
ICMPv6 Echo message.
void SetId(uint16_t id)
Set the ID of the packet.
uint16_t GetId() const
Get the ID of the packet.
void SetSeq(uint16_t seq)
Set the sequence number.
uint32_t GetSerializedSize() const override
Get the serialized size.
uint16_t GetSeq() const
Get the sequence number.
ICMPv6 header.
uint8_t GetCode() const
Get the code field.
uint8_t GetType() const
Get the type field.
void CalculatePseudoHeaderChecksum(Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
Calculate pseudo header checksum for IPv6.
void SetCode(uint8_t code)
Set the code field.
uint32_t GetSerializedSize() const override
Get the serialized size.
@ ICMPV6_ERROR_DESTINATION_UNREACHABLE
An implementation of the ICMPv6 protocol.
Time GetRetransmissionTime() const
Neighbor Discovery node constants: retransmission timer.
int GetProtocolNumber() const override
Get the protocol number.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
void Forward(Ipv6Address source, Icmpv6Header icmp, uint32_t info, Ipv6Header ipHeader, const uint8_t payload[8])
Notify an ICMPv6 reception to upper layers (if requested).
void ReceiveLLA(Icmpv6OptionLinkLayerAddress lla, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Link layer address option processing.
void SendErrorTimeExceeded(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code)
Send an error Time Exceeded.
IpL4Protocol::RxStatus Receive(Ptr< Packet > p, const Ipv4Header &header, Ptr< Ipv4Interface > interface) override
Receive method.
void DoDispose() override
Dispose this object.
void SendErrorTooBig(Ptr< Packet > malformedPacket, Ipv6Address dst, uint32_t mtu)
Send an error Too Big.
uint8_t m_maxMulticastSolicit
Neighbor Discovery node constants: max multicast solicitations.
void NotifyNewAggregate() override
This method is called by AggregateObject and completes the aggregation by setting the node in the ICM...
Time m_reachableTime
Neighbor Discovery node constants: reachable time.
NdiscCache::Ipv6PayloadHeaderPair ForgeEchoRequest(Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr< Packet > data)
Forge an Echo Request.
Time m_rsMaxRetransmissionTime
Maximum time between multicast RS retransmissions [RFC 7559].
uint32_t m_rsMaxRetransmissionCount
Maximum number of multicast RS retransmissions [RFC 7559].
ns3::TracedCallback< const Ipv6Address & > m_dadSuccessAddressTrace
The trace fired when a DAD completes and no duplicate address has been detected.
virtual Ptr< NdiscCache > CreateCache(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface)
Create a neighbor cache.
~Icmpv6L4Protocol() override
Destructor.
IpL4Protocol::DownTargetCallback6 GetDownTarget6() const override
This method allows a caller to get the current down target callback set for this L4 protocol (IPv6 ca...
void SetDownTarget6(IpL4Protocol::DownTargetCallback6 cb) override
This method allows a caller to set the current down target callback set for this L4 protocol (IPv6 ca...
uint32_t m_rsRetransmissionCount
Multicast RS retransmissions counter [RFC 7559].
void DelayedSendMessage(Ptr< Packet > packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
Helper function used during delayed solicitation.
Ptr< Node > GetNode()
Get the node.
void HandleTimeExceeded(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Time Exceeded method.
void HandleDestinationUnreachable(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Destination Unreachable method.
void HandlePacketTooBig(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Packet Too Big method.
Callback< void, uint32_t > m_startDhcpv6
The DHCPv6 callback when the M flag is set in a Router Advertisement.
Ptr< UniformRandomVariable > m_rsRetransmissionJitter
Random jitter for RS retransmissions.
bool IsAlwaysDad() const
Is the node must do DAD.
void HandleRA(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Router Advertisement method.
void SetDownTarget(IpL4Protocol::DownTargetCallback cb) override
This method allows a caller to set the current down target callback set for this L4 protocol (IPv4 ca...
void SendErrorParameterError(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
Send an error Parameter Error.
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:409
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:518
virtual void DoDispose()
Destructor implementation.
Definition object.cc:430
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition socket.h:73
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition socket.h:1162
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition socket.cc:657
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
AttributeValue implementation for Time.
Definition nstime.h:1483
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeIntegerChecker()
Definition integer.h:99
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition integer.h:35
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:250
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:273
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1484
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1504
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:690
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:253
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:267
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:454
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1398
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint8_t data[writeSize]