A Discrete-Event Network Simulator
API
icmpv6-l4-protocol.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2007-2009 Strasbourg University
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
19  * David Gross <gdavid.devel@gmail.com>
20  * Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
21  * Tommaso Pecorella <tommaso.pecorella@unifi.it>
22  */
23 
24 #include "ns3/log.h"
25 #include "ns3/assert.h"
26 #include "ns3/packet.h"
27 #include "ns3/node.h"
28 #include "ns3/boolean.h"
29 #include "ns3/ipv6-routing-protocol.h"
30 #include "ns3/ipv6-route.h"
31 #include "ns3/pointer.h"
32 #include "ns3/string.h"
33 #include "ns3/integer.h"
34 
35 #include "ipv6-l3-protocol.h"
36 #include "ipv6-interface.h"
37 #include "icmpv6-l4-protocol.h"
38 
39 namespace ns3 {
40 
41 NS_LOG_COMPONENT_DEFINE ("Icmpv6L4Protocol");
42 
43 NS_OBJECT_ENSURE_REGISTERED (Icmpv6L4Protocol);
44 
45 const uint8_t Icmpv6L4Protocol::PROT_NUMBER = 58;
46 
47 //const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERT_INTERVAL = 16; // max initial RA initial interval.
48 //const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERTISEMENTS = 3; // max initial RA transmission.
49 //const uint8_t Icmpv6L4Protocol::MAX_FINAL_RTR_ADVERTISEMENTS = 3; // max final RA transmission.
50 //const uint8_t Icmpv6L4Protocol::MIN_DELAY_BETWEEN_RAS = 3; // min delay between RA.
51 //const uint32_t Icmpv6L4Protocol::MAX_RA_DELAY_TIME = 500; // millisecond - max delay between RA.
52 
53 //const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATION_DELAY = 1; // max RS delay.
54 //const uint8_t Icmpv6L4Protocol::RTR_SOLICITATION_INTERVAL = 4; // RS interval.
55 //const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATIONS = 3; // max RS transmission.
56 
57 //const uint8_t Icmpv6L4Protocol::MAX_ANYCAST_DELAY_TIME = 1; // max anycast delay.
58 //const uint8_t Icmpv6L4Protocol::MAX_NEIGHBOR_ADVERTISEMENT = 3; // max NA transmission.
59 
60 //const double Icmpv6L4Protocol::MIN_RANDOM_FACTOR = 0.5; // min random factor.
61 //const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5; // max random factor.
62 
64 {
65  static TypeId tid = TypeId ("ns3::Icmpv6L4Protocol")
67  .SetGroupName ("Internet")
68  .AddConstructor<Icmpv6L4Protocol> ()
69  .AddAttribute ("DAD", "Always do DAD check.",
70  BooleanValue (true),
73  .AddAttribute ("SolicitationJitter", "The jitter in ms a node is allowed to wait before sending any solicitation. Some jitter aims to prevent collisions. By default, the model will wait for a duration in ms defined by a uniform random-variable between 0 and SolicitationJitter",
74  StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
76  MakePointerChecker<RandomVariableStream> ())
77  .AddAttribute ("MaxMulticastSolicit", "Neighbor Discovery node constants: max multicast solicitations.",
78  IntegerValue (3),
80  MakeIntegerChecker<uint8_t> ())
81  .AddAttribute ("MaxUnicastSolicit", "Neighbor Discovery node constants: max unicast solicitations.",
82  IntegerValue (3),
84  MakeIntegerChecker<uint8_t> ())
85  .AddAttribute ("ReachableTime", "Neighbor Discovery node constants: reachable time.",
86  TimeValue (Seconds (30)),
88  MakeTimeChecker ())
89  .AddAttribute ("RetransmissionTime", "Neighbor Discovery node constants: retransmission timer.",
90  TimeValue (Seconds (1)),
92  MakeTimeChecker ())
93  .AddAttribute ("DelayFirstProbe", "Neighbor Discovery node constants: delay for the first probe.",
94  TimeValue (Seconds (5)),
96  MakeTimeChecker ())
97  ;
98  return tid;
99 }
100 
102 {
103  NS_LOG_FUNCTION (this);
104  return Icmpv6L4Protocol::GetTypeId ();
105 }
106 
108  : m_node (0)
109 {
110  NS_LOG_FUNCTION (this);
111 }
112 
114 {
115  NS_LOG_FUNCTION (this);
116 }
117 
119 {
120  NS_LOG_FUNCTION (this);
121  for (CacheList::const_iterator it = m_cacheList.begin (); it != m_cacheList.end (); it++)
122  {
123  Ptr<NdiscCache> cache = *it;
124  cache->Dispose ();
125  cache = 0;
126  }
127  m_cacheList.clear ();
129 
130  m_node = 0;
132 }
133 
134 int64_t Icmpv6L4Protocol::AssignStreams (int64_t stream)
135 {
136  NS_LOG_FUNCTION (this << stream);
138  return 1;
139 }
140 
142 {
143  NS_LOG_FUNCTION (this);
144  if (m_node == 0)
145  {
146  Ptr<Node> node = this->GetObject<Node> ();
147  if (node != 0)
148  {
149  Ptr<Ipv6> ipv6 = this->GetObject<Ipv6> ();
150  if (ipv6 != 0 && m_downTarget.IsNull ())
151  {
152  SetNode (node);
153  ipv6->Insert (this);
155  }
156  }
157  }
159 }
160 
162 {
163  NS_LOG_FUNCTION (this << node);
164  m_node = node;
165 }
166 
168 {
169  NS_LOG_FUNCTION (this);
170  return m_node;
171 }
172 
174 {
176  return PROT_NUMBER;
177 }
178 
180 {
181  NS_LOG_FUNCTION (this);
182  return PROT_NUMBER;
183 }
184 
186 {
187  NS_LOG_FUNCTION (this);
188  return 1;
189 }
190 
192 {
193  NS_LOG_FUNCTION (this);
194  return m_alwaysDad;
195 }
196 
198 {
199  NS_LOG_FUNCTION (this << target << interface);
200  Ipv6Address addr;
202 
203  NS_ASSERT (ipv6);
204 
205  if (!m_alwaysDad)
206  {
207  return;
208  }
209 
212  NdiscCache::Ipv6PayloadHeaderPair p = ForgeNS ("::",Ipv6Address::MakeSolicitedAddress (target), target, interface->GetDevice ()->GetAddress ());
213 
214  /* update last packet UID */
215  interface->SetNsDadUid (target, p.first->GetUid ());
217 }
218 
220 {
221  NS_LOG_FUNCTION (this << packet << header);
223 }
224 
225 enum IpL4Protocol::RxStatus Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv6Header const &header, Ptr<Ipv6Interface> interface)
226 {
227  NS_LOG_FUNCTION (this << packet << header.GetSourceAddress () << header.GetDestinationAddress () << interface);
228  Ptr<Packet> p = packet->Copy ();
229  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
230 
231  /* very ugly! try to find something better in the future */
232  uint8_t type;
233  p->CopyData (&type, sizeof(type));
234 
235  switch (type)
236  {
238  if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
239  {
240  HandleRS (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
241  }
242  break;
244  if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
245  {
246  HandleRA (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
247  }
248  break;
250  HandleNS (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
251  break;
253  HandleNA (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
254  break;
256  HandleRedirection (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
257  break;
259  HandleEchoRequest (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
260  break;
262  // EchoReply does not contain any info about L4
263  // so we can not forward it up.
265  break;
267  HandleDestinationUnreachable (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
268  break;
270  HandlePacketTooBig (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
271  break;
273  HandleTimeExceeded (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
274  break;
276  HandleParameterError (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
277  break;
278  default:
279  NS_LOG_LOGIC ("Unknown ICMPv6 message type=" << type);
280  break;
281  }
282 
283  return IpL4Protocol::RX_OK;
284 }
285 
287  uint32_t info, Ipv6Header ipHeader,
288  const uint8_t payload[8])
289 {
290  NS_LOG_FUNCTION (this << source << icmp << info << ipHeader << payload);
291 
293 
295 
296  uint8_t nextHeader = ipHeader.GetNextHeader ();
297 
298  if (nextHeader != Icmpv6L4Protocol::PROT_NUMBER)
299  {
300  Ptr<IpL4Protocol> l4 = ipv6->GetProtocol (nextHeader);
301  if (l4 != 0)
302  {
303  l4->ReceiveIcmp (source, ipHeader.GetHopLimit (), icmp.GetType (), icmp.GetCode (),
304  info, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress (), payload);
305  }
306  }
307 }
308 
310 {
311  NS_LOG_FUNCTION (this << packet << src << dst << interface);
312  Icmpv6Echo request;
313  uint8_t* buf = new uint8_t[packet->GetSize ()];
314 
315  packet->RemoveHeader (request);
316  /* XXX IPv6 extension: obtain a fresh copy of data otherwise it crash... */
317  packet->CopyData (buf, packet->GetSize ());
318  Ptr<Packet> p = Create<Packet> (buf, packet->GetSize ());
319 
320  /* if we send message from ff02::* (link-local multicast), we use our link-local address */
321  SendEchoReply (dst.IsMulticast () ? interface->GetLinkLocalAddress ().GetAddress () : dst, src, request.GetId (), request.GetSeq (), p);
322  delete[] buf;
323 }
324 
325 void Icmpv6L4Protocol::HandleRA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
326 {
327  NS_LOG_FUNCTION (this << packet << src << dst << interface);
328  Ptr<Packet> p = packet->Copy ();
329  Icmpv6RA raHeader;
332  Icmpv6OptionMtu mtuHdr;
334  bool next = true;
335  bool hasLla = false;
336  bool hasMtu = false;
337  Ipv6Address defaultRouter = Ipv6Address::GetZero ();
338 
339  p->RemoveHeader (raHeader);
340 
341  if (raHeader.GetLifeTime())
342  {
343  defaultRouter = src;
344  }
345 
346  while (next == true)
347  {
348  uint8_t type = 0;
349  p->CopyData (&type, sizeof(type));
350 
351  switch (type)
352  {
354  p->RemoveHeader (prefixHdr);
355  ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (interface->GetDevice ()), prefixHdr.GetPrefix (), prefixHdr.GetPrefixLength (),
356  prefixHdr.GetFlags (), prefixHdr.GetValidTime (), prefixHdr.GetPreferredTime (), defaultRouter);
357  break;
359  /* take in account the first MTU option */
360  if (!hasMtu)
361  {
362  p->RemoveHeader (mtuHdr);
363  hasMtu = true;
365  /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
366  }
367  break;
369  /* take in account the first LLA option */
370  if (!hasLla)
371  {
372  p->RemoveHeader (llaHdr);
373  ReceiveLLA (llaHdr, src, dst, interface);
374  hasLla = true;
375  }
376  break;
377  default:
378  /* unknown option, quit */
379  next = false;
380  }
381  }
382 }
383 
385 {
386  NS_LOG_FUNCTION (this << lla << src << dst << interface);
387  Address hardwareAddress;
388  NdiscCache::Entry* entry = 0;
389  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
390 
391  /* check if we have this address in our cache */
392  entry = cache->Lookup (src);
393 
394  if (!entry)
395  {
396  entry = cache->Add (src);
397  entry->SetRouter (true);
398  entry->SetMacAddress (lla.GetAddress ());
399  entry->MarkReachable ();
400  entry->StartReachableTimer ();
401  }
402  else
403  {
404  std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
405  if (entry->IsIncomplete ())
406  {
407  entry->StopNudTimer ();
408  // mark it to reachable
409  waiting = entry->MarkReachable (lla.GetAddress ());
410  entry->StartReachableTimer ();
411  // send out waiting packet
412  for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin (); it != waiting.end (); it++)
413  {
414  cache->GetInterface ()->Send (it->first, it->second, src);
415  }
416  entry->ClearWaitingPacket ();
417  }
418  else
419  {
420  if (entry->GetMacAddress () != lla.GetAddress ())
421  {
422  entry->SetMacAddress (lla.GetAddress ());
423  entry->MarkStale ();
424  entry->SetRouter (true);
425  }
426  else
427  {
428  if (!entry->IsReachable () || !entry->IsPermanent ())
429  {
430  entry->StopNudTimer ();
431  waiting = entry->MarkReachable (lla.GetAddress ());
432  if (entry->IsProbe ())
433  {
434  for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin (); it != waiting.end (); it++)
435  {
436  cache->GetInterface ()->Send (it->first, it->second, src);
437  }
438  }
439  if (!entry->IsPermanent ())
440  {
441  entry->StartReachableTimer ();
442  }
443  }
444  }
445  }
446  }
447 }
448 
449 void Icmpv6L4Protocol::HandleRS (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
450 {
451  NS_LOG_FUNCTION (this << packet << src << dst << interface);
453  Icmpv6RS rsHeader;
454  packet->RemoveHeader (rsHeader);
455  Address hardwareAddress;
457  NdiscCache::Entry* entry = 0;
458  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
459 
460  if (src != Ipv6Address::GetAny ())
461  {
462  /* XXX search all options following the RS header */
463  /* test if the next option is SourceLinkLayerAddress */
464  uint8_t type;
465  packet->CopyData (&type, sizeof(type));
466 
468  {
469  return;
470  }
471  packet->RemoveHeader (lla);
472  NS_LOG_LOGIC ("Cache updated by RS");
473 
474  entry = cache->Lookup (src);
475  if (!entry)
476  {
477  entry = cache->Add (src);
478  entry->SetRouter (false);
479  entry->MarkStale (lla.GetAddress ());
480  }
481  else if (entry->GetMacAddress () != lla.GetAddress ())
482  {
483  entry->MarkStale (lla.GetAddress ());
484  }
485  }
486 }
487 
488 void Icmpv6L4Protocol::HandleNS (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
489 {
490  NS_LOG_FUNCTION (this << packet << src << dst << interface);
491  Icmpv6NS nsHeader ("::");
492  Ipv6InterfaceAddress ifaddr;
493  uint32_t nb = interface->GetNAddresses ();
494  uint32_t i = 0;
495  bool found = false;
496 
497  packet->RemoveHeader (nsHeader);
498 
499  Ipv6Address target = nsHeader.GetIpv6Target ();
500 
501  for (i = 0; i < nb; i++)
502  {
503  ifaddr = interface->GetAddress (i);
504 
505  if (ifaddr.GetAddress () == target)
506  {
507  found = true;
508  break;
509  }
510  }
511 
512  if (!found)
513  {
514  NS_LOG_LOGIC ("Not a NS for us");
515  return;
516  }
517 
518  if (packet->GetUid () == ifaddr.GetNsDadUid ())
519  {
520  /* don't process our own DAD probe */
521  NS_LOG_LOGIC ("Hey we receive our DAD probe!");
522  return;
523  }
524 
525  NdiscCache::Entry* entry = 0;
526  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
527  uint8_t flags = 0;
528 
529  /* search all options following the NS header */
530  Icmpv6OptionLinkLayerAddress sllaoHdr (true);
531 
532  bool next = true;
533  bool hasSllao = false;
534 
535  while (next == true)
536  {
537  uint8_t type;
538  packet->CopyData (&type, sizeof (type));
539 
540  switch (type)
541  {
543  if (!hasSllao)
544  {
545  packet->RemoveHeader (sllaoHdr);
546  hasSllao = true;
547  }
548  break;
549  default:
550  /* unknow option, quit */
551  next = false;
552  }
553  if (packet->GetSize () == 0)
554  {
555  next = false;
556  }
557  }
558 
559  Address replyMacAddress;
560 
561  if (src != Ipv6Address::GetAny ())
562  {
563  entry = cache->Lookup (src);
564  if (!entry)
565  {
566  if (!hasSllao)
567  {
568  NS_LOG_LOGIC ("Icmpv6L4Protocol::HandleNS: NS without SLLAO and we do not have a NCE, discarding.");
569  return;
570  }
571  entry = cache->Add (src);
572  entry->SetRouter (false);
573  entry->MarkStale (sllaoHdr.GetAddress ());
574  replyMacAddress = sllaoHdr.GetAddress ();
575  }
576  else if (hasSllao && (entry->GetMacAddress () != sllaoHdr.GetAddress ()))
577  {
578  entry->MarkStale (sllaoHdr.GetAddress ());
579  replyMacAddress = sllaoHdr.GetAddress ();
580  }
581  else
582  {
583  replyMacAddress = entry->GetMacAddress ();
584  }
585 
586  flags = 3; /* S + O flags */
587  }
588  else
589  {
590  /* it's a DAD */
591  flags = 1; /* O flag */
592  replyMacAddress = interface->GetDevice ()->GetMulticast (dst);
593  }
594 
595  /* send a NA to src */
597 
598  if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
599  {
600  flags += 4; /* R flag */
601  }
602 
603  Address hardwareAddress = interface->GetDevice ()->GetAddress ();
605  src.IsAny () ? dst : src, // DAD replies must go to the multicast group it was sent to.
606  &hardwareAddress,
607  flags );
608 
609  // We must bypass the IPv6 layer, as a NA must be sent regardless of the NCE status (and not change it beyond what we did already).
610  Ptr<Packet> pkt = p.first;
611  pkt->AddHeader (p.second);
612  interface->GetDevice ()->Send (pkt, replyMacAddress, Ipv6L3Protocol::PROT_NUMBER);
613 }
614 
616 {
617  NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
618  Ptr<Packet> p = Create<Packet> ();
619  Ipv6Header ipHeader;
620  Icmpv6RS rs;
621 
622  NS_LOG_LOGIC ("Forge RS (from " << src << " to " << dst << ")");
623  // RFC 4861:
624  // The link-layer address of the sender MUST NOT be included if the Source Address is the unspecified address.
625  // Otherwise, it SHOULD be included on link layers that have addresses.
626  if (!src.IsAny ())
627  {
628  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
629  p->AddHeader (llOption);
630  }
631 
633  p->AddHeader (rs);
634 
635  ipHeader.SetSourceAddress (src);
636  ipHeader.SetDestinationAddress (dst);
637  ipHeader.SetNextHeader (PROT_NUMBER);
638  ipHeader.SetPayloadLength (p->GetSize ());
639  ipHeader.SetHopLimit (255);
640 
641  return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
642 }
643 
645 {
646  NS_LOG_FUNCTION (this << src << dst << id << seq << data);
647  Ptr<Packet> p = data->Copy ();
648  Ipv6Header ipHeader;
649  Icmpv6Echo req (1);
650 
651  req.SetId (id);
652  req.SetSeq (seq);
653 
654  req.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + req.GetSerializedSize (), PROT_NUMBER);
655  p->AddHeader (req);
656 
657  ipHeader.SetSourceAddress (src);
658  ipHeader.SetDestinationAddress (dst);
659  ipHeader.SetNextHeader (PROT_NUMBER);
660  ipHeader.SetPayloadLength (p->GetSize ());
661  ipHeader.SetHopLimit (255);
662 
663  return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
664 }
665 
666 void Icmpv6L4Protocol::HandleNA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
667 {
668  NS_LOG_FUNCTION (this << packet << src << dst << interface);
669  Icmpv6NA naHeader;
671 
672  packet->RemoveHeader (naHeader);
673  Ipv6Address target = naHeader.GetIpv6Target ();
674 
675  Address hardwareAddress;
676  NdiscCache::Entry* entry = 0;
677  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
678  std::list<NdiscCache::Ipv6PayloadHeaderPair> waiting;
679 
680  /* check if we have something in our cache */
681  entry = cache->Lookup (target);
682 
683  if (!entry)
684  {
685  /* ouch!! we might be victim of a DAD */
686 
687  Ipv6InterfaceAddress ifaddr;
688  bool found = false;
689  uint32_t i = 0;
690  uint32_t nb = interface->GetNAddresses ();
691 
692  for (i = 0; i < nb; i++)
693  {
694  ifaddr = interface->GetAddress (i);
695  if (ifaddr.GetAddress () == target)
696  {
697  found = true;
698  break;
699  }
700  }
701 
702  if (found)
703  {
705  {
706  interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::INVALID);
707  }
708  }
709 
710  /* we have not initiated any communication with the target so... discard the NA */
711  return;
712  }
713 
714  /* XXX search all options following the NA header */
715  /* Get LLA */
716  uint8_t type;
717  packet->CopyData (&type, sizeof(type));
718 
720  {
721  return;
722  }
723  packet->RemoveHeader (lla);
724 
725  if (entry->IsIncomplete ())
726  {
727  /* we receive a NA so stop the retransmission timer */
728  entry->StopNudTimer ();
729 
730  if (naHeader.GetFlagS ())
731  {
732  /* mark it to reachable */
733  waiting = entry->MarkReachable (lla.GetAddress ());
734  entry->StartReachableTimer ();
735  /* send out waiting packet */
736  for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin (); it != waiting.end (); it++)
737  {
738  cache->GetInterface ()->Send (it->first, it->second, src);
739  }
740  entry->ClearWaitingPacket ();
741  }
742  else
743  {
744  entry->MarkStale (lla.GetAddress ());
745  }
746 
747  if (naHeader.GetFlagR ())
748  {
749  entry->SetRouter (true);
750  }
751  }
752  else
753  {
754  /* we receive a NA so stop the probe timer or delay timer if any */
755  entry->StopNudTimer ();
756 
757  /* if the Flag O is clear and mac address differs from the cache */
758  if (!naHeader.GetFlagO () && lla.GetAddress () != entry->GetMacAddress ())
759  {
760  if (entry->IsReachable ())
761  {
762  entry->MarkStale ();
763  }
764  return;
765  }
766  else
767  {
768  if ((!naHeader.GetFlagO () && lla.GetAddress () == entry->GetMacAddress ()) || naHeader.GetFlagO ()) /* XXX lake "no target link-layer address option supplied" */
769  {
770  entry->SetMacAddress (lla.GetAddress ());
771 
772  if (naHeader.GetFlagS ())
773  {
774  if (!entry->IsReachable () || !entry->IsPermanent ())
775  {
776  if (entry->IsProbe ())
777  {
778  waiting = entry->MarkReachable (lla.GetAddress ());
779  for (std::list<NdiscCache::Ipv6PayloadHeaderPair>::const_iterator it = waiting.begin (); it != waiting.end (); it++)
780  {
781  cache->GetInterface ()->Send (it->first, it->second, src);
782  }
783  entry->ClearWaitingPacket ();
784  }
785  else
786  {
787  entry->MarkReachable (lla.GetAddress ());
788  }
789  }
790  if (!entry->IsPermanent ())
791  {
792  entry->StartReachableTimer ();
793  }
794  }
795  else if (lla.GetAddress () != entry->GetMacAddress ())
796  {
797  entry->MarkStale ();
798  }
799  entry->SetRouter (naHeader.GetFlagR ());
800  }
801  }
802  }
803 }
804 
806 {
807  NS_LOG_FUNCTION (this << packet << src << dst << interface);
808  bool hasLla = false;
809  Ptr<Packet> p = packet->Copy ();
810  Icmpv6OptionLinkLayerAddress llOptionHeader (0);
811 
812  Icmpv6Redirection redirectionHeader;
813  p->RemoveHeader (redirectionHeader);
814 
815  /* little ugly try to find a better way */
816  uint8_t type;
817  p->CopyData (&type, sizeof(type));
819  {
820  hasLla = true;
821  p->RemoveHeader (llOptionHeader);
822  }
823 
824  Icmpv6OptionRedirected redirectedOptionHeader;
825  p->RemoveHeader (redirectedOptionHeader);
826 
827  Ipv6Address redirTarget = redirectionHeader.GetTarget ();
828  Ipv6Address redirDestination = redirectionHeader.GetDestination ();
829 
830  if (hasLla)
831  {
832  /* update the cache if needed */
833  NdiscCache::Entry* entry = 0;
834  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
835 
836  entry = cache->Lookup (redirTarget);
837  if (!entry)
838  {
839  entry = cache->Add (redirTarget);
840  /* destination and target different => necessarily a router */
841  entry->SetRouter (redirTarget != redirDestination);
842  entry->SetMacAddress (llOptionHeader.GetAddress ());
843  entry->MarkStale ();
844  }
845  else
846  {
847  if (entry->IsIncomplete () || entry->GetMacAddress () != llOptionHeader.GetAddress ())
848  {
849  /* update entry to STALE */
850  if (entry->GetMacAddress () != llOptionHeader.GetAddress ())
851  {
852  entry->SetMacAddress (llOptionHeader.GetAddress ());
853  entry->MarkStale ();
854  }
855  }
856  else
857  {
858  /* stay unchanged */
859  }
860  }
861  }
862 
863  /* add redirection in routing table */
864  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
865 
866  if (redirTarget == redirDestination)
867  {
868  ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), Ipv6Address ("::"), ipv6->GetInterfaceForAddress (dst));
869  }
870  else
871  {
872  uint32_t ifIndex = ipv6->GetInterfaceForAddress (dst);
873  ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), redirTarget, ifIndex);
874  }
875 }
876 
878 {
879  NS_LOG_FUNCTION (this << *p << src << dst << interface);
880  Ptr<Packet> pkt = p->Copy ();
881 
883  pkt->RemoveHeader (unreach);
884  Ptr<Packet> origPkt = unreach.GetPacket ();
885 
886  Ipv6Header ipHeader;
887  if ( origPkt->GetSize () > ipHeader.GetSerializedSize () )
888  {
889  origPkt->RemoveHeader (ipHeader);
890  uint8_t payload[8];
891  origPkt->CopyData (payload, 8);
892  Forward (src, unreach, unreach.GetCode (), ipHeader, payload);
893  }
894 }
895 
897 {
898  NS_LOG_FUNCTION (this << *p << src << dst << interface);
899  Ptr<Packet> pkt = p->Copy ();
900 
901  Icmpv6TimeExceeded timeexceeded;
902  pkt->RemoveHeader (timeexceeded);
903  Ptr<Packet> origPkt = timeexceeded.GetPacket ();
904  Ipv6Header ipHeader;
905  uint8_t payload[8];
906  origPkt->RemoveHeader (ipHeader);
907  origPkt->CopyData (payload, 8);
908 
909  Forward (src, timeexceeded, timeexceeded.GetCode (), ipHeader, payload);
910 }
911 
913 {
914  NS_LOG_FUNCTION (this << *p << src << dst << interface);
915  Ptr<Packet> pkt = p->Copy ();
916 
917  Icmpv6TooBig tooBig;
918  pkt->RemoveHeader (tooBig);
919  Ptr<Packet> origPkt = tooBig.GetPacket ();
920 
921  Ipv6Header ipHeader;
922  origPkt->RemoveHeader (ipHeader);
923  uint8_t payload[8];
924  origPkt->CopyData (payload, 8);
925 
927  ipv6->SetPmtu(ipHeader.GetDestinationAddress(), tooBig.GetMtu ());
928 
929  Forward (src, tooBig, tooBig.GetMtu (), ipHeader, payload);
930 }
931 
933 {
934  NS_LOG_FUNCTION (this << *p << src << dst << interface);
935  Ptr<Packet> pkt = p->Copy ();
936 
937  Icmpv6ParameterError paramErr;
938  pkt->RemoveHeader (paramErr);
939  Ptr<Packet> origPkt = paramErr.GetPacket ();
940 
941  Ipv6Header ipHeader;
942  origPkt->RemoveHeader (ipHeader);
943  uint8_t payload[8];
944  origPkt->CopyData (payload, 8);
945  Forward (src, paramErr, paramErr.GetCode (), ipHeader, payload);
946 }
947 
949 {
950  NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
953  NS_ASSERT (ipv6 != 0);
954 
955  tag.SetHopLimit (ttl);
956  packet->AddPacketTag (tag);
957  m_downTarget (packet, src, dst, PROT_NUMBER, 0);
958 }
959 
961 {
962  NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
963  SendMessage (packet, src, dst, ttl);
964 }
965 
966 void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl)
967 {
968  NS_LOG_FUNCTION (this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
970  NS_ASSERT (ipv6 != 0 && ipv6->GetRoutingProtocol () != 0);
971  Ipv6Header header;
974  Ptr<Ipv6Route> route;
975  Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
976 
977  header.SetDestinationAddress (dst);
978  route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, err);
979 
980  if (route != 0)
981  {
982  NS_LOG_LOGIC ("Route exists");
983  tag.SetHopLimit (ttl);
984  packet->AddPacketTag (tag);
985  Ipv6Address src = route->GetSource ();
986 
987  icmpv6Hdr.CalculatePseudoHeaderChecksum (src, dst, packet->GetSize () + icmpv6Hdr.GetSerializedSize (), PROT_NUMBER);
988  packet->AddHeader (icmpv6Hdr);
989  m_downTarget (packet, src, dst, PROT_NUMBER, route);
990  }
991  else
992  {
993  NS_LOG_WARN ("drop icmp message");
994  }
995 }
996 
997 void Icmpv6L4Protocol::SendNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
998 {
999  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << static_cast<uint32_t> (flags));
1000  Ptr<Packet> p = Create<Packet> ();
1001  Icmpv6NA na;
1002  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* not a source link layer */
1003 
1004  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1005  na.SetIpv6Target (src);
1006 
1007  if ((flags & 1))
1008  {
1009  na.SetFlagO (true);
1010  }
1011  if ((flags & 2) && src != Ipv6Address::GetAny ())
1012  {
1013  na.SetFlagS (true);
1014  }
1015  if ((flags & 4))
1016  {
1017  na.SetFlagR (true);
1018  }
1019 
1020  p->AddHeader (llOption);
1022  p->AddHeader (na);
1023 
1024  SendMessage (p, src, dst, 255);
1025 }
1026 
1027 void Icmpv6L4Protocol::SendEchoReply (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr<Packet> data)
1028 {
1029  NS_LOG_FUNCTION (this << src << dst << id << seq << data);
1030  Ptr<Packet> p = data->Copy ();
1031  Icmpv6Echo reply (0); /* echo reply */
1032 
1033  reply.SetId (id);
1034  reply.SetSeq (seq);
1035 
1036  reply.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + reply.GetSerializedSize (), PROT_NUMBER);
1037  p->AddHeader (reply);
1038  SendMessage (p, src, dst, 64);
1039 }
1040 
1041 void Icmpv6L4Protocol::SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
1042 {
1043  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
1044  Ptr<Packet> p = Create<Packet> ();
1045  /* Ipv6Header ipHeader; */
1046  Icmpv6NS ns (target);
1047  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1048 
1049  /* if the source is unspec, multicast the NA to all-nodes multicast */
1050  if (src == Ipv6Address::GetAny ())
1051  {
1053  }
1054 
1055  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1056 
1057  p->AddHeader (llOption);
1059  p->AddHeader (ns);
1060  if (!dst.IsMulticast ())
1061  {
1062  SendMessage (p, src, dst, 255);
1063  }
1064  else
1065  {
1066  NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
1068  }
1069 }
1070 
1072 {
1073  NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
1074  Ptr<Packet> p = Create<Packet> ();
1075  Icmpv6RS rs;
1076 
1077  // RFC 4861:
1078  // The link-layer address of the sender MUST NOT be included if the Source Address is the unspecified address.
1079  // Otherwise, it SHOULD be included on link layers that have addresses.
1080  if (!src.IsAny ())
1081  {
1082  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress);
1083  p->AddHeader (llOption);
1084  }
1085 
1086  NS_LOG_LOGIC ("Send RS (from " << src << " to " << dst << ")");
1087 
1089  p->AddHeader (rs);
1090  if (!dst.IsMulticast ())
1091  {
1092  SendMessage (p, src, dst, 255);
1093  }
1094  else
1095  {
1096  NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
1098  }
1099 }
1100 
1102 {
1103  NS_LOG_FUNCTION (this << malformedPacket << dst << (uint32_t)code);
1104  Ptr<Packet> p = Create<Packet> ();
1105  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1107 
1108  NS_LOG_LOGIC ("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1109 
1110  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1111  if (malformedPacketSize <= 1280 - 48)
1112  {
1113  header.SetPacket (malformedPacket);
1114  }
1115  else
1116  {
1117  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1118  header.SetPacket (fragment);
1119  }
1120 
1121  header.SetCode (code);
1122  SendMessage (p, dst, header, 255);
1123 }
1124 
1125 void Icmpv6L4Protocol::SendErrorTooBig (Ptr<Packet> malformedPacket, Ipv6Address dst, uint32_t mtu)
1126 {
1127  NS_LOG_FUNCTION (this << malformedPacket << dst << mtu);
1128  Ptr<Packet> p = Create<Packet> ();
1129  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1130  Icmpv6TooBig header;
1131 
1132  NS_LOG_LOGIC ("Send Too Big ( to " << dst << " )");
1133 
1134  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1135  if (malformedPacketSize <= 1280 - 48)
1136  {
1137  header.SetPacket (malformedPacket);
1138  }
1139  else
1140  {
1141  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1142  header.SetPacket (fragment);
1143  }
1144 
1145  header.SetCode (0);
1146  header.SetMtu (mtu);
1147  SendMessage (p, dst, header, 255);
1148 }
1149 
1150 void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
1151 {
1152  NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code));
1153  Ptr<Packet> p = Create<Packet> ();
1154  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1155  Icmpv6TimeExceeded header;
1156 
1157  NS_LOG_LOGIC ("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1158 
1159  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1160  if (malformedPacketSize <= 1280 - 48)
1161  {
1162  header.SetPacket (malformedPacket);
1163  }
1164  else
1165  {
1166  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1167  header.SetPacket (fragment);
1168  }
1169 
1170  header.SetCode (code);
1171  SendMessage (p, dst, header, 255);
1172 }
1173 
1174 void Icmpv6L4Protocol::SendErrorParameterError (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
1175 {
1176  NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code) << ptr);
1177  Ptr<Packet> p = Create<Packet> ();
1178  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1179  Icmpv6ParameterError header;
1180 
1181  NS_LOG_LOGIC ("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1182 
1183  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1184  if (malformedPacketSize <= 1280 - 48 )
1185  {
1186  header.SetPacket (malformedPacket);
1187  }
1188  else
1189  {
1190  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1191  header.SetPacket (fragment);
1192  }
1193 
1194  header.SetCode (code);
1195  header.SetPtr (ptr);
1196  SendMessage (p, dst, header, 255);
1197 }
1198 
1199 void Icmpv6L4Protocol::SendRedirection (Ptr<Packet> redirectedPacket, Ipv6Address src, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget)
1200 {
1201  NS_LOG_FUNCTION (this << redirectedPacket << dst << redirTarget << redirDestination << redirHardwareTarget);
1202  uint32_t llaSize = 0;
1203  Ptr<Packet> p = Create<Packet> ();
1204  uint32_t redirectedPacketSize = redirectedPacket->GetSize ();
1205  Icmpv6OptionLinkLayerAddress llOption (0);
1206 
1207  NS_LOG_LOGIC ("Send Redirection ( to " << dst << " target " << redirTarget << " destination " << redirDestination << " )");
1208 
1209  Icmpv6OptionRedirected redirectedOptionHeader;
1210 
1211  if ((redirectedPacketSize % 8) != 0)
1212  {
1213  Ptr<Packet> pad = Create<Packet> (8 - (redirectedPacketSize % 8));
1214  redirectedPacket->AddAtEnd (pad);
1215  }
1216 
1217  if (redirHardwareTarget.GetLength ())
1218  {
1219  llOption.SetAddress (redirHardwareTarget);
1220  llaSize = llOption.GetSerializedSize ();
1221  }
1222 
1223  /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1224  if (redirectedPacketSize <= (1280 - 56 - llaSize))
1225  {
1226  redirectedOptionHeader.SetPacket (redirectedPacket);
1227  }
1228  else
1229  {
1230  Ptr<Packet> fragment = redirectedPacket->CreateFragment (0, 1280 - 56 - llaSize);
1231  redirectedOptionHeader.SetPacket (fragment);
1232  }
1233 
1234  p->AddHeader (redirectedOptionHeader);
1235 
1236  if (llaSize)
1237  {
1238  p->AddHeader (llOption);
1239  }
1240 
1241  Icmpv6Redirection redirectionHeader;
1242  redirectionHeader.SetTarget (redirTarget);
1243  redirectionHeader.SetDestination (redirDestination);
1244  redirectionHeader.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + redirectionHeader.GetSerializedSize (), PROT_NUMBER);
1245  p->AddHeader (redirectionHeader);
1246 
1247  SendMessage (p, src, dst, 64);
1248 }
1249 
1251 {
1252  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << (uint32_t)flags);
1253  Ptr<Packet> p = Create<Packet> ();
1254  Ipv6Header ipHeader;
1255  Icmpv6NA na;
1256  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* we give our mac address in response */
1257 
1258  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << ")");
1259 
1260  /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet does not pass by Icmpv6L4Protocol::Lookup again */
1261 
1262  p->AddHeader (llOption);
1263  na.SetIpv6Target (src);
1264 
1265  if ((flags & 1))
1266  {
1267  na.SetFlagO (true);
1268  }
1269  if ((flags & 2) && src != Ipv6Address::GetAny ())
1270  {
1271  na.SetFlagS (true);
1272  }
1273  if ((flags & 4))
1274  {
1275  na.SetFlagR (true);
1276  }
1277 
1279  p->AddHeader (na);
1280 
1281  ipHeader.SetSourceAddress (src);
1282  ipHeader.SetDestinationAddress (dst);
1283  ipHeader.SetNextHeader (PROT_NUMBER);
1284  ipHeader.SetPayloadLength (p->GetSize ());
1285  ipHeader.SetHopLimit (255);
1286 
1287  return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
1288 }
1289 
1291 {
1292  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
1293  Ptr<Packet> p = Create<Packet> ();
1294  Ipv6Header ipHeader;
1295  Icmpv6NS ns (target);
1296  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1297 
1298  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1299 
1300  p->AddHeader (llOption);
1302  p->AddHeader (ns);
1303 
1304  ipHeader.SetSourceAddress (src);
1305  ipHeader.SetDestinationAddress (dst);
1306  ipHeader.SetNextHeader (PROT_NUMBER);
1307  ipHeader.SetPayloadLength (p->GetSize ());
1308  ipHeader.SetHopLimit (255);
1309 
1310  return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
1311 }
1312 
1314 {
1315  NS_LOG_FUNCTION (this << device);
1316 
1317  for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
1318  {
1319  if ((*i)->GetDevice () == device)
1320  {
1321  return *i;
1322  }
1323  }
1324 
1325  NS_ASSERT_MSG (false, "Icmpv6L4Protocol can not find a NDIS Cache for device " << device);
1326  /* quiet compiler */
1327  return 0;
1328 }
1329 
1331 {
1332  NS_LOG_FUNCTION (this << device << interface);
1333 
1334  Ptr<NdiscCache> cache = CreateObject<NdiscCache> ();
1335 
1336  cache->SetDevice (device, interface, this);
1337  device->AddLinkChangeCallback (MakeCallback (&NdiscCache::Flush, cache));
1338  m_cacheList.push_back (cache);
1339  return cache;
1340 }
1341 
1342 bool Icmpv6L4Protocol::Lookup (Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1343 {
1344  NS_LOG_FUNCTION (this << dst << device << cache << hardwareDestination);
1345 
1346  if (!cache)
1347  {
1348  /* try to find the cache */
1349  cache = FindCache (device);
1350  }
1351  if (cache)
1352  {
1353  NdiscCache::Entry* entry = cache->Lookup (dst);
1354  if (entry)
1355  {
1356  if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent ())
1357  {
1358  *hardwareDestination = entry->GetMacAddress ();
1359  return true;
1360  }
1361  else if (entry->IsStale ())
1362  {
1363  entry->StartDelayTimer ();
1364  entry->MarkDelay ();
1365  *hardwareDestination = entry->GetMacAddress ();
1366  return true;
1367  }
1368  }
1369  }
1370  return false;
1371 }
1372 
1373 bool Icmpv6L4Protocol::Lookup (Ptr<Packet> p, const Ipv6Header & ipHeader, Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1374 {
1375  NS_LOG_FUNCTION (this << p << ipHeader << dst << device << cache << hardwareDestination);
1376 
1377  if (!cache)
1378  {
1379  /* try to find the cache */
1380  cache = FindCache (device);
1381  }
1382  if (!cache)
1383  {
1384  return false;
1385  }
1386 
1387  NdiscCache::Entry* entry = cache->Lookup (dst);
1388  if (entry)
1389  {
1390  if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent ())
1391  {
1392  /* XXX check reachability time */
1393  /* send packet */
1394  *hardwareDestination = entry->GetMacAddress ();
1395  return true;
1396  }
1397  else if (entry->IsStale ())
1398  {
1399  /* start delay timer */
1400  entry->StartDelayTimer ();
1401  entry->MarkDelay ();
1402  *hardwareDestination = entry->GetMacAddress ();
1403  return true;
1404  }
1405  else /* INCOMPLETE or PROBE */
1406  {
1407  /* queue packet */
1408  entry->AddWaitingPacket (NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader));
1409  return false;
1410  }
1411  }
1412  else
1413  {
1414  /* we contact this node for the first time
1415  * add it to the cache and send an NS
1416  */
1417  Ipv6Address addr;
1418  NdiscCache::Entry* entry = cache->Add (dst);
1419  entry->MarkIncomplete (NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader));
1420  entry->SetRouter (false);
1421 
1422  if (dst.IsLinkLocal ())
1423  {
1424  addr = cache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
1425  }
1426  else if (cache->GetInterface ()->GetNAddresses () == 1) /* an interface have at least one address (link-local) */
1427  {
1428  /* try to resolve global address without having global address so return! */
1429  cache->Remove (entry);
1430  return false;
1431  }
1432  else
1433  {
1434  /* find source address that match destination */
1435  addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress ();
1436  }
1437 
1438  SendNS (addr, Ipv6Address::MakeSolicitedAddress (dst), dst, cache->GetDevice ()->GetAddress ());
1439 
1440  /* start retransmit timer */
1441  entry->StartRetransmitTimer ();
1442  return false;
1443  }
1444 
1445  return false;
1446 }
1447 
1449 {
1450  NS_LOG_FUNCTION (this << interface << addr);
1451 
1452  Ipv6InterfaceAddress ifaddr;
1453  bool found = false;
1454  uint32_t i = 0;
1455  uint32_t nb = interface->GetNAddresses ();
1456 
1457  for (i = 0; i < nb; i++)
1458  {
1459  ifaddr = interface->GetAddress (i);
1460 
1461  if (ifaddr.GetAddress () == addr)
1462  {
1463  found = true;
1464  break;
1465  }
1466  }
1467 
1468  if (!found)
1469  {
1470  NS_LOG_LOGIC ("Can not find the address in the interface.");
1471  }
1472 
1473  /* for the moment, this function is always called, if we was victim of a DAD the address is INVALID
1474  * and we do not set it to PREFERRED
1475  */
1476  if (found && ifaddr.GetState () != Ipv6InterfaceAddress::INVALID)
1477  {
1478  interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::PREFERRED);
1479  NS_LOG_LOGIC ("DAD OK, interface in state PREFERRED");
1480 
1481  /* send an RS if our interface is not forwarding (router) and if address is a link-local ones
1482  * (because we will send RS with it)
1483  */
1484  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
1485 
1486  if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ())
1487  {
1488  /* \todo Add random delays before sending RS
1489  * because all nodes start at the same time, there will be many of RS around 1 second of simulation time
1490  */
1491  NS_LOG_LOGIC ("Scheduled a Router Solicitation");
1492  Simulator::Schedule (Seconds (0.0), &Icmpv6L4Protocol::SendRS, this, ifaddr.GetAddress (), Ipv6Address::GetAllRoutersMulticast (), interface->GetDevice ()->GetAddress ());
1493  }
1494  else
1495  {
1496  NS_LOG_LOGIC ("Did not schedule a Router Solicitation because the interface is in forwarding mode");
1497  }
1498  }
1499 }
1500 
1501 void
1503 {
1504  NS_LOG_FUNCTION (this << &callback);
1505 }
1506 
1507 void
1509 {
1510  NS_LOG_FUNCTION (this << &callback);
1511  m_downTarget = callback;
1512 }
1513 
1516 {
1517  NS_LOG_FUNCTION (this);
1518  return (IpL4Protocol::DownTargetCallback)NULL;
1519 }
1520 
1523 {
1524  NS_LOG_FUNCTION (this);
1525  return m_downTarget;
1526 }
1527 
1528 uint8_t
1530 {
1531  return m_maxMulticastSolicit;
1532 }
1533 
1534 uint8_t
1536 {
1537  return m_maxUnicastSolicit;
1538 }
1539 
1540 Time
1542 {
1543  return m_reachableTime;
1544 }
1545 
1546 Time
1548 {
1549  return m_retransmissionTime;
1550 }
1551 
1552 Time
1554 {
1555  return m_delayFirstProbe;
1556 }
1557 
1558 
1559 } /* namespace ns3 */
1560 
a polymophic address class
Definition: address.h:91
uint8_t GetLength(void) const
Get the length of the underlying address.
Definition: address.cc:75
AttributeValue implementation for Boolean.
Definition: boolean.h:37
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1386
void Nullify(void)
Discard the implementation, set it to null.
Definition: callback.h:1391
ICMPv6 Error Destination Unreachable header.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
Ptr< Packet > GetPacket() const
Get 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.
uint16_t GetSeq() const
Get the sequence number.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
ICMPv6 header.
Definition: icmpv6-header.h:39
uint8_t GetCode() const
Get the code field.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
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.
@ ICMPV6_ND_NEIGHBOR_ADVERTISEMENT
Definition: icmpv6-header.h:58
@ ICMPV6_ERROR_DESTINATION_UNREACHABLE
Definition: icmpv6-header.h:46
An implementation of the ICMPv6 protocol.
Time GetRetransmissionTime() const
Neighbor Discovery node constants: retransmission timer.
virtual void SetDownTarget(IpL4Protocol::DownTargetCallback cb)
This method allows a caller to set the current down target callback set for this L4 protocol (IPv4 ca...
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
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 SendErrorTimeExceeded(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code)
Send an error Time Exceeded.
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.
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.
virtual Ptr< NdiscCache > CreateCache(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface)
Create a neighbor cache.
void DelayedSendMessage(Ptr< Packet > packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
Helper function used during delayed solicitation.
Ptr< Node > GetNode()
Get the node.
bool IsAlwaysDad() const
Is the node must do DAD.
void HandlePacketTooBig(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Packet Too Big method.
void SendErrorParameterError(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
Send an error Parameter Error.
void HandleRS(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Router Solicitation method.
void NotifyNewAggregate()
This method is called by AggregateObject and completes the aggregation by setting the node in the ICM...
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.
virtual void DoDispose()
Dispose this object.
void HandleNA(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Advertisement method.
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.
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 SetDownTarget6(IpL4Protocol::DownTargetCallback6 cb)
This method allows a caller to set the current down target callback set for this L4 protocol (IPv6 ca...
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.
virtual ~Icmpv6L4Protocol()
Destructor.
void SendRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Send a Router Solicitation.
Time m_retransmissionTime
Neighbor Discovery node constants: retransmission timer.
virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6(void) const
This method allows a caller to get the current down target callback set for this L4 protocol (IPv6 ca...
uint8_t GetMaxUnicastSolicit() const
Neighbor Discovery node constants: max unicast solicitations.
void HandleTimeExceeded(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Time Exceeded method.
bool Lookup(Ipv6Address dst, Ptr< NetDevice > device, Ptr< NdiscCache > cache, Address *hardwareDestination)
Lookup in the ND cache for the IPv6 address.
void HandleRedirection(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Redirection method.
void HandleEchoRequest(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Echo Request method.
virtual int GetVersion() const
Get the version of the protocol.
void HandleDestinationUnreachable(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Destination Unreachable method.
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 HandleNS(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Solicitation method.
virtual int GetProtocolNumber() const
Get the protocol number.
void ReceiveLLA(Icmpv6OptionLinkLayerAddress lla, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Link layer address option processing.
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 HandleParameterError(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Parameter Error method.
void SendNA(Ipv6Address src, Ipv6Address dst, Address *hardwareAddress, uint8_t flags)
Send a Neighbor Adverstisement.
virtual IpL4Protocol::DownTargetCallback GetDownTarget(void) const
This method allows a caller to get the current down target callback set for this L4 protocol (IPv4 ca...
static TypeId GetTypeId()
Get the type ID.
Time GetReachableTime() const
Neighbor Discovery node constants: reachable time.
virtual enum IpL4Protocol::RxStatus Receive(Ptr< Packet > p, Ipv4Header const &header, Ptr< Ipv4Interface > interface)
Receive method.
void HandleRA(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Router Advertisement method.
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.
ICMPv6 Neighbor Advertisement header.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
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.
bool GetFlagO() const
Get the O flag.
void SetFlagO(bool o)
Set the O flag.
ICMPv6 Neighbor Solicitation header.
virtual uint32_t GetSerializedSize() const
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.
Ptr< Packet > GetPacket() const
Get 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.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
ICMPv6 Redirection header.
Ipv6Address GetTarget() const
Get the IPv6 target address.
void SetDestination(Ipv6Address destination)
Set the IPv6 destination address.
Ipv6Address GetDestination() const
Get the IPv6 destination address.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
void SetTarget(Ipv6Address target)
Set the IPv6 target address.
ICMPv6 Error Time Exceeded header.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
Ptr< Packet > GetPacket() const
Get the incorrect packet.
ICMPv6 Error Too Big header.
void SetMtu(uint32_t mtu)
Set the MTU.
Ptr< Packet > GetPacket() const
Get the incorrect packet.
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:44
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.
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:35
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:90
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:143
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:80
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:85
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:65
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
void SetSourceAddress(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:95
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:75
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:105
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.
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.
uint32_t GetNAddresses(void) const
Get number of addresses on this IPv6 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:467
A record that holds information about a NdiscCache entry.
Definition: ndisc-cache.h:157
bool IsPermanent() const
Is the entry PERMANENT.
Definition: ndisc-cache.cc:587
void ClearWaitingPacket()
Clear the waiting packet list.
Definition: ndisc-cache.cc:264
std::list< Ipv6PayloadHeaderPair > MarkStale(Address mac)
Changes the state to this entry to STALE.
Definition: ndisc-cache.cc:536
void StartReachableTimer()
Start the reachable timer.
Definition: ndisc-cache.cc:424
Address GetMacAddress() const
Get the MAC address of this entry.
Definition: ndisc-cache.cc:593
void StartDelayTimer()
Start delay timer.
Definition: ndisc-cache.cc:466
std::list< Ipv6PayloadHeaderPair > MarkReachable(Address mac)
Changes the state to this entry to REACHABLE.
Definition: ndisc-cache.cc:510
bool IsIncomplete() const
Is the entry INCOMPLETE.
Definition: ndisc-cache.cc:575
bool IsDelay() const
Is the entry DELAY.
Definition: ndisc-cache.cc:569
void StartRetransmitTimer()
Start retransmit timer.
Definition: ndisc-cache.cc:479
void MarkIncomplete(Ipv6PayloadHeaderPair p)
Changes the state to this entry to INCOMPLETE.
Definition: ndisc-cache.cc:499
bool IsStale() const
Is the entry STALE.
Definition: ndisc-cache.cc:557
void SetMacAddress(Address mac)
Set the MAC address of this entry.
Definition: ndisc-cache.cc:599
bool IsProbe() const
Is the entry PROBE.
Definition: ndisc-cache.cc:581
void MarkDelay()
Change the state to this entry to DELAY.
Definition: ndisc-cache.cc:544
void SetRouter(bool router)
Set the node type.
Definition: ndisc-cache.cc:239
void AddWaitingPacket(Ipv6PayloadHeaderPair p)
Add a packet (or replace old value) in the queue.
Definition: ndisc-cache.cc:251
bool IsReachable() const
Is the entry REACHABLE.
Definition: ndisc-cache.cc:563
void StopNudTimer()
Stop NUD timer and reset the NUD retransmission counter.
Definition: ndisc-cache.cc:492
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface, Ptr< Icmpv6L4Protocol > icmpv6)
Set the device and interface.
Definition: ndisc-cache.cc:73
std::pair< Ptr< Packet >, Ipv6Header > Ipv6PayloadHeaderPair
Pair of a packet and an Ipv4 header.
Definition: ndisc-cache.h:149
virtual NdiscCache::Entry * Add(Ipv6Address to)
Add an entry.
Definition: ndisc-cache.cc:126
void Flush()
Flush the cache.
Definition: ndisc-cache.cc:153
void Remove(NdiscCache::Entry *entry)
Delete an entry.
Definition: ndisc-cache.cc:137
virtual NdiscCache::Entry * Lookup(Ipv6Address dst)
Lookup in the cache.
Definition: ndisc-cache.cc:93
Ptr< NetDevice > GetDevice() const
Get the NetDevice associated with this cache.
Definition: ndisc-cache.cc:87
Ptr< Ipv6Interface > GetInterface() const
Get the Ipv6Interface associated with this cache.
Definition: ndisc-cache.cc:81
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:325
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
void Dispose(void)
Dispose of this Object.
Definition: object.cc:214
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:390
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
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:227
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
virtual double GetValue(void)=0
Get the next random value as a double drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition: socket.h:1165
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:665
Hold variables of type string.
Definition: string.h:41
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
AttributeValue implementation for Time.
Definition: nstime.h:1353
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#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:88
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
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:85
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:45
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:227
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:1354
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#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:265
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
uint8_t data[writeSize]