bug 1042: AODV RERR implosion (missing RERR_RATELIMIT)
authorElena Buchatskaya <sunnmy@iitp.ru>
Thu, 12 May 2011 23:10:46 -0700
changeset 7159 009cd4e1b486
parent 7158 4fe055d32d78
child 7160 4082270126b5
bug 1042: AODV RERR implosion (missing RERR_RATELIMIT)
RELEASE_NOTES
src/aodv/model/aodv-routing-protocol.cc
src/aodv/model/aodv-routing-protocol.h
--- a/RELEASE_NOTES	Thu May 12 22:47:31 2011 -0700
+++ b/RELEASE_NOTES	Thu May 12 23:10:46 2011 -0700
@@ -75,6 +75,7 @@
    - bug 1056 - CSMA: padding not handled correctly for LLC encapsulation
    - bug 1058 - documentation help to avoid InternetStackHelper pitfall
    - bug 1054 - ipv6 InternetStackHelper EnablePcapIpv6All() broken
+   - bug 1042 - AODV RERR implosion (missing RERR_RATELIMIT) 
 
 Known issues
 ------------
--- a/src/aodv/model/aodv-routing-protocol.cc	Thu May 12 22:47:31 2011 -0700
+++ b/src/aodv/model/aodv-routing-protocol.cc	Thu May 12 23:10:46 2011 -0700
@@ -96,6 +96,7 @@
 RoutingProtocol::RoutingProtocol () :
   RreqRetries (2),
   RreqRateLimit (10),
+  RerrRateLimit (10),
   ActiveRouteTimeout (Seconds (3)),
   NetDiameter (35),
   NodeTraversalTime (MilliSeconds (40)),
@@ -121,8 +122,10 @@
   m_dpd (PathDiscoveryTime),
   m_nb(HelloInterval),
   m_rreqCount (0),
+  m_rerrCount (0),
   m_htimer (Timer::CANCEL_ON_DESTROY),
-  m_rreqRateLimitTimer (Timer::CANCEL_ON_DESTROY)
+  m_rreqRateLimitTimer (Timer::CANCEL_ON_DESTROY),
+  m_rerrRateLimitTimer (Timer::CANCEL_ON_DESTROY)
 {
   if (EnableHello)
     {
@@ -148,6 +151,10 @@
                      UintegerValue (10),
                      MakeUintegerAccessor (&RoutingProtocol::RreqRateLimit),
                      MakeUintegerChecker<uint32_t> ())
+      .AddAttribute ("RerrRateLimit", "Maximum number of RERR per second.",
+                     UintegerValue (10),
+                     MakeUintegerAccessor (&RoutingProtocol::RerrRateLimit),
+                     MakeUintegerChecker<uint32_t> ())
       .AddAttribute ("NodeTraversalTime", "Conservative estimate of the average one hop traversal time for packets and should include "
                      "queuing delays, interrupt processing times and transfer times.",
                      TimeValue (MilliSeconds (40)),
@@ -278,6 +285,11 @@
   m_rreqRateLimitTimer.SetFunction (&RoutingProtocol::RreqRateLimitTimerExpire,
       this);
   m_rreqRateLimitTimer.Schedule (Seconds (1));
+
+  m_rerrRateLimitTimer.SetFunction (&RoutingProtocol::RerrRateLimitTimerExpire,
+      this);
+  m_rerrRateLimitTimer.Schedule (Seconds (1));
+
 }
 
 Ptr<Ipv4Route>
@@ -1494,6 +1506,14 @@
 }
 
 void
