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