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