A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
aodv-routing-protocol.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 IITP RAS
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  * Based on
19  * NS-2 AODV model developed by the CMU/MONARCH group and optimized and
20  * tuned by Samir Das and Mahesh Marina, University of Cincinnati;
21  *
22  * AODV-UU implementation by Erik Nordström of Uppsala University
23  * http://core.it.uu.se/core/index.php/AODV-UU
24  *
25  * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
26  * Pavel Boyko <boyko@iitp.ru>
27  */
28 #define NS_LOG_APPEND_CONTEXT \
29  if (m_ipv4) { std::clog << "[node " << m_ipv4->GetObject<Node> ()->GetId () << "] "; }
30 
31 #include "aodv-routing-protocol.h"
32 #include "ns3/log.h"
33 #include "ns3/boolean.h"
34 #include "ns3/random-variable-stream.h"
35 #include "ns3/inet-socket-address.h"
36 #include "ns3/trace-source-accessor.h"
37 #include "ns3/udp-socket-factory.h"
38 #include "ns3/wifi-net-device.h"
39 #include "ns3/adhoc-wifi-mac.h"
40 #include "ns3/string.h"
41 #include "ns3/pointer.h"
42 #include <algorithm>
43 #include <limits>
44 
45 NS_LOG_COMPONENT_DEFINE ("AodvRoutingProtocol");
46 
47 namespace ns3
48 {
49 namespace aodv
50 {
51 NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol);
52 
54 const uint32_t RoutingProtocol::AODV_PORT = 654;
55 
56 //-----------------------------------------------------------------------------
58 
60 {
61 
62 public:
63  DeferredRouteOutputTag (int32_t o = -1) : Tag (), m_oif (o) {}
64 
65  static TypeId GetTypeId ()
66  {
67  static TypeId tid = TypeId ("ns3::aodv::DeferredRouteOutputTag").SetParent<Tag> ()
68  .SetParent<Tag> ()
69  .AddConstructor<DeferredRouteOutputTag> ()
70  ;
71  return tid;
72  }
73 
75  {
76  return GetTypeId ();
77  }
78 
79  int32_t GetInterface() const
80  {
81  return m_oif;
82  }
83 
84  void SetInterface(int32_t oif)
85  {
86  m_oif = oif;
87  }
88 
89  uint32_t GetSerializedSize () const
90  {
91  return sizeof(int32_t);
92  }
93 
94  void Serialize (TagBuffer i) const
95  {
96  i.WriteU32 (m_oif);
97  }
98 
100  {
101  m_oif = i.ReadU32 ();
102  }
103 
104  void Print (std::ostream &os) const
105  {
106  os << "DeferredRouteOutputTag: output interface = " << m_oif;
107  }
108 
109 private:
111  int32_t m_oif;
112 };
113 
115 
116 
117 //-----------------------------------------------------------------------------
119  RreqRetries (2),
120  RreqRateLimit (10),
121  RerrRateLimit (10),
122  ActiveRouteTimeout (Seconds (3)),
123  NetDiameter (35),
124  NodeTraversalTime (MilliSeconds (40)),
125  NetTraversalTime (Time ((2 * NetDiameter) * NodeTraversalTime)),
126  PathDiscoveryTime ( Time (2 * NetTraversalTime)),
127  MyRouteTimeout (Time (2 * std::max (PathDiscoveryTime, ActiveRouteTimeout))),
128  HelloInterval (Seconds (1)),
129  AllowedHelloLoss (2),
130  DeletePeriod (Time (5 * std::max (ActiveRouteTimeout, HelloInterval))),
131  NextHopWait (NodeTraversalTime + MilliSeconds (10)),
132  TimeoutBuffer (2),
133  BlackListTimeout (Time (RreqRetries * NetTraversalTime)),
134  MaxQueueLen (64),
135  MaxQueueTime (Seconds (30)),
136  DestinationOnly (false),
137  GratuitousReply (true),
138  EnableHello (false),
139  m_routingTable (DeletePeriod),
140  m_queue (MaxQueueLen, MaxQueueTime),
141  m_requestId (0),
142  m_seqNo (0),
143  m_rreqIdCache (PathDiscoveryTime),
144  m_dpd (PathDiscoveryTime),
145  m_nb (HelloInterval),
146  m_rreqCount (0),
147  m_rerrCount (0),
148  m_htimer (Timer::CANCEL_ON_DESTROY),
149  m_rreqRateLimitTimer (Timer::CANCEL_ON_DESTROY),
150  m_rerrRateLimitTimer (Timer::CANCEL_ON_DESTROY),
151  m_lastBcastTime (Seconds (0))
152 {
154 }
155 
156 TypeId
158 {
159  static TypeId tid = TypeId ("ns3::aodv::RoutingProtocol")
161  .AddConstructor<RoutingProtocol> ()
162  .AddAttribute ("HelloInterval", "HELLO messages emission interval.",
163  TimeValue (Seconds (1)),
164  MakeTimeAccessor (&RoutingProtocol::HelloInterval),
165  MakeTimeChecker ())
166  .AddAttribute ("RreqRetries", "Maximum number of retransmissions of RREQ to discover a route",
167  UintegerValue (2),
168  MakeUintegerAccessor (&RoutingProtocol::RreqRetries),
169  MakeUintegerChecker<uint32_t> ())
170  .AddAttribute ("RreqRateLimit", "Maximum number of RREQ per second.",
171  UintegerValue (10),
172  MakeUintegerAccessor (&RoutingProtocol::RreqRateLimit),
173  MakeUintegerChecker<uint32_t> ())
174  .AddAttribute ("RerrRateLimit", "Maximum number of RERR per second.",
175  UintegerValue (10),
176  MakeUintegerAccessor (&RoutingProtocol::RerrRateLimit),
177  MakeUintegerChecker<uint32_t> ())
178  .AddAttribute ("NodeTraversalTime", "Conservative estimate of the average one hop traversal time for packets and should include "
179  "queuing delays, interrupt processing times and transfer times.",
180  TimeValue (MilliSeconds (40)),
181  MakeTimeAccessor (&RoutingProtocol::NodeTraversalTime),
182  MakeTimeChecker ())
183  .AddAttribute ("NextHopWait", "Period of our waiting for the neighbour's RREP_ACK = 10 ms + NodeTraversalTime",
184  TimeValue (MilliSeconds (50)),
185  MakeTimeAccessor (&RoutingProtocol::NextHopWait),
186  MakeTimeChecker ())
187  .AddAttribute ("ActiveRouteTimeout", "Period of time during which the route is considered to be valid",
188  TimeValue (Seconds (3)),
189  MakeTimeAccessor (&RoutingProtocol::ActiveRouteTimeout),
190  MakeTimeChecker ())
191  .AddAttribute ("MyRouteTimeout", "Value of lifetime field in RREP generating by this node = 2 * max(ActiveRouteTimeout, PathDiscoveryTime)",
192  TimeValue (Seconds (11.2)),
193  MakeTimeAccessor (&RoutingProtocol::MyRouteTimeout),
194  MakeTimeChecker ())
195  .AddAttribute ("BlackListTimeout", "Time for which the node is put into the blacklist = RreqRetries * NetTraversalTime",
196  TimeValue (Seconds (5.6)),
197  MakeTimeAccessor (&RoutingProtocol::BlackListTimeout),
198  MakeTimeChecker ())
199  .AddAttribute ("DeletePeriod", "DeletePeriod is intended to provide an upper bound on the time for which an upstream node A "
200  "can have a neighbor B as an active next hop for destination D, while B has invalidated the route to D."
201  " = 5 * max (HelloInterval, ActiveRouteTimeout)",
202  TimeValue (Seconds (15)),
203  MakeTimeAccessor (&RoutingProtocol::DeletePeriod),
204  MakeTimeChecker ())
205  .AddAttribute ("TimeoutBuffer", "Its purpose is to provide a buffer for the timeout so that if the RREP is delayed"
206  " due to congestion, a timeout is less likely to occur while the RREP is still en route back to the source.",
207  UintegerValue (2),
208  MakeUintegerAccessor (&RoutingProtocol::TimeoutBuffer),
209  MakeUintegerChecker<uint16_t> ())
210  .AddAttribute ("NetDiameter", "Net diameter measures the maximum possible number of hops between two nodes in the network",
211  UintegerValue (35),
212  MakeUintegerAccessor (&RoutingProtocol::NetDiameter),
213  MakeUintegerChecker<uint32_t> ())
214  .AddAttribute ("NetTraversalTime", "Estimate of the average net traversal time = 2 * NodeTraversalTime * NetDiameter",
215  TimeValue (Seconds (2.8)),
216  MakeTimeAccessor (&RoutingProtocol::NetTraversalTime),
217  MakeTimeChecker ())
218  .AddAttribute ("PathDiscoveryTime", "Estimate of maximum time needed to find route in network = 2 * NetTraversalTime",
219  TimeValue (Seconds (5.6)),
220  MakeTimeAccessor (&RoutingProtocol::PathDiscoveryTime),
221  MakeTimeChecker ())
222  .AddAttribute ("MaxQueueLen", "Maximum number of packets that we allow a routing protocol to buffer.",
223  UintegerValue (64),
224  MakeUintegerAccessor (&RoutingProtocol::SetMaxQueueLen,
226  MakeUintegerChecker<uint32_t> ())
227  .AddAttribute ("MaxQueueTime", "Maximum time packets can be queued (in seconds)",
228  TimeValue (Seconds (30)),
229  MakeTimeAccessor (&RoutingProtocol::SetMaxQueueTime,
231  MakeTimeChecker ())
232  .AddAttribute ("AllowedHelloLoss", "Number of hello messages which may be loss for valid link.",
233  UintegerValue (2),
234  MakeUintegerAccessor (&RoutingProtocol::AllowedHelloLoss),
235  MakeUintegerChecker<uint16_t> ())
236  .AddAttribute ("GratuitousReply", "Indicates whether a gratuitous RREP should be unicast to the node originated route discovery.",
237  BooleanValue (true),
238  MakeBooleanAccessor (&RoutingProtocol::SetGratuitousReplyFlag,
240  MakeBooleanChecker ())
241  .AddAttribute ("DestinationOnly", "Indicates only the destination may respond to this RREQ.",
242  BooleanValue (false),
243  MakeBooleanAccessor (&RoutingProtocol::SetDesinationOnlyFlag,
245  MakeBooleanChecker ())
246  .AddAttribute ("EnableHello", "Indicates whether a hello messages enable.",
247  BooleanValue (true),
248  MakeBooleanAccessor (&RoutingProtocol::SetHelloEnable,
250  MakeBooleanChecker ())
251  .AddAttribute ("EnableBroadcast", "Indicates whether a broadcast data packets forwarding enable.",
252  BooleanValue (true),
253  MakeBooleanAccessor (&RoutingProtocol::SetBroadcastEnable,
255  MakeBooleanChecker ())
256  .AddAttribute ("UniformRv",
257  "Access to the underlying UniformRandomVariable",
258  StringValue ("ns3::UniformRandomVariable"),
259  MakePointerAccessor (&RoutingProtocol::m_uniformRandomVariable),
260  MakePointerChecker<UniformRandomVariable> ())
261  ;
262  return tid;
263 }
264 
265 void
267 {
268  MaxQueueLen = len;
269  m_queue.SetMaxQueueLen (len);
270 }
271 void
273 {
274  MaxQueueTime = t;
276 }
277 
279 {
280 }
281 
282 void
284 {
285  m_ipv4 = 0;
286  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::iterator iter =
287  m_socketAddresses.begin (); iter != m_socketAddresses.end (); iter++)
288  {
289  iter->first->Close ();
290  }
291  m_socketAddresses.clear ();
293 }
294 
295 void
297 {
298  *stream->GetStream () << "Node: " << m_ipv4->GetObject<Node> ()->GetId () << " Time: " << Simulator::Now ().GetSeconds () << "s ";
299  m_routingTable.Print (stream);
300 }
301 
302 int64_t
304 {
305  NS_LOG_FUNCTION (this << stream);
307  return 1;
308 }
309 
310 void
312 {
313  NS_LOG_FUNCTION (this);
314  if (EnableHello)
315  {
316  m_nb.ScheduleTimer ();
317  }
319  this);
320  m_rreqRateLimitTimer.Schedule (Seconds (1));
321 
323  this);
324  m_rerrRateLimitTimer.Schedule (Seconds (1));
325 
326 }
327 
330  Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
331 {
332  NS_LOG_FUNCTION (this << header << (oif ? oif->GetIfIndex () : 0));
333  if (!p)
334  {
335  NS_LOG_DEBUG("Packet is == 0");
336  return LoopbackRoute (header, oif); // later
337  }
338  if (m_socketAddresses.empty ())
339  {
340  sockerr = Socket::ERROR_NOROUTETOHOST;
341  NS_LOG_LOGIC ("No aodv interfaces");
342  Ptr<Ipv4Route> route;
343  return route;
344  }
345  sockerr = Socket::ERROR_NOTERROR;
346  Ptr<Ipv4Route> route;
347  Ipv4Address dst = header.GetDestination ();
349  if (m_routingTable.LookupValidRoute (dst, rt))
350  {
351  route = rt.GetRoute ();
352  NS_ASSERT (route != 0);
353  NS_LOG_DEBUG ("Exist route to " << route->GetDestination () << " from interface " << route->GetSource ());
354  if (oif != 0 && route->GetOutputDevice () != oif)
355  {
356  NS_LOG_DEBUG ("Output device doesn't match. Dropped.");
357  sockerr = Socket::ERROR_NOROUTETOHOST;
358  return Ptr<Ipv4Route> ();
359  }
362  return route;
363  }
364 
365  // Valid route not found, in this case we return loopback.
366  // Actual route request will be deferred until packet will be fully formed,
367  // routed to loopback, received from loopback and passed to RouteInput (see below)
368  uint32_t iif = (oif ? m_ipv4->GetInterfaceForDevice (oif) : -1);
369  DeferredRouteOutputTag tag (iif);
370  NS_LOG_DEBUG ("Valid Route not found");
371  if (!p->PeekPacketTag (tag))
372  {
373  p->AddPacketTag (tag);
374  }
375  return LoopbackRoute (header, oif);
376 }
377 
378 void
381 {
382  NS_LOG_FUNCTION (this << p << header);
383  NS_ASSERT (p != 0 && p != Ptr<Packet> ());
384 
385  QueueEntry newEntry (p, header, ucb, ecb);
386  bool result = m_queue.Enqueue (newEntry);
387  if (result)
388  {
389  NS_LOG_LOGIC ("Add packet " << p->GetUid () << " to queue. Protocol " << (uint16_t) header.GetProtocol ());
391  bool result = m_routingTable.LookupRoute (header.GetDestination (), rt);
392  if(!result || ((rt.GetFlag () != IN_SEARCH) && result))
393  {
394  NS_LOG_LOGIC ("Send new RREQ for outbound packet to " <<header.GetDestination ());
395  SendRequest (header.GetDestination ());
396  }
397  }
398 }
399 
400 bool
404 {
405  NS_LOG_FUNCTION (this << p->GetUid () << header.GetDestination () << idev->GetAddress ());
406  if (m_socketAddresses.empty ())
407  {
408  NS_LOG_LOGIC ("No aodv interfaces");
409  return false;
410  }
411  NS_ASSERT (m_ipv4 != 0);
412  NS_ASSERT (p != 0);
413  // Check if input device supports IP
414  NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);
415  int32_t iif = m_ipv4->GetInterfaceForDevice (idev);
416 
417  Ipv4Address dst = header.GetDestination ();
418  Ipv4Address origin = header.GetSource ();
419 
420  // Deferred route request
421  if (idev == m_lo)
422  {
424  if (p->PeekPacketTag (tag))
425  {
426  DeferredRouteOutput (p, header, ucb, ecb);
427  return true;
428  }
429  }
430 
431  // Duplicate of own packet
432  if (IsMyOwnAddress (origin))
433  return true;
434 
435  // AODV is not a multicast routing protocol
436  if (dst.IsMulticast ())
437  {
438  return false;
439  }
440 
441  // Broadcast local delivery/forwarding
442  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =
443  m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
444  {
445  Ipv4InterfaceAddress iface = j->second;
446  if (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()) == iif)
447  if (dst == iface.GetBroadcast () || dst.IsBroadcast ())
448  {
449  if (m_dpd.IsDuplicate (p, header))
450  {
451  NS_LOG_DEBUG ("Duplicated packet " << p->GetUid () << " from " << origin << ". Drop.");
452  return true;
453  }
455  Ptr<Packet> packet = p->Copy ();
456  if (lcb.IsNull () == false)
457  {
458  NS_LOG_LOGIC ("Broadcast local delivery to " << iface.GetLocal ());
459  lcb (p, header, iif);
460  // Fall through to additional processing
461  }
462  else
463  {
464  NS_LOG_ERROR ("Unable to deliver packet locally due to null callback " << p->GetUid () << " from " << origin);
465  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
466  }
467  if (!EnableBroadcast)
468  {
469  return true;
470  }
471  if (header.GetTtl () > 1)
472  {
473  NS_LOG_LOGIC ("Forward broadcast. TTL " << (uint16_t) header.GetTtl ());
474  RoutingTableEntry toBroadcast;
475  if (m_routingTable.LookupRoute (dst, toBroadcast))
476  {
477  Ptr<Ipv4Route> route = toBroadcast.GetRoute ();
478  ucb (route, packet, header);
479  }
480  else
481  {
482  NS_LOG_DEBUG ("No route to forward broadcast. Drop packet " << p->GetUid ());
483  }
484  }
485  else
486  {
487  NS_LOG_DEBUG ("TTL exceeded. Drop packet " << p->GetUid ());
488  }
489  return true;
490  }
491  }
492 
493  // Unicast local delivery
494  if (m_ipv4->IsDestinationAddress (dst, iif))
495  {
497  RoutingTableEntry toOrigin;
498  if (m_routingTable.LookupValidRoute (origin, toOrigin))
499  {
501  m_nb.Update (toOrigin.GetNextHop (), ActiveRouteTimeout);
502  }
503  if (lcb.IsNull () == false)
504  {
505  NS_LOG_LOGIC ("Unicast local delivery to " << dst);
506  lcb (p, header, iif);
507  }
508  else
509  {
510  NS_LOG_ERROR ("Unable to deliver packet locally due to null callback " << p->GetUid () << " from " << origin);
511  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
512  }
513  return true;
514  }
515 
516  // Forwarding
517  return Forwarding (p, header, ucb, ecb);
518 }
519 
520 bool
523 {
524  NS_LOG_FUNCTION (this);
525  Ipv4Address dst = header.GetDestination ();
526  Ipv4Address origin = header.GetSource ();
528  RoutingTableEntry toDst;
529  if (m_routingTable.LookupRoute (dst, toDst))
530  {
531  if (toDst.GetFlag () == VALID)
532  {
533  Ptr<Ipv4Route> route = toDst.GetRoute ();
534  NS_LOG_LOGIC (route->GetSource ()<<" forwarding to " << dst << " from " << origin << " packet " << p->GetUid ());
535 
536  /*
537  * Each time a route is used to forward a data packet, its Active Route
538  * Lifetime field of the source, destination and the next hop on the
539  * path to the destination is updated to be no less than the current
540  * time plus ActiveRouteTimeout.
541  */
545  /*
546  * Since the route between each originator and destination pair is expected to be symmetric, the
547  * Active Route Lifetime for the previous hop, along the reverse path back to the IP source, is also updated
548  * to be no less than the current time plus ActiveRouteTimeout
549  */
550  RoutingTableEntry toOrigin;
551  m_routingTable.LookupRoute (origin, toOrigin);
552  UpdateRouteLifeTime (toOrigin.GetNextHop (), ActiveRouteTimeout);
553 
555  m_nb.Update (toOrigin.GetNextHop (), ActiveRouteTimeout);
556 
557  ucb (route, p, header);
558  return true;
559  }
560  else
561  {
562  if (toDst.GetValidSeqNo ())
563  {
564  SendRerrWhenNoRouteToForward (dst, toDst.GetSeqNo (), origin);
565  NS_LOG_DEBUG ("Drop packet " << p->GetUid () << " because no route to forward it.");
566  return false;
567  }
568  }
569  }
570  NS_LOG_LOGIC ("route not found to "<< dst << ". Send RERR message.");
571  NS_LOG_DEBUG ("Drop packet " << p->GetUid () << " because no route to forward it.");
572  SendRerrWhenNoRouteToForward (dst, 0, origin);
573  return false;
574 }
575 
576 void
578 {
579  NS_ASSERT (ipv4 != 0);
580  NS_ASSERT (m_ipv4 == 0);
581 
582  if (EnableHello)
583  {
585  m_htimer.Schedule (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 100)));
586  }
587 
588  m_ipv4 = ipv4;
589 
590  // Create lo route. It is asserted that the only one interface up for now is loopback
591  NS_ASSERT (m_ipv4->GetNInterfaces () == 1 && m_ipv4->GetAddress (0, 0).GetLocal () == Ipv4Address ("127.0.0.1"));
592  m_lo = m_ipv4->GetNetDevice (0);
593  NS_ASSERT (m_lo != 0);
594  // Remember lo route
595  RoutingTableEntry rt (/*device=*/ m_lo, /*dst=*/ Ipv4Address::GetLoopback (), /*know seqno=*/ true, /*seqno=*/ 0,
596  /*iface=*/ Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask ("255.0.0.0")),
597  /*hops=*/ 1, /*next hop=*/ Ipv4Address::GetLoopback (),
598  /*lifetime=*/ Simulator::GetMaximumSimulationTime ());
600 
602 }
603 
604 void
606 {
607  NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ());
609  if (l3->GetNAddresses (i) > 1)
610  {
611  NS_LOG_WARN ("AODV does not work with more then one address per each interface.");
612  }
613  Ipv4InterfaceAddress iface = l3->GetAddress (i, 0);
614  if (iface.GetLocal () == Ipv4Address ("127.0.0.1"))
615  return;
616 
617  // Create a socket to listen only on this interface
618  Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),
620  NS_ASSERT (socket != 0);
622  socket->BindToNetDevice (l3->GetNetDevice (i));
624  socket->SetAllowBroadcast (true);
625  socket->SetAttribute ("IpTtl", UintegerValue (1));
626  m_socketAddresses.insert (std::make_pair (socket, iface));
627 
628  // Add local broadcast record to the routing table
630  RoutingTableEntry rt (/*device=*/ dev, /*dst=*/ iface.GetBroadcast (), /*know seqno=*/ true, /*seqno=*/ 0, /*iface=*/ iface,
631  /*hops=*/ 1, /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/ Simulator::GetMaximumSimulationTime ());
633 
634  // Allow neighbor manager use this interface for layer 2 feedback if possible
636  if (wifi == 0)
637  return;
638  Ptr<WifiMac> mac = wifi->GetMac ();
639  if (mac == 0)
640  return;
641 
642  mac->TraceConnectWithoutContext ("TxErrHeader", m_nb.GetTxErrorCallback ());
643  m_nb.AddArpCache (l3->GetInterface (i)->GetArpCache ());
644 }
645 
646 void
648 {
649  NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ());
650 
651  // Disable layer 2 link state monitoring (if possible)
653  Ptr<NetDevice> dev = l3->GetNetDevice (i);
654  Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();
655  if (wifi != 0)
656  {
657  Ptr<WifiMac> mac = wifi->GetMac ()->GetObject<AdhocWifiMac> ();
658  if (mac != 0)
659  {
660  mac->TraceDisconnectWithoutContext ("TxErrHeader",
662  m_nb.DelArpCache (l3->GetInterface (i)->GetArpCache ());
663  }
664  }
665 
666  // Close socket
668  NS_ASSERT (socket);
669  socket->Close ();
670  m_socketAddresses.erase (socket);
671  if (m_socketAddresses.empty ())
672  {
673  NS_LOG_LOGIC ("No aodv interfaces");
674  m_htimer.Cancel ();
675  m_nb.Clear ();
677  return;
678  }
680 }
681 
682 void
684 {
685  NS_LOG_FUNCTION (this << " interface " << i << " address " << address);
687  if (!l3->IsUp (i))
688  return;
689  if (l3->GetNAddresses (i) == 1)
690  {
691  Ipv4InterfaceAddress iface = l3->GetAddress (i, 0);
693  if (!socket)
694  {
695  if (iface.GetLocal () == Ipv4Address ("127.0.0.1"))
696  return;
697  // Create a socket to listen only on this interface
698  Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),
700  NS_ASSERT (socket != 0);
702  socket->BindToNetDevice (l3->GetNetDevice (i));
703  // Bind to any IP address so that broadcasts can be received
705  socket->SetAllowBroadcast (true);
706  m_socketAddresses.insert (std::make_pair (socket, iface));
707 
708  // Add local broadcast record to the routing table
711  RoutingTableEntry rt (/*device=*/ dev, /*dst=*/ iface.GetBroadcast (), /*know seqno=*/ true,
712  /*seqno=*/ 0, /*iface=*/ iface, /*hops=*/ 1,
713  /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/ Simulator::GetMaximumSimulationTime ());
715  }
716  }
717  else
718  {
719  NS_LOG_LOGIC ("AODV does not work with more then one address per each interface. Ignore added address");
720  }
721 }
722 
723 void
725 {
726  NS_LOG_FUNCTION (this);
727  Ptr<Socket> socket = FindSocketWithInterfaceAddress (address);
728  if (socket)
729  {
731  m_socketAddresses.erase (socket);
733  if (l3->GetNAddresses (i))
734  {
735  Ipv4InterfaceAddress iface = l3->GetAddress (i, 0);
736  // Create a socket to listen only on this interface
737  Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),
739  NS_ASSERT (socket != 0);
741  // Bind to any IP address so that broadcasts can be received
743  socket->SetAllowBroadcast (true);
744  m_socketAddresses.insert (std::make_pair (socket, iface));
745 
746  // Add local broadcast record to the routing table
748  RoutingTableEntry rt (/*device=*/ dev, /*dst=*/ iface.GetBroadcast (), /*know seqno=*/ true, /*seqno=*/ 0, /*iface=*/ iface,
749  /*hops=*/ 1, /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/ Simulator::GetMaximumSimulationTime ());
751  }
752  if (m_socketAddresses.empty ())
753  {
754  NS_LOG_LOGIC ("No aodv interfaces");
755  m_htimer.Cancel ();
756  m_nb.Clear ();
758  return;
759  }
760  }
761  else
762  {
763  NS_LOG_LOGIC ("Remove address not participating in AODV operation");
764  }
765 }
766 
767 bool
769 {
770  NS_LOG_FUNCTION (this << src);
771  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =
772  m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
773  {
774  Ipv4InterfaceAddress iface = j->second;
775  if (src == iface.GetLocal ())
776  {
777  return true;
778  }
779  }
780  return false;
781 }
782 
785 {
786  NS_LOG_FUNCTION (this << hdr);
787  NS_ASSERT (m_lo != 0);
788  Ptr<Ipv4Route> rt = Create<Ipv4Route> ();
789  rt->SetDestination (hdr.GetDestination ());
790  //
791  // Source address selection here is tricky. The loopback route is
792  // returned when AODV does not have a route; this causes the packet
793  // to be looped back and handled (cached) in RouteInput() method
794  // while a route is found. However, connection-oriented protocols
795  // like TCP need to create an endpoint four-tuple (src, src port,
796  // dst, dst port) and create a pseudo-header for checksumming. So,
797  // AODV needs to guess correctly what the eventual source address
798  // will be.
799  //
800  // For single interface, single address nodes, this is not a problem.
801  // When there are possibly multiple outgoing interfaces, the policy
802  // implemented here is to pick the first available AODV interface.
803  // If RouteOutput() caller specified an outgoing interface, that
804  // further constrains the selection of source address
805  //
806  std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin ();
807  if (oif)
808  {
809  // Iterate to find an address on the oif device
810  for (j = m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
811  {
812  Ipv4Address addr = j->second.GetLocal ();
813  int32_t interface = m_ipv4->GetInterfaceForAddress (addr);
814  if (oif == m_ipv4->GetNetDevice (static_cast<uint32_t> (interface)))
815  {
816  rt->SetSource (addr);
817  break;
818  }
819  }
820  }
821  else
822  {
823  rt->SetSource (j->second.GetLocal ());
824  }
825  NS_ASSERT_MSG (rt->GetSource () != Ipv4Address (), "Valid AODV source address not found");
826  rt->SetGateway (Ipv4Address ("127.0.0.1"));
827  rt->SetOutputDevice (m_lo);
828  return rt;
829 }
830 
831 void
833 {
834  NS_LOG_FUNCTION ( this << dst);
835  // A node SHOULD NOT originate more than RREQ_RATELIMIT RREQ messages per second.
836  if (m_rreqCount == RreqRateLimit)
837  {
838  Simulator::Schedule (m_rreqRateLimitTimer.GetDelayLeft () + MicroSeconds (100),
839  &RoutingProtocol::SendRequest, this, dst);
840  return;
841  }
842  else
843  m_rreqCount++;
844  // Create RREQ header
845  RreqHeader rreqHeader;
846  rreqHeader.SetDst (dst);
847 
849  if (m_routingTable.LookupRoute (dst, rt))
850  {
851  rreqHeader.SetHopCount (rt.GetHop ());
852  if (rt.GetValidSeqNo ())
853  rreqHeader.SetDstSeqno (rt.GetSeqNo ());
854  else
855  rreqHeader.SetUnknownSeqno (true);
856  rt.SetFlag (IN_SEARCH);
857  m_routingTable.Update (rt);
858  }
859  else
860  {
861  rreqHeader.SetUnknownSeqno (true);
862  Ptr<NetDevice> dev = 0;
863  RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ dst, /*validSeqNo=*/ false, /*seqno=*/ 0,
864  /*iface=*/ Ipv4InterfaceAddress (),/*hop=*/ 0,
865  /*nextHop=*/ Ipv4Address (), /*lifeTime=*/ Seconds (0));
866  newEntry.SetFlag (IN_SEARCH);
867  m_routingTable.AddRoute (newEntry);
868  }
869 
870  if (GratuitousReply)
871  rreqHeader.SetGratiousRrep (true);
872  if (DestinationOnly)
873  rreqHeader.SetDestinationOnly (true);
874 
875  m_seqNo++;
876  rreqHeader.SetOriginSeqno (m_seqNo);
877  m_requestId++;
878  rreqHeader.SetId (m_requestId);
879  rreqHeader.SetHopCount (0);
880 
881  // Send RREQ as subnet directed broadcast from each interface used by aodv
882  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =
883  m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
884  {
885  Ptr<Socket> socket = j->first;
886  Ipv4InterfaceAddress iface = j->second;
887 
888  rreqHeader.SetOrigin (iface.GetLocal ());
890 
891  Ptr<Packet> packet = Create<Packet> ();
892  packet->AddHeader (rreqHeader);
893  TypeHeader tHeader (AODVTYPE_RREQ);
894  packet->AddHeader (tHeader);
895  // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
896  Ipv4Address destination;
897  if (iface.GetMask () == Ipv4Mask::GetOnes ())
898  {
899  destination = Ipv4Address ("255.255.255.255");
900  }
901  else
902  {
903  destination = iface.GetBroadcast ();
904  }
905  NS_LOG_DEBUG ("Send RREQ with id " << rreqHeader.GetId () << " to socket");
907  Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, destination);
908  }
909  ScheduleRreqRetry (dst);
910 }
911 
912 void
914 {
915  socket->SendTo (packet, 0, InetSocketAddress (destination, AODV_PORT));
916 
917 }
918 void
920 {
921  NS_LOG_FUNCTION (this << dst);
922  if (m_addressReqTimer.find (dst) == m_addressReqTimer.end ())
923  {
925  m_addressReqTimer[dst] = timer;
926  }
928  m_addressReqTimer[dst].Remove ();
929  m_addressReqTimer[dst].SetArguments (dst);
931  m_routingTable.LookupRoute (dst, rt);
932  rt.IncrementRreqCnt ();
933  m_routingTable.Update (rt);
934  m_addressReqTimer[dst].Schedule (Time (rt.GetRreqCnt () * NetTraversalTime));
935  NS_LOG_LOGIC ("Scheduled RREQ retry in " << Time (rt.GetRreqCnt () * NetTraversalTime).GetSeconds () << " seconds");
936 }
937 
938 void
940 {
941  NS_LOG_FUNCTION (this << socket);
942  Address sourceAddress;
943  Ptr<Packet> packet = socket->RecvFrom (sourceAddress);
944  InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
945  Ipv4Address sender = inetSourceAddr.GetIpv4 ();
946  Ipv4Address receiver = m_socketAddresses[socket].GetLocal ();
947  NS_LOG_DEBUG ("AODV node " << this << " received a AODV packet from " << sender << " to " << receiver);
948 
949  UpdateRouteToNeighbor (sender, receiver);
950  TypeHeader tHeader (AODVTYPE_RREQ);
951  packet->RemoveHeader (tHeader);
952  if (!tHeader.IsValid ())
953  {
954  NS_LOG_DEBUG ("AODV message " << packet->GetUid () << " with unknown type received: " << tHeader.Get () << ". Drop");
955  return; // drop
956  }
957  switch (tHeader.Get ())
958  {
959  case AODVTYPE_RREQ:
960  {
961  RecvRequest (packet, receiver, sender);
962  break;
963  }
964  case AODVTYPE_RREP:
965  {
966  RecvReply (packet, receiver, sender);
967  break;
968  }
969  case AODVTYPE_RERR:
970  {
971  RecvError (packet, sender);
972  break;
973  }
974  case AODVTYPE_RREP_ACK:
975  {
976  RecvReplyAck (sender);
977  break;
978  }
979  }
980 }
981 
982 bool
984 {
985  NS_LOG_FUNCTION (this << addr << lifetime);
987  if (m_routingTable.LookupRoute (addr, rt))
988  {
989  if (rt.GetFlag () == VALID)
990  {
991  NS_LOG_DEBUG ("Updating VALID route");
992  rt.SetRreqCnt (0);
993  rt.SetLifeTime (std::max (lifetime, rt.GetLifeTime ()));
994  m_routingTable.Update (rt);
995  return true;
996  }
997  }
998  return false;
999 }
1000 
1001 void
1003 {
1004  NS_LOG_FUNCTION (this << "sender " << sender << " receiver " << receiver);
1005  RoutingTableEntry toNeighbor;
1006  if (!m_routingTable.LookupRoute (sender, toNeighbor))
1007  {
1009  RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ sender, /*know seqno=*/ false, /*seqno=*/ 0,
1010  /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),
1011  /*hops=*/ 1, /*next hop=*/ sender, /*lifetime=*/ ActiveRouteTimeout);
1012  m_routingTable.AddRoute (newEntry);
1013  }
1014  else
1015  {
1017  if (toNeighbor.GetValidSeqNo () && (toNeighbor.GetHop () == 1) && (toNeighbor.GetOutputDevice () == dev))
1018  {
1019  toNeighbor.SetLifeTime (std::max (ActiveRouteTimeout, toNeighbor.GetLifeTime ()));
1020  }
1021  else
1022  {
1023  RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ sender, /*know seqno=*/ false, /*seqno=*/ 0,
1024  /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),
1025  /*hops=*/ 1, /*next hop=*/ sender, /*lifetime=*/ std::max (ActiveRouteTimeout, toNeighbor.GetLifeTime ()));
1026  m_routingTable.Update (newEntry);
1027  }
1028  }
1029 
1030 }
1031 
1032 void
1034 {
1035  NS_LOG_FUNCTION (this);
1036  RreqHeader rreqHeader;
1037  p->RemoveHeader (rreqHeader);
1038 
1039  // A node ignores all RREQs received from any node in its blacklist
1040  RoutingTableEntry toPrev;
1041  if (m_routingTable.LookupRoute (src, toPrev))
1042  {
1043  if (toPrev.IsUnidirectional ())
1044  {
1045  NS_LOG_DEBUG ("Ignoring RREQ from node in blacklist");
1046  return;
1047  }
1048  }
1049 
1050  uint32_t id = rreqHeader.GetId ();
1051  Ipv4Address origin = rreqHeader.GetOrigin ();
1052 
1053  /*
1054  * Node checks to determine whether it has received a RREQ with the same Originator IP Address and RREQ ID.
1055  * If such a RREQ has been received, the node silently discards the newly received RREQ.
1056  */
1057  if (m_rreqIdCache.IsDuplicate (origin, id))
1058  {
1059  NS_LOG_DEBUG ("Ignoring RREQ due to duplicate");
1060  return;
1061  }
1062 
1063  // Increment RREQ hop count
1064  uint8_t hop = rreqHeader.GetHopCount () + 1;
1065  rreqHeader.SetHopCount (hop);
1066 
1067  /*
1068  * When the reverse route is created or updated, the following actions on the route are also carried out:
1069  * 1. the Originator Sequence Number from the RREQ is compared to the corresponding destination sequence number
1070  * in the route table entry and copied if greater than the existing value there
1071  * 2. the valid sequence number field is set to true;
1072  * 3. the next hop in the routing table becomes the node from which the RREQ was received
1073  * 4. the hop count is copied from the Hop Count in the RREQ message;
1074  * 5. the Lifetime is set to be the maximum of (ExistingLifetime, MinimalLifetime), where
1075  * MinimalLifetime = current time + 2*NetTraversalTime - 2*HopCount*NodeTraversalTime
1076  */
1077  RoutingTableEntry toOrigin;
1078  if (!m_routingTable.LookupRoute (origin, toOrigin))
1079  {
1081  RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ origin, /*validSeno=*/ true, /*seqNo=*/ rreqHeader.GetOriginSeqno (),
1082  /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0), /*hops=*/ hop,
1083  /*nextHop*/ src, /*timeLife=*/ Time ((2 * NetTraversalTime - 2 * hop * NodeTraversalTime)));
1084  m_routingTable.AddRoute (newEntry);
1085  }
1086  else
1087  {
1088  if (toOrigin.GetValidSeqNo ())
1089  {
1090  if (int32_t (rreqHeader.GetOriginSeqno ()) - int32_t (toOrigin.GetSeqNo ()) > 0)
1091  toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ());
1092  }
1093  else
1094  toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ());
1095  toOrigin.SetValidSeqNo (true);
1096  toOrigin.SetNextHop (src);
1098  toOrigin.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));
1099  toOrigin.SetHop (hop);
1100  toOrigin.SetLifeTime (std::max (Time (2 * NetTraversalTime - 2 * hop * NodeTraversalTime),
1101  toOrigin.GetLifeTime ()));
1102  m_routingTable.Update (toOrigin);
1103  //m_nb.Update (src, Time (AllowedHelloLoss * HelloInterval));
1104  }
1105 
1106 
1107  RoutingTableEntry toNeighbor;
1108  if (!m_routingTable.LookupRoute (src, toNeighbor))
1109  {
1110  NS_LOG_DEBUG ("Neighbor:" << src << " not found in routing table. Creating an entry");
1112  RoutingTableEntry newEntry (dev, src, false, rreqHeader.GetOriginSeqno (),
1113  m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),
1114  1, src, ActiveRouteTimeout);
1115  m_routingTable.AddRoute (newEntry);
1116  }
1117  else
1118  {
1119  toNeighbor.SetLifeTime (ActiveRouteTimeout);
1120  toNeighbor.SetValidSeqNo (false);
1121  toNeighbor.SetSeqNo (rreqHeader.GetOriginSeqno ());
1122  toNeighbor.SetFlag (VALID);
1123  toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));
1124  toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));
1125  m_routingTable.Update (toNeighbor);
1126  }
1128 
1129  NS_LOG_LOGIC (receiver << " receive RREQ with hop count " << static_cast<uint32_t>(rreqHeader.GetHopCount ())
1130  << " ID " << rreqHeader.GetId ()
1131  << " to destination " << rreqHeader.GetDst ());
1132 
1133  // A node generates a RREP if either:
1134  // (i) it is itself the destination,
1135  if (IsMyOwnAddress (rreqHeader.GetDst ()))
1136  {
1137  m_routingTable.LookupRoute (origin, toOrigin);
1138  NS_LOG_DEBUG ("Send reply since I am the destination");
1139  SendReply (rreqHeader, toOrigin);
1140  return;
1141  }
1142  /*
1143  * (ii) or it has an active route to the destination, the destination sequence number in the node's existing route table entry for the destination
1144  * is valid and greater than or equal to the Destination Sequence Number of the RREQ, and the "destination only" flag is NOT set.
1145  */
1146  RoutingTableEntry toDst;
1147  Ipv4Address dst = rreqHeader.GetDst ();
1148  if (m_routingTable.LookupRoute (dst, toDst))
1149  {
1150  /*
1151  * Drop RREQ, This node RREP wil make a loop.
1152  */
1153  if (toDst.GetNextHop () == src)
1154  {
1155  NS_LOG_DEBUG ("Drop RREQ from " << src << ", dest next hop " << toDst.GetNextHop ());
1156  return;
1157  }
1158  /*
1159  * The Destination Sequence number for the requested destination is set to the maximum of the corresponding value
1160  * received in the RREQ message, and the destination sequence value currently maintained by the node for the requested destination.
1161  * However, the forwarding node MUST NOT modify its maintained value for the destination sequence number, even if the value
1162  * received in the incoming RREQ is larger than the value currently maintained by the forwarding node.
1163  */
1164  if ((rreqHeader.GetUnknownSeqno () || (int32_t (toDst.GetSeqNo ()) - int32_t (rreqHeader.GetDstSeqno ()) >= 0))
1165  && toDst.GetValidSeqNo () )
1166  {
1167  if (!rreqHeader.GetDestinationOnly () && toDst.GetFlag () == VALID)
1168  {
1169  m_routingTable.LookupRoute (origin, toOrigin);
1170  SendReplyByIntermediateNode (toDst, toOrigin, rreqHeader.GetGratiousRrep ());
1171  return;
1172  }
1173  rreqHeader.SetDstSeqno (toDst.GetSeqNo ());
1174  rreqHeader.SetUnknownSeqno (false);
1175  }
1176  }
1177 
1178  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =
1179  m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
1180  {
1181  Ptr<Socket> socket = j->first;
1182  Ipv4InterfaceAddress iface = j->second;
1183  Ptr<Packet> packet = Create<Packet> ();
1184  packet->AddHeader (rreqHeader);
1185  TypeHeader tHeader (AODVTYPE_RREQ);
1186  packet->AddHeader (tHeader);
1187  // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
1188  Ipv4Address destination;
1189  if (iface.GetMask () == Ipv4Mask::GetOnes ())
1190  {
1191  destination = Ipv4Address ("255.255.255.255");
1192  }
1193  else
1194  {
1195  destination = iface.GetBroadcast ();
1196  }
1198  Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, destination);
1199 
1200  }
1201 }
1202 
1203 void
1204 RoutingProtocol::SendReply (RreqHeader const & rreqHeader, RoutingTableEntry const & toOrigin)
1205 {
1206  NS_LOG_FUNCTION (this << toOrigin.GetDestination ());
1207  /*
1208  * Destination node MUST increment its own sequence number by one if the sequence number in the RREQ packet is equal to that
1209  * incremented value. Otherwise, the destination does not change its sequence number before generating the RREP message.
1210  */
1211  if (!rreqHeader.GetUnknownSeqno () && (rreqHeader.GetDstSeqno () == m_seqNo + 1))
1212  m_seqNo++;
1213  RrepHeader rrepHeader ( /*prefixSize=*/ 0, /*hops=*/ 0, /*dst=*/ rreqHeader.GetDst (),
1214  /*dstSeqNo=*/ m_seqNo, /*origin=*/ toOrigin.GetDestination (), /*lifeTime=*/ MyRouteTimeout);
1215  Ptr<Packet> packet = Create<Packet> ();
1216  packet->AddHeader (rrepHeader);
1217  TypeHeader tHeader (AODVTYPE_RREP);
1218  packet->AddHeader (tHeader);
1220  NS_ASSERT (socket);
1221  socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), AODV_PORT));
1222 }
1223 
1224 void
1226 {
1227  NS_LOG_FUNCTION (this);
1228  RrepHeader rrepHeader (/*prefix size=*/ 0, /*hops=*/ toDst.GetHop (), /*dst=*/ toDst.GetDestination (), /*dst seqno=*/ toDst.GetSeqNo (),
1229  /*origin=*/ toOrigin.GetDestination (), /*lifetime=*/ toDst.GetLifeTime ());
1230  /* If the node we received a RREQ for is a neighbor we are
1231  * probably facing a unidirectional link... Better request a RREP-ack
1232  */
1233  if (toDst.GetHop () == 1)
1234  {
1235  rrepHeader.SetAckRequired (true);
1236  RoutingTableEntry toNextHop;
1237  m_routingTable.LookupRoute (toOrigin.GetNextHop (), toNextHop);
1239  toNextHop.m_ackTimer.SetArguments (toNextHop.GetDestination (), BlackListTimeout);
1240  toNextHop.m_ackTimer.SetDelay (NextHopWait);
1241  }
1242  toDst.InsertPrecursor (toOrigin.GetNextHop ());
1243  toOrigin.InsertPrecursor (toDst.GetNextHop ());
1244  m_routingTable.Update (toDst);
1245  m_routingTable.Update (toOrigin);
1246 
1247  Ptr<Packet> packet = Create<Packet> ();
1248  packet->AddHeader (rrepHeader);
1249  TypeHeader tHeader (AODVTYPE_RREP);
1250  packet->AddHeader (tHeader);
1252  NS_ASSERT (socket);
1253  socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), AODV_PORT));
1254 
1255  // Generating gratuitous RREPs
1256  if (gratRep)
1257  {
1258  RrepHeader gratRepHeader (/*prefix size=*/ 0, /*hops=*/ toOrigin.GetHop (), /*dst=*/ toOrigin.GetDestination (),
1259  /*dst seqno=*/ toOrigin.GetSeqNo (), /*origin=*/ toDst.GetDestination (),
1260  /*lifetime=*/ toOrigin.GetLifeTime ());
1261  Ptr<Packet> packetToDst = Create<Packet> ();
1262  packetToDst->AddHeader (gratRepHeader);
1263  TypeHeader type (AODVTYPE_RREP);
1264  packetToDst->AddHeader (type);
1266  NS_ASSERT (socket);
1267  NS_LOG_LOGIC ("Send gratuitous RREP " << packet->GetUid ());
1268  socket->SendTo (packetToDst, 0, InetSocketAddress (toDst.GetNextHop (), AODV_PORT));
1269  }
1270 }
1271 
1272 void
1274 {
1275  NS_LOG_FUNCTION (this << " to " << neighbor);
1276  RrepAckHeader h;
1277  TypeHeader typeHeader (AODVTYPE_RREP_ACK);
1278  Ptr<Packet> packet = Create<Packet> ();
1279  packet->AddHeader (h);
1280  packet->AddHeader (typeHeader);
1281  RoutingTableEntry toNeighbor;
1282  m_routingTable.LookupRoute (neighbor, toNeighbor);
1283  Ptr<Socket> socket = FindSocketWithInterfaceAddress (toNeighbor.GetInterface ());
1284  NS_ASSERT (socket);
1285  socket->SendTo (packet, 0, InetSocketAddress (neighbor, AODV_PORT));
1286 }
1287 
1288 void
1290 {
1291  NS_LOG_FUNCTION (this << " src " << sender);
1292  RrepHeader rrepHeader;
1293  p->RemoveHeader (rrepHeader);
1294  Ipv4Address dst = rrepHeader.GetDst ();
1295  NS_LOG_LOGIC ("RREP destination " << dst << " RREP origin " << rrepHeader.GetOrigin ());
1296 
1297  uint8_t hop = rrepHeader.GetHopCount () + 1;
1298  rrepHeader.SetHopCount (hop);
1299 
1300  // If RREP is Hello message
1301  if (dst == rrepHeader.GetOrigin ())
1302  {
1303  ProcessHello (rrepHeader, receiver);
1304  return;
1305  }
1306 
1307  /*
1308  * If the route table entry to the destination is created or updated, then the following actions occur:
1309  * - the route is marked as active,
1310  * - the destination sequence number is marked as valid,
1311  * - the next hop in the route entry is assigned to be the node from which the RREP is received,
1312  * which is indicated by the source IP address field in the IP header,
1313  * - the hop count is set to the value of the hop count from RREP message + 1
1314  * - the expiry time is set to the current time plus the value of the Lifetime in the RREP message,
1315  * - and the destination sequence number is the Destination Sequence Number in the RREP message.
1316  */
1318  RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ dst, /*validSeqNo=*/ true, /*seqno=*/ rrepHeader.GetDstSeqno (),
1319  /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),/*hop=*/ hop,
1320  /*nextHop=*/ sender, /*lifeTime=*/ rrepHeader.GetLifeTime ());
1321  RoutingTableEntry toDst;
1322  if (m_routingTable.LookupRoute (dst, toDst))
1323  {
1324  /*
1325  * The existing entry is updated only in the following circumstances:
1326  * (i) the sequence number in the routing table is marked as invalid in route table entry.
1327  */
1328  if (!toDst.GetValidSeqNo ())
1329  {
1330  m_routingTable.Update (newEntry);
1331  }
1332  // (ii)the Destination Sequence Number in the RREP is greater than the node's copy of the destination sequence number and the known value is valid,
1333  else if ((int32_t (rrepHeader.GetDstSeqno ()) - int32_t (toDst.GetSeqNo ())) > 0)
1334  {
1335  m_routingTable.Update (newEntry);
1336  }
1337  else
1338  {
1339  // (iii) the sequence numbers are the same, but the route is marked as inactive.
1340  if ((rrepHeader.GetDstSeqno () == toDst.GetSeqNo ()) && (toDst.GetFlag () != VALID))
1341  {
1342  m_routingTable.Update (newEntry);
1343  }
1344  // (iv) the sequence numbers are the same, and the New Hop Count is smaller than the hop count in route table entry.
1345  else if ((rrepHeader.GetDstSeqno () == toDst.GetSeqNo ()) && (hop < toDst.GetHop ()))
1346  {
1347  m_routingTable.Update (newEntry);
1348  }
1349  }
1350  }
1351  else
1352  {
1353  // The forward route for this destination is created if it does not already exist.
1354  NS_LOG_LOGIC ("add new route");
1355  m_routingTable.AddRoute (newEntry);
1356  }
1357  // Acknowledge receipt of the RREP by sending a RREP-ACK message back
1358  if (rrepHeader.GetAckRequired ())
1359  {
1360  SendReplyAck (sender);
1361  rrepHeader.SetAckRequired (false);
1362  }
1363  NS_LOG_LOGIC ("receiver " << receiver << " origin " << rrepHeader.GetOrigin ());
1364  if (IsMyOwnAddress (rrepHeader.GetOrigin ()))
1365  {
1366  if (toDst.GetFlag () == IN_SEARCH)
1367  {
1368  m_routingTable.Update (newEntry);
1369  m_addressReqTimer[dst].Remove ();
1370  m_addressReqTimer.erase (dst);
1371  }
1372  m_routingTable.LookupRoute (dst, toDst);
1373  SendPacketFromQueue (dst, toDst.GetRoute ());
1374  return;
1375  }
1376 
1377  RoutingTableEntry toOrigin;
1378  if (!m_routingTable.LookupRoute (rrepHeader.GetOrigin (), toOrigin) || toOrigin.GetFlag () == IN_SEARCH)
1379  {
1380  return; // Impossible! drop.
1381  }
1382  toOrigin.SetLifeTime (std::max (ActiveRouteTimeout, toOrigin.GetLifeTime ()));
1383  m_routingTable.Update (toOrigin);
1384 
1385  // Update information about precursors
1386  if (m_routingTable.LookupValidRoute (rrepHeader.GetDst (), toDst))
1387  {
1388  toDst.InsertPrecursor (toOrigin.GetNextHop ());
1389  m_routingTable.Update (toDst);
1390 
1391  RoutingTableEntry toNextHopToDst;
1392  m_routingTable.LookupRoute (toDst.GetNextHop (), toNextHopToDst);
1393  toNextHopToDst.InsertPrecursor (toOrigin.GetNextHop ());
1394  m_routingTable.Update (toNextHopToDst);
1395 
1396  toOrigin.InsertPrecursor (toDst.GetNextHop ());
1397  m_routingTable.Update (toOrigin);
1398 
1399  RoutingTableEntry toNextHopToOrigin;
1400  m_routingTable.LookupRoute (toOrigin.GetNextHop (), toNextHopToOrigin);
1401  toNextHopToOrigin.InsertPrecursor (toDst.GetNextHop ());
1402  m_routingTable.Update (toNextHopToOrigin);
1403  }
1404 
1405  Ptr<Packet> packet = Create<Packet> ();
1406  packet->AddHeader (rrepHeader);
1407  TypeHeader tHeader (AODVTYPE_RREP);
1408  packet->AddHeader (tHeader);
1410  NS_ASSERT (socket);
1411  socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), AODV_PORT));
1412 }
1413 
1414 void
1416 {
1417  NS_LOG_FUNCTION (this);
1418  RoutingTableEntry rt;
1419  if(m_routingTable.LookupRoute (neighbor, rt))
1420  {
1421  rt.m_ackTimer.Cancel ();
1422  rt.SetFlag (VALID);
1423  m_routingTable.Update (rt);
1424  }
1425 }
1426 
1427 void
1429 {
1430  NS_LOG_FUNCTION (this << "from " << rrepHeader.GetDst ());
1431  /*
1432  * Whenever a node receives a Hello message from a neighbor, the node
1433  * SHOULD make sure that it has an active route to the neighbor, and
1434  * create one if necessary.
1435  */
1436  RoutingTableEntry toNeighbor;
1437  if (!m_routingTable.LookupRoute (rrepHeader.GetDst (), toNeighbor))
1438  {
1440  RoutingTableEntry newEntry (/*device=*/ dev, /*dst=*/ rrepHeader.GetDst (), /*validSeqNo=*/ true, /*seqno=*/ rrepHeader.GetDstSeqno (),
1441  /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),
1442  /*hop=*/ 1, /*nextHop=*/ rrepHeader.GetDst (), /*lifeTime=*/ rrepHeader.GetLifeTime ());
1443  m_routingTable.AddRoute (newEntry);
1444  }
1445  else
1446  {
1447  toNeighbor.SetLifeTime (std::max (Time (AllowedHelloLoss * HelloInterval), toNeighbor.GetLifeTime ()));
1448  toNeighbor.SetSeqNo (rrepHeader.GetDstSeqno ());
1449  toNeighbor.SetValidSeqNo (true);
1450  toNeighbor.SetFlag (VALID);
1451  toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));
1452  toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));
1453  m_routingTable.Update (toNeighbor);
1454  }
1455  if (EnableHello)
1456  {
1457  m_nb.Update (rrepHeader.GetDst (), Time (AllowedHelloLoss * HelloInterval));
1458  }
1459 }
1460 
1461 void
1463 {
1464  NS_LOG_FUNCTION (this << " from " << src);
1465  RerrHeader rerrHeader;
1466  p->RemoveHeader (rerrHeader);
1467  std::map<Ipv4Address, uint32_t> dstWithNextHopSrc;
1468  std::map<Ipv4Address, uint32_t> unreachable;
1469  m_routingTable.GetListOfDestinationWithNextHop (src, dstWithNextHopSrc);
1470  std::pair<Ipv4Address, uint32_t> un;
1471  while (rerrHeader.RemoveUnDestination (un))
1472  {
1473  for (std::map<Ipv4Address, uint32_t>::const_iterator i =
1474  dstWithNextHopSrc.begin (); i != dstWithNextHopSrc.end (); ++i)
1475  {
1476  if (i->first == un.first)
1477  {
1478  unreachable.insert (un);
1479  }
1480  }
1481  }
1482 
1483  std::vector<Ipv4Address> precursors;
1484  for (std::map<Ipv4Address, uint32_t>::const_iterator i = unreachable.begin ();
1485  i != unreachable.end ();)
1486  {
1487  if (!rerrHeader.AddUnDestination (i->first, i->second))
1488  {
1489  TypeHeader typeHeader (AODVTYPE_RERR);
1490  Ptr<Packet> packet = Create<Packet> ();
1491  packet->AddHeader (rerrHeader);
1492  packet->AddHeader (typeHeader);
1493  SendRerrMessage (packet, precursors);
1494  rerrHeader.Clear ();
1495  }
1496  else
1497  {
1498  RoutingTableEntry toDst;
1499  m_routingTable.LookupRoute (i->first, toDst);
1500  toDst.GetPrecursors (precursors);
1501  ++i;
1502  }
1503  }
1504  if (rerrHeader.GetDestCount () != 0)
1505  {
1506  TypeHeader typeHeader (AODVTYPE_RERR);
1507  Ptr<Packet> packet = Create<Packet> ();
1508  packet->AddHeader (rerrHeader);
1509  packet->AddHeader (typeHeader);
1510  SendRerrMessage (packet, precursors);
1511  }
1513 }
1514 
1515 void
1517 {
1518  NS_LOG_LOGIC (this);
1519  RoutingTableEntry toDst;
1520  if (m_routingTable.LookupValidRoute (dst, toDst))
1521  {
1522  SendPacketFromQueue (dst, toDst.GetRoute ());
1523  NS_LOG_LOGIC ("route to " << dst << " found");
1524  return;
1525  }
1526  /*
1527  * If a route discovery has been attempted RreqRetries times at the maximum TTL without
1528  * receiving any RREP, all data packets destined for the corresponding destination SHOULD be
1529  * dropped from the buffer and a Destination Unreachable message SHOULD be delivered to the application.
1530  */
1531  if (toDst.GetRreqCnt () == RreqRetries)
1532  {
1533  NS_LOG_LOGIC ("route discovery to " << dst << " has been attempted RreqRetries (" << RreqRetries << ") times");
1534  m_addressReqTimer.erase (dst);
1536  NS_LOG_DEBUG ("Route not found. Drop all packets with dst " << dst);
1537  m_queue.DropPacketWithDst (dst);
1538  return;
1539  }
1540 
1541  if (toDst.GetFlag () == IN_SEARCH)
1542  {
1543  NS_LOG_LOGIC ("Resend RREQ to " << dst << " ttl " << NetDiameter);
1544  SendRequest (dst);
1545  }
1546  else
1547  {
1548  NS_LOG_DEBUG ("Route down. Stop search. Drop packet with destination " << dst);
1549  m_addressReqTimer.erase (dst);
1551  m_queue.DropPacketWithDst (dst);
1552  }
1553 }
1554 
1555 void
1557 {
1558  NS_LOG_FUNCTION (this);
1559  Time offset = Time (Seconds (0));
1560  if (m_lastBcastTime > Time (Seconds (0)))
1561  {
1562  offset = Simulator::Now () - m_lastBcastTime;
1563  NS_LOG_DEBUG ("Hello deferred due to last bcast at:" << m_lastBcastTime);
1564  }
1565  else
1566  {
1567  SendHello ();
1568  }
1569  m_htimer.Cancel ();
1570  Time diff = HelloInterval - offset;
1571  m_htimer.Schedule (std::max (Time (Seconds (0)), diff));
1572  m_lastBcastTime = Time (Seconds (0));
1573 }
1574 
1575 void
1577 {
1578  NS_LOG_FUNCTION (this);
1579  m_rreqCount = 0;
1580  m_rreqRateLimitTimer.Schedule (Seconds (1));
1581 }
1582 
1583 void
1585 {
1586  NS_LOG_FUNCTION (this);
1587  m_rerrCount = 0;
1588  m_rerrRateLimitTimer.Schedule (Seconds (1));
1589 }
1590 
1591 void
1593 {
1594  NS_LOG_FUNCTION (this);
1595  m_routingTable.MarkLinkAsUnidirectional (neighbor, blacklistTimeout);
1596 }
1597 
1598 void
1600 {
1601  NS_LOG_FUNCTION (this);
1602  /* Broadcast a RREP with TTL = 1 with the RREP message fields set as follows:
1603  * Destination IP Address The node's IP address.
1604  * Destination Sequence Number The node's latest sequence number.
1605  * Hop Count 0
1606  * Lifetime AllowedHelloLoss * HelloInterval
1607  */
1608  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
1609  {
1610  Ptr<Socket> socket = j->first;
1611  Ipv4InterfaceAddress iface = j->second;
1612  RrepHeader helloHeader (/*prefix size=*/ 0, /*hops=*/ 0, /*dst=*/ iface.GetLocal (), /*dst seqno=*/ m_seqNo,
1613  /*origin=*/ iface.GetLocal (),/*lifetime=*/ Time (AllowedHelloLoss * HelloInterval));
1614  Ptr<Packet> packet = Create<Packet> ();
1615  packet->AddHeader (helloHeader);
1616  TypeHeader tHeader (AODVTYPE_RREP);
1617  packet->AddHeader (tHeader);
1618  // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
1619  Ipv4Address destination;
1620  if (iface.GetMask () == Ipv4Mask::GetOnes ())
1621  {
1622  destination = Ipv4Address ("255.255.255.255");
1623  }
1624  else
1625  {
1626  destination = iface.GetBroadcast ();
1627  }
1628  Time jitter = Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10)));
1629  Simulator::Schedule (jitter, &RoutingProtocol::SendTo, this , socket, packet, destination);
1630  }
1631 }
1632 
1633 void
1635 {
1636  NS_LOG_FUNCTION (this);
1637  QueueEntry queueEntry;
1638  while (m_queue.Dequeue (dst, queueEntry))
1639  {
1641  Ptr<Packet> p = ConstCast<Packet> (queueEntry.GetPacket ());
1642  if (p->RemovePacketTag (tag) &&
1643  tag.GetInterface() != -1 &&
1645  {
1646  NS_LOG_DEBUG ("Output device doesn't match. Dropped.");
1647  return;
1648  }
1650  Ipv4Header header = queueEntry.GetIpv4Header ();
1651  header.SetSource (route->GetSource ());
1652  header.SetTtl (header.GetTtl () + 1); // compensate extra TTL decrement by fake loopback routing
1653  ucb (route, p, header);
1654  }
1655 }
1656 
1657 void
1659 {
1660  NS_LOG_FUNCTION (this << nextHop);
1661  RerrHeader rerrHeader;
1662  std::vector<Ipv4Address> precursors;
1663  std::map<Ipv4Address, uint32_t> unreachable;
1664 
1665  RoutingTableEntry toNextHop;
1666  if (!m_routingTable.LookupRoute (nextHop, toNextHop))
1667  return;
1668  toNextHop.GetPrecursors (precursors);
1669  rerrHeader.AddUnDestination (nextHop, toNextHop.GetSeqNo ());
1670  m_routingTable.GetListOfDestinationWithNextHop (nextHop, unreachable);
1671  for (std::map<Ipv4Address, uint32_t>::const_iterator i = unreachable.begin (); i
1672  != unreachable.end ();)
1673  {
1674  if (!rerrHeader.AddUnDestination (i->first, i->second))
1675  {
1676  NS_LOG_LOGIC ("Send RERR message with maximum size.");
1677  TypeHeader typeHeader (AODVTYPE_RERR);
1678  Ptr<Packet> packet = Create<Packet> ();
1679  packet->AddHeader (rerrHeader);
1680  packet->AddHeader (typeHeader);
1681  SendRerrMessage (packet, precursors);
1682  rerrHeader.Clear ();
1683  }
1684  else
1685  {
1686  RoutingTableEntry toDst;
1687  m_routingTable.LookupRoute (i->first, toDst);
1688  toDst.GetPrecursors (precursors);
1689  ++i;
1690  }
1691  }
1692  if (rerrHeader.GetDestCount () != 0)
1693  {
1694  TypeHeader typeHeader (AODVTYPE_RERR);
1695  Ptr<Packet> packet = Create<Packet> ();
1696  packet->AddHeader (rerrHeader);
1697  packet->AddHeader (typeHeader);
1698  SendRerrMessage (packet, precursors);
1699  }
1700  unreachable.insert (std::make_pair (nextHop, toNextHop.GetSeqNo ()));
1702 }
1703 
1704 void
1706  uint32_t dstSeqNo, Ipv4Address origin)
1707 {
1708  NS_LOG_FUNCTION (this);
1709  // A node SHOULD NOT originate more than RERR_RATELIMIT RERR messages per second.
1710  if (m_rerrCount == RerrRateLimit)
1711  {
1712  // Just make sure that the RerrRateLimit timer is running and will expire
1714  // discard the packet and return
1715  NS_LOG_LOGIC ("RerrRateLimit reached at " << Simulator::Now ().GetSeconds () << " with timer delay left "
1717  << "; suppressing RERR");
1718  return;
1719  }
1720  RerrHeader rerrHeader;
1721  rerrHeader.AddUnDestination (dst, dstSeqNo);
1722  RoutingTableEntry toOrigin;
1723  Ptr<Packet> packet = Create<Packet> ();
1724  packet->AddHeader (rerrHeader);
1725  packet->AddHeader (TypeHeader (AODVTYPE_RERR));
1726  if (m_routingTable.LookupValidRoute (origin, toOrigin))
1727  {
1729  toOrigin.GetInterface ());
1730  NS_ASSERT (socket);
1731  NS_LOG_LOGIC ("Unicast RERR to the source of the data transmission");
1732  socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), AODV_PORT));
1733  }
1734  else
1735  {
1736  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator i =
1737  m_socketAddresses.begin (); i != m_socketAddresses.end (); ++i)
1738  {
1739  Ptr<Socket> socket = i->first;
1740  Ipv4InterfaceAddress iface = i->second;
1741  NS_ASSERT (socket);
1742  NS_LOG_LOGIC ("Broadcast RERR message from interface " << iface.GetLocal ());
1743  // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
1744  Ipv4Address destination;
1745  if (iface.GetMask () == Ipv4Mask::GetOnes ())
1746  {
1747  destination = Ipv4Address ("255.255.255.255");
1748  }
1749  else
1750  {
1751  destination = iface.GetBroadcast ();
1752  }
1753  socket->SendTo (packet, 0, InetSocketAddress (destination, AODV_PORT));
1754  }
1755  }
1756 }
1757 
1758 void
1759 RoutingProtocol::SendRerrMessage (Ptr<Packet> packet, std::vector<Ipv4Address> precursors)
1760 {
1761  NS_LOG_FUNCTION (this);
1762 
1763  if (precursors.empty ())
1764  {
1765  NS_LOG_LOGIC ("No precursors");
1766  return;
1767  }
1768  // A node SHOULD NOT originate more than RERR_RATELIMIT RERR messages per second.
1769  if (m_rerrCount == RerrRateLimit)
1770  {
1771  // Just make sure that the RerrRateLimit timer is running and will expire
1773  // discard the packet and return
1774  NS_LOG_LOGIC ("RerrRateLimit reached at " << Simulator::Now ().GetSeconds () << " with timer delay left "
1776  << "; suppressing RERR");
1777  return;
1778  }
1779  // If there is only one precursor, RERR SHOULD be unicast toward that precursor
1780  if (precursors.size () == 1)
1781  {
1782  RoutingTableEntry toPrecursor;
1783  if (m_routingTable.LookupValidRoute (precursors.front (), toPrecursor))
1784  {
1785  Ptr<Socket> socket = FindSocketWithInterfaceAddress (toPrecursor.GetInterface ());
1786  NS_ASSERT (socket);
1787  NS_LOG_LOGIC ("one precursor => unicast RERR to " << toPrecursor.GetDestination () << " from " << toPrecursor.GetInterface ().GetLocal ());
1788  Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, precursors.front ());
1789  m_rerrCount++;
1790  }
1791  return;
1792  }
1793 
1794  // Should only transmit RERR on those interfaces which have precursor nodes for the broken route
1795  std::vector<Ipv4InterfaceAddress> ifaces;
1796  RoutingTableEntry toPrecursor;
1797  for (std::vector<Ipv4Address>::const_iterator i = precursors.begin (); i != precursors.end (); ++i)
1798  {
1799  if (m_routingTable.LookupValidRoute (*i, toPrecursor) &&
1800  std::find (ifaces.begin (), ifaces.end (), toPrecursor.GetInterface ()) == ifaces.end ())
1801  {
1802  ifaces.push_back (toPrecursor.GetInterface ());
1803  }
1804  }
1805 
1806  for (std::vector<Ipv4InterfaceAddress>::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i)
1807  {
1809  NS_ASSERT (socket);
1810  NS_LOG_LOGIC ("Broadcast RERR message from interface " << i->GetLocal ());
1811  // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
1812  Ipv4Address destination;
1813  if (i->GetMask () == Ipv4Mask::GetOnes ())
1814  {
1815  destination = Ipv4Address ("255.255.255.255");
1816  }
1817  else
1818  {
1819  destination = i->GetBroadcast ();
1820  }
1821  Simulator::Schedule (Time (MilliSeconds (m_uniformRandomVariable->GetInteger (0, 10))), &RoutingProtocol::SendTo, this, socket, packet, destination);
1822  }
1823 }
1824 
1827 {
1828  NS_LOG_FUNCTION (this << addr);
1829  for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =
1830  m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
1831  {
1832  Ptr<Socket> socket = j->first;
1833  Ipv4InterfaceAddress iface = j->second;
1834  if (iface == addr)
1835  return socket;
1836  }
1837  Ptr<Socket> socket;
1838  return socket;
1839 }
1840 
1841 }
1842 }