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 #include "ipv6-route.h"
28 #include "ipv6-routing-protocol.h"
29 
30 #include "ns3/assert.h"
31 #include "ns3/boolean.h"
32 #include "ns3/double.h"
33 #include "ns3/integer.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 (auto 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 
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  auto 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)
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 (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 
592 void
594  const Ipv6Address& src,
595  const Ipv6Address& dst,
596  Ptr<Ipv6Interface> interface)
597 {
598  NS_LOG_FUNCTION(this << packet << src << dst << interface);
600  Icmpv6RS rsHeader;
601  packet->RemoveHeader(rsHeader);
602  Address hardwareAddress;
604  NdiscCache::Entry* entry = nullptr;
605  Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
606 
607  if (src != Ipv6Address::GetAny())
608  {
609  /* XXX search all options following the RS header */
610  /* test if the next option is SourceLinkLayerAddress */
611  uint8_t type;
612  packet->CopyData(&type, sizeof(type));
613 
615  {
616  return;
617  }
618  packet->RemoveHeader(lla);
619  NS_LOG_LOGIC("Cache updated by RS");
620 
621  entry = cache->Lookup(src);
622  if (!entry)
623  {
624  entry = cache->Add(src);
625  entry->SetRouter(false);
626  entry->MarkStale(lla.GetAddress());
627  }
628  else if (entry->GetMacAddress() != lla.GetAddress())
629  {
630  entry->MarkStale(lla.GetAddress());
631  }
632  }
633 }
634 
635 void
637  const Ipv6Address& src,
638  const Ipv6Address& dst,
639  Ptr<Ipv6Interface> interface)
640 {
641  NS_LOG_FUNCTION(this << packet << src << dst << interface);
642  Icmpv6NS nsHeader("::");
643  Ipv6InterfaceAddress ifaddr;
644  uint32_t nb = interface->GetNAddresses();
645  uint32_t i = 0;
646  bool found = false;
647 
648  packet->RemoveHeader(nsHeader);
649 
650  Ipv6Address target = nsHeader.GetIpv6Target();
651 
652  for (i = 0; i < nb; i++)
653  {
654  ifaddr = interface->GetAddress(i);
655 
656  if (ifaddr.GetAddress() == target)
657  {
658  found = true;
659  break;
660  }
661  }
662 
663  if (!found)
664  {
665  NS_LOG_LOGIC("Not a NS for us");
666  return;
667  }
668 
669  if (packet->GetUid() == ifaddr.GetNsDadUid())
670  {
671  /* don't process our own DAD probe */
672  NS_LOG_LOGIC("Hey we receive our DAD probe!");
673  return;
674  }
675 
676  NdiscCache::Entry* entry = nullptr;
677  Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
678  uint8_t flags = 0;
679 
680  /* search all options following the NS header */
681  Icmpv6OptionLinkLayerAddress sllaoHdr(true);
682 
683  bool next = true;
684  bool hasSllao = false;
685 
686  while (next)
687  {
688  uint8_t type;
689  packet->CopyData(&type, sizeof(type));
690 
691  switch (type)
692  {
694  if (!hasSllao)
695  {
696  packet->RemoveHeader(sllaoHdr);
697  hasSllao = true;
698  }
699  break;
700  default:
701  /* unknown option, quit */
702  next = false;
703  }
704  if (packet->GetSize() == 0)
705  {
706  next = false;
707  }
708  }
709 
710  Address replyMacAddress;
711 
712  if (src != Ipv6Address::GetAny())
713  {
714  entry = cache->Lookup(src);
715  if (!entry)
716  {
717  if (!hasSllao)
718  {
719  NS_LOG_LOGIC("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a "
720  "NCE, discarding.");
721  return;
722  }
723  entry = cache->Add(src);
724  entry->SetRouter(false);
725  entry->MarkStale(sllaoHdr.GetAddress());
726  replyMacAddress = sllaoHdr.GetAddress();
727  }
728  else if (hasSllao && (entry->GetMacAddress() != sllaoHdr.GetAddress()))
729  {
730  entry->MarkStale(sllaoHdr.GetAddress());
731  replyMacAddress = sllaoHdr.GetAddress();
732  }
733  else
734  {
735  replyMacAddress = entry->GetMacAddress();
736  }
737 
738  flags = 3; /* S + O flags */
739  }
740  else
741  {
742  /* it's a DAD */
743  flags = 1; /* O flag */
744  replyMacAddress = interface->GetDevice()->GetMulticast(dst);
745  }
746 
747  /* send a NA to src */
749 
750  if (ipv6->IsForwarding(ipv6->GetInterfaceForDevice(interface->GetDevice())))
751  {
752  flags += 4; /* R flag */
753  }
754 
755  Address hardwareAddress = interface->GetDevice()->GetAddress();
757  target.IsLinkLocal() ? interface->GetLinkLocalAddress().GetAddress() : ifaddr.GetAddress(),
758  src.IsAny() ? dst : src, // DAD replies must go to the multicast group it was sent to.
759  &hardwareAddress,
760  flags);
761 
762  // We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not
763  // change it beyond what we did already).
764  Ptr<Packet> pkt = p.first;
765  pkt->AddHeader(p.second);
766  interface->GetDevice()->Send(pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
767 }
768 
771 {
772  NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
773  Ptr<Packet> p = Create<Packet>();
774  Ipv6Header ipHeader;
775  Icmpv6RS rs;
776 
777  NS_LOG_LOGIC("Forge RS (from " << src << " to " << dst << ")");
778  // RFC 4861:
779  // The link-layer address of the sender MUST NOT be included if the Source Address is the
780  // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
781  if (!src.IsAny())
782  {
784  true,
785  hardwareAddress); /* we give our mac address in response */
786  p->AddHeader(llOption);
787  }
788 
790  p->AddHeader(rs);
791 
792  ipHeader.SetSource(src);
793  ipHeader.SetDestination(dst);
794  ipHeader.SetNextHeader(PROT_NUMBER);
795  ipHeader.SetPayloadLength(p->GetSize());
796  ipHeader.SetHopLimit(255);
797 
798  return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
799 }
800 
803  Ipv6Address dst,
804  uint16_t id,
805  uint16_t seq,
807 {
808  NS_LOG_FUNCTION(this << src << dst << id << seq << data);
809  Ptr<Packet> p = data->Copy();
810  Ipv6Header ipHeader;
811  Icmpv6Echo req(true);
812 
813  req.SetId(id);
814  req.SetSeq(seq);
815 
817  dst,
818  p->GetSize() + req.GetSerializedSize(),
819  PROT_NUMBER);
820  p->AddHeader(req);
821 
822  ipHeader.SetSource(src);
823  ipHeader.SetDestination(dst);
824  ipHeader.SetNextHeader(PROT_NUMBER);
825  ipHeader.SetPayloadLength(p->GetSize());
826  ipHeader.SetHopLimit(255);
827 
828  return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
829 }
830 
831 void
833  const Ipv6Address& src,
834  const Ipv6Address& dst,
835  Ptr<Ipv6Interface> interface)
836 {
837  NS_LOG_FUNCTION(this << packet << src << dst << interface);
838  Icmpv6NA naHeader;
840 
841  packet->RemoveHeader(naHeader);
842  Ipv6Address target = naHeader.GetIpv6Target();
843 
844  Address hardwareAddress;
845  NdiscCache::Entry* entry = nullptr;
846  Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
847  std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
848 
849  /* check if we have something in our cache */
850  entry = cache->Lookup(target);
851 
852  if (!entry)
853  {
854  /* ouch!! we might be victim of a DAD */
855 
856  Ipv6InterfaceAddress ifaddr;
857  bool found = false;
858  uint32_t i = 0;
859  uint32_t nb = interface->GetNAddresses();
860 
861  for (i = 0; i < nb; i++)
862  {
863  ifaddr = interface->GetAddress(i);
864  if (ifaddr.GetAddress() == target)
865  {
866  found = true;
867  break;
868  }
869  }
870 
871  if (found)
872  {
873  if (ifaddr.GetState() == Ipv6InterfaceAddress::TENTATIVE ||
875  {
876  interface->SetState(ifaddr.GetAddress(), Ipv6InterfaceAddress::INVALID);
877  }
878  }
879 
880  /* we have not initiated any communication with the target so... discard the NA */
881  return;
882  }
883 
884  /* XXX search all options following the NA header */
885  /* Get LLA */
886  uint8_t type;
887  packet->CopyData(&type, sizeof(type));
888 
890  {
891  return;
892  }
893  packet->RemoveHeader(lla);
894 
895  /* we receive a NA so stop the probe timer or delay timer if any */
896  entry->StopNudTimer();
897  switch (entry->m_state)
898  {
900  /* we receive a NA so stop the retransmission timer */
901  entry->StopNudTimer();
902 
903  if (naHeader.GetFlagS())
904  {
905  /* mark it to reachable */
906  waiting = entry->MarkReachable(lla.GetAddress());
907  entry->StartReachableTimer();
908  /* send out waiting packet */
909  for (auto it = waiting.begin(); it != waiting.end(); it++)
910  {
911  cache->GetInterface()->Send(it->first, it->second, src);
912  }
913  entry->ClearWaitingPacket();
914  }
915  else
916  {
917  entry->MarkStale(lla.GetAddress());
918  }
919 
920  if (naHeader.GetFlagR())
921  {
922  entry->SetRouter(true);
923  }
924  return;
925  }
927  /* if the Flag O is clear and mac address differs from the cache */
928  if (!naHeader.GetFlagO() && lla.GetAddress() != entry->GetMacAddress())
929  {
930  entry->MarkStale();
931  return;
932  }
933  else
934  {
935  entry->SetMacAddress(lla.GetAddress());
936  if (naHeader.GetFlagS())
937  {
938  entry->StartReachableTimer();
939  }
940  else if (lla.GetAddress() != entry->GetMacAddress())
941  {
942  entry->MarkStale();
943  }
944  entry->SetRouter(naHeader.GetFlagR());
945  }
946  break;
947  }
950  /* if the Flag O is clear and mac address differs from the cache */
951  if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
952  {
953  entry->SetMacAddress(lla.GetAddress());
954  if (naHeader.GetFlagS())
955  {
956  entry->MarkReachable(lla.GetAddress());
957  entry->StartReachableTimer();
958  }
959  else if (lla.GetAddress() != entry->GetMacAddress())
960  {
961  entry->MarkStale();
962  }
963  entry->SetRouter(naHeader.GetFlagR());
964  }
965  return;
966  }
968  if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
969  {
970  entry->SetMacAddress(lla.GetAddress());
971  if (naHeader.GetFlagS())
972  {
973  waiting = entry->MarkReachable(lla.GetAddress());
974  for (auto it = waiting.begin(); it != waiting.end(); it++)
975  {
976  cache->GetInterface()->Send(it->first, it->second, src);
977  }
978  entry->ClearWaitingPacket();
979  entry->StartReachableTimer();
980  }
981  else if (lla.GetAddress() != entry->GetMacAddress())
982  {
983  entry->MarkStale();
984  }
985  entry->SetRouter(naHeader.GetFlagR());
986  }
987  return;
988  }
991  if (naHeader.GetFlagO() || lla.GetAddress() == entry->GetMacAddress())
992  {
993  entry->SetMacAddress(lla.GetAddress());
994  if (lla.GetAddress() != entry->GetMacAddress())
995  {
996  entry->MarkStale();
997  }
998  entry->SetRouter(naHeader.GetFlagR());
999  }
1000  return;
1001  }
1002  }
1003  // Silence compiler warning
1004 }
1005 
1006 void
1008  const Ipv6Address& src,
1009  const Ipv6Address& dst,
1010  Ptr<Ipv6Interface> interface)
1011 {
1012  NS_LOG_FUNCTION(this << packet << src << dst << interface);
1013  bool hasLla = false;
1014  Ptr<Packet> p = packet->Copy();
1015  Icmpv6OptionLinkLayerAddress llOptionHeader(false);
1016 
1017  Icmpv6Redirection redirectionHeader;
1018  p->RemoveHeader(redirectionHeader);
1019 
1020  /* little ugly try to find a better way */
1021  uint8_t type;
1022  p->CopyData(&type, sizeof(type));
1024  {
1025  hasLla = true;
1026  p->RemoveHeader(llOptionHeader);
1027  }
1028 
1029  Icmpv6OptionRedirected redirectedOptionHeader;
1030  p->RemoveHeader(redirectedOptionHeader);
1031 
1032  Ipv6Address redirTarget = redirectionHeader.GetTarget();
1033  Ipv6Address redirDestination = redirectionHeader.GetDestination();
1034 
1035  if (hasLla)
1036  {
1037  /* update the cache if needed */
1038  NdiscCache::Entry* entry = nullptr;
1039  Ptr<NdiscCache> cache = FindCache(interface->GetDevice());
1040 
1041  entry = cache->Lookup(redirTarget);
1042  if (!entry)
1043  {
1044  entry = cache->Add(redirTarget);
1045  /* destination and target different => necessarily a router */
1046  entry->SetRouter(redirTarget != redirDestination);
1047  entry->SetMacAddress(llOptionHeader.GetAddress());
1048  entry->MarkStale();
1049  }
1050  else
1051  {
1052  if (entry->IsIncomplete() || entry->GetMacAddress() != llOptionHeader.GetAddress())
1053  {
1054  /* update entry to STALE */
1055  if (entry->GetMacAddress() != llOptionHeader.GetAddress())
1056  {
1057  entry->SetMacAddress(llOptionHeader.GetAddress());
1058  entry->MarkStale();
1059  }
1060  }
1061  else
1062  {
1063  /* stay unchanged */
1064  }
1065  }
1066  }
1067 
1068  /* add redirection in routing table */
1069  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6>();
1070 
1071  if (redirTarget == redirDestination)
1072  {
1073  ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1074  Ipv6Prefix(128),
1075  Ipv6Address("::"),
1076  ipv6->GetInterfaceForAddress(dst));
1077  }
1078  else
1079  {
1080  uint32_t ifIndex = ipv6->GetInterfaceForAddress(dst);
1081  ipv6->GetRoutingProtocol()->NotifyAddRoute(redirDestination,
1082  Ipv6Prefix(128),
1083  redirTarget,
1084  ifIndex);
1085  }
1086 }
1087 
1088 void
1090  const Ipv6Address& src,
1091  const Ipv6Address& dst,
1092  Ptr<Ipv6Interface> interface)
1093 {
1094  NS_LOG_FUNCTION(this << *p << src << dst << interface);
1095  Ptr<Packet> pkt = p->Copy();
1096 
1098  pkt->RemoveHeader(unreach);
1099 
1100  Ipv6Header ipHeader;
1101  if (pkt->GetSize() > ipHeader.GetSerializedSize())
1102  {
1103  pkt->RemoveHeader(ipHeader);
1104  uint8_t payload[8];
1105  pkt->CopyData(payload, 8);
1106  Forward(src, unreach, unreach.GetCode(), ipHeader, payload);
1107  }
1108 }
1109 
1110 void
1112  const Ipv6Address& src,
1113  const Ipv6Address& dst,
1114  Ptr<Ipv6Interface> interface)
1115 {
1116  NS_LOG_FUNCTION(this << *p << src << dst << interface);
1117  Ptr<Packet> pkt = p->Copy();
1118 
1119  Icmpv6TimeExceeded timeexceeded;
1120  pkt->RemoveHeader(timeexceeded);
1121 
1122  Ipv6Header ipHeader;
1123  if (pkt->GetSize() > ipHeader.GetSerializedSize())
1124  {
1125  Ipv6Header ipHeader;
1126  pkt->RemoveHeader(ipHeader);
1127  uint8_t payload[8];
1128  pkt->CopyData(payload, 8);
1129  Forward(src, timeexceeded, timeexceeded.GetCode(), ipHeader, payload);
1130  }
1131 }
1132 
1133 void
1135  const Ipv6Address& src,
1136  const Ipv6Address& dst,
1137  Ptr<Ipv6Interface> interface)
1138 {
1139  NS_LOG_FUNCTION(this << *p << src << dst << interface);
1140  Ptr<Packet> pkt = p->Copy();
1141 
1142  Icmpv6TooBig tooBig;
1143  pkt->RemoveHeader(tooBig);
1144 
1145  Ipv6Header ipHeader;
1146  if (pkt->GetSize() > ipHeader.GetSerializedSize())
1147  {
1148  pkt->RemoveHeader(ipHeader);
1149  uint8_t payload[8];
1150  pkt->CopyData(payload, 8);
1151 
1153  ipv6->SetPmtu(ipHeader.GetDestination(), tooBig.GetMtu());
1154 
1155  Forward(src, tooBig, tooBig.GetMtu(), ipHeader, payload);
1156  }
1157 }
1158 
1159 void
1161  const Ipv6Address& src,
1162  const Ipv6Address& dst,
1163  Ptr<Ipv6Interface> interface)
1164 {
1165  NS_LOG_FUNCTION(this << *p << src << dst << interface);
1166  Ptr<Packet> pkt = p->Copy();
1167 
1168  Icmpv6ParameterError paramErr;
1169  pkt->RemoveHeader(paramErr);
1170 
1171  Ipv6Header ipHeader;
1172  if (pkt->GetSize() > ipHeader.GetSerializedSize())
1173  {
1174  pkt->RemoveHeader(ipHeader);
1175  uint8_t payload[8];
1176  pkt->CopyData(payload, 8);
1177  Forward(src, paramErr, paramErr.GetCode(), ipHeader, payload);
1178  }
1179 }
1180 
1181 void
1183 {
1184  NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1187  NS_ASSERT(ipv6);
1188 
1189  tag.SetHopLimit(ttl);
1190  packet->AddPacketTag(tag);
1191  m_downTarget(packet, src, dst, PROT_NUMBER, nullptr);
1192 }
1193 
1194 void
1196  Ipv6Address src,
1197  Ipv6Address dst,
1198  uint8_t ttl)
1199 {
1200  NS_LOG_FUNCTION(this << packet << src << dst << (uint32_t)ttl);
1201  SendMessage(packet, src, dst, ttl);
1202 }
1203 
1204 void
1206  Ipv6Address dst,
1207  Icmpv6Header& icmpv6Hdr,
1208  uint8_t ttl)
1209 {
1210  NS_LOG_FUNCTION(this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
1212  NS_ASSERT(ipv6 && ipv6->GetRoutingProtocol());
1213  Ipv6Header header;
1215  Socket::SocketErrno err;
1216  Ptr<Ipv6Route> route;
1217  Ptr<NetDevice> oif(nullptr); // specify non-zero if bound to a source address
1218 
1219  header.SetDestination(dst);
1220  route = ipv6->GetRoutingProtocol()->RouteOutput(packet, header, oif, err);
1221 
1222  if (route)
1223  {
1224  NS_LOG_LOGIC("Route exists");
1225  tag.SetHopLimit(ttl);
1226  packet->AddPacketTag(tag);
1227  Ipv6Address src = route->GetSource();
1228 
1229  icmpv6Hdr.CalculatePseudoHeaderChecksum(src,
1230  dst,
1231  packet->GetSize() + icmpv6Hdr.GetSerializedSize(),
1232  PROT_NUMBER);
1233  packet->AddHeader(icmpv6Hdr);
1234  m_downTarget(packet, src, dst, PROT_NUMBER, route);
1235  }
1236  else
1237  {
1238  NS_LOG_WARN("drop icmp message");
1239  }
1240 }
1241 
1242 void
1243 Icmpv6L4Protocol::SendNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1244 {
1245  NS_LOG_FUNCTION(this << src << dst << hardwareAddress << static_cast<uint32_t>(flags));
1246  Ptr<Packet> p = Create<Packet>();
1247  Icmpv6NA na;
1248  Icmpv6OptionLinkLayerAddress llOption(false, *hardwareAddress); /* not a source link layer */
1249 
1250  NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1251  na.SetIpv6Target(src);
1252 
1253  if (flags & 1)
1254  {
1255  na.SetFlagO(true);
1256  }
1257  if ((flags & 2) && src != Ipv6Address::GetAny())
1258  {
1259  na.SetFlagS(true);
1260  }
1261  if (flags & 4)
1262  {
1263  na.SetFlagR(true);
1264  }
1265 
1266  p->AddHeader(llOption);
1268  p->AddHeader(na);
1269 
1270  SendMessage(p, src, dst, 255);
1271 }
1272 
1273 void
1275  Ipv6Address dst,
1276  uint16_t id,
1277  uint16_t seq,
1278  Ptr<Packet> data)
1279 {
1280  NS_LOG_FUNCTION(this << src << dst << id << seq << data);
1281  Ptr<Packet> p = data->Copy();
1282  Icmpv6Echo reply(false); /* echo reply */
1283 
1284  reply.SetId(id);
1285  reply.SetSeq(seq);
1286 
1288  dst,
1289  p->GetSize() + reply.GetSerializedSize(),
1290  PROT_NUMBER);
1291  p->AddHeader(reply);
1292  SendMessage(p, src, dst, 64);
1293 }
1294 
1295 void
1297  Ipv6Address dst,
1298  Ipv6Address target,
1299  Address hardwareAddress)
1300 {
1301  NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1302  Ptr<Packet> p = Create<Packet>();
1303  /* Ipv6Header ipHeader; */
1304  Icmpv6NS ns(target);
1306  true,
1307  hardwareAddress); /* we give our mac address in response */
1308 
1309  /* if the source is unspec, multicast the NA to all-nodes multicast */
1310  if (src == Ipv6Address::GetAny())
1311  {
1313  }
1314 
1315  NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1316 
1317  p->AddHeader(llOption);
1319  p->AddHeader(ns);
1320  if (!dst.IsMulticast())
1321  {
1322  SendMessage(p, src, dst, 255);
1323  }
1324  else
1325  {
1326  NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1329  this,
1330  p,
1331  src,
1332  dst,
1333  255);
1334  }
1335 }
1336 
1337 void
1339 {
1340  NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1341  Ptr<Packet> p = Create<Packet>();
1342  Icmpv6RS rs;
1343 
1344  // RFC 4861:
1345  // The link-layer address of the sender MUST NOT be included if the Source Address is the
1346  // unspecified address. Otherwise, it SHOULD be included on link layers that have addresses.
1347  if (!src.IsAny())
1348  {
1349  Icmpv6OptionLinkLayerAddress llOption(true, hardwareAddress);
1350  p->AddHeader(llOption);
1351  }
1352 
1353  if (!src.IsAny())
1354  {
1356  if (ipv6->GetInterfaceForAddress(src) == -1)
1357  {
1358  NS_LOG_INFO("Preventing RS from being sent or rescheduled because the source address "
1359  << src << " has been removed");
1360  return;
1361  }
1362  }
1363 
1364  NS_LOG_LOGIC("Send RS (from " << src << " to " << dst << ")");
1365 
1367  p->AddHeader(rs);
1368  if (!dst.IsMulticast())
1369  {
1370  SendMessage(p, src, dst, 255);
1371  }
1372  else
1373  {
1374  NS_LOG_LOGIC("Destination is Multicast, using DelayedSendMessage");
1375  Time rsDelay = Time(0);
1376  Time rsTimeout = Time(0);
1377 
1378  if (m_rsRetransmissionCount == 0)
1379  {
1380  // First RS transmission - also add some jitter to desynchronize nodes.
1384  }
1385  else
1386  {
1387  // Following RS transmission - adding further jitter is unnecessary.
1389  if (rsTimeout > m_rsMaxRetransmissionTime)
1390  {
1392  }
1393  }
1394  m_rsPrevRetransmissionTimeout = rsTimeout;
1395  Simulator::Schedule(rsDelay, &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
1398  this,
1399  src,
1400  dst,
1401  hardwareAddress);
1402  }
1403 }
1404 
1405 void
1407 {
1408  NS_LOG_FUNCTION(this << src << dst << hardwareAddress);
1409 
1410  if (m_rsMaxRetransmissionCount == 0)
1411  {
1412  // Unbound number of retransmissions - just add one to signal that we're in retransmission
1413  // mode.
1415  }
1416  else
1417  {
1420  {
1421  NS_LOG_LOGIC("Maximum number of multicast RS reached, giving up.");
1422  return;
1423  }
1424  }
1425 
1426  if (m_rsMaxRetransmissionDuration != Time(0) &&
1428  {
1429  NS_LOG_LOGIC("Maximum RS retransmission time reached, giving up.");
1430  return;
1431  }
1432 
1433  SendRS(src, dst, hardwareAddress);
1434 }
1435 
1436 void
1438  Ipv6Address dst,
1439  uint8_t code)
1440 {
1441  NS_LOG_FUNCTION(this << malformedPacket << dst << (uint32_t)code);
1442  uint32_t malformedPacketSize = malformedPacket->GetSize();
1444  header.SetCode(code);
1445 
1446  NS_LOG_LOGIC("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1447 
1448  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1449  if (malformedPacketSize <= 1280 - 48)
1450  {
1451  header.SetPacket(malformedPacket);
1452  SendMessage(malformedPacket, dst, header, 255);
1453  }
1454  else
1455  {
1456  Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1457  header.SetPacket(fragment);
1458  SendMessage(fragment, dst, header, 255);
1459  }
1460 }
1461 
1462 void
1463 Icmpv6L4Protocol::SendErrorTooBig(Ptr<Packet> malformedPacket, Ipv6Address dst, uint32_t mtu)
1464 {
1465  NS_LOG_FUNCTION(this << malformedPacket << dst << mtu);
1466  uint32_t malformedPacketSize = malformedPacket->GetSize();
1467  Icmpv6TooBig header;
1468  header.SetCode(0);
1469  header.SetMtu(mtu);
1470 
1471  NS_LOG_LOGIC("Send Too Big ( to " << dst << " )");
1472 
1473  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1474  if (malformedPacketSize <= 1280 - 48)
1475  {
1476  header.SetPacket(malformedPacket);
1477  SendMessage(malformedPacket, dst, header, 255);
1478  }
1479  else
1480  {
1481  Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1482  header.SetPacket(fragment);
1483  SendMessage(fragment, dst, header, 255);
1484  }
1485 }
1486 
1487 void
1489 {
1490  NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code));
1491  uint32_t malformedPacketSize = malformedPacket->GetSize();
1492  Icmpv6TimeExceeded header;
1493  header.SetCode(code);
1494 
1495  NS_LOG_LOGIC("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1496 
1497  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1498  if (malformedPacketSize <= 1280 - 48)
1499  {
1500  header.SetPacket(malformedPacket);
1501  SendMessage(malformedPacket, dst, header, 255);
1502  }
1503  else
1504  {
1505  Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1506  header.SetPacket(fragment);
1507  SendMessage(fragment, dst, header, 255);
1508  }
1509 }
1510 
1511 void
1513  Ipv6Address dst,
1514  uint8_t code,
1515  uint32_t ptr)
1516 {
1517  NS_LOG_FUNCTION(this << malformedPacket << dst << static_cast<uint32_t>(code) << ptr);
1518  uint32_t malformedPacketSize = malformedPacket->GetSize();
1519  Icmpv6ParameterError header;
1520  header.SetCode(code);
1521  header.SetPtr(ptr);
1522 
1523  NS_LOG_LOGIC("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1524 
1525  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1526  if (malformedPacketSize <= 1280 - 48)
1527  {
1528  header.SetPacket(malformedPacket);
1529  SendMessage(malformedPacket, dst, header, 255);
1530  }
1531  else
1532  {
1533  Ptr<Packet> fragment = malformedPacket->CreateFragment(0, 1280 - 48);
1534  header.SetPacket(fragment);
1535  SendMessage(fragment, dst, header, 255);
1536  }
1537 }
1538 
1539 void
1541  Ipv6Address src,
1542  Ipv6Address dst,
1543  Ipv6Address redirTarget,
1544  Ipv6Address redirDestination,
1545  Address redirHardwareTarget)
1546 {
1547  NS_LOG_FUNCTION(this << redirectedPacket << dst << redirTarget << redirDestination
1548  << redirHardwareTarget);
1549  uint32_t llaSize = 0;
1550  Ptr<Packet> p = Create<Packet>();
1551  uint32_t redirectedPacketSize = redirectedPacket->GetSize();
1552  Icmpv6OptionLinkLayerAddress llOption(false);
1553 
1554  NS_LOG_LOGIC("Send Redirection ( to " << dst << " target " << redirTarget << " destination "
1555  << redirDestination << " )");
1556 
1557  Icmpv6OptionRedirected redirectedOptionHeader;
1558 
1559  if ((redirectedPacketSize % 8) != 0)
1560  {
1561  Ptr<Packet> pad = Create<Packet>(8 - (redirectedPacketSize % 8));
1562  redirectedPacket->AddAtEnd(pad);
1563  }
1564 
1565  if (redirHardwareTarget.GetLength())
1566  {
1567  llOption.SetAddress(redirHardwareTarget);
1568  llaSize = llOption.GetSerializedSize();
1569  }
1570 
1571  /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1572  if (redirectedPacketSize <= (1280 - 56 - llaSize))
1573  {
1574  redirectedOptionHeader.SetPacket(redirectedPacket);
1575  }
1576  else
1577  {
1578  Ptr<Packet> fragment = redirectedPacket->CreateFragment(0, 1280 - 56 - llaSize);
1579  redirectedOptionHeader.SetPacket(fragment);
1580  }
1581 
1582  p->AddHeader(redirectedOptionHeader);
1583 
1584  if (llaSize)
1585  {
1586  p->AddHeader(llOption);
1587  }
1588 
1589  Icmpv6Redirection redirectionHeader;
1590  redirectionHeader.SetTarget(redirTarget);
1591  redirectionHeader.SetDestination(redirDestination);
1592  redirectionHeader.CalculatePseudoHeaderChecksum(src,
1593  dst,
1594  p->GetSize() +
1595  redirectionHeader.GetSerializedSize(),
1596  PROT_NUMBER);
1597  p->AddHeader(redirectionHeader);
1598 
1599  SendMessage(p, src, dst, 64);
1600 }
1601 
1603 Icmpv6L4Protocol::ForgeNA(Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1604 {
1605  NS_LOG_FUNCTION(this << src << dst << hardwareAddress << (uint32_t)flags);
1606  Ptr<Packet> p = Create<Packet>();
1607  Ipv6Header ipHeader;
1608  Icmpv6NA na;
1610  false,
1611  *hardwareAddress); /* we give our mac address in response */
1612 
1613  NS_LOG_LOGIC("Send NA ( from " << src << " to " << dst << ")");
1614 
1615  /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet
1616  * does not pass by Icmpv6L4Protocol::Lookup again */
1617 
1618  p->AddHeader(llOption);
1619  na.SetIpv6Target(src);
1620 
1621  if (flags & 1)
1622  {
1623  na.SetFlagO(true);
1624  }
1625  if ((flags & 2) && src != Ipv6Address::GetAny())
1626  {
1627  na.SetFlagS(true);
1628  }
1629  if (flags & 4)
1630  {
1631  na.SetFlagR(true);
1632  }
1633 
1635  p->AddHeader(na);
1636 
1637  ipHeader.SetSource(src);
1638  ipHeader.SetDestination(dst);
1639  ipHeader.SetNextHeader(PROT_NUMBER);
1640  ipHeader.SetPayloadLength(p->GetSize());
1641  ipHeader.SetHopLimit(255);
1642 
1643  return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1644 }
1645 
1648  Ipv6Address dst,
1649  Ipv6Address target,
1650  Address hardwareAddress)
1651 {
1652  NS_LOG_FUNCTION(this << src << dst << target << hardwareAddress);
1653  Ptr<Packet> p = Create<Packet>();
1654  Ipv6Header ipHeader;
1655  Icmpv6NS ns(target);
1657  true,
1658  hardwareAddress); /* we give our mac address in response */
1659 
1660  NS_LOG_LOGIC("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1661 
1662  p->AddHeader(llOption);
1664  p->AddHeader(ns);
1665 
1666  ipHeader.SetSource(src);
1667  ipHeader.SetDestination(dst);
1668  ipHeader.SetNextHeader(PROT_NUMBER);
1669  ipHeader.SetPayloadLength(p->GetSize());
1670  ipHeader.SetHopLimit(255);
1671 
1672  return NdiscCache::Ipv6PayloadHeaderPair(p, ipHeader);
1673 }
1674 
1677 {
1678  NS_LOG_FUNCTION(this << device);
1679 
1680  for (auto i = m_cacheList.begin(); i != m_cacheList.end(); i++)
1681  {
1682  if ((*i)->GetDevice() == device)
1683  {
1684  return *i;
1685  }
1686  }
1687 
1688  NS_ASSERT_MSG(false, "Icmpv6L4Protocol can not find a NDIS Cache for device " << device);
1689  /* quiet compiler */
1690  return nullptr;
1691 }
1692 
1695 {
1696  NS_LOG_FUNCTION(this << device << interface);
1697 
1698  Ptr<NdiscCache> cache = CreateObject<NdiscCache>();
1699 
1700  cache->SetDevice(device, interface, this);
1701  device->AddLinkChangeCallback(MakeCallback(&NdiscCache::Flush, cache));
1702  m_cacheList.push_back(cache);
1703  return cache;
1704 }
1705 
1706 bool
1708  Ptr<NetDevice> device,
1709  Ptr<NdiscCache> cache,
1710  Address* hardwareDestination)
1711 {
1712  NS_LOG_FUNCTION(this << dst << device << cache << hardwareDestination);
1713 
1714  if (!cache)
1715  {
1716  /* try to find the cache */
1717  cache = FindCache(device);
1718  }
1719  if (cache)
1720  {
1721  NdiscCache::Entry* entry = cache->Lookup(dst);
1722  if (entry)
1723  {
1724  if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1725  entry->IsAutoGenerated())
1726  {
1727  *hardwareDestination = entry->GetMacAddress();
1728  return true;
1729  }
1730  else if (entry->IsStale())
1731  {
1732  entry->StartDelayTimer();
1733  entry->MarkDelay();
1734  *hardwareDestination = entry->GetMacAddress();
1735  return true;
1736  }
1737  }
1738  }
1739  return false;
1740 }
1741 
1742 bool
1744  const Ipv6Header& ipHeader,
1745  Ipv6Address dst,
1746  Ptr<NetDevice> device,
1747  Ptr<NdiscCache> cache,
1748  Address* hardwareDestination)
1749 {
1750  NS_LOG_FUNCTION(this << p << ipHeader << dst << device << cache << hardwareDestination);
1751 
1752  if (!cache)
1753  {
1754  /* try to find the cache */
1755  cache = FindCache(device);
1756  }
1757  if (!cache)
1758  {
1759  return false;
1760  }
1761 
1762  NdiscCache::Entry* entry = cache->Lookup(dst);
1763  if (entry)
1764  {
1765  if (entry->IsReachable() || entry->IsDelay() || entry->IsPermanent() ||
1766  entry->IsAutoGenerated())
1767  {
1768  /* XXX check reachability time */
1769  /* send packet */
1770  *hardwareDestination = entry->GetMacAddress();
1771  return true;
1772  }
1773  else if (entry->IsStale())
1774  {
1775  /* start delay timer */
1776  entry->StartDelayTimer();
1777  entry->MarkDelay();
1778  *hardwareDestination = entry->GetMacAddress();
1779  return true;
1780  }
1781  else /* INCOMPLETE or PROBE */
1782  {
1783  /* queue packet */
1785  return false;
1786  }
1787  }
1788  else
1789  {
1790  /* we contact this node for the first time
1791  * add it to the cache and send an NS
1792  */
1793  Ipv6Address addr;
1794  NdiscCache::Entry* entry = cache->Add(dst);
1796  entry->SetRouter(false);
1797 
1798  if (dst.IsLinkLocal())
1799  {
1800  addr = cache->GetInterface()->GetLinkLocalAddress().GetAddress();
1801  }
1802  else if (cache->GetInterface()->GetNAddresses() ==
1803  1) /* an interface have at least one address (link-local) */
1804  {
1805  /* try to resolve global address without having global address so return! */
1806  cache->Remove(entry);
1807  return false;
1808  }
1809  else
1810  {
1811  /* find source address that match destination */
1812  addr = cache->GetInterface()->GetAddressMatchingDestination(dst).GetAddress();
1813  }
1814 
1815  SendNS(addr, Ipv6Address::MakeSolicitedAddress(dst), dst, cache->GetDevice()->GetAddress());
1816 
1817  /* start retransmit timer */
1818  entry->StartRetransmitTimer();
1819  return false;
1820  }
1821 
1822  return false;
1823 }
1824 
1825 void
1827 {
1828  NS_LOG_FUNCTION(this << interface << addr);
1829 
1830  Ipv6InterfaceAddress ifaddr;
1831  bool found = false;
1832  uint32_t i = 0;
1833  uint32_t nb = interface->GetNAddresses();
1834 
1835  for (i = 0; i < nb; i++)
1836  {
1837  ifaddr = interface->GetAddress(i);
1838 
1839  if (ifaddr.GetAddress() == addr)
1840  {
1841  found = true;
1842  break;
1843  }
1844  }
1845 
1846  if (!found)
1847  {
1848  NS_LOG_LOGIC("Can not find the address in the interface.");
1849  }
1850 
1851  /* for the moment, this function is always called, if we was victim of a DAD the address is
1852  * INVALID and we do not set it to PREFERRED
1853  */
1854  if (found && ifaddr.GetState() != Ipv6InterfaceAddress::INVALID)
1855  {
1856  interface->SetState(ifaddr.GetAddress(), Ipv6InterfaceAddress::PREFERRED);
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 
1888 void
1890 {
1891  NS_LOG_FUNCTION(this << &callback);
1892 }
1893 
1894 void
1896 {
1897  NS_LOG_FUNCTION(this << &callback);
1898  m_downTarget = callback;
1899 }
1900 
1903 {
1904  NS_LOG_FUNCTION(this);
1906 }
1907 
1910 {
1911  NS_LOG_FUNCTION(this);
1912  return m_downTarget;
1913 }
1914 
1915 uint8_t
1917 {
1918  return m_maxMulticastSolicit;
1919 }
1920 
1921 uint8_t
1923 {
1924  return m_maxUnicastSolicit;
1925 }
1926 
1927 Time
1929 {
1930  return m_reachableTime;
1931 }
1932 
1933 Time
1935 {
1936  return m_retransmissionTime;
1937 }
1938 
1939 Time
1941 {
1942  return m_delayFirstProbe;
1943 }
1944 
1945 Time
1947 {
1948  return m_dadTimeout;
1949 }
1950 
1951 } /* namespace ns3 */
a polymophic address class
Definition: address.h:101
uint8_t GetLength() const
Get the length of the underlying address.
Definition: address.cc:78
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:575
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
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.
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].
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.
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:49
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:35
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:455
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:331
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:352
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:861
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:960
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:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
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:668
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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
#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_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#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:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:839
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
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:704
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Definition: integer.h:46
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
uint8_t data[writeSize]