A Discrete-Event Network Simulator
API
icmpv6-l4-protocol.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2009 Strasbourg University
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
18  * David Gross <gdavid.devel@gmail.com>
19  * Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
20  * Tommaso Pecorella <tommaso.pecorella@unifi.it>
21  */
22 
23 #include "icmpv6-l4-protocol.h"
24 
25 #include "ipv6-interface.h"
26 #include "ipv6-l3-protocol.h"
27 
28 #include "ns3/assert.h"
29 #include "ns3/boolean.h"
30 #include "ns3/double.h"
31 #include "ns3/integer.h"
32 #include "ns3/ipv6-route.h"
33 #include "ns3/ipv6-routing-protocol.h"
34 #include "ns3/log.h"
35 #include "ns3/node.h"
36 #include "ns3/packet.h"
37 #include "ns3/pointer.h"
38 #include "ns3/string.h"
39 #include "ns3/uinteger.h"
40 
41 namespace ns3
42 {
43 
44 NS_LOG_COMPONENT_DEFINE("Icmpv6L4Protocol");
45 
46 NS_OBJECT_ENSURE_REGISTERED(Icmpv6L4Protocol);
47 
48 const uint8_t Icmpv6L4Protocol::PROT_NUMBER = 58;
49 
50 // const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERT_INTERVAL = 16; // max initial RA initial
51 // interval. const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERTISEMENTS = 3; // max initial RA
52 // transmission. const uint8_t Icmpv6L4Protocol::MAX_FINAL_RTR_ADVERTISEMENTS = 3; // max final
53 // RA transmission. const uint8_t Icmpv6L4Protocol::MIN_DELAY_BETWEEN_RAS = 3; // min
54 // delay between RA. const uint32_t Icmpv6L4Protocol::MAX_RA_DELAY_TIME = 500; //
55 // millisecond - max delay between RA.
56 
57 // const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATION_DELAY = 1; // max RS delay.
58 // const uint8_t Icmpv6L4Protocol::RTR_SOLICITATION_INTERVAL = 4; // RS interval.
59 // const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATIONS = 3; // max RS transmission.
60 
61 // const uint8_t Icmpv6L4Protocol::MAX_ANYCAST_DELAY_TIME = 1; // max anycast delay.
62 // const uint8_t Icmpv6L4Protocol::MAX_NEIGHBOR_ADVERTISEMENT = 3; // max NA transmission.
63 
64 // const double Icmpv6L4Protocol::MIN_RANDOM_FACTOR = 0.5; // min random factor.
65 // const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5; // max random factor.
66 
67 TypeId
69 {
70  static TypeId tid =
71  TypeId("ns3::Icmpv6L4Protocol")
73  .SetGroupName("Internet")
74  .AddConstructor<Icmpv6L4Protocol>()
75  .AddAttribute("DAD",
76  "Always do DAD check.",
77  BooleanValue(true),
80  .AddAttribute(
81  "SolicitationJitter",
82  "The jitter in ms a node is allowed to wait before sending any solicitation. Some "
83  "jitter aims to prevent collisions. By default, the model will wait for a duration "
84  "in ms defined by a uniform random-variable between 0 and SolicitationJitter",
85  StringValue("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
87  MakePointerChecker<RandomVariableStream>())
88  .AddAttribute("MaxMulticastSolicit",
89  "Neighbor Discovery node constants: max multicast solicitations.",
90  IntegerValue(3),
92  MakeIntegerChecker<uint8_t>())
93  .AddAttribute("MaxUnicastSolicit",
94  "Neighbor Discovery node constants: max unicast solicitations.",
95  IntegerValue(3),
97  MakeIntegerChecker<uint8_t>())
98  .AddAttribute("ReachableTime",
99  "Neighbor Discovery node constants: reachable time.",
100  TimeValue(Seconds(30)),
102  MakeTimeChecker())
103  .AddAttribute("RetransmissionTime",
104  "Neighbor Discovery node constants: retransmission timer.",
105  TimeValue(Seconds(1)),
107  MakeTimeChecker())
108  .AddAttribute("DelayFirstProbe",
109  "Neighbor Discovery node constants: delay for the first probe.",
110  TimeValue(Seconds(5)),
112  MakeTimeChecker())
113  .AddAttribute("DadTimeout",
114  "Duplicate Address Detection (DAD) timeout",
115  TimeValue(Seconds(1)),
117  MakeTimeChecker())
118  .AddAttribute("RsRetransmissionJitter",
119  "Multicast RS retransmission randomization quantity",
120  StringValue("ns3::UniformRandomVariable[Min=-0.1|Max=0.1]"),
122  MakePointerChecker<RandomVariableStream>())
123  .AddAttribute("RsInitialRetransmissionTime",
124  "Multicast RS initial retransmission time.",
125  TimeValue(Seconds(4)),
127  MakeTimeChecker())
128  .AddAttribute("RsMaxRetransmissionTime",
129  "Multicast RS maximum retransmission time (0 means unbound).",
130  TimeValue(Seconds(3600)),
132  MakeTimeChecker())
133  .AddAttribute(
134  "RsMaxRetransmissionCount",
135  "Multicast RS maximum retransmission count (0 means unbound). "
136  "Note: RFC 7559 suggest a zero value (infinite). The default is 4 to avoid "
137  "non-terminating simulations.",
138  UintegerValue(4),
140  MakeUintegerChecker<uint32_t>())
141  .AddAttribute("RsMaxRetransmissionDuration",
142  "Multicast RS maximum retransmission duration (0 means unbound).",
143  TimeValue(Seconds(0)),
145  MakeTimeChecker());
146  return tid;
147 }
148 
149 TypeId
151 {
152  NS_LOG_FUNCTION(this);
154 }
155 
157  : m_node(nullptr)
158 {
159  NS_LOG_FUNCTION(this);
160 }
161 
163 {
164  NS_LOG_FUNCTION(this);
165 }
166 
167 void
169 {
170  NS_LOG_FUNCTION(this);
171  for (CacheList::const_iterator it = m_cacheList.begin(); it != m_cacheList.end(); it++)
172  {
173  Ptr<NdiscCache> cache = *it;
174  cache->Dispose();
175  cache = nullptr;
176  }
177  m_cacheList.clear();
179 
180  m_node = nullptr;
182 }
183 
184 int64_t
186 {
187  NS_LOG_FUNCTION(this << stream);
189  m_rsRetransmissionJitter->SetStream(stream + 1);
190  return 2;
191 }
192 
193 void
195 {
196  NS_LOG_FUNCTION(this);
197  if (!m_node)
198  {
199  Ptr<Node> node = this->GetObject<Node>();
200  if (node)
201  {
202  Ptr<Ipv6> ipv6 = this->GetObject<Ipv6>();
203  if (ipv6 && m_downTarget.IsNull())
204  {
205  SetNode(node);
206  ipv6->Insert(this);
208  }
209  }
210  }
212 }
213 
214 void
216 {
217  NS_LOG_FUNCTION(this << node);
218  m_node = node;
219 }
220 
221 Ptr<Node>
223 {
224  NS_LOG_FUNCTION(this);
225  return m_node;
226 }
227 
228 uint16_t
230 {
232  return PROT_NUMBER;
233 }
234 
235 int
237 {
238  NS_LOG_FUNCTION(this);
239  return PROT_NUMBER;
240 }
241 
242 int
244 {
245  NS_LOG_FUNCTION(this);
246  return 1;
247 }
248 
249 bool
251 {
252  NS_LOG_FUNCTION(this);
253  return m_alwaysDad;
254 }
255 
256 void
258 {
259  NS_LOG_FUNCTION(this << target << interface);
260  Ipv6Address addr;
262 
263  NS_ASSERT(ipv6);
264 
265  if (!m_alwaysDad)
266  {
267  return;
268  }
269 
274  target,
275  interface->GetDevice()->GetAddress());
276 
277  /* update last packet UID */
278  interface->SetNsDadUid(target, p.first->GetUid());
281  interface,
282  p.first,
283  p.second,
285 }
286 
289  const Ipv4Header& header,
290  Ptr<Ipv4Interface> interface)
291 {
292  NS_LOG_FUNCTION(this << packet << header);
294 }
295 
297 Icmpv6L4Protocol::Receive(Ptr<Packet> packet,
298  const Ipv6Header& header,
299  Ptr<Ipv6Interface> interface)
300 {
301  NS_LOG_FUNCTION(this << packet << header.GetSource() << header.GetDestination() << interface);
302  Ptr<Packet> p = packet->Copy();
303  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
304 
305  /* very ugly! try to find something better in the future */
306  uint8_t type;
307  p->CopyData(&type, sizeof(type));
308 
309  switch (type)
310  {
312  if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
313  {
314  HandleRS(p, header.GetSource(), header.GetDestination(), interface);
315  }
316  break;
318  if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
319  {
320  HandleRA(p, header.GetSource(), header.GetDestination(), interface);
321  }
322  break;
324  HandleNS(p, header.GetSource(), header.GetDestination(), interface);
325  break;
327  HandleNA(p, header.GetSource(), header.GetDestination(), interface);
328  break;
330  HandleRedirection(p, header.GetSource(), header.GetDestination(), interface);
331  break;
333  HandleEchoRequest(p, header.GetSource(), header.GetDestination(), interface);
334  break;
336  // EchoReply does not contain any info about L4
337  // so we can not forward it up.
339  break;
341  HandleDestinationUnreachable(p, header.GetSource(), header.GetDestination(), interface);
342  break;
344  HandlePacketTooBig(p, header.GetSource(), header.GetDestination(), interface);
345  break;
347  HandleTimeExceeded(p, header.GetSource(), header.GetDestination(), interface);
348  break;
350  HandleParameterError(p, header.GetSource(), header.GetDestination(), interface);
351  break;
352  default:
353  NS_LOG_LOGIC("Unknown ICMPv6 message type=" << type);
354  break;
355  }
356 
357  return IpL4Protocol::RX_OK;
358 }
359 
360 void
362  Icmpv6Header icmp,
363  uint32_t info,
364  Ipv6Header ipHeader,
365  const uint8_t payload[8])
366 {
367  NS_LOG_FUNCTION(this << source << icmp << info << ipHeader << payload);
368 
370 
372 
373  uint8_t nextHeader = ipHeader.GetNextHeader();
374 
375  if (nextHeader != Icmpv6L4Protocol::PROT_NUMBER)
376  {
377  Ptr<IpL4Protocol> l4 = ipv6->GetProtocol(nextHeader);
378  if (l4)
379  {
380  l4->ReceiveIcmp(source,
381  ipHeader.GetHopLimit(),
382  icmp.GetType(),
383  icmp.GetCode(),
384  info,
385  ipHeader.GetSource(),
386  ipHeader.GetDestination(),
387  payload);
388  }
389  }
390 }
391 
392 void
394  const Ipv6Address& src,
395  const Ipv6Address& dst,
396  Ptr<Ipv6Interface> interface)
397 {
398  NS_LOG_FUNCTION(this << packet << src << dst << interface);
399  Icmpv6Echo request;
400  uint8_t* buf = new uint8_t[packet->GetSize()];
401 
402  packet->RemoveHeader(request);
403  /* XXX IPv6 extension: obtain a fresh copy of data otherwise it crash... */
404  packet->CopyData(buf, packet->GetSize());
405  Ptr<Packet> p = Create<Packet>(buf, packet->GetSize());
406 
407  /* if we send message from ff02::* (link-local multicast), we use our link-local address */
408  SendEchoReply(dst.IsMulticast() ? interface->GetLinkLocalAddress().GetAddress() : dst,
409  src,
410  request.GetId(),
411  request.GetSeq(),
412  p);
413  delete[] buf;
414 }
415 
416 void
418  const Ipv6Address& src,
419  const Ipv6Address& dst,
420  Ptr<Ipv6Interface> interface)
421 {
422  NS_LOG_FUNCTION(this << packet << src << dst << interface);
423 
425  {
427  // We need to update this in case we need to restart RS retransmissions.
429  }
430 
431  Ptr<Packet> p = packet->Copy();
432  Icmpv6RA raHeader;
435  Icmpv6OptionMtu mtuHdr;
437  bool next = true;
438  bool hasLla = false;
439  bool hasMtu = false;
440  Ipv6Address defaultRouter = Ipv6Address::GetZero();
441 
442  p->RemoveHeader(raHeader);
443 
444  if (raHeader.GetLifeTime())
445  {
446  defaultRouter = src;
447  }
448 
449  while (next == true)
450  {
451  uint8_t type = 0;
452  p->CopyData(&type, sizeof(type));
453 
454  switch (type)
455  {
457  p->RemoveHeader(prefixHdr);
458  ipv6->AddAutoconfiguredAddress(ipv6->GetInterfaceForDevice(interface->GetDevice()),
459  prefixHdr.GetPrefix(),
460  prefixHdr.GetPrefixLength(),
461  prefixHdr.GetFlags(),
462  prefixHdr.GetValidTime(),
463  prefixHdr.GetPreferredTime(),
464  defaultRouter);
465  break;
467  /* take in account the first MTU option */
468  if (!hasMtu)
469  {
470  p->RemoveHeader(mtuHdr);
471  hasMtu = true;
473  /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
474  }
475  break;
477  /* take in account the first LLA option */
478  if (!hasLla)
479  {
480  p->RemoveHeader(llaHdr);
481  ReceiveLLA(llaHdr, src, dst, interface);
482  hasLla = true;
483  }
484  break;
485  default:
486  /* unknown option, quit */
487  next = false;
488  }
489  }
490 }
491 
492 void
494  const Ipv6Address& src,
495  const Ipv6Address& dst,
496  Ptr<Ipv6Interface> interface)
497 {
498  NS_LOG_FUNCTION(this << lla << src << dst << interface);
499  Address hardwareAddress;
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 (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin();
526  it != waiting.end();
527  it++)
528  {
529  cache->GetInterface()->Send(it->first, it->second, src);
530  }
531  entry->ClearWaitingPacket();
532  return;
533  }
536  if (entry->GetMacAddress() != lla.GetAddress())
537  {
538  entry->SetMacAddress(lla.GetAddress());
539  entry->MarkStale();
540  entry->SetRouter(true);
541  }
542  else
543  {
544  entry->StopNudTimer();
545  waiting = entry->MarkReachable(lla.GetAddress());
546  entry->StartReachableTimer();
547  }
548  return;
549  }
551  if (entry->GetMacAddress() != lla.GetAddress())
552  {
553  entry->SetMacAddress(lla.GetAddress());
554  entry->MarkStale();
555  entry->SetRouter(true);
556  }
557  else
558  {
559  entry->StopNudTimer();
560  waiting = entry->MarkReachable(lla.GetAddress());
561  for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it =
562  waiting.begin();
563  it != waiting.end();
564  it++)
565  {
566  cache->GetInterface()->Send(it->first, it->second, src);
567  }
568  entry->StartReachableTimer();
569  }
570  return;
571  }
573  if (entry->GetMacAddress() != lla.GetAddress())
574  {
575  entry->SetMacAddress(lla.GetAddress());
576  entry->MarkStale();
577  entry->SetRouter(true);
578  }
579  entry->StartReachableTimer();
580  return;
581  }
584  if (entry->GetMacAddress() != lla.GetAddress())
585  {
586  entry->SetMacAddress(lla.GetAddress());
587  entry->MarkStale();
588  entry->SetRouter(true);
589  }
590  return;
591  }
592  }
593  return; // Silence compiler warning
594  }
595 }
596 
597 void
599  const Ipv6Address& src,
600  const Ipv6Address& dst,
601  Ptr<Ipv6Interface> interface)
602 {
603  NS_LOG_FUNCTION(this << packet << src << dst << interface);
605  Icmpv6RS rsHeader;
606  packet->RemoveHeader(rsHeader);
607  Address hardwareAddress;
609  NdiscCache::Entry* entry = nullptr;
610  Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
611 
612  if (src != Ipv6Address::GetAny())
613  {
614  /* XXX search all options following the RS header */
615  /* test if the next option is SourceLinkLayerAddress */
616  uint8_t type;
617  packet->CopyData(&type, sizeof(type));
618 
620  {
621  return;
622  }
623  packet->RemoveHeader(lla);
624  NS_LOG_LOGIC("Cache updated by RS");
625 
626  entry = cache->Lookup(src);
627  if (!entry)
628  {
629  entry = cache->Add(src);
630  entry->SetRouter(false);
631  entry->MarkStale(lla.GetAddress());
632  }
633  else if (entry->GetMacAddress() != lla.GetAddress())
634  {
635  entry->MarkStale(lla.GetAddress());
636  }
637  }
638 }
639 
640 void
642  const Ipv6Address& src,
643  const Ipv6Address& dst,
644  Ptr<Ipv6Interface> interface)
645 {
646  NS_LOG_FUNCTION(this << packet << src << dst << interface);
647  Icmpv6NS nsHeader("::");
648  Ipv6InterfaceAddress ifaddr;
649  uint32_t nb = interface->GetNAddresses();
650  uint32_t i = 0;
651  bool found = false;
652 
653  packet->RemoveHeader(nsHeader);
654 
655  Ipv6Address target = nsHeader.GetIpv6Target();
656 
657  for (i = 0; i < nb; i++)
658  {
659  ifaddr = interface->GetAddress(i);
660 
661  if (ifaddr.GetAddress() == target)
662  {
663  found = true;
664  break;
665  }
666  }
667 
668  if (!found)
669  {
670  NS_LOG_LOGIC("Not a NS for us");
671  return;
672  }
673 
674  if (packet->GetUid() == ifaddr.GetNsDadUid())
675  {
676  /* don't process our own DAD probe */
677  NS_LOG_LOGIC("Hey we receive our DAD probe!");
678  return;
679  }
680 
681  NdiscCache::Entry* entry = nullptr;
682  Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
683  uint8_t flags = 0;
684 
685  /* search all options following the NS header */
686  Icmpv6OptionLinkLayerAddress sllaoHdr(true);
687 
688  bool next = true;
689  bool hasSllao = false;
690 
691  while (next == true)
692  {
693  uint8_t type;
694  packet->CopyData(&type, sizeof(type));
695 
696  switch (type)
697  {
699  if (!hasSllao)
700  {
701  packet->RemoveHeader(sllaoHdr);
702  hasSllao = true;
703  }
704  break;
705  default:
706  /* unknown option, quit */
707  next = false;
708  }
709  if (packet->GetSize() == 0)
710  {
711  next = false;
712  }
713  }
714 
715  Address replyMacAddress;
716 
717  if (src != Ipv6Address::GetAny())
718  {
719  entry = cache->Lookup(src);
720  if (!entry)
721  {
722  if (!hasSllao)
723  {
724  NS_LOG_LOGIC("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a "
725  "NCE, discarding.");
726  return;
727  }
728  entry = cache->Add(src);
729  entry->SetRouter(false);
730  entry->MarkStale(sllaoHdr.GetAddress());
731  replyMacAddress = sllaoHdr.GetAddress();
732  }
733  else if (hasSllao && (entry->GetMacAddress() != sllaoHdr.GetAddress()))
734  {
735  entry->MarkStale(sllaoHdr.GetAddress());
736  replyMacAddress = sllaoHdr.GetAddress();
737  }
738  else
739  {
740  replyMacAddress = entry->GetMacAddress();
741  }
742 
743  flags = 3; /* S + O flags */
744  }
745  else
746  {
747  /* it's a DAD */
748  flags = 1; /* O flag */
749  replyMacAddress = interface->GetDevice()->GetMulticast(dst);
750  }
751 
752  /* send a NA to src */
754 
755  if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
756  {
757  flags += 4; /* R flag */
758  }
759 
760  Address hardwareAddress = interface->GetDevice()->GetAddress();
762  target.IsLinkLocal() ? interface->GetLinkLocalAddress().GetAddress() : ifaddr.GetAddress(),
763  src.IsAny() ? dst : src, // DAD replies must go to the multicast group it was sent to.
764  &hardwareAddress,
765  flags);
766 
767  // We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not
768  // change it beyond what we did already).
769  Ptr<Packet> pkt = p.first;
770  pkt->AddHeader(p.second);
771  interface->GetDevice()->Send(pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
772 }
773 
776 {
777  NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
778  Ptr<Packet> p = Create<Packet>();
779  Ipv6Header ipHeader;
780  Icmpv6RS rs;
781 
782  NS_LOG_LOGIC("Forge RS (from " << src << " to " << dst << ")");
783  // RFC 4861:
784  // The link-layer address of the sender MUST NOT be included if the Source Address is the
785  // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
786  if (!src.IsAny())
787  {
789  1,
790  hardwareAddress); /* we give our mac address in response */
791  p->AddHeader(llOption);
792  }
793 
795  p->AddHeader(rs);
796 
797  ipHeader.SetSource(src);
798  ipHeader.SetDestination(dst);
799  ipHeader.SetNextHeader(PROT_NUMBER);
800  ipHeader.SetPayloadLength(p->GetSize());
801  ipHeader.SetHopLimit(255);
802 
803  return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
804 }
805 
808  Ipv6Address dst,
809  uint16_t id,
810  uint16_t seq,
812 {
813  NS_LOG_FUNCTION(this << src << dst << id << seq << data);
814  Ptr<Packet> p = data->Copy();
815  Ipv6Header ipHeader;
816  Icmpv6Echo req(1);
817 
818  req.SetId(id);
819  req.SetSeq(seq);
820 
822  dst,
823  p->GetSize() + req.GetSerializedSize(),
824  PROT_NUMBER);
825  p->AddHeader(req);
826 
827  ipHeader.SetSource(src);
828  ipHeader.SetDestination(dst);
829  ipHeader.SetNextHeader(PROT_NUMBER);
830  ipHeader.SetPayloadLength(p->GetSize());
831  ipHeader.SetHopLimit(255);
832 
833  return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
834 }
835 
836 void
838  const Ipv6Address& src,
839  const Ipv6Address& dst,
840  Ptr<Ipv6Interface> interface)
841 {
842  NS_LOG_FUNCTION(this << packet << src << dst << interface);
843  Icmpv6NA naHeader;
845 
846  packet->RemoveHeader(naHeader);
847  Ipv6Address target = naHeader.GetIpv6Target();
848 
849  Address hardwareAddress;
850  NdiscCache::Entry* entry = nullptr;
851  Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
852  std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
853 
854  /* check if we have something in our cache */
855  entry = cache->Lookup(target);
856 
857  if (!entry)
858  {
859  /* ouch!! we might be victim of a DAD */
860 
861  Ipv6InterfaceAddress ifaddr;
862  bool found = false;
863  uint32_t i = 0;
864  uint32_t nb = interface->GetNAddresses();
865 
866  for (i = 0; i < nb; i++)
867  {
868  ifaddr = interface->GetAddress(i);
869  if (ifaddr.GetAddress() == target)
870  {
871  found = true;
872  break;
873  }
874  }
875 
876  if (found)
877  {
878  if (ifaddr.GetState() == Ipv6InterfaceAddress::TENTATIVE ||
880  {
881  interface->SetState(ifaddr.GetAddress(), Ipv6InterfaceAddress::INVALID);
882  }
883  }
884 
885  /* we have not initiated any communication with the target so... discard the NA */
886  return;
887  }
888 
889  /* XXX search all options following the NA header */
890  /* Get LLA */
891  uint8_t type;
892  packet->CopyData(&type, sizeof(type));
893 
895  {
896  return;
897  }
898  packet->RemoveHeader(lla);
899 
900  /* we receive a NA so stop the probe timer or delay timer if any */
901  entry->StopNudTimer();
902  switch (entry->m_state)
903  {
905  /* we receive a NA so stop the retransmission timer */
906  entry->StopNudTimer();
907 
908  if (naHeader.GetFlagS())
909  {
910  /* mark it to reachable */
911  waiting = entry->MarkReachable(lla.GetAddress());
912  entry->StartReachableTimer();
913  /* send out waiting packet */
914  for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin();
915  it != waiting.end();
916  it++)
917  {
918  cache->GetInterface()->Send(it->first, it->second, src);
919  }
920  entry->ClearWaitingPacket();
921  }
922  else
923  {
924  entry->MarkStale(lla.GetAddress());
925  }
926 
927  if (naHeader.GetFlagR())
928  {
929  entry->SetRouter(true);
930  }
931  return;
932  }
934  /* if the Flag O is clear and mac address differs from the cache */
935  if (!naHeader.GetFlagO() && lla.GetAddress() != entry->GetMacAddress())
936  {
937  entry->MarkStale();
938  return;
939  }
940  else
941  {
942  entry->SetMacAddress(lla.GetAddress());
943  if (naHeader.GetFlagS())
944  {
945  entry->StartReachableTimer();
946  }
947  else if (lla.GetAddress() != entry->GetMacAddress())
948  {
949  entry->MarkStale();
950  }
951  entry->SetRouter(naHeader.GetFlagR());
952  }
953  break;
954  }
957  /* if the Flag O is clear and mac address differs from the cache */
958  if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
959  {
960  entry->SetMacAddress(lla.GetAddress());
961  if (naHeader.GetFlagS())
962  {
963  entry->MarkReachable(lla.GetAddress());
964  entry->StartReachableTimer();
965  }
966  else if (lla.GetAddress() != entry->GetMacAddress())
967  {
968  entry->MarkStale();
969  }
970  entry->SetRouter(naHeader.GetFlagR());
971  }
972  return;
973  }
975  if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
976  {
977  entry->SetMacAddress(lla.GetAddress());
978  if (naHeader.GetFlagS())
979  {
980  waiting = entry->MarkReachable(lla.GetAddress());
981  for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it =
982  waiting.begin();
983  it != waiting.end();
984  it++)
985  {
986  cache->GetInterface()->Send(it->first, it->second, src);
987  }
988  entry->ClearWaitingPacket();
989  entry->StartReachableTimer();
990  }
991  else if (lla.GetAddress() != entry->GetMacAddress())
992  {
993  entry->MarkStale();
994  }
995  entry->SetRouter(naHeader.GetFlagR());
996  }
997  return;
998  }
1001  if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
1002  {
1003  entry->SetMacAddress(lla.GetAddress());
1004  if (lla.GetAddress() != entry->GetMacAddress())
1005  {
1006  entry->MarkStale();
1007  }
1008  entry->SetRouter(naHeader.GetFlagR());
1009  }
1010  return;
1011  }
1012  }
1013  // Silence compiler warning
1014 }
1015 
1016 void
1018  const Ipv6Address& src,
1019  const Ipv6Address& dst,
1020  Ptr<Ipv6Interface> interface)
1021 {
1022  NS_LOG_FUNCTION(this << packet << src << dst << interface);
1023  bool hasLla = false;
1024  Ptr<Packet> p = packet->Copy();
1025  Icmpv6OptionLinkLayerAddress llOptionHeader(0);
1026 
1027  Icmpv6Redirection redirectionHeader;
1028  p->RemoveHeader(redirectionHeader);
1029 
1030  /* little ugly try to find a better way */
1031  uint8_t type;
1032  p->CopyData(&type, sizeof(type));
1034  {
1035  hasLla = true;
1036  p->RemoveHeader(llOptionHeader);
1037  }
1038 
1039  Icmpv6OptionRedirected redirectedOptionHeader;
1040  p->RemoveHeader(redirectedOptionHeader);
1041 
1042  Ipv6Address redirTarget = redirectionHeader.GetTarget();
1043  Ipv6Address redirDestination = redirectionHeader.GetDestination();
1044 
1045  if (hasLla)
1046  {
1047  /* update the cache if needed */
1048  NdiscCache::Entry* entry = nullptr;
1049  Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
1050 
1051  entry = cache->Lookup(redirTarget);
1052  if (!entry)
1053  {
1054  entry = cache->Add(redirTarget);
1055  /* destination and target different => necessarily a router */
1056  entry->SetRouter(redirTarget != redirDestination);
1057  entry->SetMacAddress(llOptionHeader.GetAddress());
1058  entry->MarkStale();
1059  }
1060  else
1061  {
1062  if (entry->IsIncomplete() || entry->GetMacAddress() != llOptionHeader.GetAddress())
1063  {
1064  /* update entry to STALE */
1065  if (entry->GetMacAddress() != llOptionHeader.GetAddress())
1066  {
1067  entry->SetMacAddress(llOptionHeader.GetAddress());
1068  entry->MarkStale();
1069  }
1070  }
1071  else
1072  {
1073  /* stay unchanged */
1074  }
1075  }
1076  }
1077 
1078  /* add redirection in routing table */
1079  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1080 
1081  if (redirTarget == redirDestination)
1082  {
1083  ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1084  Ipv6Prefix(128),
1085  Ipv6Address("::"),
1086  ipv6->GetInterfaceForAddress(dst));
1087  }
1088  else
1089  {
1090  uint32_t ifIndex = ipv6->GetInterfaceForAddress(dst);
1091  ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1092  Ipv6Prefix(128),
1093  redirTarget,
1094  ifIndex);
1095  }
1096 }
1097 
1098 void
1100  const Ipv6Address& src,
1101  const Ipv6Address& dst,
1102  Ptr<Ipv6Interface> interface)
1103 {
1104  NS_LOG_FUNCTION(this << *p << src << dst << interface);
1105  Ptr<Packet> pkt = p->Copy();
1106 
1108  pkt->RemoveHeader(unreach);
1109 
1110  Ipv6Header ipHeader;
1111  if (pkt->GetSize() > ipHeader.GetSerializedSize())
1112  {
1113  pkt->RemoveHeader(ipHeader);
1114  uint8_t payload[8];
1115  pkt->CopyData(payload, 8);
1116  Forward(src, unreach, unreach.GetCode(), ipHeader, payload);
1117  }
1118 }
1119 
1120 void
1122  const Ipv6Address& src,
1123  const Ipv6Address& dst,
1124  Ptr<Ipv6Interface> interface)
1125 {
1126  NS_LOG_FUNCTION(this << *p << src << dst << interface);
1127  Ptr<Packet> pkt = p->Copy();
1128 
1129  Icmpv6TimeExceeded timeexceeded;
1130  pkt->RemoveHeader(timeexceeded);
1131 
1132  Ipv6Header ipHeader;
1133  if (pkt->GetSize() > ipHeader.GetSerializedSize())
1134  {
1135  Ipv6Header ipHeader;
1136  pkt->RemoveHeader(ipHeader);
1137  uint8_t payload[8];
1138  pkt->CopyData(payload, 8);
1139  Forward(src, timeexceeded, timeexceeded.GetCode(), ipHeader, payload);
1140  }
1141 }
1142 
1143 void
1145  const Ipv6Address& src,
1146  const Ipv6Address& dst,
1147  Ptr<Ipv6Interface> interface)
1148 {
1149  NS_LOG_FUNCTION(this << *p << src << dst << interface);
1150  Ptr<Packet> pkt = p->Copy();
1151 
1152  Icmpv6TooBig tooBig;
1153  pkt->RemoveHeader(tooBig);
1154 
1155  Ipv6Header ipHeader;
1156  if (pkt->GetSize() > ipHeader.GetSerializedSize())
1157  {
1158  pkt->RemoveHeader(ipHeader);
1159  uint8_t payload[8];
1160  pkt->CopyData(payload, 8);
1161 
1163  ipv6->SetPmtu(ipHeader.GetDestination(), tooBig.GetMtu());
1164 
1165  Forward(src, tooBig, tooBig.GetMtu(), ipHeader, payload);
1166  }
1167 }
1168 
1169 void
1171  const Ipv6Address& src,
1172  const Ipv6Address& dst,
1173  Ptr<Ipv6Interface> interface)
1174 {
1175  NS_LOG_FUNCTION(this << *p << src << dst << interface);
1176  Ptr<Packet> pkt = p->Copy();
1177 
1178  Icmpv6ParameterError paramErr;
1179  pkt->RemoveHeader(paramErr);
1180 
1181  Ipv6Header ipHeader;
1182  if (pkt->GetSize() > ipHeader.GetSerializedSize())
1183  {
1184  pkt->RemoveHeader(ipHeader);
1185  uint8_t payload[8];
1186  pkt->CopyData(payload, 8);
1187  Forward(src, paramErr, paramErr.GetCode(), ipHeader, payload);
1188  }
1189 }
1190 
1191 void
1193 {
1194  NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1197  NS_ASSERT(ipv6);
1198 
1199  tag.SetHopLimit(ttl);
1200  packet->AddPacketTag(tag);
1201  m_downTarget(packet, src, dst, PROT_NUMBER, nullptr);
1202 }
1203 
1204 void
1206  Ipv6Address src,
1207  Ipv6Address dst,
1208  uint8_t ttl)
1209 {
1210  NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1211  SendMessage(packet, src, dst, ttl);
1212 }
1213 
1214 void
1216  Ipv6Address dst,
1217  Icmpv6Header& icmpv6Hdr,
1218  uint8_t ttl)
1219 {
1220  NS_LOG_FUNCTION(this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
1222  NS_ASSERT(ipv6 && ipv6->GetRoutingProtocol());
1223  Ipv6Header header;
1225  Socket::SocketErrno err;
1226  Ptr<Ipv6Route> route;
1227  Ptr<NetDevice> oif(nullptr); // specify non-zero if bound to a source address
1228 
1229  header.SetDestination(dst);
1230  route = ipv6->GetRoutingProtocol()->RouteOutput(packet, header, oif, err);
1231 
1232  if (route)
1233  {
1234  NS_LOG_LOGIC("Route exists");
1235  tag.SetHopLimit(ttl);
1236  packet->AddPacketTag(tag);
1237  Ipv6Address src = route->GetSource();
1238 
1239  icmpv6Hdr.CalculatePseudoHeaderChecksum(src,
1240  dst,
1241  packet->GetSize() + icmpv6Hdr.GetSerializedSize(),
1242  PROT_NUMBER);
1243  packet->AddHeader(icmpv6Hdr);
1244  m_downTarget(packet, src, dst, PROT_NUMBER, route);
1245  }
1246  else
1247  {
1248  NS_LOG_WARN("drop icmp message");
1249  }
1250 }
1251 
1252 void
1253 Icmpv6L4Protocol::SendNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1254 {
1255  NS_LOG_FUNCTION(this << src << dst << hardwareAddress << static_cast<uint32_t>(flags));
1256  Ptr<Packet> p = Create<Packet>();
1257  Icmpv6NA na;
1258  Icmpv6OptionLinkLayerAddress llOption(0, *hardwareAddress); /* not a source link layer */
1259 
1260  NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1261  na.SetIpv6Target(src);
1262 
1263  if ((flags & 1))
1264  {
1265  na.SetFlagO(true);
1266  }
1267  if ((flags & 2) && src != Ipv6Address::GetAny())
1268  {
1269  na.SetFlagS(true);
1270  }
1271  if ((flags & 4))
1272  {
1273  na.SetFlagR(true);
1274  }
1275 
1276  p->AddHeader(llOption);
1278  p->AddHeader(na);
1279 
1280  SendMessage(p, src, dst, 255);
1281 }
1282 
1283 void
1285  Ipv6Address dst,
1286  uint16_t id,
1287  uint16_t seq,
1288  Ptr<Packet> data)
1289 {
1290  NS_LOG_FUNCTION(this << src << dst << id << seq << data);
1291  Ptr<Packet> p = data->Copy();
1292  Icmpv6Echo reply(0); /* echo reply */
1293 
1294  reply.SetId(id);
1295  reply.SetSeq(seq);
1296 
1298  dst,
1299  p->GetSize() + reply.GetSerializedSize(),
1300  PROT_NUMBER);
1301  p->AddHeader(reply);
1302  SendMessage(p, src, dst, 64);
1303 }
1304 
1305 void
1307  Ipv6Address dst,
1308  Ipv6Address target,
1309  Address hardwareAddress)
1310 {
1311  NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1312  Ptr<Packet> p = Create<Packet>();
1313  /* Ipv6Header ipHeader; */
1314  Icmpv6NS ns(target);
1316  1,
1317  hardwareAddress); /* we give our mac address in response */
1318 
1319  /* if the source is unspec, multicast the NA to all-nodes multicast */
1320  if (src == Ipv6Address::GetAny())
1321  {
1323  }
1324 
1325  NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1326 
1327  p->AddHeader(llOption);
1329  p->AddHeader(ns);
1330  if (!dst.IsMulticast())
1331  {
1332  SendMessage(p, src, dst, 255);
1333  }
1334  else
1335  {
1336  NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1339  this,
1340  p,
1341  src,
1342  dst,
1343  255);
1344  }
1345 }
1346 
1347 void
1349 {
1350  NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1351  Ptr<Packet> p = Create<Packet>();
1352  Icmpv6RS rs;
1353 
1354  // RFC 4861:
1355  // The link-layer address of the sender MUST NOT be included if the Source Address is the
1356  // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
1357  if (!src.IsAny())
1358  {
1359  Icmpv6OptionLinkLayerAddress llOption(1, hardwareAddress);
1360  p->AddHeader(llOption);
1361  }
1362 
1363  NS_LOG_LOGIC("Send RS (from " << src << " to " << dst << ")");
1364 
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.
1383  }
1384  else
1385  {
1386  // Following RS transmission - adding further jitter is unnecessary.
1388  if (rsTimeout > m_rsMaxRetransmissionTime)
1389  {
1391  }
1392  }
1393  m_rsPrevRetransmissionTimeout = rsTimeout;
1394  Simulator::Schedule(rsDelay, &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
1397  this,
1398  src,
1399  dst,
1400  hardwareAddress);
1401  }
1402 }
1403 
1404 void
1406 {
1407  NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1408 
1409  if (m_rsMaxRetransmissionCount == 0)
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 != Time(0) &&
1427  {
1428  NS_LOG_LOGIC("Maximum RS retransmission time reached, giving up.");
1429  return;
1430  }
1431 
1432  SendRS(src, dst, hardwareAddress);
1433 }
1434 
1435 void
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 
1461 void
1462 Icmpv6L4Protocol::SendErrorTooBig(Ptr<Packet> malformedPacket, Ipv6Address dst, uint32_t mtu)
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 
1486 void
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 
1510 void
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 
1538 void
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;
1549  Ptr<Packet> p = Create<Packet>();
1550  uint32_t redirectedPacketSize = redirectedPacket->GetSize();
1551  Icmpv6OptionLinkLayerAddress llOption(0);
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 
1602 Icmpv6L4Protocol::ForgeNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1603 {
1604  NS_LOG_FUNCTION(this << src << dst << hardwareAddress << (uint32_t)flags);
1605  Ptr<Packet> p = Create<Packet>();
1606  Ipv6Header ipHeader;
1607  Icmpv6NA na;
1609  0,
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 
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);
1652  Ptr<Packet> p = Create<Packet>();
1653  Ipv6Header ipHeader;
1654  Icmpv6NS ns(target);
1656  1,
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);
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 (CacheList::const_iterator 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 
1697  Ptr<NdiscCache> cache = CreateObject<NdiscCache>();
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 
1705 bool
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 
1741 bool
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 
1824 void
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  {
1855  interface->SetState(ifaddr.GetAddress(), Ipv6InterfaceAddress::PREFERRED);
1856  NS_LOG_LOGIC("DAD OK, interface in state PREFERRED");
1857 
1858  /* send an RS if our interface is not forwarding (router) and if address is a link-local
1859  * ones (because we will send RS with it)
1860  */
1861  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1862 
1863  if (!ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())) &&
1864  addr.IsLinkLocal())
1865  {
1866  /* \todo Add random delays before sending RS
1867  * because all nodes start at the same time, there will be many of RS around 1 second of
1868  * simulation time
1869  */
1870  NS_LOG_LOGIC("Scheduled a first Router Solicitation");
1874  this,
1875  ifaddr.GetAddress(),
1877  interface->GetDevice()->GetAddress());
1878  }
1879  else
1880  {
1881  NS_LOG_LOGIC("Did not schedule a Router Solicitation because the interface is in "
1882  "forwarding mode");
1883  }
1884  }
1885 }
1886 
1887 void
1889 {
1890  NS_LOG_FUNCTION(this << &callback);
1891 }
1892 
1893 void
1895 {
1896  NS_LOG_FUNCTION(this << &callback);
1897  m_downTarget = callback;
1898 }
1899 
1902 {
1903  NS_LOG_FUNCTION(this);
1905 }
1906 
1909 {
1910  NS_LOG_FUNCTION(this);
1911  return m_downTarget;
1912 }
1913 
1914 uint8_t
1916 {
1917  return m_maxMulticastSolicit;
1918 }
1919 
1920 uint8_t
1922 {
1923  return m_maxUnicastSolicit;
1924 }
1925 
1926 Time
1928 {
1929  return m_reachableTime;
1930 }
1931 
1932 Time
1934 {
1935  return m_retransmissionTime;
1936 }
1937 
1938 Time
1940 {
1941  return m_delayFirstProbe;
1942 }
1943 
1944 Time
1946 {
1947  return m_dadTimeout;
1948 }
1949 
1950 } /* namespace ns3 */
a polymophic address class
Definition: address.h:100
uint8_t GetLength() const
Get the length of the underlying address.
Definition: address.cc:78
AttributeValue implementation for Boolean.
Definition: boolean.h:37
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:578
bool IsNull() const
Check for null implementation.
Definition: callback.h:572
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
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.
Definition: icmpv6-header.h:38
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_ND_NEIGHBOR_ADVERTISEMENT
Definition: icmpv6-header.h:57
@ ICMPV6_ERROR_DESTINATION_UNREACHABLE
Definition: icmpv6-header.h:45
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.
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].
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.
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.
enum IpL4Protocol::RxStatus Receive(Ptr< Packet > p, const Ipv4Header &header, Ptr< Ipv4Interface > interface) override
Receive method.
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).
virtual void SendNS(Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
Send a Neighbor Solicitation.
void SendRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Send a Router Solicitation.
Time m_retransmissionTime
Neighbor Discovery node constants: retransmission timer.
uint8_t GetMaxUnicastSolicit() const
Neighbor Discovery node constants: max unicast solicitations.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
void HandleEchoRequest(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Echo Request method.
void HandleParameterError(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Parameter Error method.
void HandleNS(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Solicitation method.
Time m_rsMaxRetransmissionDuration
Maximum duration of multicast RS retransmissions [RFC 7559].
void HandleRedirection(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Redirection method.
virtual bool Lookup(Ipv6Address dst, Ptr< NetDevice > device, Ptr< NdiscCache > cache, Address *hardwareDestination)
Lookup in the ND cache for the IPv6 address.
Time m_rsPrevRetransmissionTimeout
Previous multicast RS retransmissions timeout [RFC 7559].
IpL4Protocol::DownTargetCallback GetDownTarget() const override
This method allows a caller to get the current down target callback set for this L4 protocol (IPv4 ca...
EventId m_handleRsTimeoutEvent
RS timeout handler event.
virtual int GetVersion() const
Get the version of the protocol.
Ptr< RandomVariableStream > m_solicitationJitter
Random jitter before sending solicitations.
void SendMessage(Ptr< Packet > packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
Send a packet via ICMPv6, note that packet already contains ICMPv6 header.
Time m_delayFirstProbe
Neighbor Discovery node constants: delay for the first probe.
void SendEchoReply(Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr< Packet > data)
Send a Echo Reply.
NdiscCache::Ipv6PayloadHeaderPair ForgeRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Forge a Router Solicitation.
NdiscCache::Ipv6PayloadHeaderPair ForgeNS(Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
Forge a Neighbor Solicitation.
void SendNA(Ipv6Address src, Ipv6Address dst, Address *hardwareAddress, uint8_t flags)
Send a Neighbor Advertisement.
Time m_rsInitialRetransmissionTime
Initial multicast RS retransmission time [RFC 7559].
static TypeId GetTypeId()
Get the type ID.
Time GetReachableTime() const
Neighbor Discovery node constants: reachable time.
CacheList m_cacheList
A list of cache by device.
uint8_t GetMaxMulticastSolicit() const
Neighbor Discovery node constants: max multicast solicitations.
void SetNode(Ptr< Node > node)
Set the node.
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
void HandleNA(Ptr< Packet > p, const Ipv6Address &src, const Ipv6Address &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Advertisement method.
ICMPv6 Neighbor Advertisement header.
bool GetFlagS() const
Get the S flag.
void SetFlagS(bool s)
Set the S flag.
void SetIpv6Target(Ipv6Address target)
Set the IPv6 target field.
void SetFlagR(bool r)
Set the R flag.
Ipv6Address GetIpv6Target() const
Get the IPv6 target field.
bool GetFlagR() const
Get the R flag.
uint32_t GetSerializedSize() const override
Get the serialized size.
bool GetFlagO() const
Get the O flag.
void SetFlagO(bool o)
Set the O flag.
ICMPv6 Neighbor Solicitation header.
uint32_t GetSerializedSize() const override
Get the serialized size.
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).
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:45
L4 Protocol abstract base class.
virtual void ReceiveIcmp(Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo, Ipv4Address payloadSource, Ipv4Address payloadDestination, const uint8_t payload[8])
Called from lower-level layers to send the ICMP packet up in the stack.
Callback< void, Ptr< Packet >, Ipv4Address, Ipv4Address, uint8_t, Ptr< Ipv4Route > > DownTargetCallback
callback to send packets over IPv4
RxStatus
Rx status codes.
Packet header for IPv4.
Definition: ipv4-header.h:34
Describes an IPv6 address.
Definition: ipv6-address.h:50
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:36
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:118
void SetSource(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:106
uint8_t GetHopLimit() const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:100
uint8_t GetNextHeader() const
Get the next header.
Definition: ipv6-header.cc:88
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:94
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:124
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:70
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Definition: ipv6-header.cc:159
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:82
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:82
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.
Ipv6InterfaceAddress GetLinkLocalAddress() const
Get link-local address from IPv6 interface.
Ipv6InterfaceAddress GetAddressMatchingDestination(Ipv6Address dst)
Get an address which is in the same network prefix as destination.
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 SetNsDadUid(Ipv6Address address, uint32_t uid)
Update NS DAD packet UID of an interface address.
void Send(Ptr< Packet > p, const Ipv6Header &hdr, Ipv6Address dest)
Send a packet through this interface.
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
void SetState(Ipv6Address address, Ipv6InterfaceAddress::State_e state)
Update state of an interface address.
IPv6 layer implementation.
static const uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
Describes an IPv6 prefix.
Definition: ipv6-address.h:456
A record that holds information about a NdiscCache entry.
Definition: ndisc-cache.h:167
bool IsPermanent() const
Is the entry PERMANENT.
Definition: ndisc-cache.cc:659
NdiscCacheEntryState_e m_state
The state of the entry.
Definition: ndisc-cache.h:194
@ PROBE
Try to contact IPv6 address to know again its L2 address.
Definition: ndisc-cache.h:186
@ STALE
Mapping is stale.
Definition: ndisc-cache.h:184
@ REACHABLE
Mapping exists between IPv6 and L2 addresses.
Definition: ndisc-cache.h:183
@ PERMANENT
Permanent Mapping exists between IPv6 and L2 addresses.
Definition: ndisc-cache.h:187
@ DELAY
Try to wait contact from remote host.
Definition: ndisc-cache.h:185
@ INCOMPLETE
No mapping between IPv6 and L2 addresses.
Definition: ndisc-cache.h:182
@ STATIC_AUTOGENERATED
Permanent entries generate by NeighborCacheHelper.
Definition: ndisc-cache.h:188
void ClearWaitingPacket()
Clear the waiting packet list.
Definition: ndisc-cache.cc:286
std::list< Ipv6PayloadHeaderPair > MarkStale(Address mac)
Changes the state to this entry to STALE.
Definition: ndisc-cache.cc:592
void StartReachableTimer()
Start the reachable timer.
Definition: ndisc-cache.cc:469
Address GetMacAddress() const
Get the MAC address of this entry.
Definition: ndisc-cache.cc:673
void StartDelayTimer()
Start delay timer.
Definition: ndisc-cache.cc:514
std::list< Ipv6PayloadHeaderPair > MarkReachable(Address mac)
Changes the state to this entry to REACHABLE.
Definition: ndisc-cache.cc:562
bool IsIncomplete() const
Is the entry INCOMPLETE.
Definition: ndisc-cache.cc:645
bool IsDelay() const
Is the entry DELAY.
Definition: ndisc-cache.cc:638
void StartRetransmitTimer()
Start retransmit timer.
Definition: ndisc-cache.cc:528
void MarkIncomplete(Ipv6PayloadHeaderPair p)
Changes the state to this entry to INCOMPLETE.
Definition: ndisc-cache.cc:550
bool IsStale() const
Is the entry STALE.
Definition: ndisc-cache.cc:624
void SetMacAddress(Address mac)
Set the MAC address of this entry.
Definition: ndisc-cache.cc:680
void MarkDelay()
Change the state to this entry to DELAY.
Definition: ndisc-cache.cc:601
void SetRouter(bool router)
Set the node type.
Definition: ndisc-cache.cc:258
bool IsAutoGenerated() const
Is the entry STATIC_AUTOGENERATED.
Definition: ndisc-cache.cc:666
void AddWaitingPacket(Ipv6PayloadHeaderPair p)
Add a packet (or replace old value) in the queue.
Definition: ndisc-cache.cc:272
bool IsReachable() const
Is the entry REACHABLE.
Definition: ndisc-cache.cc:631
void StopNudTimer()
Stop NUD timer and reset the NUD retransmission counter.
Definition: ndisc-cache.cc:542
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface, Ptr< Icmpv6L4Protocol > icmpv6)
Set the device and interface.
Definition: ndisc-cache.cc:75
std::pair< Ptr< Packet >, Ipv6Header > Ipv6PayloadHeaderPair
Pair of a packet and an Ipv4 header.
Definition: ndisc-cache.h:159
virtual NdiscCache::Entry * Add(Ipv6Address to)
Add an entry.
Definition: ndisc-cache.cc:134
void Flush()
Flush the cache.
Definition: ndisc-cache.cc:163
void Remove(NdiscCache::Entry *entry)
Delete an entry.
Definition: ndisc-cache.cc:146
virtual NdiscCache::Entry * Lookup(Ipv6Address dst)
Lookup in the cache.
Definition: ndisc-cache.cc:100
Ptr< NetDevice > GetDevice() const
Get the NetDevice associated with this cache.
Definition: ndisc-cache.cc:93
Ptr< Ipv6Interface > GetInterface() const
Get the Ipv6Interface associated with this cache.
Definition: ndisc-cache.cc:86
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:332
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
void Dispose()
Dispose of this Object.
Definition: object.cc:219
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:238
uint64_t GetUid() const
Returns the packet's Uid.
Definition: packet.cc:412
virtual double GetValue()=0
Get the next random value drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition: socket.h:1170
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:666
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1423
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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:86
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:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
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:46
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:231
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:1424
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:46
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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:261
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:848
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:707
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
uint8_t data[writeSize]