A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
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_OBJECT_ENSURE_REGISTERED (Icmpv6L4Protocol)
43  ;
44 
45 NS_LOG_COMPONENT_DEFINE ("Icmpv6L4Protocol")
46  ;
47 
48 const uint8_t Icmpv6L4Protocol::PROT_NUMBER = 58;
49 
54 const uint32_t Icmpv6L4Protocol::MAX_RA_DELAY_TIME = 500; /* millisecond */
55 
59 
64 const uint32_t Icmpv6L4Protocol::REACHABLE_TIME = 30000;
65 const uint32_t Icmpv6L4Protocol::RETRANS_TIMER = 1000;
67 const double Icmpv6L4Protocol::MIN_RANDOM_FACTOR = 0.5;
68 const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5;
69 
71 {
72  static TypeId tid = TypeId ("ns3::Icmpv6L4Protocol")
74  .AddConstructor<Icmpv6L4Protocol> ()
75  .AddAttribute ("DAD", "Always do DAD check.",
76  BooleanValue (true),
77  MakeBooleanAccessor (&Icmpv6L4Protocol::m_alwaysDad),
78  MakeBooleanChecker ())
79  .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",
80  StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
81  MakePointerAccessor (&Icmpv6L4Protocol::m_solicitationJitter),
82  MakePointerChecker<RandomVariableStream> ())
83 
84  ;
85  return tid;
86 }
87 
89  : m_node (0)
90 {
91  NS_LOG_FUNCTION (this);
92 }
93 
95 {
96  NS_LOG_FUNCTION (this);
97 }
98 
100 {
101  NS_LOG_FUNCTION (this);
102  for (CacheList::const_iterator it = m_cacheList.begin (); it != m_cacheList.end (); it++)
103  {
104  Ptr<NdiscCache> cache = *it;
105  cache->Dispose ();
106  cache = 0;
107  }
108  m_cacheList.clear ();
110 
111  m_node = 0;
113 }
114 
115 int64_t Icmpv6L4Protocol::AssignStreams (int64_t stream)
116 {
117  NS_LOG_FUNCTION (this << stream);
119  return 1;
120 }
121 
123 {
124  NS_LOG_FUNCTION (this);
125  if (m_node == 0)
126  {
127  Ptr<Node> node = this->GetObject<Node> ();
128  if (node != 0)
129  {
130  Ptr<Ipv6L3Protocol> ipv6 = this->GetObject<Ipv6L3Protocol> ();
131  if (ipv6 != 0 && m_downTarget.IsNull ())
132  {
133  SetNode (node);
134  ipv6->Insert (this);
135  Ptr<Ipv6RawSocketFactoryImpl> rawFactory = CreateObject<Ipv6RawSocketFactoryImpl> ();
136  ipv6->AggregateObject (rawFactory);
138  }
139  }
140  }
142 }
143 
145 {
146  NS_LOG_FUNCTION (this << node);
147  m_node = node;
148 }
149 
151 {
153  return PROT_NUMBER;
154 }
155 
157 {
158  NS_LOG_FUNCTION (this);
159  return PROT_NUMBER;
160 }
161 
163 {
164  NS_LOG_FUNCTION (this);
165  return 1;
166 }
167 
169 {
170  NS_LOG_FUNCTION (this);
171  return m_alwaysDad;
172 }
173 
175 {
176  NS_LOG_FUNCTION (this << target << interface);
177  Ipv6Address addr;
179 
180  NS_ASSERT (ipv6);
181 
182  if (!m_alwaysDad)
183  {
184  return;
185  }
186 
189  Ptr<Packet> p = ForgeNS ("::",Ipv6Address::MakeSolicitedAddress (target), target, interface->GetDevice ()->GetAddress ());
190 
191  /* update last packet UID */
192  interface->SetNsDadUid (target, p->GetUid ());
194 }
195 
197 {
198  NS_LOG_FUNCTION (this << packet << header);
200 }
201 
203 {
204  NS_LOG_FUNCTION (this << packet << header.GetSourceAddress () << header.GetDestinationAddress () << interface);
205  Ptr<Packet> p = packet->Copy ();
206  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
207 
208  /* very ugly! try to find something better in the future */
209  uint8_t type;
210  p->CopyData (&type, sizeof(type));
211 
212  switch (type)
213  {
215  if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
216  {
217  HandleRS (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
218  }
219  break;
221  if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
222  {
223  HandleRA (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
224  }
225  break;
227  HandleNS (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
228  break;
230  HandleNA (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
231  break;
233  HandleRedirection (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
234  break;
236  HandleEchoRequest (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
237  break;
239  // EchoReply does not contain any info about L4
240  // so we can not forward it up.
242  break;
244  HandleDestinationUnreachable (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
245  break;
247  HandlePacketTooBig (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
248  break;
250  HandleTimeExceeded (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
251  break;
253  HandleParameterError (p, header.GetSourceAddress (), header.GetDestinationAddress (), interface);
254  break;
255  default:
256  NS_LOG_LOGIC ("Unknown ICMPv6 message type=" << type);
257  break;
258  }
259 
260  return IpL4Protocol::RX_OK;
261 }
262 
264  uint32_t info, Ipv6Header ipHeader,
265  const uint8_t payload[8])
266 {
267  NS_LOG_FUNCTION (this << source << icmp << info << ipHeader << payload);
268 
270 
272 
273  uint8_t nextHeader = ipHeader.GetNextHeader ();
274 
275  Ptr<IpL4Protocol> l4 = ipv6->GetProtocol (nextHeader);
276  if (l4 != 0)
277  {
278  l4->ReceiveIcmp (source, ipHeader.GetHopLimit (), icmp.GetType (), icmp.GetCode (),
279  info, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress (), payload);
280  }
281 }
282 
284 {
285  NS_LOG_FUNCTION (this << packet << src << dst << interface);
286  Icmpv6Echo request;
287  uint8_t* buf = new uint8_t[packet->GetSize ()];
288 
289  packet->RemoveHeader (request);
290  /* XXX IPv6 extension: obtain a fresh copy of data otherwise it crash... */
291  packet->CopyData (buf, packet->GetSize ());
292  Ptr<Packet> p = Create<Packet> (buf, packet->GetSize ());
293 
294  /* if we send message from ff02::* (link-local multicast), we use our link-local address */
295  SendEchoReply (dst.IsMulticast () ? interface->GetLinkLocalAddress ().GetAddress () : dst, src, request.GetId (), request.GetSeq (), p);
296  delete[] buf;
297 }
298 
299 void Icmpv6L4Protocol::HandleRA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
300 {
301  NS_LOG_FUNCTION (this << packet << src << dst << interface);
302  Ptr<Packet> p = packet->Copy ();
303  Icmpv6RA raHeader;
306  Icmpv6OptionMtu mtuHdr;
308  bool next = true;
309  bool hasLla = false;
310  bool hasMtu = false;
311  Ipv6Address defaultRouter = Ipv6Address::GetZero ();
312 
313  p->RemoveHeader (raHeader);
314 
315  if (raHeader.GetLifeTime())
316  {
317  defaultRouter = src;
318  }
319 
320  while (next == true)
321  {
322  uint8_t type = 0;
323  p->CopyData (&type, sizeof(type));
324 
325  switch (type)
326  {
328  p->RemoveHeader (prefixHdr);
329  ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (interface->GetDevice ()), prefixHdr.GetPrefix (), prefixHdr.GetPrefixLength (),
330  prefixHdr.GetFlags (), prefixHdr.GetValidTime (), prefixHdr.GetPreferredTime (), defaultRouter);
331  break;
333  /* take in account the first MTU option */
334  if (!hasMtu)
335  {
336  p->RemoveHeader (mtuHdr);
337  hasMtu = true;
339  /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
340  }
341  break;
343  /* take in account the first LLA option */
344  if (!hasLla)
345  {
346  p->RemoveHeader (llaHdr);
347  ReceiveLLA (llaHdr, src, dst, interface);
348  hasLla = true;
349  }
350  break;
351  default:
352  /* unknow option, quit */
353  next = false;
354  }
355  }
356 }
357 
359 {
360  NS_LOG_FUNCTION (this << lla << src << dst << interface);
361  Address hardwareAddress;
362  NdiscCache::Entry* entry = 0;
363  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
364 
365  /* check if we have this address in our cache */
366  entry = cache->Lookup (src);
367 
368  if (!entry)
369  {
370  entry = cache->Add (src);
371  entry->SetRouter (true);
372  entry->SetMacAddress (lla.GetAddress ());
373  entry->MarkReachable ();
374  entry->StartReachableTimer ();
375  }
376  else
377  {
378  std::list<Ptr<Packet> > waiting;
379  if (entry->IsIncomplete ())
380  {
381  entry->StopRetransmitTimer ();
382  // mark it to reachable
383  waiting = entry->MarkReachable (lla.GetAddress ());
384  entry->StopReachableTimer ();
385  entry->StartReachableTimer ();
386  // send out waiting packet
387  for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
388  {
389  cache->GetInterface ()->Send (*it, src);
390  }
391  entry->ClearWaitingPacket ();
392  }
393  else
394  {
395  if (entry->GetMacAddress () != lla.GetAddress ())
396  {
397  entry->SetMacAddress (lla.GetAddress ());
398  entry->MarkStale ();
399  entry->SetRouter (true);
400  }
401  else
402  {
403  if (!entry->IsReachable ())
404  {
405  entry->StopProbeTimer ();
406  entry->StopDelayTimer ();
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->StopReachableTimer ();
416  entry->StartReachableTimer ();
417  }
418  }
419  }
420  }
421 }
422 
423 void Icmpv6L4Protocol::HandleRS (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
424 {
425  NS_LOG_FUNCTION (this << packet << src << dst << interface);
427  Icmpv6RS rsHeader;
428  packet->RemoveHeader (rsHeader);
429  Address hardwareAddress;
431  NdiscCache::Entry* entry = 0;
432  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
433 
434  if (src != Ipv6Address::GetAny ())
435  {
436  /* XXX search all options following the RS header */
437  /* test if the next option is SourceLinkLayerAddress */
438  uint8_t type;
439  packet->CopyData (&type, sizeof(type));
440 
442  {
443  return;
444  }
445  packet->RemoveHeader (lla);
446  NS_LOG_LOGIC ("Cache updated by RS");
447 
448  entry = cache->Lookup (src);
449  if (!entry)
450  {
451  entry = cache->Add (src);
452  entry->SetRouter (false);
453  entry->MarkStale (lla.GetAddress ());
454  }
455  else if (entry->GetMacAddress () != lla.GetAddress ())
456  {
457  entry->MarkStale (lla.GetAddress ());
458  }
459  }
460 }
461 
462 void Icmpv6L4Protocol::HandleNS (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
463 {
464  NS_LOG_FUNCTION (this << packet << src << dst << interface);
465  Icmpv6NS nsHeader ("::");
466  Ipv6InterfaceAddress ifaddr;
467  uint32_t nb = interface->GetNAddresses ();
468  uint32_t i = 0;
469  bool found = false;
470 
471  packet->RemoveHeader (nsHeader);
472 
473  Ipv6Address target = nsHeader.GetIpv6Target ();
474 
475  for (i = 0; i < nb; i++)
476  {
477  ifaddr = interface->GetAddress (i);
478 
479  if (ifaddr.GetAddress () == target)
480  {
481  found = true;
482  break;
483  }
484  }
485 
486  if (!found)
487  {
488  NS_LOG_LOGIC ("Not a NS for us");
489  return;
490  }
491 
492  if (packet->GetUid () == ifaddr.GetNsDadUid ())
493  {
494  /* don't process our own DAD probe */
495  NS_LOG_LOGIC ("Hey we receive our DAD probe!");
496  return;
497  }
498 
500  Address hardwareAddress;
501  NdiscCache::Entry* entry = 0;
502  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
503  uint8_t flags = 0;
504 
505  /* XXX search all options following the NS header */
506 
507  if (src != Ipv6Address::GetAny ())
508  {
509  uint8_t type;
510  packet->CopyData (&type, sizeof(type));
511 
513  {
514  return;
515  }
516 
517  /* Get LLA */
518  packet->RemoveHeader (lla);
519 
520  entry = cache->Lookup (src);
521  if (!entry)
522  {
523  entry = cache->Add (src);
524  entry->SetRouter (false);
525  entry->MarkStale (lla.GetAddress ());
526  }
527  else if (entry->GetMacAddress () != lla.GetAddress ())
528  {
529  entry->MarkStale (lla.GetAddress ());
530  }
531 
532  flags = 3; /* S + O flags */
533  }
534  else
535  {
536  /* it means someone do a DAD */
537  flags = 1; /* O flag */
538  }
539 
540  /* send a NA to src */
542 
543  if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
544  {
545  flags += 4; /* R flag */
546  }
547 
548  hardwareAddress = interface->GetDevice ()->GetAddress ();
549  Ptr<Packet> p = ForgeNA (target.IsLinkLocal () ? interface->GetLinkLocalAddress ().GetAddress () : ifaddr.GetAddress (), src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src, &hardwareAddress, flags );
550  interface->Send (p, src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src);
551 
552  /* not a NS for us discard it */
553 }
554 
556 {
557  NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
558  Ptr<Packet> p = Create<Packet> ();
559  Ipv6Header ipHeader;
560  Icmpv6RS rs;
561  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
562 
563  NS_LOG_LOGIC ("Send RS ( from " << src << " to " << dst << ")");
564  p->AddHeader (llOption);
565 
567  p->AddHeader (rs);
568 
569  ipHeader.SetSourceAddress (src);
570  ipHeader.SetDestinationAddress (dst);
571  ipHeader.SetNextHeader (PROT_NUMBER);
572  ipHeader.SetPayloadLength (p->GetSize ());
573  ipHeader.SetHopLimit (255);
574 
575  p->AddHeader (ipHeader);
576 
577  return p;
578 }
579 
581 {
582  NS_LOG_FUNCTION (this << src << dst << id << seq << data);
583  Ptr<Packet> p = data->Copy ();
584  Ipv6Header ipHeader;
585  Icmpv6Echo req (1);
586 
587  req.SetId (id);
588  req.SetSeq (seq);
589 
590  p->AddHeader (req);
591 
592  return p;
593 }
594 
595 void Icmpv6L4Protocol::HandleNA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
596 {
597  NS_LOG_FUNCTION (this << packet << src << dst << interface);
598  Icmpv6NA naHeader;
600 
601  packet->RemoveHeader (naHeader);
602  Ipv6Address target = naHeader.GetIpv6Target ();
603 
604  Address hardwareAddress;
605  NdiscCache::Entry* entry = 0;
606  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
607  std::list<Ptr<Packet> > waiting;
608 
609  /* check if we have something in our cache */
610  entry = cache->Lookup (target);
611 
612  if (!entry)
613  {
614  /* ouch!! we might be victim of a DAD */
615 
616  Ipv6InterfaceAddress ifaddr;
617  bool found = false;
618  uint32_t i = 0;
619  uint32_t nb = interface->GetNAddresses ();
620 
621  for (i = 0; i < nb; i++)
622  {
623  ifaddr = interface->GetAddress (i);
624  if (ifaddr.GetAddress () == target)
625  {
626  found = true;
627  break;
628  }
629  }
630 
631  if (found)
632  {
634  {
635  interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::INVALID);
636  }
637  }
638 
639  /* we have not initiated any communication with the target so... discard the NA */
640  return;
641  }
642 
643  /* XXX search all options following the NA header */
644  /* Get LLA */
645  uint8_t type;
646  packet->CopyData (&type, sizeof(type));
647 
649  {
650  return;
651  }
652  packet->RemoveHeader (lla);
653 
654  if (entry->IsIncomplete ())
655  {
656  /* we receive a NA so stop the retransmission timer */
657  entry->StopRetransmitTimer ();
658 
659  if (naHeader.GetFlagS ())
660  {
661  /* mark it to reachable */
662  waiting = entry->MarkReachable (lla.GetAddress ());
663  entry->StopReachableTimer ();
664  entry->StartReachableTimer ();
665  /* send out waiting packet */
666  for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
667  {
668  cache->GetInterface ()->Send (*it, src);
669  }
670  entry->ClearWaitingPacket ();
671  }
672  else
673  {
674  entry->MarkStale (lla.GetAddress ());
675  }
676 
677  if (naHeader.GetFlagR ())
678  {
679  entry->SetRouter (true);
680  }
681  }
682  else
683  {
684  /* we receive a NA so stop the probe timer or delay timer if any */
685  entry->StopProbeTimer ();
686  entry->StopDelayTimer ();
687 
688  /* if the Flag O is clear and mac address differs from the cache */
689  if (!naHeader.GetFlagO () && lla.GetAddress () != entry->GetMacAddress ())
690  {
691  if (entry->IsReachable ())
692  {
693  entry->MarkStale ();
694  }
695  return;
696  }
697  else
698  {
699  if ((!naHeader.GetFlagO () && lla.GetAddress () == entry->GetMacAddress ()) || naHeader.GetFlagO ()) /* XXX lake "no target link-layer address option supplied" */
700  {
701  entry->SetMacAddress (lla.GetAddress ());
702 
703  if (naHeader.GetFlagS ())
704  {
705  if (!entry->IsReachable ())
706  {
707  if (entry->IsProbe ())
708  {
709  waiting = entry->MarkReachable (lla.GetAddress ());
710  for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
711  {
712  cache->GetInterface ()->Send (*it, src);
713  }
714  entry->ClearWaitingPacket ();
715  }
716  else
717  {
718  entry->MarkReachable (lla.GetAddress ());
719  }
720  }
721  entry->StopReachableTimer ();
722  entry->StartReachableTimer ();
723  }
724  else if (lla.GetAddress () != entry->GetMacAddress ())
725  {
726  entry->MarkStale ();
727  }
728  entry->SetRouter (naHeader.GetFlagR ());
729  }
730  }
731  }
732 }
733 
735 {
736  NS_LOG_FUNCTION (this << packet << src << dst << interface);
737  bool hasLla = false;
738  Ptr<Packet> p = packet->Copy ();
739  Icmpv6OptionLinkLayerAddress llOptionHeader (0);
740 
741  Icmpv6Redirection redirectionHeader;
742  p->RemoveHeader (redirectionHeader);
743 
744  /* little ugly try to find a better way */
745  uint8_t type;
746  p->CopyData (&type, sizeof(type));
748  {
749  hasLla = true;
750  p->RemoveHeader (llOptionHeader);
751  }
752 
753  Icmpv6OptionRedirected redirectedOptionHeader;
754  p->RemoveHeader (redirectedOptionHeader);
755 
756  Ipv6Address redirTarget = redirectionHeader.GetTarget ();
757  Ipv6Address redirDestination = redirectionHeader.GetDestination ();
758 
759  if (hasLla)
760  {
761  /* update the cache if needed */
762  NdiscCache::Entry* entry = 0;
763  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
764 
765  entry = cache->Lookup (redirTarget);
766  if (!entry)
767  {
768  entry = cache->Add (redirTarget);
769  /* destination and target different => necessarily a router */
770  entry->SetRouter (!redirTarget.IsEqual (redirDestination) ? true : false);
771  entry->SetMacAddress (llOptionHeader.GetAddress ());
772  entry->MarkStale ();
773  }
774  else
775  {
776  if (entry->IsIncomplete () || entry->GetMacAddress () != llOptionHeader.GetAddress ())
777  {
778  /* update entry to STALE */
779  if (entry->GetMacAddress () != llOptionHeader.GetAddress ())
780  {
781  entry->SetMacAddress (llOptionHeader.GetAddress ());
782  entry->MarkStale ();
783  }
784  }
785  else
786  {
787  /* stay unchanged */
788  }
789  }
790  }
791 
792  /* add redirection in routing table */
793  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
794 
795  if (redirTarget.IsEqual (redirDestination))
796  {
797  ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), Ipv6Address ("::"), ipv6->GetInterfaceForAddress (dst));
798  }
799  else
800  {
801  uint32_t ifIndex = ipv6->GetInterfaceForAddress (dst);
802  ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), redirTarget, ifIndex);
803  }
804 }
805 
807 {
808  NS_LOG_FUNCTION (this << *p << src << dst << interface);
809  Ptr<Packet> pkt = p->Copy ();
810 
812  pkt->RemoveHeader (unreach);
813  Ptr<Packet> origPkt = unreach.GetPacket ();
814 
815  Ipv6Header ipHeader;
816  if ( origPkt->GetSerializedSize () > ipHeader.GetSerializedSize () )
817  {
818  origPkt->RemoveHeader (ipHeader);
819  uint8_t payload[8];
820  origPkt->CopyData (payload, 8);
821  Forward (src, unreach, unreach.GetCode (), ipHeader, payload);
822  }
823 }
824 
826 {
827  NS_LOG_FUNCTION (this << *p << src << dst << interface);
828  Ptr<Packet> pkt = p->Copy ();
829 
830  Icmpv6TimeExceeded timeexceeded;
831  pkt->RemoveHeader (timeexceeded);
832  Ptr<Packet> origPkt = timeexceeded.GetPacket ();
833  Ipv6Header ipHeader;
834  uint8_t payload[8];
835  origPkt->RemoveHeader (ipHeader);
836  origPkt->CopyData (payload, 8);
837 
838  Forward (src, timeexceeded, timeexceeded.GetCode (), ipHeader, payload);
839 }
840 
842 {
843  NS_LOG_FUNCTION (this << *p << src << dst << interface);
844  Ptr<Packet> pkt = p->Copy ();
845 
846  Icmpv6TooBig tooBig;
847  pkt->RemoveHeader (tooBig);
848  Ptr<Packet> origPkt = tooBig.GetPacket ();
849 
850  Ipv6Header ipHeader;
851  origPkt->RemoveHeader (ipHeader);
852  uint8_t payload[8];
853  origPkt->CopyData (payload, 8);
854 
856  ipv6->SetPmtu(ipHeader.GetDestinationAddress(), tooBig.GetMtu ());
857 
858  Forward (src, tooBig, tooBig.GetMtu (), ipHeader, payload);
859 }
860 
862 {
863  NS_LOG_FUNCTION (this << *p << src << dst << interface);
864  Ptr<Packet> pkt = p->Copy ();
865 
866  Icmpv6ParameterError paramErr;
867  pkt->RemoveHeader (paramErr);
868  Ptr<Packet> origPkt = paramErr.GetPacket ();
869 
870  Ipv6Header ipHeader;
871  origPkt->RemoveHeader (ipHeader);
872  uint8_t payload[8];
873  origPkt->CopyData (payload, 8);
874  Forward (src, paramErr, paramErr.GetCode (), ipHeader, payload);
875 }
876 
878 {
879  NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
881  SocketIpTtlTag tag;
882  NS_ASSERT (ipv6 != 0);
883 
884  tag.SetTtl (ttl);
885  packet->AddPacketTag (tag);
886  m_downTarget (packet, src, dst, PROT_NUMBER, 0);
887 }
888 
890 {
891  NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
892  SendMessage (packet, src, dst, ttl);
893 }
894 
895 void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl)
896 {
897  NS_LOG_FUNCTION (this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
899  NS_ASSERT (ipv6 != 0 && ipv6->GetRoutingProtocol () != 0);
900  Ipv6Header header;
901  SocketIpTtlTag tag;
903  Ptr<Ipv6Route> route;
904  Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
905 
906  header.SetDestinationAddress (dst);
907  route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, err);
908 
909  if (route != 0)
910  {
911  NS_LOG_LOGIC ("Route exists");
912  tag.SetTtl (ttl);
913  packet->AddPacketTag (tag);
914  Ipv6Address src = route->GetSource ();
915 
916  icmpv6Hdr.CalculatePseudoHeaderChecksum (src, dst, packet->GetSize () + icmpv6Hdr.GetSerializedSize (), PROT_NUMBER);
917  packet->AddHeader (icmpv6Hdr);
918  m_downTarget (packet, src, dst, PROT_NUMBER, route);
919  }
920  else
921  {
922  NS_LOG_WARN ("drop icmp message");
923  }
924 }
925 
926 void Icmpv6L4Protocol::SendNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
927 {
928  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << static_cast<uint32_t> (flags));
929  Ptr<Packet> p = Create<Packet> ();
930  Icmpv6NA na;
931  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* not a source link layer */
932 
933  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << " target " << src << ")");
934  na.SetIpv6Target (src);
935 
936  if ((flags & 1))
937  {
938  na.SetFlagO (true);
939  }
940  if ((flags & 2) && src != Ipv6Address::GetAny ())
941  {
942  na.SetFlagS (true);
943  }
944  if ((flags & 4))
945  {
946  na.SetFlagR (true);
947  }
948 
949  p->AddHeader (llOption);
950  na.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + na.GetSerializedSize (), PROT_NUMBER);
951  p->AddHeader (na);
952 
953  SendMessage (p, src, dst, 255);
954 }
955 
956 void Icmpv6L4Protocol::SendEchoReply (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr<Packet> data)
957 {
958  NS_LOG_FUNCTION (this << src << dst << id << seq << data);
959  Ptr<Packet> p = data->Copy ();
960  Icmpv6Echo reply (0); /* echo reply */
961 
962  reply.SetId (id);
963  reply.SetSeq (seq);
964 
965  reply.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + reply.GetSerializedSize (), PROT_NUMBER);
966  p->AddHeader (reply);
967  SendMessage (p, src, dst, 64);
968 }
969 
970 void Icmpv6L4Protocol::SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
971 {
972  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
973  Ptr<Packet> p = Create<Packet> ();
974  /* Ipv6Header ipHeader; */
975  Icmpv6NS ns (target);
976  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
977 
978  /* if the source is unspec, multicast the NA to all-nodes multicast */
979  if (src == Ipv6Address::GetAny ())
980  {
982  }
983 
984  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
985 
986  p->AddHeader (llOption);
987  ns.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + ns.GetSerializedSize (), PROT_NUMBER);
988  p->AddHeader (ns);
989  if (!dst.IsMulticast ())
990  {
991  SendMessage (p, src, dst, 255);
992  }
993  else
994  {
995  NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
996  Simulator::Schedule (Time (MilliSeconds (m_solicitationJitter->GetValue ())), &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
997  }
998 }
999 
1001 {
1002  NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
1003  Ptr<Packet> p = Create<Packet> ();
1004  Icmpv6RS rs;
1005  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1006 
1007  /* if the source is unspec, multicast the NA to all-nodes multicast */
1008  if (src != Ipv6Address::GetAny ())
1009  {
1010  p->AddHeader (llOption);
1011  }
1012 
1013  NS_LOG_LOGIC ("Send RS ( from " << src << " to " << dst << ")");
1014 
1015  rs.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + rs.GetSerializedSize (), PROT_NUMBER);
1016  p->AddHeader (rs);
1017  if (!dst.IsMulticast ())
1018  {
1019  SendMessage (p, src, dst, 255);
1020  }
1021  else
1022  {
1023  NS_LOG_LOGIC ("Destination is Multicast, using DelayedSendMessage");
1024  Simulator::Schedule (Time (MilliSeconds (m_solicitationJitter->GetValue ())), &Icmpv6L4Protocol::DelayedSendMessage, this, p, src, dst, 255);
1025  }
1026 }
1027 
1029 {
1030  NS_LOG_FUNCTION (this << malformedPacket << dst << (uint32_t)code);
1031  Ptr<Packet> p = Create<Packet> ();
1032  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1034 
1035  NS_LOG_LOGIC ("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
1036 
1037  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1038  if (malformedPacketSize <= 1280 - 48)
1039  {
1040  header.SetPacket (malformedPacket);
1041  }
1042  else
1043  {
1044  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1045  header.SetPacket (fragment);
1046  }
1047 
1048  header.SetCode (code);
1049  SendMessage (p, dst, header, 255);
1050 }
1051 
1052 void Icmpv6L4Protocol::SendErrorTooBig (Ptr<Packet> malformedPacket, Ipv6Address dst, uint32_t mtu)
1053 {
1054  NS_LOG_FUNCTION (this << malformedPacket << dst << mtu);
1055  Ptr<Packet> p = Create<Packet> ();
1056  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1057  Icmpv6TooBig header;
1058 
1059  NS_LOG_LOGIC ("Send Too Big ( to " << dst << " )");
1060 
1061  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1062  if (malformedPacketSize <= 1280 - 48)
1063  {
1064  header.SetPacket (malformedPacket);
1065  }
1066  else
1067  {
1068  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1069  header.SetPacket (fragment);
1070  }
1071 
1072  header.SetCode (0);
1073  header.SetMtu (mtu);
1074  SendMessage (p, dst, header, 255);
1075 }
1076 
1077 void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
1078 {
1079  NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code));
1080  Ptr<Packet> p = Create<Packet> ();
1081  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1082  Icmpv6TimeExceeded header;
1083 
1084  NS_LOG_LOGIC ("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
1085 
1086  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1087  if (malformedPacketSize <= 1280 - 48)
1088  {
1089  header.SetPacket (malformedPacket);
1090  }
1091  else
1092  {
1093  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1094  header.SetPacket (fragment);
1095  }
1096 
1097  header.SetCode (code);
1098  SendMessage (p, dst, header, 255);
1099 }
1100 
1101 void Icmpv6L4Protocol::SendErrorParameterError (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
1102 {
1103  NS_LOG_FUNCTION (this << malformedPacket << dst << static_cast<uint32_t> (code) << ptr);
1104  Ptr<Packet> p = Create<Packet> ();
1105  uint32_t malformedPacketSize = malformedPacket->GetSize ();
1106  Icmpv6ParameterError header;
1107 
1108  NS_LOG_LOGIC ("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
1109 
1110  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
1111  if (malformedPacketSize <= 1280 - 48 )
1112  {
1113  header.SetPacket (malformedPacket);
1114  }
1115  else
1116  {
1117  Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
1118  header.SetPacket (fragment);
1119  }
1120 
1121  header.SetCode (code);
1122  header.SetPtr (ptr);
1123  SendMessage (p, dst, header, 255);
1124 }
1125 
1126 void Icmpv6L4Protocol::SendRedirection (Ptr<Packet> redirectedPacket, Ipv6Address src, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget)
1127 {
1128  NS_LOG_FUNCTION (this << redirectedPacket << dst << redirTarget << redirDestination << redirHardwareTarget);
1129  uint32_t llaSize = 0;
1130  Ptr<Packet> p = Create<Packet> ();
1131  uint32_t redirectedPacketSize = redirectedPacket->GetSize ();
1132  Icmpv6OptionLinkLayerAddress llOption (0);
1133 
1134  NS_LOG_LOGIC ("Send Redirection ( to " << dst << " target " << redirTarget << " destination " << redirDestination << " )");
1135 
1136  Icmpv6OptionRedirected redirectedOptionHeader;
1137 
1138  if ((redirectedPacketSize % 8) != 0)
1139  {
1140  Ptr<Packet> pad = Create<Packet> (8 - (redirectedPacketSize % 8));
1141  redirectedPacket->AddAtEnd (pad);
1142  }
1143 
1144  if (redirHardwareTarget.GetLength ())
1145  {
1146  llOption.SetAddress (redirHardwareTarget);
1147  llaSize = llOption.GetSerializedSize ();
1148  }
1149 
1150  /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
1151  if (redirectedPacketSize <= (1280 - 56 - llaSize))
1152  {
1153  redirectedOptionHeader.SetPacket (redirectedPacket);
1154  }
1155  else
1156  {
1157  Ptr<Packet> fragment = redirectedPacket->CreateFragment (0, 1280 - 56 - llaSize);
1158  redirectedOptionHeader.SetPacket (fragment);
1159  }
1160 
1161  p->AddHeader (redirectedOptionHeader);
1162 
1163  if (llaSize)
1164  {
1165  p->AddHeader (llOption);
1166  }
1167 
1168  Icmpv6Redirection redirectionHeader;
1169  redirectionHeader.SetTarget (redirTarget);
1170  redirectionHeader.SetDestination (redirDestination);
1171  redirectionHeader.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + redirectionHeader.GetSerializedSize (), PROT_NUMBER);
1172  p->AddHeader (redirectionHeader);
1173 
1174  SendMessage (p, src, dst, 64);
1175 }
1176 
1177 Ptr<Packet> Icmpv6L4Protocol::ForgeNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
1178 {
1179  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << (uint32_t)flags);
1180  Ptr<Packet> p = Create<Packet> ();
1181  Ipv6Header ipHeader;
1182  Icmpv6NA na;
1183  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* we give our mac address in response */
1184 
1185  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << ")");
1186 
1187  /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet does not pass by Icmpv6L4Protocol::Lookup again */
1188 
1189  p->AddHeader (llOption);
1190  na.SetIpv6Target (src);
1191 
1192  if ((flags & 1))
1193  {
1194  na.SetFlagO (true);
1195  }
1196  if ((flags & 2) && src != Ipv6Address::GetAny ())
1197  {
1198  na.SetFlagS (true);
1199  }
1200  if ((flags & 4))
1201  {
1202  na.SetFlagR (true);
1203  }
1204 
1206  p->AddHeader (na);
1207 
1208  ipHeader.SetSourceAddress (src);
1209  ipHeader.SetDestinationAddress (dst);
1210  ipHeader.SetNextHeader (PROT_NUMBER);
1211  ipHeader.SetPayloadLength (p->GetSize ());
1212  ipHeader.SetHopLimit (255);
1213 
1214  p->AddHeader (ipHeader);
1215 
1216  return p;
1217 }
1218 
1220 {
1221  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
1222  Ptr<Packet> p = Create<Packet> ();
1223  Ipv6Header ipHeader;
1224  Icmpv6NS ns (target);
1225  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress); /* we give our mac address in response */
1226 
1227  /* if the source is unspec, multicast the NA to all-nodes multicast */
1228  if (src == Ipv6Address::GetAny ())
1229  {
1231  }
1232 
1233  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
1234 
1235  p->AddHeader (llOption);
1237  p->AddHeader (ns);
1238 
1239  ipHeader.SetSourceAddress (src);
1240  ipHeader.SetDestinationAddress (dst);
1241  ipHeader.SetNextHeader (PROT_NUMBER);
1242  ipHeader.SetPayloadLength (p->GetSize ());
1243  ipHeader.SetHopLimit (255);
1244 
1245  p->AddHeader (ipHeader);
1246 
1247  return p;
1248 }
1249 
1251 {
1252  NS_LOG_FUNCTION (this << device);
1253 
1254  for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
1255  {
1256  if ((*i)->GetDevice () == device)
1257  {
1258  return *i;
1259  }
1260  }
1261 
1262  NS_ASSERT (false);
1263  /* quiet compiler */
1264  return 0;
1265 }
1266 
1268 {
1269  NS_LOG_FUNCTION (this << device << interface);
1270 
1271  Ptr<NdiscCache> cache = CreateObject<NdiscCache> ();
1272 
1273  cache->SetDevice (device, interface);
1274  device->AddLinkChangeCallback (MakeCallback (&NdiscCache::Flush, cache));
1275  m_cacheList.push_back (cache);
1276  return cache;
1277 }
1278 
1279 bool Icmpv6L4Protocol::Lookup (Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1280 {
1281  NS_LOG_FUNCTION (this << dst << device << cache << hardwareDestination);
1282 
1283  if (!cache)
1284  {
1285  /* try to find the cache */
1286  cache = FindCache (device);
1287  }
1288  if (cache)
1289  {
1290  NdiscCache::Entry* entry = cache->Lookup (dst);
1291  if (entry)
1292  {
1293  if (entry->IsReachable () || entry->IsDelay ())
1294  {
1295  *hardwareDestination = entry->GetMacAddress ();
1296  return true;
1297  }
1298  else if (entry->IsStale ())
1299  {
1300  entry->StartDelayTimer ();
1301  entry->MarkDelay ();
1302  *hardwareDestination = entry->GetMacAddress ();
1303  return true;
1304  }
1305  }
1306  }
1307  return false;
1308 }
1309 
1310 bool Icmpv6L4Protocol::Lookup (Ptr<Packet> p, Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
1311 {
1312  NS_LOG_FUNCTION (this << p << dst << device << cache << hardwareDestination);
1313 
1314  if (!cache)
1315  {
1316  /* try to find the cache */
1317  cache = FindCache (device);
1318  }
1319  if (!cache)
1320  {
1321  return false;
1322  }
1323 
1324  NdiscCache::Entry* entry = cache->Lookup (dst);
1325  if (entry)
1326  {
1327  if (entry->IsReachable () || entry->IsDelay ())
1328  {
1329  /* XXX check reachability time */
1330  /* send packet */
1331  *hardwareDestination = entry->GetMacAddress ();
1332  return true;
1333  }
1334  else if (entry->IsStale ())
1335  {
1336  /* start delay timer */
1337  entry->StartDelayTimer ();
1338  entry->MarkDelay ();
1339  *hardwareDestination = entry->GetMacAddress ();
1340  return true;
1341  }
1342  else /* PROBE */
1343  {
1344  /* queue packet */
1345  entry->AddWaitingPacket (p);
1346  return false;
1347  }
1348  }
1349  else
1350  {
1351  /* we contact this node for the first time
1352  * add it to the cache and send an NS
1353  */
1354  Ipv6Address addr;
1355  NdiscCache::Entry* entry = cache->Add (dst);
1356  entry->MarkIncomplete (p);
1357  entry->SetRouter (false);
1358 
1359  if (dst.IsLinkLocal ())
1360  {
1361  addr = cache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
1362  }
1363  else if (cache->GetInterface ()->GetNAddresses () == 1) /* an interface have at least one address (link-local) */
1364  {
1365  /* try to resolve global address without having global address so return! */
1366  cache->Remove (entry);
1367  return false;
1368  }
1369  else
1370  {
1371  /* find source address that match destination */
1372  addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress ();
1373  }
1374 
1375  SendNS (addr, Ipv6Address::MakeSolicitedAddress (dst), dst, cache->GetDevice ()->GetAddress ());
1376 
1377  /* start retransmit timer */
1378  entry->StartRetransmitTimer ();
1379  return false;
1380  }
1381 
1382  return false;
1383 }
1384 
1386 {
1388  NS_LOG_LOGIC (interface << " " << addr);
1389  Ipv6InterfaceAddress ifaddr;
1390  bool found = false;
1391  uint32_t i = 0;
1392  uint32_t nb = interface->GetNAddresses ();
1393 
1394  for (i = 0; i < nb; i++)
1395  {
1396  ifaddr = interface->GetAddress (i);
1397 
1398  if (ifaddr.GetAddress () == addr)
1399  {
1400  found = true;
1401  break;
1402  }
1403  }
1404 
1405  /* for the moment, this function is always called, if we was victim of a DAD the address is INVALID
1406  * and we do not set it to PREFERRED
1407  */
1408  if (found && ifaddr.GetState () != Ipv6InterfaceAddress::INVALID)
1409  {
1410  interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::PREFERRED);
1411  NS_LOG_LOGIC ("DAD OK, interface in state PREFERRED");
1412 
1413  /* send an RS if our interface is not forwarding (router) and if address is a link-local ones
1414  * (because we will send RS with it)
1415  */
1416  Ptr<Ipv6> ipv6 = icmpv6->m_node->GetObject<Ipv6> ();
1417 
1418  if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ())
1419  {
1420  /* \todo Add random delays before sending RS
1421  * because all nodes start at the same time, there will be many of RS arround 1 second of simulation time
1422  */
1423  Simulator::Schedule (Seconds (0.0), &Icmpv6L4Protocol::SendRS, PeekPointer (icmpv6), ifaddr.GetAddress (), Ipv6Address::GetAllRoutersMulticast (), interface->GetDevice ()->GetAddress ());
1424  }
1425  }
1426 }
1427 
1428 void
1430 {
1431  NS_LOG_FUNCTION (this << &callback);
1432 }
1433 
1434 void
1436 {
1437  NS_LOG_FUNCTION (this << &callback);
1438  m_downTarget = callback;
1439 }
1440 
1443 {
1444  NS_LOG_FUNCTION (this);
1445  return (IpL4Protocol::DownTargetCallback)NULL;
1446 }
1447 
1450 {
1451  NS_LOG_FUNCTION (this);
1452  return m_downTarget;
1453 }
1454 
1455 } /* namespace ns3 */
1456 
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:82
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.
Doxygen 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.
keep track of time values and allow control of global simulation resolution
Definition: nstime.h:81
Doxygen 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)
Definition: log.h:345
void MarkIncomplete(Ptr< Packet > p)
Changes the state to this entry to INCOMPLETE.
Definition: ndisc-cache.cc:429
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
Doxygen introspection did not find any typical Config paths.
void SetState(Ipv6Address address, Ipv6InterfaceAddress::State_e state)
Update state of an interface address.
Hold a bool native type.
Definition: boolean.h:38
Doxygen introspection did not find any typical Config paths.
Doxygen 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.
NS_LOG_COMPONENT_DEFINE("GrantedTimeWindowMpiInterface")
Address GetMacAddress() const
Get the MAC address of this entry.
Definition: ndisc-cache.cc:510
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:79
hold variables of type string
Definition: string.h:19
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...
Doxygen introspection did not find any typical Config paths.
IPv6 layer implementation.
Ptr< Node > m_node
The node.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:841
Doxygen introspection did not find any typical Config paths.
void SendRS(Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
Send a Router Solicitation.
Doxygen 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
A packet is allocated a new uid when it is created empty or with zero-filled payload.
Definition: packet.cc:393
uint8_t GetType() const
Get the type field.
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1014
#define NS_ASSERT(condition)
Definition: assert.h:64
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.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
Ipv6InterfaceAddress GetAddress(uint32_t index) const
Get an address from IPv6 interface.
IPv6 address associated with an interface.
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
Definition: packet.h:650
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.
void StopReachableTimer()
Stop the reachable timer.
Definition: ndisc-cache.cc:377
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:336
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.
Definition: log.h:309
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:824
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:996
void SetTarget(Ipv6Address target)
Set the IPv6 target address.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
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:440
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:86
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:492
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.
Doxygen 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.
Doxygen 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.
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.
Doxygen 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.
T * PeekPointer(const Ptr< T > &p)
Definition: ptr.h:279
uint8_t GetLength(void) const
Definition: address.cc:75
static const uint32_t REACHABLE_TIME
Neighbor Discovery node constants : reachable time.
Doxygen 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.
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:1238
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)
Definition: log.h:368
void StopProbeTimer()
Stop probe timer.
Definition: ndisc-cache.cc:391
Ptr< Packet > ForgeNS(Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
Forge a Neighbor Solicitation.
void StartRetransmitTimer()
Start retransmit timer.
Definition: ndisc-cache.cc:414
#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:193
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)
This method is invoked whenever two sets of objects are aggregated together.
Definition: object.cc:315
Ptr< Packet > Copy(void) const
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:504
uint8_t GetHopLimit(void) const
Get the "Hop limit" field (TTL).
Definition: ipv6-header.cc:92
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...
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.
Doxygen 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:180
void StartDelayTimer()
Start delay timer.
Definition: ndisc-cache.cc:399
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:369
bool m_alwaysDad
Always do DAD ?
bool IsIncomplete() const
Is the entry INCOMPLETE.
Definition: ndisc-cache.cc:498
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:466
void SetMacAddress(Address mac)
Set the MAC address of this entry.
Definition: ndisc-cache.cc:516
static const double MAX_RANDOM_FACTOR
Neighbor Discovery node constants : max random factor.
Doxygen introspection did not find any typical Config paths.
void SetFlagS(bool s)
Set the S flag.
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:46
NdiscCache::Entry * Lookup(Ipv6Address dst)
Lookup in the cache.
Definition: ndisc-cache.cc:91
void HandleRA(Ptr< Packet > p, Ipv6Address const &src, Ipv6Address const &dst, Ptr< Ipv6Interface > interface)
Receive Router Advertisement method.
#define NS_LOG_WARN(msg)
Definition: log.h:280
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:474
virtual int GetVersion() const
Get the version of the protocol.
uint32_t GetSerializedSize(void) const
Definition: packet.cc:565
static const uint32_t RETRANS_TIMER
Neighbor Discovery node constants : retransmission timer.
void SetDestination(Ipv6Address destination)
Set the IPv6 destination address.
void StopRetransmitTimer()
Stop retransmit timer.
Definition: ndisc-cache.cc:422
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:102
void StopDelayTimer()
Stop delay timer.
Definition: ndisc-cache.cc:407
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:387
virtual void DoDispose()
Dispose this object.
void Nullify(void)
Discard the implementation, set it to null.
Definition: callback.h:1018
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:381
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:131
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:168
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:486
void SetPacket(Ptr< Packet > p)
Set the incorrect packet.
uint32_t GetMtu() const
Get the MTU field.
Ptr< T > GetObject(void) const
Definition: object.h:361
Doxygen introspection did not find any typical Config paths.
a unique identifier for an interface.
Definition: type-id.h:49
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 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:611
void Dispose(void)
Run the DoDispose methods of this object and all the objects aggregated to it.
Definition: object.cc:205
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:480
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:112
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.