A Discrete-Event Network Simulator
API
icmpv6-l4-protocol.cc
Go to the documentation of this file.
1 
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 
35 #include "ipv6-l3-protocol.h"
36 #include "ipv6-interface.h"
37 #include "icmpv6-l4-protocol.h"
38 #include "ndisc-cache.h"
39 
40 namespace ns3 {
41 
42 NS_LOG_COMPONENT_DEFINE ("Icmpv6L4Protocol");
43 
44 NS_OBJECT_ENSURE_REGISTERED (Icmpv6L4Protocol);
45 
46 const uint8_t Icmpv6L4Protocol::PROT_NUMBER = 58;
47 
52 const uint32_t Icmpv6L4Protocol::MAX_RA_DELAY_TIME = 500; /* millisecond */
53 
57 
62 const uint32_t Icmpv6L4Protocol::REACHABLE_TIME = 30000;
63 const uint32_t Icmpv6L4Protocol::RETRANS_TIMER = 1000;
65 const double Icmpv6L4Protocol::MIN_RANDOM_FACTOR = 0.5;
66 const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5;
67 
69 {
70  static TypeId tid = TypeId ("ns3::Icmpv6L4Protocol")
72  .SetGroupName ("Internet")
73  .AddConstructor<Icmpv6L4Protocol> ()
74  .AddAttribute ("DAD", "Always do DAD check.",
75  BooleanValue (true),
78  .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",
79  StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
81  MakePointerChecker<RandomVariableStream> ())
82 
83  ;
84  return tid;
85 }
86 
88  : m_node (0)
89 {
90  NS_LOG_FUNCTION (this);
91 }
92 
94 {
95  NS_LOG_FUNCTION (this);
96 }
97 
99 {
100  NS_LOG_FUNCTION (this);
101  for (CacheList::const_iterator it = m_cacheList.begin (); it != m_cacheList.end (); it++)
102  {
103  Ptr<NdiscCache> cache = *it;
104  cache->Dispose ();
105  cache = 0;
106  }
107  m_cacheList.clear ();
109 
110  m_node = 0;
112 }
113 
114 int64_t Icmpv6L4Protocol::AssignStreams (int64_t stream)
115 {
116  NS_LOG_FUNCTION (this << stream);
118  return 1;
119 }
120 
122 {
123  NS_LOG_FUNCTION (this);
124  if (m_node == 0)
125  {
126  Ptr<Node> node = this->GetObject<Node> ();
127  if (node != 0)
128  {
129  Ptr<Ipv6L3Protocol> ipv6 = this->GetObject<Ipv6L3Protocol> ();
130  if (ipv6 != 0 && m_downTarget.IsNull ())
131  {
132  SetNode (node);
133  ipv6->Insert (this);
134  Ptr<Ipv6RawSocketFactoryImpl> rawFactory = CreateObject<Ipv6RawSocketFactoryImpl> ();
135  ipv6->AggregateObject (rawFactory);
137  }
138  }
139  }
141 }
142 
144 {
145  NS_LOG_FUNCTION (this << node);
146  m_node = node;
147 }
148 
150 {
152  return PROT_NUMBER;
153 }
154 
156 {
157  NS_LOG_FUNCTION (this);
158  return PROT_NUMBER;
159 }
160 
162 {
163  NS_LOG_FUNCTION (this);
164  return 1;
165 }
166 
168 {
169  NS_LOG_FUNCTION (this);
170  return m_alwaysDad;
171 }
172 
174 {
175  NS_LOG_FUNCTION (this << target << interface);
176  Ipv6Address addr;
178 
179  NS_ASSERT (ipv6);
180 
181  if (!m_alwaysDad)
182  {
183  return;
184  }
185 
188  Ptr<Packet> p = ForgeNS ("::",Ipv6Address::MakeSolicitedAddress (target), target, interface->GetDevice ()->GetAddress ());
189 
190  /* update last packet UID */
191  interface->SetNsDadUid (target, p->GetUid ());
193 }
194 
196 {
197  NS_LOG_FUNCTION (this << packet << header);
199 }
200 
202 {
203  NS_LOG_FUNCTION (this << packet << header.GetSourceAddress () << header.GetDestinationAddress () << interface);
204  Ptr<Packet> p = packet->Copy ();
205  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
206 
207  /* very ugly! try to find something better in the future */
208  uint8_t type;
209  p->CopyData (&type, sizeof(type));
210 
211  switch (type)
212  {
214  if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
215  {
216  HandleRS (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
217  }
218  break;
220  if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
221  {
222  HandleRA (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
223  }
224  break;
226  HandleNS (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
227  break;
229  HandleNA (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
230  break;
232  HandleRedirection (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
233  break;
235  HandleEchoRequest (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
236  break;
238  // EchoReply does not contain any info about L4
239  // so we can not forward it up.
241  break;
243  HandleDestinationUnreachable (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
244  break;
246  HandlePacketTooBig (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
247  break;
249  HandleTimeExceeded (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
250  break;
252  HandleParameterError (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
253  break;
254  default:
255  NS_LOG_LOGIC ("Unknown ICMPv6 message type=" << type);
256  break;
257  }
258 
259  return IpL4Protocol::RX_OK;
260 }
261 
263  uint32_t info, Ipv6Header ipHeader,
264  const uint8_t payload[8])
265 {
266  NS_LOG_FUNCTION (this << source << icmp << info << ipHeader << payload);
267 
269 
271 
272  uint8_t nextHeader = ipHeader.GetNextHeader ();
273 
274  if (nextHeader != Icmpv6L4Protocol::PROT_NUMBER)
275  {
276  Ptr<IpL4Protocol> l4 = ipv6->GetProtocol (nextHeader);
277  if (l4 != 0)
278  {
279  l4->ReceiveIcmp (source, ipHeader.GetHopLimit (), icmp.GetType (), icmp.GetCode (),
280  info, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress (), payload);
281  }
282  }
283 }
284 
286 {
287  NS_LOG_FUNCTION (this << packet << src << dst << interface);
288  Icmpv6Echo request;
289  uint8_t* buf = new uint8_t[packet->GetSize ()];
290 
291  packet->RemoveHeader (request);
292  /* XXX IPv6 extension: obtain a fresh copy of data otherwise it crash... */
293  packet->CopyData (buf, packet->GetSize ());
294  Ptr<Packet> p = Create<Packet> (buf, packet->GetSize ());
295 
296  /* if we send message from ff02::* (link-local multicast), we use our link-local address */
297  SendEchoReply (dst.IsMulticast () ? interface->GetLinkLocalAddress ().GetAddress () : dst, src, request.GetId (), request.GetSeq (), p);
298  delete[] buf;
299 }
300 
301 void Icmpv6L4Protocol::HandleRA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
302 {
303  NS_LOG_FUNCTION (this << packet << src << dst << interface);
304  Ptr<Packet> p = packet->Copy ();
305  Icmpv6RA raHeader;
308  Icmpv6OptionMtu mtuHdr;
310  bool next = true;
311  bool hasLla = false;
312  bool hasMtu = false;
313  Ipv6Address defaultRouter = Ipv6Address::GetZero ();
314 
315  p->RemoveHeader (raHeader);
316 
317  if (raHeader.GetLifeTime())
318  {
319  defaultRouter = src;
320  }
321 
322  while (next == true)
323  {
324  uint8_t type = 0;
325  p->CopyData (&type, sizeof(type));
326 
327  switch (type)
328  {
330  p->RemoveHeader (prefixHdr);
331  ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (interface->GetDevice ()), prefixHdr.GetPrefix (), prefixHdr.GetPrefixLength (),
332  prefixHdr.GetFlags (), prefixHdr.GetValidTime (), prefixHdr.GetPreferredTime (), defaultRouter);
333  break;
335  /* take in account the first MTU option */
336  if (!hasMtu)
337  {
338  p->RemoveHeader (mtuHdr);
339  hasMtu = true;
341  /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
342  }
343  break;
345  /* take in account the first LLA option */
346  if (!hasLla)
347  {
348  p->RemoveHeader (llaHdr);
349  ReceiveLLA (llaHdr, src, dst, interface);
350  hasLla = true;
351  }
352  break;
353  default:
354  /* unknow option, quit */
355  next = false;
356  }
357  }
358 }
359 
361 {
362  NS_LOG_FUNCTION (this << lla << src << dst << interface);
363  Address hardwareAddress;
364  NdiscCache::Entry* entry = 0;
365  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
366 
367  /* check if we have this address in our cache */
368  entry = cache->Lookup (src);
369 
370  if (!entry)
371  {
372  entry = cache->Add (src);
373  entry->SetRouter (true);
374  entry->SetMacAddress (lla.GetAddress ());
375  entry->MarkReachable ();
376  entry->StartReachableTimer ();
377  }
378  else
379  {
380  std::list<Ptr<Packet> > waiting;
381  if (entry->IsIncomplete ())
382  {
383  entry->StopNudTimer ();
384  // mark it to reachable
385  waiting = entry->MarkReachable (lla.GetAddress ());
386  entry->StartReachableTimer ();
387  // send out waiting packet
388  for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
389  {
390  cache->GetInterface ()->Send (*it, src);
391  }
392  entry->ClearWaitingPacket ();
393  }
394  else
395  {
396  if (entry->GetMacAddress () != lla.GetAddress ())
397  {
398  entry->SetMacAddress (lla.GetAddress ());
399  entry->MarkStale ();
400  entry->SetRouter (true);
401  }
402  else
403  {
404  if (!entry->IsReachable ())
405  {
406  entry->StopNudTimer ();
407  waiting = entry->MarkReachable (lla.GetAddress ());
408  if (entry->IsProbe ())
409  {
410  for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
411  {
412  cache->GetInterface ()->Send (*it, src);
413  }
414  }
415  entry->StartReachableTimer ();
416  }
417  }
418  }
419  }
420 }
421 
422 void Icmpv6L4Protocol::HandleRS (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
423 {
424  NS_LOG_FUNCTION (this << packet << src << dst << interface);
426  Icmpv6RS rsHeader;
427  packet->RemoveHeader (rsHeader);
428  Address hardwareAddress;
430  NdiscCache::Entry* entry = 0;
431  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
432 
433  if (src != Ipv6Address::GetAny ())
434  {
435  /* XXX search all options following the RS header */
436  /* test if the next option is SourceLinkLayerAddress */
437  uint8_t type;
438  packet->CopyData (&type, sizeof(type));
439 
441  {
442  return;
443  }
444  packet->RemoveHeader (lla);
445  NS_LOG_LOGIC ("Cache updated by RS");
446 
447  entry = cache->Lookup (src);
448  if (!entry)
449  {
450  entry = cache->Add (src);
451  entry->SetRouter (false);
452  entry->MarkStale (lla.GetAddress ());
453  }
454  else if (entry->GetMacAddress () != lla.GetAddress ())
455  {
456  entry->MarkStale (lla.GetAddress ());
457  }
458  }
459 }
460 
461 void Icmpv6L4Protocol::HandleNS (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
462 {
463  NS_LOG_FUNCTION (this << packet << src << dst << interface);
464  Icmpv6NS nsHeader ("::");
465  Ipv6InterfaceAddress ifaddr;
466  uint32_t nb = interface->GetNAddresses ();
467  uint32_t i = 0;
468  bool found = false;
469 
470  packet->RemoveHeader (nsHeader);
471 
472  Ipv6Address target = nsHeader.GetIpv6Target ();
473 
474  for (i = 0; i < nb; i++)
475  {
476  ifaddr = interface->GetAddress (i);
477 
478  if (ifaddr.GetAddress () == target)
479  {
480  found = true;
481  break;
482  }
483  }
484 
485  if (!found)
486  {
487  NS_LOG_LOGIC ("Not a NS for us");
488  return;
489  }
490 
491  if (packet->GetUid () == ifaddr.GetNsDadUid ())
492  {
493  /* don't process our own DAD probe */
494  NS_LOG_LOGIC ("Hey we receive our DAD probe!");
495  return;
496  }
497 
499  Address hardwareAddress;
500  NdiscCache::Entry* entry = 0;
501  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
502  uint8_t flags = 0;
503 
504  /* XXX search all options following the NS header */
505 
506  if (src != Ipv6Address::GetAny ())
507  {
508  uint8_t type;
509  packet->CopyData (&type, sizeof(type));
510 
512  {
513  return;
514  }
515 
516  /* Get LLA */
517  packet->RemoveHeader (lla);
518 
519  entry = cache->Lookup (src);
520  if (!entry)
521  {
522  entry = cache->Add (src);
523  entry->SetRouter (false);
524  entry->MarkStale (lla.GetAddress ());
525  }
526  else if (entry->GetMacAddress () != lla.GetAddress ())
527  {
528  entry->MarkStale (lla.GetAddress ());
529  }
530 
531  flags = 3; /* S + O flags */
532  }
533  else
534  {
535  /* it means someone do a DAD */
536  flags = 1; /* O flag */
537  }
538 
539  /* send a NA to src */
541 
542  if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
543  {
544  flags += 4; /* R flag */
545  }
546 
547  hardwareAddress = interface->GetDevice ()->GetAddress ();
548  Ptr<Packet> p = ForgeNA (target.IsLinkLocal () ? interface->GetLinkLocalAddress ().GetAddress () : ifaddr.GetAddress (), src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src, &hardwareAddress, flags );
549  interface->Send (p, src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src);
550 
551  /* not a NS for us discard it */
552 }
553 
555 {
556  NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
557  Ptr<Packet> p = Create<Packet> ();
558  Ipv6Header ipHeader;
559  Icmpv6RS rs;
560  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
561 
562  NS_LOG_LOGIC ("Send RS ( from " << src << " to " << dst << ")");
563  p->AddHeader (llOption);
564 
566  p->AddHeader (rs);
567 
568  ipHeader.SetSourceAddress (src);
569  ipHeader.SetDestinationAddress (dst);
570  ipHeader.SetNextHeader (PROT_NUMBER);
571  ipHeader.SetPayloadLength (p->GetSize ());
572  ipHeader.SetHopLimit (255);
573 
574  p->AddHeader (ipHeader);
575 
576  return p;
577 }
578 
580 {
581  NS_LOG_FUNCTION (this << src << dst << id << seq << data);
582  Ptr<Packet> p = data->Copy ();
583  Ipv6Header ipHeader;
584  Icmpv6Echo req (1);
585 
586  req.SetId (id);
587  req.SetSeq (seq);
588 
589  req.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + req.GetSerializedSize (), PROT_NUMBER);
590  p->AddHeader (req);
591 
592  ipHeader.SetSourceAddress (src);
593  ipHeader.SetDestinationAddress (dst);
594  ipHeader.SetNextHeader (PROT_NUMBER);
595  ipHeader.SetPayloadLength (p->GetSize ());
596  ipHeader.SetHopLimit (255);
597 
598  p->AddHeader (ipHeader);
599 
600  return p;
601 }
602 
603 void Icmpv6L4Protocol::HandleNA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
604 {
605  NS_LOG_FUNCTION (this << packet << src << dst << interface);
606  Icmpv6NA naHeader;
608 
609  packet->RemoveHeader (naHeader);
610  Ipv6Address target = naHeader.GetIpv6Target ();
611 
612  Address hardwareAddress;
613  NdiscCache::Entry* entry = 0;
614  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
615  std::list<Ptr<Packet> > waiting;
616 
617  /* check if we have something in our cache */
618  entry = cache->Lookup (target);
619 
620  if (!entry)
621  {
622  /* ouch!! we might be victim of a DAD */
623 
624  Ipv6InterfaceAddress ifaddr;
625  bool found = false;
626  uint32_t i = 0;
627  uint32_t nb = interface->GetNAddresses ();
628 
629  for (i = 0; i < nb; i++)
630  {
631  ifaddr = interface->GetAddress (i);
632  if (ifaddr.GetAddress () == target)
633  {
634  found = true;
635  break;
636  }
637  }
638 
639  if (found)
640  {
642  {
643  interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::INVALID);
644  }
645  }
646 
647  /* we have not initiated any communication with the target so... discard the NA */
648  return;
649  }
650 
651  /* XXX search all options following the NA header */
652  /* Get LLA */
653  uint8_t type;
654  packet->CopyData (&type, sizeof(type));
655 
657  {
658  return;
659  }
660  packet->RemoveHeader (lla);
661 
662  if (entry->IsIncomplete ())
663  {
664  /* we receive a NA so stop the retransmission timer */
665  entry->StopNudTimer ();
666 
667  if (naHeader.GetFlagS ())
668  {
669  /* mark it to reachable */
670  waiting = entry->MarkReachable (lla.GetAddress ());
671  entry->StartReachableTimer ();
672  /* send out waiting packet */
673  for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
674  {
675  cache->GetInterface ()->Send (*it, src);
676  }
677  entry->ClearWaitingPacket ();
678  }
679  else
680  {
681  entry->MarkStale (lla.GetAddress ());
682  }
683 
684  if (naHeader.GetFlagR ())
685  {
686  entry->SetRouter (true);
687  }
688  }
689  else
690  {
691  /* we receive a NA so stop the probe timer or delay timer if any */
692  entry->StopNudTimer ();
693 
694  /* if the Flag O is clear and mac address differs from the cache */
695  if (!naHeader.GetFlagO () && lla.GetAddress () != entry->GetMacAddress ())
696  {
697  if (entry->IsReachable ())
698  {
699  entry->MarkStale ();
700  }
701  return;
702  }
703  else
704  {
705  if ((!naHeader.GetFlagO () && lla.GetAddress () == entry->GetMacAddress ()) || naHeader.GetFlagO ()) /* XXX lake "no target link-layer address option supplied" */
706  {
707  entry->SetMacAddress (lla.GetAddress ());
708 
709  if (naHeader.GetFlagS ())
710  {
711  if (!entry->IsReachable ())
712  {
713  if (entry->IsProbe ())
714  {
715  waiting = entry->MarkReachable (lla.GetAddress ());
716  for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
717  {
718  cache->GetInterface ()->Send (*it, src);
719  }
720  entry->ClearWaitingPacket ();
721  }
722  else
723  {
724  entry->MarkReachable (lla.GetAddress ());
725  }
726  }
727  entry->StartReachableTimer ();
728  }
729  else if (lla.GetAddress () != entry->GetMacAddress ())
730  {
731  entry->MarkStale ();
732  }
733  entry->SetRouter (naHeader.GetFlagR ());
734  }
735  }
736  }
737 }
738 
740 {
741  NS_LOG_FUNCTION (this << packet << src << dst << interface);
742  bool hasLla = false;
743  Ptr<Packet> p = packet->Copy ();
744  Icmpv6OptionLinkLayerAddress llOptionHeader (0);
745 
746  Icmpv6Redirection redirectionHeader;
747  p->RemoveHeader (redirectionHeader);
748 
749  /* little ugly try to find a better way */
750  uint8_t type;
751  p->CopyData (&type, sizeof(type));
753  {
754  hasLla = true;
755  p->RemoveHeader (llOptionHeader);
756  }
757 
758  Icmpv6OptionRedirected redirectedOptionHeader;
759  p->RemoveHeader (redirectedOptionHeader);
760 
761  Ipv6Address redirTarget = redirectionHeader.GetTarget ();
762  Ipv6Address redirDestination = redirectionHeader.GetDestination ();
763 
764  if (hasLla)
765  {
766  /* update the cache if needed */
767  NdiscCache::Entry* entry = 0;
768  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
769 
770  entry = cache->Lookup (redirTarget);
771  if (!entry)
772  {
773  entry = cache->Add (redirTarget);
774  /* destination and target different => necessarily a router */
775  entry->SetRouter (!redirTarget.IsEqual (redirDestination) ? true : false);
776  entry->SetMacAddress (llOptionHeader.GetAddress ());
777  entry->MarkStale ();
778  }
779  else
780  {
781  if (entry->IsIncomplete () || entry->GetMacAddress () != llOptionHeader.GetAddress ())
782  {
783  /* update entry to STALE */
784  if (entry->GetMacAddress () != llOptionHeader.GetAddress ())
785  {
786  entry->SetMacAddress (llOptionHeader.GetAddress ());
787  entry->MarkStale ();
788  }
789  }
790  else
791  {
792  /* stay unchanged */
793  }
794  }
795  }
796 
797  /* add redirection in routing table */
798  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
799 
800  if (redirTarget.IsEqual (redirDestination))
801  {
802  ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), Ipv6Address ("::"), ipv6->GetInterfaceForAddress (dst));
803  }
804  else
805  {
806  uint32_t ifIndex = ipv6->GetInterfaceForAddress (dst);
807  ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), redirTarget, ifIndex);
808  }
809 }
810 
812 {
813  NS_LOG_FUNCTION (this << *p << src << dst << interface);
814  Ptr<Packet> pkt = p->Copy ();
815 
817  pkt->RemoveHeader (unreach);
818  Ptr<Packet> origPkt = unreach.GetPacket ();
819 
820  Ipv6Header ipHeader;
821  if ( origPkt->GetSize () > ipHeader.GetSerializedSize () )
822  {
823  origPkt->RemoveHeader (ipHeader);
824  uint8_t payload[8];
825  origPkt->CopyData (payload, 8);
826  Forward (src, unreach, unreach.GetCode (), ipHeader, payload);
827  }
828 }
829 
831 {
832  NS_LOG_FUNCTION (this << *p << src << dst << interface);
833  Ptr<Packet> pkt = p->Copy ();
834 
835  Icmpv6TimeExceeded timeexceeded;
836  pkt->RemoveHeader (timeexceeded);
837  Ptr<Packet> origPkt = timeexceeded.GetPacket ();
838  Ipv6Header ipHeader;
839  uint8_t payload[8];
840  origPkt->RemoveHeader (ipHeader);
841  origPkt->CopyData (payload, 8);
842 
843  Forward (src, timeexceeded, timeexceeded.GetCode (), ipHeader, payload);
844 }
845 
847 {
848  NS_LOG_FUNCTION (this << *p << src << dst << interface);
849  Ptr<Packet> pkt = p->Copy ();
850 
851  Icmpv6TooBig tooBig;
852  pkt->RemoveHeader (tooBig);
853  Ptr<Packet> origPkt = tooBig.GetPacket ();
854 
855  Ipv6Header ipHeader;
856  origPkt->RemoveHeader (ipHeader);
857  uint8_t payload[8];
858  origPkt->CopyData (payload, 8);
859 
861  ipv6->SetPmtu(ipHeader.GetDestinationAddress(), tooBig.GetMtu ());
862 
863  Forward (src, tooBig, tooBig.GetMtu (), ipHeader, payload);
864 }
865 
867 {
868  NS_LOG_FUNCTION (this << *p << src << dst << interface);
869  Ptr<Packet> pkt = p->Copy ();
870 
871  Icmpv6ParameterError paramErr;
872  pkt->RemoveHeader (paramErr);
873  Ptr<Packet> origPkt = paramErr.GetPacket ();
874 
875  Ipv6Header ipHeader;
876  origPkt->RemoveHeader (ipHeader);
877  uint8_t payload[8];
878  origPkt->CopyData (payload, 8);
879  Forward (src, paramErr, paramErr.GetCode (), ipHeader, payload);
880 }
881 
883 {
884  NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
886  SocketIpTtlTag tag;
887  NS_ASSERT (ipv6 != 0);
888 
889  tag.SetTtl (ttl);
890  packet->AddPacketTag (tag);
891  m_downTarget (packet, src, dst, PROT_NUMBER, 0);
892 }
893 
895 {
896  NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
897  SendMessage (packet, src, dst, ttl);
898 }
899 
900 void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl)
901 {
902  NS_LOG_FUNCTION (this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
904  NS_ASSERT (ipv6 != 0 && ipv6->GetRoutingProtocol () != 0);
905  Ipv6Header header;
906  SocketIpTtlTag tag;
908  Ptr<Ipv6Route> route;
909  Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
910 
911  header.SetDestinationAddress (dst);
912  route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, err);
913 
914  if (route != 0)
915  {
916  NS_LOG_LOGIC ("Route exists");
917  tag.SetTtl (ttl);
918  packet->AddPacketTag (tag);
919  Ipv6Address src = route->GetSource ();
920 
921  icmpv6Hdr.CalculatePseudoHeaderChecksum (src, dst, packet->GetSize () + icmpv6Hdr.GetSerializedSize (), PROT_NUMBER);
922  packet->AddHeader (icmpv6Hdr);
923  m_downTarget (packet, src, dst, PROT_NUMBER, route);
924  }
925  else
926  {
927  NS_LOG_WARN ("drop icmp message");
928  }
929 }
930 
931 void Icmpv6L4Protocol::SendNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
932 {
933  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << static_cast<uint32_t> (flags));
934  Ptr<Packet> p = Create<Packet> ();
935  Icmpv6NA na;
936  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* not a source link layer */
937 
938  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << " target " << src << ")");
939  na.SetIpv6Target (src);
940 
941  if ((flags & 1))
942  {
943  na.SetFlagO (true);
944  }
945  if ((flags & 2) && src != Ipv6Address::GetAny ())
946  {
947  na.SetFlagS (true);
948  }
949  if ((flags & 4))
950  {
951  na.SetFlagR (true);
952  }
953 
954  p->AddHeader (llOption);
955  na.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + na.GetSerializedSize (), PROT_NUMBER);
956  p->AddHeader (na);
957 
958  SendMessage (p, src, dst, 255);
959 }
960 
961 void Icmpv6L4Protocol::SendEchoReply (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr<Packet> data)
962 {
963  NS_LOG_FUNCTION (this << src << dst << id << seq << data);
964  Ptr<Packet> p = data->Copy ();
965  Icmpv6Echo reply (0); /* echo reply */
966 
967  reply.SetId (id);
968  reply.SetSeq (seq);
969 
970  reply.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + reply.GetSerializedSize (), PROT_NUMBER);
971  p->AddHeader (reply);
972  SendMessage (p, src, dst, 64);
973 }
974 
975 void Icmpv6L4Protocol::SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
976 {
977  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
978  Ptr<Packet> p = Create<Packet> ();
979  /* Ipv6Header ipHeader; */
980  Icmpv6NS ns (target);
981  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
982 
983  /* if the source is unspec, multicast the NA to all-nodes multicast */
984  if (src == Ipv6Address::GetAny ())
985  {
987  }
988 
989  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
990 
991  p->AddHeader (llOption);
992  ns.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + ns.GetSerializedSize (), PROT_NUMBER);
993  p->AddHeader (ns);
994  if (!dst.IsMulticast ())
995  {
996  SendMessage (p, src, dst, 255);
997  }
998  else
999  {
1000  NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
1002  }
1003 }
1004 
1006 {
1007  NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
1008  Ptr<Packet> p = Create<Packet> ();
1009  Icmpv6RS rs;
1010  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1011 
1012  /* if the source is unspec, multicast the NA to all-nodes multicast */
1013  if (src != Ipv6Address::GetAny ())
1014  {
1015  p->AddHeader (llOption);
1016  }
1017 
1018  NS_LOG_LOGIC ("Send RS ( from " << src << " to " << dst << ")");
1019 
1020  rs.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + rs.GetSerializedSize (), PROT_NUMBER);
1021  p->AddHeader (rs);
1022  if (!dst.IsMulticast ())
1023  {
1024  SendMessage (p, src, dst, 255);
1025  }
1026  else
1027  {
1028  NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
1030  }
1031 }
1032 
1034 {
1035  NS_LOG_FUNCTION (this << malformedPacket << dst << (uint32_t)code);
1036  Ptr<Packet> p = Create<Packet> ();
1037  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1039 
1040  NS_LOG_LOGIC ("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1041 
1042  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1043  if (malformedPacketSize <= 1280 - 48)
1044  {
1045  header.SetPacket (malformedPacket);
1046  }
1047  else
1048  {
1049  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1050  header.SetPacket (fragment);
1051  }
1052 
1053  header.SetCode (code);
1054  SendMessage (p, dst, header, 255);
1055 }
1056 
1057 void Icmpv6L4Protocol::SendErrorTooBig (Ptr<Packet> malformedPacket, Ipv6Address dst, uint32_t mtu)
1058 {
1059  NS_LOG_FUNCTION (this << malformedPacket << dst << mtu);
1060  Ptr<Packet> p = Create<Packet> ();
1061  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1062  Icmpv6TooBig header;
1063 
1064  NS_LOG_LOGIC ("Send Too Big ( to " << dst << " )");
1065 
1066  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1067  if (malformedPacketSize <= 1280 - 48)
1068  {
1069  header.SetPacket (malformedPacket);
1070  }
1071  else
1072  {
1073  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1074  header.SetPacket (fragment);
1075  }
1076 
1077  header.SetCode (0);
1078  header.SetMtu (mtu);
1079  SendMessage (p, dst, header, 255);
1080 }
1081 
1082 void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
1083 {
1084  NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code));
1085  Ptr<Packet> p = Create<Packet> ();
1086  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1087  Icmpv6TimeExceeded header;
1088 
1089  NS_LOG_LOGIC ("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1090 
1091  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1092  if (malformedPacketSize <= 1280 - 48)
1093  {
1094  header.SetPacket (malformedPacket);
1095  }
1096  else
1097  {
1098  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1099  header.SetPacket (fragment);
1100  }
1101 
1102  header.SetCode (code);
1103  SendMessage (p, dst, header, 255);
1104 }
1105 
1106 void Icmpv6L4Protocol::SendErrorParameterError (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
1107 {
1108  NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code) << ptr);
1109  Ptr<Packet> p = Create<Packet> ();
1110  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1111  Icmpv6ParameterError header;
1112 
1113  NS_LOG_LOGIC ("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1114 
1115  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1116  if (malformedPacketSize <= 1280 - 48 )
1117  {
1118  header.SetPacket (malformedPacket);
1119  }
1120  else
1121  {
1122  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1123  header.SetPacket (fragment);
1124  }
1125 
1126  header.SetCode (code);
1127  header.SetPtr (ptr);
1128  SendMessage (p, dst, header, 255);
1129 }
1130 
1131 void Icmpv6L4Protocol::SendRedirection (Ptr<Packet> redirectedPacket, Ipv6Address src, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget)
1132 {
1133  NS_LOG_FUNCTION (this << redirectedPacket << dst << redirTarget << redirDestination << redirHardwareTarget);
1134  uint32_t llaSize = 0;
1135  Ptr<Packet> p = Create<Packet> ();
1136  uint32_t redirectedPacketSize = redirectedPacket->GetSize ();
1137  Icmpv6OptionLinkLayerAddress llOption (0);
1138 
1139  NS_LOG_LOGIC ("Send Redirection ( to " << dst << " target " << redirTarget << " destination " << redirDestination << " )");
1140 
1141  Icmpv6OptionRedirected redirectedOptionHeader;
1142 
1143  if ((redirectedPacketSize % 8) != 0)
1144  {
1145  Ptr<Packet> pad = Create<Packet> (8 - (redirectedPacketSize % 8));
1146  redirectedPacket->AddAtEnd (pad);
1147  }
1148 
1149  if (redirHardwareTarget.GetLength ())
1150  {
1151  llOption.SetAddress (redirHardwareTarget);
1152  llaSize = llOption.GetSerializedSize ();
1153  }
1154 
1155  /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1156  if (redirectedPacketSize <= (1280 - 56 - llaSize))
1157  {
1158  redirectedOptionHeader.SetPacket (redirectedPacket);
1159  }
1160  else
1161  {
1162  Ptr<Packet> fragment = redirectedPacket->CreateFragment (0, 1280 - 56 - llaSize);
1163  redirectedOptionHeader.SetPacket (fragment);
1164  }
1165 
1166  p->AddHeader (redirectedOptionHeader);
1167 
1168  if (llaSize)
1169  {
1170  p->AddHeader (llOption);
1171  }
1172 
1173  Icmpv6Redirection redirectionHeader;
1174  redirectionHeader.SetTarget (redirTarget);
1175  redirectionHeader.SetDestination (redirDestination);
1176  redirectionHeader.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + redirectionHeader.GetSerializedSize (), PROT_NUMBER);
1177  p->AddHeader (redirectionHeader);
1178 
1179  SendMessage (p, src, dst, 64);
1180 }
1181 
1182 Ptr<Packet> Icmpv6L4Protocol::ForgeNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1183 {
1184  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << (uint32_t)flags);
1185  Ptr<Packet> p = Create<Packet> ();
1186  Ipv6Header ipHeader;
1187  Icmpv6NA na;
1188  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* we give our mac address in response */
1189 
1190  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << ")");
1191 
1192  /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet does not pass by Icmpv6L4Protocol::Lookup again */
1193 
1194  p->AddHeader (llOption);
1195  na.SetIpv6Target (src);
1196 
1197  if ((flags & 1))
1198  {
1199  na.SetFlagO (true);
1200  }
1201  if ((flags & 2) && src != Ipv6Address::GetAny ())
1202  {
1203  na.SetFlagS (true);
1204  }
1205  if ((flags & 4))
1206  {
1207  na.SetFlagR (true);
1208  }
1209 
1211  p->AddHeader (na);
1212 
1213  ipHeader.SetSourceAddress (src);
1214  ipHeader.SetDestinationAddress (dst);
1215  ipHeader.SetNextHeader (PROT_NUMBER);
1216  ipHeader.SetPayloadLength (p->GetSize ());
1217  ipHeader.SetHopLimit (255);
1218 
1219  p->AddHeader (ipHeader);
1220 
1221  return p;
1222 }
1223 
1225 {
1226  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
1227  Ptr<Packet> p = Create<Packet> ();
1228  Ipv6Header ipHeader;
1229  Icmpv6NS ns (target);
1230  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1231 
1232  /* if the source is unspec, multicast the NA to all-nodes multicast */
1233  if (src == Ipv6Address::GetAny ())
1234  {
1236  }
1237 
1238  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1239 
1240  p->AddHeader (llOption);
1242  p->AddHeader (ns);
1243 
1244  ipHeader.SetSourceAddress (src);
1245  ipHeader.SetDestinationAddress (dst);
1246  ipHeader.SetNextHeader (PROT_NUMBER);
1247  ipHeader.SetPayloadLength (p->GetSize ());
1248  ipHeader.SetHopLimit (255);
1249 
1250  p->AddHeader (ipHeader);
1251 
1252  return p;
1253 }
1254 
1256 {
1257  NS_LOG_FUNCTION (this << device);
1258 
1259  for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
1260  {
1261  if ((*i)->GetDevice () == device)
1262  {
1263  return *i;
1264  }
1265  }
1266 
1267  NS_ASSERT (false);
1268  /* quiet compiler */
1269  return 0;
1270 }
1271 
1273 {
1274  NS_LOG_FUNCTION (this << device << interface);
1275 
1276  Ptr<NdiscCache> cache = CreateObject<NdiscCache> ();
1277 
1278  cache->SetDevice (device, interface);
1279  device->AddLinkChangeCallback (MakeCallback (&NdiscCache::Flush, cache));
1280  m_cacheList.push_back (cache);
1281  return cache;
1282 }
1283 
1284 bool Icmpv6L4Protocol::Lookup (Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1285 {
1286  NS_LOG_FUNCTION (this << dst << device << cache << hardwareDestination);
1287 
1288  if (!cache)
1289  {
1290  /* try to find the cache */
1291  cache = FindCache (device);
1292  }
1293  if (cache)
1294  {
1295  NdiscCache::Entry* entry = cache->Lookup (dst);
1296  if (entry)
1297  {
1298  if (entry->IsReachable () || entry->IsDelay ())
1299  {
1300  *hardwareDestination = entry->GetMacAddress ();
1301  return true;
1302  }
1303  else if (entry->IsStale ())
1304  {
1305  entry->StartDelayTimer ();
1306  entry->MarkDelay ();
1307  *hardwareDestination = entry->GetMacAddress ();
1308  return true;
1309  }
1310  }
1311  }
1312  return false;
1313 }
1314 
1315 bool Icmpv6L4Protocol::Lookup (Ptr<Packet> p, Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1316 {
1317  NS_LOG_FUNCTION (this << p << dst << device << cache << hardwareDestination);
1318 
1319  if (!cache)
1320  {
1321  /* try to find the cache */
1322  cache = FindCache (device);
1323  }
1324  if (!cache)
1325  {
1326  return false;
1327  }
1328 
1329  NdiscCache::Entry* entry = cache->Lookup (dst);
1330  if (entry)
1331  {
1332  if (entry->IsReachable () || entry->IsDelay ())
1333  {
1334  /* XXX check reachability time */
1335  /* send packet */
1336  *hardwareDestination = entry->GetMacAddress ();
1337  return true;
1338  }
1339  else if (entry->IsStale ())
1340  {
1341  /* start delay timer */
1342  entry->StartDelayTimer ();
1343  entry->MarkDelay ();
1344  *hardwareDestination = entry->GetMacAddress ();
1345  return true;
1346  }
1347  else /* INCOMPLETE or PROBE */
1348  {
1349  /* queue packet */
1350  entry->AddWaitingPacket (p);
1351  return false;
1352  }
1353  }
1354  else
1355  {
1356  /* we contact this node for the first time
1357  * add it to the cache and send an NS
1358  */
1359  Ipv6Address addr;
1360  NdiscCache::Entry* entry = cache->Add (dst);
1361  entry->MarkIncomplete (p);
1362  entry->SetRouter (false);
1363 
1364  if (dst.IsLinkLocal ())
1365  {
1366  addr = cache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
1367  }
1368  else if (cache->GetInterface ()->GetNAddresses () == 1) /* an interface have at least one address (link-local) */
1369  {
1370  /* try to resolve global address without having global address so return! */
1371  cache->Remove (entry);
1372  return false;
1373  }
1374  else
1375  {
1376  /* find source address that match destination */
1377  addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress ();
1378  }
1379 
1380  SendNS (addr, Ipv6Address::MakeSolicitedAddress (dst), dst, cache->GetDevice ()->GetAddress ());
1381 
1382  /* start retransmit timer */
1383  entry->StartRetransmitTimer ();
1384  return false;
1385  }
1386 
1387  return false;
1388 }
1389 
1391 {
1393  NS_LOG_LOGIC (interface << " " << addr);
1394  Ipv6InterfaceAddress ifaddr;
1395  bool found = false;
1396  uint32_t i = 0;
1397  uint32_t nb = interface->GetNAddresses ();
1398 
1399  for (i = 0; i < nb; i++)
1400  {
1401  ifaddr = interface->GetAddress (i);
1402 
1403  if (ifaddr.GetAddress () == addr)
1404  {
1405  found = true;
1406  break;
1407  }
1408  }
1409 
1410  /* for the moment, this function is always called, if we was victim of a DAD the address is INVALID
1411  * and we do not set it to PREFERRED
1412  */
1413  if (found && ifaddr.GetState () != Ipv6InterfaceAddress::INVALID)
1414  {
1415  interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::PREFERRED);
1416  NS_LOG_LOGIC ("DAD OK, interface in state PREFERRED");
1417 
1418  /* send an RS if our interface is not forwarding (router) and if address is a link-local ones
1419  * (because we will send RS with it)
1420  */
1421  Ptr<Ipv6> ipv6 = icmpv6->m_node->GetObject<Ipv6> ();
1422 
1423  if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ())
1424  {
1425  /* \todo Add random delays before sending RS
1426  * because all nodes start at the same time, there will be many of RS arround 1 second of simulation time
1427  */
1428  Simulator::Schedule (Seconds (0.0), &Icmpv6L4Protocol::SendRS, PeekPointer (icmpv6), ifaddr.GetAddress (), Ipv6Address::GetAllRoutersMulticast (), interface->GetDevice ()->GetAddress ());
1429  }
1430  }
1431 }
1432 
1433 void
1435 {
1436  NS_LOG_FUNCTION (this << &callback);
1437 }
1438 
1439 void
1441 {
1442  NS_LOG_FUNCTION (this << &callback);
1443  m_downTarget = callback;
1444 }
1445 
1448 {
1449  NS_LOG_FUNCTION (this);
1450  return (IpL4Protocol::DownTargetCallback)NULL;
1451 }
1452 
1455 {
1456  NS_LOG_FUNCTION (this);
1457  return m_downTarget;
1458 }
1459 
1460 } /* namespace ns3 */
1461 
void DelayedSendMessage(Ptr< Packet > packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
Helper function used during delayed solicitation.
bool IsAny() const
If the IPv6 address is the "Any" address.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:144
uint8_t GetNextHeader(void) const
Get the next header.
Definition: ipv6-header.cc:81
void SetPayloadLength(uint16_t len)
Set the "Payload length" field.
Definition: ipv6-header.cc:66
void SetPacket(Ptr< Packet > packet)
Set the redirected packet.
void CalculatePseudoHeaderChecksum(Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
Calculate pseudo header checksum for IPv6.
Introspection did not find any typical Config paths.
uint16_t GetId() const
Get the ID of the packet.
static const uint8_t MAX_ANYCAST_DELAY_TIME
Neighbor Discovery node constants : max anycast delay.
uint32_t GetNsDadUid() const
Get the latest DAD probe packet UID.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Introspection did not find any typical Config paths.
Definition: ipv6-header.h:33
bool Lookup(Ipv6Address dst, Ptr< NetDevice > device, Ptr< NdiscCache > cache, Address *hardwareDestination)
Lookup in the ND cache for the IPv6 address.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void MarkIncomplete(Ptr< Packet > p)
Changes the state to this entry to INCOMPLETE.
Definition: ndisc-cache.cc:447
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
Introspection did not find any typical Config paths.
void SetState(Ipv6Address address, Ipv6InterfaceAddress::State_e state)
Update state of an interface address.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
AttributeValue implementation for Boolean.
Definition: boolean.h:34
Introspection did not find any typical Config paths.
Introspection did not find any typical Config paths.
void SendNA(Ipv6Address src, Ipv6Address dst, Address *hardwareAddress, uint8_t flags)
Send a Neighbor Adverstisement.
void HandleNS(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Solicitation method.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
Address GetMacAddress() const
Get the MAC address of this entry.
Definition: ndisc-cache.cc:528
NdiscCache::Entry * Add(Ipv6Address to)
Add an entry.
Definition: ndisc-cache.cc:103
static const uint8_t MAX_INITIAL_RTR_ADVERTISEMENTS
Neighbor Discovery router constants : max initial RA transmission.
Ptr< Packet > GetPacket() const
Get the incorrect packet.
Ipv6Address GetTarget() const
Get the IPv6 target address.
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:80
Hold variables of type string.
Definition: string.h:41
void StopNudTimer()
Stop NUD timer and reset the NUD retransmission counter.
Definition: ndisc-cache.cc:440
virtual uint32_t GetSerializedSize() const
Get the serialized size.
static const uint8_t MAX_FINAL_RTR_ADVERTISEMENTS
Neighbor Discovery router constants : max final RA transmission.
void Send(Ptr< Packet > packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr< Ipv6Route > route)
Higher-level layers call this method to send a packet down the stack to the MAC and PHY layers...
Introspection did not find any typical Config paths.
IPv6 layer implementation.
Ptr< Node > m_node
The node.
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:81
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:836
Introspection did not find any typical Config paths.
void SendRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Send a Router Solicitation.
Introspection did not find any typical Config paths.
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:380
uint8_t GetType() const
Get the type field.
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1078
#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
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.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:562
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
Ipv6InterfaceAddress GetAddress(uint32_t index) const
Get an address from IPv6 interface.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
IPv6 address associated with an interface.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:874
void SetPtr(uint32_t ptr)
Set the pointer field.
static const uint8_t PROT_NUMBER
ICMPv6 protocol number (58).
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...
bool GetFlagS() const
Get the S flag.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:766
void SetNextHeader(uint8_t next)
Set the "Next header" field.
Definition: ipv6-header.cc:76
Invalid state (after a DAD failed)
bool IsEqual(const Ipv6Address &other) const
Comparison operation between two Ipv6Addresses.
virtual ~Icmpv6L4Protocol()
Destructor.
static const uint8_t RTR_SOLICITATION_INTERVAL
Neighbor Discovery host constants : RS interval.
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:339
static const uint8_t MAX_RTR_SOLICITATIONS
Neighbor Discovery host constants : max RS transmission.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:819
void SetMtu(uint32_t mtu)
Set the MTU.
void SetNode(Ptr< Node > node)
Set the node.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:999
void SetTarget(Ipv6Address target)
Set the IPv6 target address.
virtual int GetProtocolNumber() const
Get the protocol number.
std::list< Ptr< Packet > > MarkReachable(Address mac)
Changes the state to this entry to REACHABLE.
Definition: ndisc-cache.cc:458
Icmpv6L4Protocol()
Constructor.
uint16_t GetLifeTime() const
Get the node Life time (Neighbor Discovery).
virtual double GetValue(void)=0
Returns a random double from the underlying distribution.
a polymophic address class
Definition: address.h:90
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
static void FunctionDadTimeout(Ptr< Icmpv6L4Protocol > icmpv6, Ipv6Interface *interface, Ipv6Address addr)
Function called when DAD timeout.
virtual enum IpL4Protocol::RxStatus Receive(Ptr< Packet > p, Ipv4Header const &header, Ptr< Ipv4Interface > interface)
Receive method.
void SendErrorTooBig(Ptr< Packet > malformedPacket, Ipv6Address dst, uint32_t mtu)
Send an error Too Big.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
Ptr< Ipv6Interface > GetInterface() const
Get the Ipv6Interface associated with this cache.
Definition: ndisc-cache.cc:79
void NotifyNewAggregate()
This method is called by AddAgregate and completes the aggregation by setting the node in the ICMPv6 ...
bool IsDelay() const
Is the entry DELAY.
Definition: ndisc-cache.cc:510
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:228
Packet header for IPv4.
Definition: ipv4-header.h:31
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:317
bool GetFlagR() const
Get the R flag.
The IPv6 representation of a network interface.
Introspection did not find any typical Config paths.
void HandleRedirection(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Redirection method.
Ipv6Address GetAddress() const
Get the IPv6 address.
Ipv6Address GetIpv6Target() const
Get the IPv6 target field.
Introspection did not find any typical Config paths.
Definition: icmpv6-header.h:37
uint32_t GetNAddresses(void) const
Get number of addresses on this IPv6 interface.
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:210
static const uint32_t MAX_RA_DELAY_TIME
Neighbor Discovery router constants : max delay between RA.
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 SendErrorParameterError(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
Send an error Parameter Error.
Ptr< Packet > GetPacket() const
Get the incorrect packet.
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition: socket.cc:584
void SetIpv6Target(Ipv6Address target)
Set the IPv6 target field.
void HandleTimeExceeded(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Time Exceeded method.
void Flush()
Flush the cache.
Definition: ndisc-cache.cc:130
void SendErrorTimeExceeded(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code)
Send an error Time Exceeded.
Introspection did not find any typical Config paths.
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
uint8_t data[writeSize]
bool IsAlwaysDad() const
Is the node must do DAD.
uint8_t GetLength(void) const
Get the length of the underlying address.
Definition: address.cc:75
static const uint32_t REACHABLE_TIME
Neighbor Discovery node constants : reachable time.
Introspection did not find any typical Config paths.
Ptr< Packet > GetPacket() const
Get the incorrect packet.
static const double MIN_RANDOM_FACTOR
Neighbor Discovery node constants : min random factor.
An implementation of the ICMPv6 protocol.
Ptr< NdiscCache > FindCache(Ptr< NetDevice > device)
Get the cache corresponding to the device.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1296
virtual Ptr< NetDevice > GetDevice() const
Get the NetDevice.
Ptr< Packet > ForgeNA(Ipv6Address src, Ipv6Address dst, Address *hardwareAddress, uint8_t flags)
Forge a Neighbor Advertisement.
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
Ptr< RandomVariableStream > m_solicitationJitter
Random jitter before sending solicitations.
bool GetFlagO() const
Get the O flag.
void HandleRS(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Router Solicitation method.
void Send(Ptr< Packet > p, Ipv6Address dest)
Send a packet through this interface.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
Ptr< Packet > ForgeNS(Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
Forge a Neighbor Solicitation.
void StartRetransmitTimer()
Start retransmit timer.
Definition: ndisc-cache.cc:428
#define list
uint16_t GetSeq() const
Get the sequence number.
void SetNsDadUid(Ipv6Address address, uint32_t uid)
Update NS DAD packet UID of an interface address.
void ClearWaitingPacket()
Clear the waiting packet list.
Definition: ndisc-cache.cc:233
virtual uint32_t GetSerializedSize() const
Get the serialized size.
void HandleEchoRequest(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Echo Request method.
void HandleParameterError(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Parameter Error method.
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:318
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
static const uint8_t MAX_MULTICAST_SOLICIT
Neighbor Discovery node constants : max multicast solicitations.
bool IsProbe() const
Is the entry PROBE.
Definition: ndisc-cache.cc:522
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:91
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SendErrorDestinationUnreachable(Ptr< Packet > malformedPacket, Ipv6Address dst, uint8_t code)
Send an error Destination Unreachable.
void SendEchoReply(Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr< Packet > data)
Send a Echo Reply.
static TypeId GetTypeId()
Interface ID.
static const uint8_t MAX_NEIGHBOR_ADVERTISEMENT
Neighbor Discovery node constants : max NA transmission.
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...
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
static uint16_t GetStaticProtocolNumber()
Get ICMPv6 protocol number.
void SetCode(uint8_t code)
Set the code field.
Ipv6InterfaceAddress::State_e GetState() const
Get the address state.
Introspection did not find any typical Config paths.
uint8_t GetCode() const
Get the code field.
void AddWaitingPacket(Ptr< Packet > p)
Add a packet (or replace old value) in the queue.
Definition: ndisc-cache.cc:220
void StartDelayTimer()
Start delay timer.
Definition: ndisc-cache.cc:416
IpL4Protocol::DownTargetCallback6 m_downTarget
callback to Ipv6::Send
static const uint8_t MAX_INITIAL_RTR_ADVERT_INTERVAL
Neighbor Discovery router constants : max initial RA initial interval.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
static Ipv6Address GetAllNodesMulticast()
Get the "all nodes multicast" address.
void StartReachableTimer()
Start the reachable timer.
Definition: ndisc-cache.cc:391
bool m_alwaysDad
Always do DAD ?
bool IsIncomplete() const
Is the entry INCOMPLETE.
Definition: ndisc-cache.cc:516
L4 Protocol abstract base class.
void SendMessage(Ptr< Packet > packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
Send a packet via ICMPv6, note that packet already contains ICMPv6 header.
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...
Ptr< Packet > ForgeRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Forge a Router Solicitation.
void Remove(NdiscCache::Entry *entry)
Delete an entry.
Definition: ndisc-cache.cc:114
static const uint8_t MIN_DELAY_BETWEEN_RAS
Neighbor Discovery router constants : min delay between RA.
void SetFlagR(bool r)
Set the R flag.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
void SendRedirection(Ptr< Packet > redirectedPacket, Ipv6Address src, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget)
Send an ICMPv6 Redirection.
std::list< Ptr< Packet > > MarkStale(Address mac)
Changes the state to this entry to STALE.
Definition: ndisc-cache.cc:484
void SetMacAddress(Address mac)
Set the MAC address of this entry.
Definition: ndisc-cache.cc:534
static const double MAX_RANDOM_FACTOR
Neighbor Discovery node constants : max random factor.
Introspection did not find any typical Config paths.
void SetFlagS(bool s)
Set the S flag.
void SetSourceAddress(Ipv6Address src)
Set the "Source address" field.
Definition: ipv6-header.cc:96
CacheList m_cacheList
A list of cache by 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...
Ipv6InterfaceAddress GetLinkLocalAddress() const
Get link-local address from IPv6 interface.
Describes an IPv6 address.
Definition: ipv6-address.h:47
NdiscCache::Entry * Lookup(Ipv6Address dst)
Lookup in the cache.
Definition: ndisc-cache.cc:91
void SetHopLimit(uint8_t limit)
Set the "Hop limit" field (TTL).
Definition: ipv6-header.cc:86
void HandleRA(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Router Advertisement method.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:228
void ReceiveLLA(Icmpv6OptionLinkLayerAddress lla, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Link layer address option processing.
void MarkDelay()
Change the state to this entry to DELAY.
Definition: ndisc-cache.cc:492
virtual int GetVersion() const
Get the version of the protocol.
static const uint32_t RETRANS_TIMER
Neighbor Discovery node constants : retransmission timer.
void SetDestination(Ipv6Address destination)
Set the IPv6 destination address.
Ptr< Packet > ForgeEchoRequest(Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr< Packet > data)
Forge an Echo Request.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:866
void SetDevice(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface)
Set the device and interface.
Definition: ndisc-cache.cc:72
Describes an IPv6 prefix.
Definition: ipv6-address.h:389
virtual void DoDispose()
Dispose this object.
void Nullify(void)
Discard the implementation, set it to null.
Definition: callback.h:1082
Ipv6Address GetDestination() const
Get the IPv6 destination address.
Ipv6Address GetIpv6Target() const
Get the IPv6 target field.
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:368
static const uint8_t MAX_RTR_SOLICITATION_DELAY
Neighbor Discovery host constants : max RS delay.
A record that holds information about an NdiscCache entry.
Definition: ndisc-cache.h:138
RxStatus
Rx status codes.
Address is tentative but we are optimistic so we can send packet even if DAD is not yet finished...
void HandleNA(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Neighbor Advertisement method.
void SetRouter(bool router)
Set the node type.
Definition: ndisc-cache.cc:208
static const uint8_t DELAY_FIRST_PROBE_TIME
Neighbor Discovery node constants : delay for the first probe.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
void SetSeq(uint16_t seq)
Set the sequence number.
void HandlePacketTooBig(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Packet Too Big method.
bool IsReachable() const
Is the entry REACHABLE.
Definition: ndisc-cache.cc:504
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
uint32_t GetMtu() const
Get the MTU field.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:455
Introspection did not find any typical Config paths.
a unique identifier for an interface.
Definition: type-id.h:57
Ptr< Packet > GetPacket() const
Get the incorrect packet.
Ipv6InterfaceAddress GetAddressMatchingDestination(Ipv6Address dst)
Get an address which is in the same network prefix as destination.
virtual uint32_t GetSerializedSize() const
Get the serialized size.
void SetDestinationAddress(Ipv6Address dst)
Set the "Destination address" field.
Definition: ipv6-header.cc:106
void SetFlagO(bool o)
Set the O flag.
Ptr< NetDevice > GetDevice() const
Get the NetDevice associated with this cache.
Definition: ndisc-cache.cc:85
TypeId SetParent(TypeId tid)
Definition: type-id.cc:638
void Dispose(void)
Dispose of this Object.
Definition: object.cc:208
void SendNS(Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
Send a Neighbor Solicitation.
Address is tentative, no packet can be sent unless DAD finished.
bool IsStale() const
Is the entry STALE.
Definition: ndisc-cache.cc:498
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111
Ptr< NdiscCache > CreateCache(Ptr< NetDevice > device, Ptr< Ipv6Interface > interface)
Create a neighbor cache.
void SetId(uint16_t id)
Set the ID of the packet.
void HandleDestinationUnreachable(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Destination Unreachable method.
static Ipv6Address MakeSolicitedAddress(Ipv6Address addr)
Make the solicited IPv6 address.
static Ipv6Address GetAllRoutersMulticast()
Get the "all routers multicast" address.
static const uint8_t MAX_UNICAST_SOLICIT
Neighbor Discovery node constants : max unicast solicitations.