+RoutingProtocol::RerrRateLimitTimerExpire ()
+{
+  NS_LOG_FUNCTION (this);
+  m_rerrCount = 0;
+  m_rerrRateLimitTimer.Schedule (Seconds (1));
+}
+
+void
 RoutingProtocol::AckTimerExpire (Ipv4Address neighbor, Time blacklistTimeout)
 {
   NS_LOG_FUNCTION (this);
@@ -1610,6 +1630,17 @@
     uint32_t dstSeqNo, Ipv4Address origin)
 {
   NS_LOG_FUNCTION (this);
+  // A node SHOULD NOT originate more than RERR_RATELIMIT RERR messages per second.
+  if (m_rerrCount == RerrRateLimit)
+    {
+      // Just make sure that the RerrRateLimit timer is running and will expire
+      NS_ASSERT (m_rerrRateLimitTimer.IsRunning ());
+      // discard the packet and return
+      NS_LOG_LOGIC ("RerrRateLimit reached at " << Simulator::Now ().GetSeconds () << " with timer delay left " 
+                    << m_rerrRateLimitTimer.GetDelayLeft ().GetSeconds ()
+                    << "; suppressing RERR");
+      return;
+    }
   RerrHeader rerrHeader;
   rerrHeader.AddUnDestination (dst, dstSeqNo);
   RoutingTableEntry toOrigin;
@@ -1658,6 +1689,17 @@
       NS_LOG_LOGIC ("No precursors");
       return;
     }
+  // A node SHOULD NOT originate more than RERR_RATELIMIT RERR messages per second.
+  if (m_rerrCount == RerrRateLimit)
+    {
+      // Just make sure that the RerrRateLimit timer is running and will expire
+      NS_ASSERT (m_rerrRateLimitTimer.IsRunning ());
+      // discard the packet and return
+      NS_LOG_LOGIC ("RerrRateLimit reached at " << Simulator::Now ().GetSeconds () << " with timer delay left " 
+                    << m_rerrRateLimitTimer.GetDelayLeft ().GetSeconds ()
+                    << "; suppressing RERR");
+      return;
+    }
   // If there is only one precursor, RERR SHOULD be unicast toward that precursor
   if (precursors.size () == 1)
     {
@@ -1668,6 +1710,7 @@
           NS_ASSERT (socket);
           NS_LOG_LOGIC ("one precursor => unicast RERR to " << toPrecursor.GetDestination() << " from " << toPrecursor.GetInterface ().GetLocal ());
           socket->SendTo (packet, 0, InetSocketAddress (precursors.front (), AODV_PORT));
+          m_rerrCount++;
         }
       return;
     }
@@ -1700,6 +1743,7 @@
           destination = i->GetBroadcast ();
         }
       socket->SendTo (packet, 0, InetSocketAddress (destination, AODV_PORT));
+      m_rerrCount++;
     }
 }
 
--- a/src/aodv/model/aodv-routing-protocol.h	Thu May 12 22:47:31 2011 -0700
+++ b/src/aodv/model/aodv-routing-protocol.h	Thu May 12 23:10:46 2011 -0700
@@ -94,6 +94,7 @@
   //\{
   uint32_t RreqRetries;             ///< Maximum number of retransmissions of RREQ with TTL = NetDiameter to discover a route
   uint16_t RreqRateLimit;           ///< Maximum number of RREQ per second.
+  uint16_t RerrRateLimit;           ///< Maximum number of REER per second.
   Time ActiveRouteTimeout;          ///< Period of time during which the route is considered to be valid.
   uint32_t NetDiameter;             ///< Net diameter measures the maximum possible number of hops between two nodes in the network
   /**
@@ -153,6 +154,8 @@
   Neighbors m_nb;
   /// Number of RREQs used for RREQ rate control
   uint16_t m_rreqCount;
+  /// Number of RERRs used for RERR rate control
+  uint16_t m_rerrCount;
 
 private:
   /// Start protocol operation
@@ -241,6 +244,10 @@
   Timer m_rreqRateLimitTimer;
   /// Reset RREQ count and schedule RREQ rate limit timer with delay 1 sec.
   void RreqRateLimitTimerExpire ();
+  /// RERR rate limit timer
+  Timer m_rerrRateLimitTimer;
+  /// Reset RERR count and schedule RERR rate limit timer with delay 1 sec.
+  void RerrRateLimitTimerExpire ();
   /// Map IP address + RREQ timer.
   std::map<Ipv4Address, Timer> m_addressReqTimer;
   /// Handle route discovery process