diff --git a/RELEASE_NOTES b/RELEASE_NOTES index f54623990..dc978d706 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -75,6 +75,7 @@ since ns-3.10, in many cases referencing the Bugzilla bug number. - 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 ------------ diff --git a/src/aodv/model/aodv-routing-protocol.cc b/src/aodv/model/aodv-routing-protocol.cc index 106f81205..0c4b44995 100644 --- a/src/aodv/model/aodv-routing-protocol.cc +++ b/src/aodv/model/aodv-routing-protocol.cc @@ -96,6 +96,7 @@ struct DeferredRouteOutputTag : public Tag RoutingProtocol::RoutingProtocol () : RreqRetries (2), RreqRateLimit (10), + RerrRateLimit (10), ActiveRouteTimeout (Seconds (3)), NetDiameter (35), NodeTraversalTime (MilliSeconds (40)), @@ -121,8 +122,10 @@ RoutingProtocol::RoutingProtocol () : 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 @@ RoutingProtocol::GetTypeId (void) UintegerValue (10), MakeUintegerAccessor (&RoutingProtocol::RreqRateLimit), MakeUintegerChecker ()) + .AddAttribute ("RerrRateLimit", "Maximum number of RERR per second.", + UintegerValue (10), + MakeUintegerAccessor (&RoutingProtocol::RerrRateLimit), + MakeUintegerChecker ()) .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 @@ RoutingProtocol::Start () m_rreqRateLimitTimer.SetFunction (&RoutingProtocol::RreqRateLimitTimerExpire, this); m_rreqRateLimitTimer.Schedule (Seconds (1)); + + m_rerrRateLimitTimer.SetFunction (&RoutingProtocol::RerrRateLimitTimerExpire, + this); + m_rerrRateLimitTimer.Schedule (Seconds (1)); + } Ptr @@ -1493,6 +1505,14 @@ RoutingProtocol::RreqRateLimitTimerExpire () m_rreqRateLimitTimer.Schedule (Seconds (1)); } +void +RoutingProtocol::RerrRateLimitTimerExpire () +{ + NS_LOG_FUNCTION (this); + m_rerrCount = 0; + m_rerrRateLimitTimer.Schedule (Seconds (1)); +} + void RoutingProtocol::AckTimerExpire (Ipv4Address neighbor, Time blacklistTimeout) { @@ -1610,6 +1630,17 @@ RoutingProtocol::SendRerrWhenNoRouteToForward (Ipv4Address dst, 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 @@ RoutingProtocol::SendRerrMessage (Ptr packet, std::vector p 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 @@ RoutingProtocol::SendRerrMessage (Ptr packet, std::vector p 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 @@ RoutingProtocol::SendRerrMessage (Ptr packet, std::vector p destination = i->GetBroadcast (); } socket->SendTo (packet, 0, InetSocketAddress (destination, AODV_PORT)); + m_rerrCount++; } } diff --git a/src/aodv/model/aodv-routing-protocol.h b/src/aodv/model/aodv-routing-protocol.h index 9f1b63570..25a17af41 100644 --- a/src/aodv/model/aodv-routing-protocol.h +++ b/src/aodv/model/aodv-routing-protocol.h @@ -94,6 +94,7 @@ private: //\{ 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 @@ private: 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 @@ private: 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 m_addressReqTimer; /// Handle route discovery process