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 
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.GetSource () << header.GetDestination () << 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.GetSource (), header.GetDestination (), interface);
241  }
242  break;
244  if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
245  {
246  HandleRA (p, header.GetSource (), header.GetDestination (), interface);
247  }
248  break;
250  HandleNS (p, header.GetSource (), header.GetDestination (), interface);
251  break;
253  HandleNA (p, header.GetSource (), header.GetDestination (), interface);
254  break;
256  HandleRedirection (p, header.GetSource (), header.GetDestination (), interface);
257  break;
259  HandleEchoRequest (p, header.GetSource (), header.GetDestination (), 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.GetSource (), header.GetDestination (), interface);
268  break;
270  HandlePacketTooBig (p, header.GetSource (), header.GetDestination (), interface);
271  break;
273  HandleTimeExceeded (p, header.GetSource (), header.GetDestination (), interface);
274  break;
276  HandleParameterError (p, header.GetSource (), header.GetDestination (), 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.GetSource (), ipHeader.GetDestination (), 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.SetSource (src);
636  ipHeader.SetDestination (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.SetSource (src);
658  ipHeader.SetDestination (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 
885  Ipv6Header ipHeader;
886  if (pkt->GetSize () > ipHeader.GetSerializedSize ())
887  {
888  pkt->RemoveHeader (ipHeader);
889  uint8_t payload[8];
890  pkt->CopyData (payload, 8);
891  Forward (src, unreach, unreach.GetCode (), ipHeader, payload);
892  }
893 }
894 
896 {
897  NS_LOG_FUNCTION (this << *p << src << dst << interface);
898  Ptr<Packet> pkt = p->Copy ();
899 
900  Icmpv6TimeExceeded timeexceeded;
901  pkt->RemoveHeader (timeexceeded);
902 
903  Ipv6Header ipHeader;
904  if (pkt->GetSize () > ipHeader.GetSerializedSize ())
905  {
906  Ipv6Header ipHeader;
907  pkt->RemoveHeader (ipHeader);
908  uint8_t payload[8];
909  pkt->CopyData (payload, 8);
910  Forward (src, timeexceeded, timeexceeded.GetCode (), ipHeader, payload);
911  }
912 }
913 
915 {
916  NS_LOG_FUNCTION (this << *p << src << dst << interface);
917  Ptr<Packet> pkt = p->Copy ();
918 
919  Icmpv6TooBig tooBig;
920  pkt->RemoveHeader (tooBig);
921 
922  Ipv6Header ipHeader;
923  if (pkt->GetSize () > ipHeader.GetSerializedSize ())
924  {
925  pkt->RemoveHeader (ipHeader);
926  uint8_t payload[8];
927  pkt->CopyData (payload, 8);
928 
930  ipv6->SetPmtu (ipHeader.GetDestination (), tooBig.GetMtu ());
931 
932  Forward (src, tooBig, tooBig.GetMtu (), ipHeader, payload);
933  }
934 }
935 
937 {
938  NS_LOG_FUNCTION (this << *p << src << dst << interface);
939  Ptr<Packet> pkt = p->Copy ();
940 
941  Icmpv6ParameterError paramErr;
942  pkt->RemoveHeader (paramErr);
943 
944  Ipv6Header ipHeader;
945  if (pkt->GetSize () > ipHeader.GetSerializedSize ())
946  {
947  pkt->RemoveHeader (ipHeader);
948  uint8_t payload[8];
949  pkt->CopyData (payload, 8);
950  Forward (src, paramErr, paramErr.GetCode (), ipHeader, payload);
951  }
952 }
953 
955 {
956  NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
959  NS_ASSERT (ipv6 != 0);
960 
961  tag.SetHopLimit (ttl);
962  packet->AddPacketTag (tag);
963  m_downTarget (packet, src, dst, PROT_NUMBER, 0);
964 }
965 
967 {
968  NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
969  SendMessage (packet, src, dst, ttl);
970 }
971 
972 void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl)
973 {
974  NS_LOG_FUNCTION (this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
976  NS_ASSERT (ipv6 != 0 && ipv6->GetRoutingProtocol () != 0);
977  Ipv6Header header;
980  Ptr<Ipv6Route> route;
981  Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
982 
983  header.SetDestination (dst);
984  route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, err);
985 
986  if (route != 0)
987  {
988  NS_LOG_LOGIC ("Route exists");
989  tag.SetHopLimit (ttl);
990  packet->AddPacketTag (tag);
991  Ipv6Address src = route->GetSource ();
992 
993  icmpv6Hdr.CalculatePseudoHeaderChecksum (src, dst, packet->GetSize () + icmpv6Hdr.GetSerializedSize (), PROT_NUMBER);
994  packet->AddHeader (icmpv6Hdr);
995  m_downTarget (packet, src, dst, PROT_NUMBER, route);
996  }
997  else
998  {
999  NS_LOG_WARN ("drop icmp message");
1000  }
1001 }
1002 
1003 void Icmpv6L4Protocol::SendNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1004 {
1005  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << static_cast<uint32_t> (flags));
1006  Ptr<Packet> p = Create<Packet> ();
1007  Icmpv6NA na;
1008  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* not a source link layer */
1009 
1010  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << " target " << src << ")");
1011  na.SetIpv6Target (src);
1012 
1013  if ((flags & 1))
1014  {
1015  na.SetFlagO (true);
1016  }
1017  if ((flags & 2) && src != Ipv6Address::GetAny ())
1018  {
1019  na.SetFlagS (true);
1020  }
1021  if ((flags & 4))
1022  {
1023  na.SetFlagR (true);
1024  }
1025 
1026  p->AddHeader (llOption);
1028  p->AddHeader (na);
1029 
1030  SendMessage (p, src, dst, 255);
1031 }
1032 
1033 void Icmpv6L4Protocol::SendEchoReply (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr<Packet> data)
1034 {
1035  NS_LOG_FUNCTION (this << src << dst << id << seq << data);
1036  Ptr<Packet> p = data->Copy ();
1037  Icmpv6Echo reply (0); /* echo reply */
1038 
1039  reply.SetId (id);
1040  reply.SetSeq (seq);
1041 
1042  reply.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + reply.GetSerializedSize (), PROT_NUMBER);
1043  p->AddHeader (reply);
1044  SendMessage (p, src, dst, 64);
1045 }
1046 
1047 void Icmpv6L4Protocol::SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
1048 {
1049  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
1050  Ptr<Packet> p = Create<Packet> ();
1051  /* Ipv6Header ipHeader; */
1052  Icmpv6NS ns (target);
1053  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1054 
1055  /* if the source is unspec, multicast the NA to all-nodes multicast */
1056  if (src == Ipv6Address::GetAny ())
1057  {
1059  }
1060 
1061  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1062 
1063  p->AddHeader (llOption);
1065  p->AddHeader (ns);
1066  if (!dst.IsMulticast ())
1067  {
1068  SendMessage (p, src, dst, 255);
1069  }
1070  else
1071  {
1072  NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
1074  }
1075 }
1076 
1078 {
1079  NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
1080  Ptr<Packet> p = Create<Packet> ();
1081  Icmpv6RS rs;
1082 
1083  // RFC 4861:
1084  // The link-layer address of the sender MUST NOT be included if the Source Address is the unspecified address.
1085  // Otherwise, it SHOULD be included on link layers that have addresses.
1086  if (!src.IsAny ())
1087  {
1088  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress);
1089  p->AddHeader (llOption);
1090  }
1091 
1092  NS_LOG_LOGIC ("Send RS (from " << src << " to " << dst << ")");
1093 
1095  p->AddHeader (rs);
1096  if (!dst.IsMulticast ())
1097  {
1098  SendMessage (p, src, dst, 255);
1099  }
1100  else
1101  {
1102  NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
1104  }
1105 }
1106 
1108 {
1109  NS_LOG_FUNCTION (this << malformedPacket << dst << (uint32_t)code);
1110  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1112  header.SetCode (code);
1113 
1114  NS_LOG_LOGIC ("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1115 
1116  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1117  if (malformedPacketSize <= 1280 - 48)
1118  {
1119  header.SetPacket (malformedPacket);
1120  SendMessage (malformedPacket, dst, header, 255);
1121  }
1122  else
1123  {
1124  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1125  header.SetPacket (fragment);
1126  SendMessage (fragment, dst, header, 255);
1127  }
1128 }
1129 
1130 void Icmpv6L4Protocol::SendErrorTooBig (Ptr<Packet> malformedPacket, Ipv6Address dst, uint32_t mtu)
1131 {
1132  NS_LOG_FUNCTION (this << malformedPacket << dst << mtu);
1133  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1134  Icmpv6TooBig header;
1135  header.SetCode (0);
1136  header.SetMtu (mtu);
1137 
1138  NS_LOG_LOGIC ("Send Too Big ( to " << dst << " )");
1139 
1140  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1141  if (malformedPacketSize <= 1280 - 48)
1142  {
1143  header.SetPacket (malformedPacket);
1144  SendMessage (malformedPacket, dst, header, 255);
1145  }
1146  else
1147  {
1148  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1149  header.SetPacket (fragment);
1150  SendMessage (fragment, dst, header, 255);
1151  }
1152 }
1153 
1154 void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
1155 {
1156  NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code));
1157  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1158  Icmpv6TimeExceeded header;
1159  header.SetCode (code);
1160 
1161  NS_LOG_LOGIC ("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1162 
1163  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1164  if (malformedPacketSize <= 1280 - 48)
1165  {
1166  header.SetPacket (malformedPacket);
1167  SendMessage (malformedPacket, dst, header, 255);
1168  }
1169  else
1170  {
1171  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1172  header.SetPacket (fragment);
1173  SendMessage (fragment, dst, header, 255);
1174  }
1175 }
1176 
1177 void Icmpv6L4Protocol::SendErrorParameterError (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
1178 {
1179  NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code) << ptr);
1180  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1181  Icmpv6ParameterError header;
1182  header.SetCode (code);
1183  header.SetPtr (ptr);
1184 
1185  NS_LOG_LOGIC ("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1186 
1187  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1188  if (malformedPacketSize <= 1280 - 48 )
1189  {
1190  header.SetPacket (malformedPacket);
1191  SendMessage (malformedPacket, dst, header, 255);
1192  }
1193  else
1194  {
1195  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1196  header.SetPacket (fragment);
1197  SendMessage (fragment, dst, header, 255);
1198  }
1199 }
1200 
1201 void Icmpv6L4Protocol::SendRedirection (Ptr<Packet> redirectedPacket, Ipv6Address src, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget)
1202 {
1203  NS_LOG_FUNCTION (this << redirectedPacket << dst << redirTarget << redirDestination << redirHardwareTarget);
1204  uint32_t llaSize = 0;
1205  Ptr<Packet> p = Create<Packet> ();
1206  uint32_t redirectedPacketSize = redirectedPacket->GetSize ();
1207  Icmpv6OptionLinkLayerAddress llOption (0);
1208 
1209  NS_LOG_LOGIC ("Send Redirection ( to " << dst << " target " << redirTarget << " destination " << redirDestination << " )");
1210 
1211  Icmpv6OptionRedirected redirectedOptionHeader;
1212 
1213  if ((redirectedPacketSize % 8) != 0)
1214  {
1215  Ptr<Packet> pad = Create<Packet> (8 - (redirectedPacketSize % 8));
1216  redirectedPacket->AddAtEnd (pad);
1217  }
1218 
1219  if (redirHardwareTarget.GetLength ())
1220  {
1221  llOption.SetAddress (redirHardwareTarget);
1222  llaSize = llOption.GetSerializedSize ();
1223  }
1224 
1225  /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1226  if (redirectedPacketSize <= (1280 - 56 - llaSize))
1227  {
1228  redirectedOptionHeader.SetPacket (redirectedPacket);
1229  }
1230  else
1231  {
1232  Ptr<Packet> fragment = redirectedPacket->CreateFragment (0, 1280 - 56 - llaSize);
1233  redirectedOptionHeader.SetPacket (fragment);
1234  }
1235 
1236  p->AddHeader (redirectedOptionHeader);
1237 
1238  if (llaSize)
1239  {
1240  p->AddHeader (llOption);
1241  }
1242 
1243  Icmpv6Redirection redirectionHeader;
1244  redirectionHeader.SetTarget (redirTarget);
1245  redirectionHeader.SetDestination (redirDestination);
1246  redirectionHeader.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + redirectionHeader.GetSerializedSize (), PROT_NUMBER);
1247  p->AddHeader (redirectionHeader);
1248 
1249  SendMessage (p, src, dst, 64);
1250 }
1251 
1253 {
1254  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << (uint32_t)flags);
1255  Ptr<Packet> p = Create<Packet> ();
1256  Ipv6Header ipHeader;
1257  Icmpv6NA na;
1258  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* we give our mac address in response */
1259 
1260  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << ")");
1261 
1262  /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet does not pass by Icmpv6L4Protocol::Lookup again */
1263 
1264  p->AddHeader (llOption);
1265  na.SetIpv6Target (src);
1266 
1267  if ((flags & 1))
1268  {
1269  na.SetFlagO (true);
1270  }
1271  if ((flags & 2) && src != Ipv6Address::GetAny ())
1272  {
1273  na.SetFlagS (true);
1274  }
1275  if ((flags & 4))
1276  {
1277  na.SetFlagR (true);
1278  }
1279 
1281  p->AddHeader (na);
1282 
1283  ipHeader.SetSource (src);
1284  ipHeader.SetDestination (dst);
1285  ipHeader.SetNextHeader (PROT_NUMBER);
1286  ipHeader.SetPayloadLength (p->GetSize ());
1287  ipHeader.SetHopLimit (255);
1288 
1289  return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
1290 }
1291 
1293 {
1294  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
1295  Ptr<Packet> p = Create<Packet> ();
1296  Ipv6Header ipHeader;
1297  Icmpv6NS ns (target);
1298  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1299 
1300  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1301 
1302  p->AddHeader (llOption);
1304  p->AddHeader (ns);
1305 
1306  ipHeader.SetSource (src);
1307  ipHeader.SetDestination (dst);
1308  ipHeader.SetNextHeader (PROT_NUMBER);
1309  ipHeader.SetPayloadLength (p->GetSize ());
1310  ipHeader.SetHopLimit (255);
1311 
1312  return NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader);
1313 }
1314 
1316 {
1317  NS_LOG_FUNCTION (this << device);
1318 
1319  for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
1320  {
1321  if ((*i)->GetDevice () == device)
1322  {
1323  return *i;
1324  }
1325  }
1326 
1327  NS_ASSERT_MSG (false, "Icmpv6L4Protocol can not find a NDIS Cache for device " << device);
1328  /* quiet compiler */
1329  return 0;
1330 }
1331 
1333 {
1334  NS_LOG_FUNCTION (this << device << interface);
1335 
1336  Ptr<NdiscCache> cache = CreateObject<NdiscCache> ();
1337 
1338  cache->SetDevice (device, interface, this);
1340  m_cacheList.push_back (cache);
1341  return cache;
1342 }
1343 
1344 bool Icmpv6L4Protocol::Lookup (Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1345 {
1346  NS_LOG_FUNCTION (this << dst << device << cache << hardwareDestination);
1347 
1348  if (!cache)
1349  {
1350  /* try to find the cache */
1351  cache = FindCache (device);
1352  }
1353  if (cache)
1354  {
1355  NdiscCache::Entry* entry = cache->Lookup (dst);
1356  if (entry)
1357  {
1358  if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent ())
1359  {
1360  *hardwareDestination = entry->GetMacAddress ();
1361  return true;
1362  }
1363  else if (entry->IsStale ())
1364  {
1365  entry->StartDelayTimer ();
1366  entry->MarkDelay ();
1367  *hardwareDestination = entry->GetMacAddress ();
1368  return true;
1369  }
1370  }
1371  }
1372  return false;
1373 }
1374 
1375 bool Icmpv6L4Protocol::Lookup (Ptr<Packet> p, const Ipv6Header & ipHeader, Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1376 {
1377  NS_LOG_FUNCTION (this << p << ipHeader << dst << device << cache << hardwareDestination);
1378 
1379  if (!cache)
1380  {
1381  /* try to find the cache */
1382  cache = FindCache (device);
1383  }
1384  if (!cache)
1385  {
1386  return false;
1387  }
1388 
1389  NdiscCache::Entry* entry = cache->Lookup (dst);
1390  if (entry)
1391  {
1392  if (entry->IsReachable () || entry->IsDelay () || entry->IsPermanent ())
1393  {
1394  /* XXX check reachability time */
1395  /* send packet */
1396  *hardwareDestination = entry->GetMacAddress ();
1397  return true;
1398  }
1399  else if (entry->IsStale ())
1400  {
1401  /* start delay timer */
1402  entry->StartDelayTimer ();
1403  entry->MarkDelay ();
1404  *hardwareDestination = entry->GetMacAddress ();
1405  return true;
1406  }
1407  else /* INCOMPLETE or PROBE */
1408  {
1409  /* queue packet */
1410  entry->AddWaitingPacket (NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader));
1411  return false;
1412  }
1413  }
1414  else
1415  {
1416  /* we contact this node for the first time
1417  * add it to the cache and send an NS
1418  */
1419  Ipv6Address addr;
1420  NdiscCache::Entry* entry = cache->Add (dst);
1421  entry->MarkIncomplete (NdiscCache::Ipv6PayloadHeaderPair (p, ipHeader));
1422  entry->SetRouter (false);
1423 
1424  if (dst.IsLinkLocal ())
1425  {
1426  addr = cache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
1427  }
1428  else if (cache->GetInterface ()->GetNAddresses () == 1) /* an interface have at least one address (link-local) */
1429  {
1430  /* try to resolve global address without having global address so return! */
1431  cache->Remove (entry);
1432  return false;
1433  }
1434  else
1435  {
1436  /* find source address that match destination */
1437  addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress ();
1438  }
1439 
1440  SendNS (addr, Ipv6Address::MakeSolicitedAddress (dst), dst, cache->GetDevice ()->GetAddress ());
1441 
1442  /* start retransmit timer */
1443  entry->StartRetransmitTimer ();
1444  return false;
1445  }
1446 
1447  return false;
1448 }
1449 
1451 {
1452  NS_LOG_FUNCTION (this << interface << addr);
1453 
1454  Ipv6InterfaceAddress ifaddr;
1455  bool found = false;
1456  uint32_t i = 0;
1457  uint32_t nb = interface->GetNAddresses ();
1458 
1459  for (i = 0; i < nb; i++)
1460  {
1461  ifaddr = interface->GetAddress (i);
1462 
1463  if (ifaddr.GetAddress () == addr)
1464  {
1465  found = true;
1466  break;
1467  }
1468  }
1469 
1470  if (!found)
1471  {
1472  NS_LOG_LOGIC ("Can not find the address in the interface.");
1473  }
1474 
1475  /* for the moment, this function is always called, if we was victim of a DAD the address is INVALID
1476  * and we do not set it to PREFERRED
1477  */
1478  if (found && ifaddr.GetState () != Ipv6InterfaceAddress::INVALID)
1479  {
1480  interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::PREFERRED);
1481  NS_LOG_LOGIC ("DAD OK, interface in state PREFERRED");
1482 
1483  /* send an RS if our interface is not forwarding (router) and if address is a link-local ones
1484  * (because we will send RS with it)
1485  */
1486  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
1487 
1488  if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ())
1489  {
1490  /* \todo Add random delays before sending RS
1491  * because all nodes start at the same time, there will be many of RS around 1 second of simulation time
1492  */
1493  NS_LOG_LOGIC ("Scheduled a Router Solicitation");
1495  }
1496  else
1497  {
1498  NS_LOG_LOGIC ("Did not schedule a Router Solicitation because the interface is in forwarding mode");
1499  }
1500  }
1501 }
1502 
1503 void
1505 {
1506  NS_LOG_FUNCTION (this << &callback);
1507 }
1508 
1509 void
1511 {
1512  NS_LOG_FUNCTION (this << &callback);
1513  m_downTarget = callback;
1514 }
1515 
1518 {
1519  NS_LOG_FUNCTION (this);
1520  return (IpL4Protocol::DownTargetCallback)NULL;
1521 }
1522 
1525 {
1526  NS_LOG_FUNCTION (this);
1527  return m_downTarget;
1528 }
1529 
1530 uint8_t
1532 {
1533  return m_maxMulticastSolicit;
1534 }
1535 
1536 uint8_t
1538 {
1539  return m_maxUnicastSolicit;
1540 }
1541 
1542 Time
1544 {
1545  return m_reachableTime;
1546 }
1547 
1548 Time
1550 {
1551  return m_retransmissionTime;
1552 }
1553 
1554 Time
1556 {
1557  return m_delayFirstProbe;
1558 }
1559 
1560 
1561 } /* namespace ns3 */
1562 
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.
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.
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.
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: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:36
void SetDestination(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:115
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:90
Ipv6Address GetSource(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:105
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:163
void SetSource(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:95
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 GetDestination(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:125
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:75
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:456
A record that holds information about a NdiscCache entry.
Definition: ndisc-cache.h:161
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:153
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 bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber)=0
virtual Address GetAddress(void) const =0
virtual Address GetMulticast(Ipv4Address multicastGroup) const =0
Make and return a MAC multicast address using the provided multicast group.
virtual void AddLinkChangeCallback(Callback< void > callback)=0
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void Dispose(void)
Dispose of this Object.
Definition: object.cc:214
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:325
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:856
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:556
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:103
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
#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:1309
#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:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
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:522
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:1648
uint8_t data[writeSize]