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);
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  */
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