Issue #25   Replacing usage of TCP RTT estimator with a customized version

In the current commit, RTT estimator does not implement Karn's algorithm
and takes into account all RTT samples, including ambiguous samples from
retransmitted Interests.
diff --git a/apps/ndn-consumer.cc b/apps/ndn-consumer.cc
index 3a14e48..1b85cfb 100644
--- a/apps/ndn-consumer.cc
+++ b/apps/ndn-consumer.cc
@@ -33,6 +33,7 @@
 #include "ns3/ndn-interest.h"
 #include "ns3/ndn-content-object.h"
 #include "ns3/ndnSIM/utils/ndn-fw-hop-count-tag.h"
+#include "ns3/ndnSIM/utils/ndn-rtt-mean-deviation.h"
 
 #include <boost/ref.hpp>
 #include <boost/lexical_cast.hpp>
diff --git a/apps/ndn-consumer.h b/apps/ndn-consumer.h
index 970da4c..75705cd 100644
--- a/apps/ndn-consumer.h
+++ b/apps/ndn-consumer.h
@@ -27,8 +27,7 @@
 #include "ns3/ndn-name-components.h"
 #include "ns3/nstime.h"
 #include "ns3/data-rate.h"
-//#include "ns3/internet-module.h"
-#include "ns3/rtt-estimator.h"
+#include "ns3/ndn-rtt-estimator.h"
 
 #include <set>
 #include <map>
diff --git a/utils/ndn-rtt-estimator.cc b/utils/ndn-rtt-estimator.cc
new file mode 100644
index 0000000..93193d2
--- /dev/null
+++ b/utils/ndn-rtt-estimator.cc
@@ -0,0 +1,248 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// THIS IS A COPY OF rtt-estimator.cc from internet module with minor modifications
+
+// Ported from:
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley.  Georgia Tech, Spring 2002
+
+// Implements several variations of round trip time estimators
+
+#include <iostream>
+
+#include "ndn-rtt-estimator.h"
+#include "ns3/simulator.h"
+#include "ns3/double.h"
+#include "ns3/integer.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("ndn.RttEstimator");
+
+namespace ns3 {
+
+namespace ndn {
+
+NS_OBJECT_ENSURE_REGISTERED (RttEstimator);
+
+TypeId
+RttEstimator::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ndn::RttEstimator")
+    .SetParent<Object> ()
+    .AddAttribute ("MaxMultiplier",
+                   "Maximum RTO Multiplier",
+                   UintegerValue (64),
+                   MakeUintegerAccessor (&RttEstimator::m_maxMultiplier),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("InitialEstimation",
+                   "Initial RTT estimation",
+                   TimeValue (Seconds (1.0)),
+                   MakeTimeAccessor (&RttEstimator::m_initialEstimatedRtt),
+                   MakeTimeChecker ())
+    .AddAttribute ("MinRTO",
+                   "Minimum retransmit timeout value",
+                   TimeValue (Seconds (0.2)), // RFC2988 says min RTO=1 sec, but Linux uses 200ms. See http://www.postel.org/pipermail/end2end-interest/2004-November/004402.html
+                   MakeTimeAccessor (&RttEstimator::SetMinRto,
+                                     &RttEstimator::GetMinRto),
+                   MakeTimeChecker ())
+    .AddAttribute ("MaxRTO",
+                   "Maximum retransmit timeout value",
+                   TimeValue (Seconds (200.0)),
+                   MakeTimeAccessor (&RttEstimator::SetMaxRto,
+                                     &RttEstimator::GetMaxRto),
+                   MakeTimeChecker ())
+  ;
+  return tid;
+}
+
+void
+RttEstimator::SetMinRto (Time minRto)
+{
+  NS_LOG_FUNCTION (this << minRto);
+  m_minRto = minRto;
+}
+Time
+RttEstimator::GetMinRto (void) const
+{
+  return m_minRto;
+}
+
+void
+RttEstimator::SetMaxRto (Time maxRto)
+{
+  NS_LOG_FUNCTION (this << maxRto);
+  m_maxRto = maxRto;
+}
+Time
+RttEstimator::GetMaxRto (void) const
+{
+  return m_maxRto;
+}
+
+void
+RttEstimator::SetCurrentEstimate (Time estimate)
+{
+  NS_LOG_FUNCTION (this << estimate);
+  m_currentEstimatedRtt = estimate;
+}
+Time
+RttEstimator::GetCurrentEstimate (void) const
+{
+  return m_currentEstimatedRtt;
+}
+
+
+//RttHistory methods
+RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t)
+  : seq (s), count (c), time (t), retx (false)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+RttHistory::RttHistory (const RttHistory& h)
+  : seq (h.seq), count (h.count), time (h.time), retx (h.retx)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+// Base class methods
+
+RttEstimator::RttEstimator ()
+  : m_next (1),
+    m_nSamples (0),
+    m_multiplier (1),
+    m_history ()
+{
+  NS_LOG_FUNCTION (this);
+  //note next=1 everywhere since first segment will have sequence 1
+
+  // We need attributes initialized here, not later, so use the
+  // ConstructSelf() technique documented in the manual
+  ObjectBase::ConstructSelf (AttributeConstructionList ());
+  m_currentEstimatedRtt = m_initialEstimatedRtt;
+  NS_LOG_DEBUG ("Initialize m_currentEstimatedRtt to " << m_currentEstimatedRtt.GetSeconds () << " sec.");
+}
+
+RttEstimator::RttEstimator (const RttEstimator& c)
+  : Object (c), m_next (c.m_next),
+    m_maxMultiplier (c.m_maxMultiplier),
+    m_initialEstimatedRtt (c.m_initialEstimatedRtt),
+    m_currentEstimatedRtt (c.m_currentEstimatedRtt), m_minRto (c.m_minRto), m_maxRto (c.m_maxRto),
+    m_nSamples (c.m_nSamples), m_multiplier (c.m_multiplier),
+    m_history (c.m_history)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+RttEstimator::~RttEstimator ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void RttEstimator::SentSeq (SequenceNumber32 seq, uint32_t size)
+{
+  NS_LOG_FUNCTION (this << seq << size);
+  // Note that a particular sequence has been sent
+  if (seq == m_next)
+    { // This is the next expected one, just log at end
+      m_history.push_back (RttHistory (seq, size, Simulator::Now () ));
+      m_next = seq + SequenceNumber32 (size); // Update next expected
+    }
+  else
+    { // This is a retransmit, find in list and mark as re-tx
+      for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i)
+        {
+          if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count))))
+            { // Found it
+              i->retx = true;
+              // One final test..be sure this re-tx does not extend "next"
+              if ((seq + SequenceNumber32 (size)) > m_next)
+                {
+                  m_next = seq + SequenceNumber32 (size);
+                  i->count = ((seq + SequenceNumber32 (size)) - i->seq); // And update count in hist
+                }
+              break;
+            }
+        }
+    }
+}
+
+Time RttEstimator::AckSeq (SequenceNumber32 ackSeq)
+{
+  NS_LOG_FUNCTION (this << ackSeq);
+  // An ack has been received, calculate rtt and log this measurement
+  // Note we use a linear search (O(n)) for this since for the common
+  // case the ack'ed packet will be at the head of the list
+  Time m = Seconds (0.0);
+  if (m_history.size () == 0) return (m);    // No pending history, just exit
+  RttHistory& h = m_history.front ();
+  if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
+    { // Ok to use this sample
+      m = Simulator::Now () - h.time; // Elapsed time
+      Measurement (m);                // Log the measurement
+      ResetMultiplier ();             // Reset multiplier on valid measurement
+    }
+  // Now delete all ack history with seq <= ack
+  while(m_history.size () > 0)
+    {
+      RttHistory& h = m_history.front ();
+      if ((h.seq + SequenceNumber32 (h.count)) > ackSeq) break;               // Done removing
+      m_history.pop_front (); // Remove
+    }
+  return m;
+}
+
+void RttEstimator::ClearSent ()
+{
+  NS_LOG_FUNCTION (this);
+  // Clear all history entries
+  m_next = 1;
+  m_history.clear ();
+}
+
+void RttEstimator::IncreaseMultiplier ()
+{
+  NS_LOG_FUNCTION (this);
+  m_multiplier = (m_multiplier*2 < m_maxMultiplier) ? m_multiplier*2 : m_maxMultiplier;
+  NS_LOG_DEBUG ("Multiplier increased to " << m_multiplier);
+}
+
+void RttEstimator::ResetMultiplier ()
+{
+  NS_LOG_FUNCTION (this);
+  m_multiplier = 1;
+}
+
+void RttEstimator::Reset ()
+{
+  NS_LOG_FUNCTION (this);
+  // Reset to initial state
+  m_next = 1;
+  m_currentEstimatedRtt = m_initialEstimatedRtt;
+  m_history.clear ();         // Remove all info from the history
+  m_nSamples = 0;
+  ResetMultiplier ();
+}
+
+
+} // namespace ndn
+} // namespace ns3
diff --git a/utils/ndn-rtt-estimator.h b/utils/ndn-rtt-estimator.h
new file mode 100644
index 0000000..6bf6aa8
--- /dev/null
+++ b/utils/ndn-rtt-estimator.h
@@ -0,0 +1,172 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
+//
+
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley.  Georgia Tech, Spring 2002
+
+// THIS IS A COPY OF rtt-estimator.h from internet module with minor modifications
+
+#ifndef NDN_RTT_ESTIMATOR_H
+#define NDN_RTT_ESTIMATOR_H
+
+#include <deque>
+#include "ns3/sequence-number.h"
+#include "ns3/nstime.h"
+#include "ns3/object.h"
+
+namespace ns3 {
+
+namespace ndn {
+
+/**
+ * \ingroup tcp
+ *
+ * \brief Helper class to store RTT measurements
+ */
+class RttHistory {
+public:
+  RttHistory (SequenceNumber32 s, uint32_t c, Time t);
+  RttHistory (const RttHistory& h); // Copy constructor
+public:
+  SequenceNumber32  seq;  // First sequence number in packet sent
+  uint32_t        count;  // Number of bytes sent
+  Time            time;   // Time this one was sent
+  bool            retx;   // True if this has been retransmitted
+};
+
+typedef std::deque<RttHistory> RttHistory_t;
+
+/**
+ * \ingroup tcp
+ *
+ * \brief Base class for all RTT Estimators
+ */
+class RttEstimator : public Object {
+public:
+  static TypeId GetTypeId (void);
+
+  RttEstimator();
+  RttEstimator (const RttEstimator&);
+
+  virtual ~RttEstimator();
+
+  /**
+   * \brief Note that a particular sequence has been sent
+   * \param seq the packet sequence number.
+   * \param size the packet size.
+   */
+  virtual void SentSeq (SequenceNumber32 seq, uint32_t size);
+
+  /**
+   * \brief Note that a particular ack sequence has been received
+   * \param ackSeq the ack sequence number.
+   * \return The measured RTT for this ack.
+   */
+  virtual Time AckSeq (SequenceNumber32 ackSeq);
+
+  /**
+   * \brief Clear all history entries
+   */
+  virtual void ClearSent ();
+
+  /**
+   * \brief Add a new measurement to the estimator. Pure virtual function.
+   * \param t the new RTT measure.
+   */
+  virtual void  Measurement (Time t) = 0;
+
+  /**
+   * \brief Returns the estimated RTO. Pure virtual function.
+   * \return the estimated RTO.
+   */
+  virtual Time RetransmitTimeout () = 0;
+
+  virtual Ptr<RttEstimator> Copy () const = 0;
+
+  /**
+   * \brief Increase the estimation multiplier up to MaxMultiplier.
+   */
+  virtual void IncreaseMultiplier ();
+
+  /**
+   * \brief Resets the estimation multiplier to 1.
+   */
+  virtual void ResetMultiplier ();
+
+  /**
+   * \brief Resets the estimation to its initial state.
+   */
+  virtual void Reset ();
+
+  /**
+   * \brief Sets the Minimum RTO.
+   * \param minRto The minimum RTO returned by the estimator.
+   */
+  void SetMinRto (Time minRto);
+
+  /**
+   * \brief Get the Minimum RTO.
+   * \return The minimum RTO returned by the estimator.
+   */
+  Time GetMinRto (void) const;
+
+  /**
+   * \brief Sets the Maximum RTO.
+   * \param minRto The maximum RTO returned by the estimator.
+   */
+  void SetMaxRto (Time maxRto);
+
+  /**
+   * \brief Get the Maximum RTO.
+   * \return The maximum RTO returned by the estimator.
+   */
+  Time GetMaxRto (void) const;
+
+  /**
+   * \brief Sets the current RTT estimate (forcefully).
+   * \param estimate The current RTT estimate.
+   */
+  void SetCurrentEstimate (Time estimate);
+
+  /**
+   * \brief gets the current RTT estimate.
+   * \return The current RTT estimate.
+   */
+  Time GetCurrentEstimate (void) const;
+
+private:
+  SequenceNumber32 m_next;    // Next expected sequence to be sent
+  uint16_t m_maxMultiplier;
+  Time m_initialEstimatedRtt;
+
+protected:
+  Time         m_currentEstimatedRtt;     // Current estimate
+  Time         m_minRto;                  // minimum value of the timeout
+  Time         m_maxRto;                  // maximum value of the timeout
+  uint32_t     m_nSamples;                // Number of samples
+  uint16_t     m_multiplier;              // RTO Multiplier
+  RttHistory_t m_history;     // List of sent packet
+};
+
+} // namespace ndn
+
+} // namespace ns3
+
+#endif /* RTT_ESTIMATOR_H */
diff --git a/utils/ndn-rtt-mean-deviation.cc b/utils/ndn-rtt-mean-deviation.cc
new file mode 100644
index 0000000..8675479
--- /dev/null
+++ b/utils/ndn-rtt-mean-deviation.cc
@@ -0,0 +1,160 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//           (c) 2013 University of Arizona
+//           (c) 2013 University of California, Los Angeles
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
+//         Cheng Yi <yic@email.arizona.edu>
+//         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+//
+
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley.  Georgia Tech, Spring 2002
+
+#include "ndn-rtt-mean-deviation.h"
+#include "ns3/simulator.h"
+#include "ns3/double.h"
+#include "ns3/integer.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("ndn.RttMeanDeviation");
+
+namespace ns3 {
+namespace ndn {
+
+//---------------------------------------------------------------------------------
+// A modified version of Mean-Deviation Estimator optimized for NDN packet delivery
+
+NS_OBJECT_ENSURE_REGISTERED (RttMeanDeviation);
+
+TypeId
+RttMeanDeviation::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ndn::RttMeanDeviation")
+    .SetParent<RttEstimator> ()
+    .AddConstructor<RttMeanDeviation> ()
+    .AddAttribute ("Gain",
+                   "Gain used in estimating the RTT (smoothed RTT), must be 0 < Gain < 1",
+                   DoubleValue (0.125),
+                   MakeDoubleAccessor (&RttMeanDeviation::m_gain),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("Gain2",
+                   "Gain2 used in estimating the RTT (variance), must be 0 < Gain2 < 1",
+                   DoubleValue (0.25),
+                   MakeDoubleAccessor (&RttMeanDeviation::m_gain2),
+                   MakeDoubleChecker<double> ())
+  ;
+  return tid;
+}
+
+RttMeanDeviation::RttMeanDeviation() :
+  m_variance (0)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c)
+  : RttEstimator (c), m_gain (c.m_gain), m_gain2 (c.m_gain2), m_variance (c.m_variance)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void RttMeanDeviation::Measurement (Time m)
+{
+  NS_LOG_FUNCTION (this << m);
+  if (m_nSamples)
+    { // Not first
+      Time err (m - m_currentEstimatedRtt);
+      double gErr = err.ToDouble (Time::S) * m_gain;
+      m_currentEstimatedRtt += Time::FromDouble (gErr, Time::S);
+      Time difference = Abs (err) - m_variance;
+      NS_LOG_DEBUG ("m_variance += " << Time::FromDouble (difference.ToDouble (Time::S) * m_gain2, Time::S));
+      m_variance += Time::FromDouble (difference.ToDouble (Time::S) * m_gain2, Time::S);
+    }
+  else
+    { // First sample
+      m_currentEstimatedRtt = m;             // Set estimate to current
+      //variance = sample / 2;               // And variance to current / 2
+      // m_variance = m; // try this  why????
+      m_variance = Seconds (m.ToDouble (Time::S) / 2);
+      NS_LOG_DEBUG ("(first sample) m_variance += " << m);
+    }
+  m_nSamples++;
+}
+
+Time RttMeanDeviation::RetransmitTimeout ()
+{
+  NS_LOG_FUNCTION (this);
+
+  double retval = std::min (m_maxRto.ToDouble (Time::S),
+                            std::max (m_multiplier*m_minRto.ToDouble (Time::S),
+                                      m_multiplier*(m_currentEstimatedRtt.ToDouble (Time::S) + 4 * m_variance.ToDouble (Time::S))));
+
+  NS_LOG_DEBUG ("RetransmitTimeout:  return " << retval);
+
+  return Seconds (retval);
+}
+
+Ptr<RttEstimator> RttMeanDeviation::Copy () const
+{
+  NS_LOG_FUNCTION (this);
+  return CopyObject<RttMeanDeviation> (this);
+}
+
+void RttMeanDeviation::Reset ()
+{
+  NS_LOG_FUNCTION (this);
+  // Reset to initial state
+  m_variance = Seconds (0);
+  RttEstimator::Reset ();
+}
+
+void RttMeanDeviation::Gain (double g)
+{
+  NS_LOG_FUNCTION (this);
+  NS_ASSERT_MSG( (g > 0) && (g < 1), "RttMeanDeviation: Gain must be less than 1 and greater than 0" );
+  m_gain = g;
+}
+
+Time RttMeanDeviation::AckSeq (SequenceNumber32 ackSeq)
+{
+  NS_LOG_FUNCTION (this << ackSeq);
+  // An ack has been received, calculate rtt and log this measurement
+  // Note we use a linear search (O(n)) for this since for the common
+  // case the ack'ed packet will be at the head of the list
+  Time m = Seconds (0.0);
+  if (m_history.size () == 0) return (m);    // No pending history, just exit
+
+  for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i)
+  {
+      if (ackSeq == i->seq)
+      { // Found it
+          m = Simulator::Now () - i->time;// Elapsed time
+          Measurement (m);                // Log the measurement
+          ResetMultiplier ();             // Reset multiplier on valid measurement
+          m_history.erase(i);
+          break;
+      }
+  }
+
+  return m;
+}
+
+} // namespace ndn
+} // namespace ns3
+
diff --git a/utils/ndn-rtt-mean-deviation.h b/utils/ndn-rtt-mean-deviation.h
new file mode 100644
index 0000000..7ceecce
--- /dev/null
+++ b/utils/ndn-rtt-mean-deviation.h
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//           (c) 2013 University of Arizona
+//           (c) 2013 University of California, Los Angeles
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: Rajib Bhattacharjea<raj.b@gatech.edu>
+//         Cheng Yi <yic@email.arizona.edu>
+//         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+//
+
+// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// George F. Riley.  Georgia Tech, Spring 2002
+
+
+#ifndef NDN_RTT_MEAN_DEVIATION_H
+#define NDN_RTT_MEAN_DEVIATION_H
+
+#include <ns3/ndnSIM/utils/ndn-rtt-estimator.h>
+
+namespace ns3 {
+namespace ndn {
+
+/**
+ * \ingroup ndn
+ *
+ * \brief The modified version of "Mean--Deviation" RTT estimator, as discussed by Van Jacobson that better suits NDN communication model
+ *
+ * This class implements the "Mean--Deviation" RTT estimator, as discussed
+ * by Van Jacobson and Michael J. Karels, in
+ * "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
+ *
+ */
+class RttMeanDeviation : public RttEstimator {
+public:
+  static TypeId GetTypeId (void);
+
+  RttMeanDeviation ();
+  RttMeanDeviation (const RttMeanDeviation&);
+
+  Time AckSeq (SequenceNumber32 ackSeq);
+  void Measurement (Time measure);
+  Time RetransmitTimeout ();
+  Ptr<RttEstimator> Copy () const;
+  void Reset ();
+  void Gain (double g);
+
+private:
+  double       m_gain;       // Filter gain
+  double       m_gain2;      // Filter gain
+  Time         m_variance;   // Current variance
+};
+
+} // namespace ndn
+} // namespace ns3
+
+#endif // NDN_RTT_MEAN_DEVIATION
diff --git a/wscript b/wscript
index ae00638..835cdaf 100644
--- a/wscript
+++ b/wscript
@@ -128,6 +128,7 @@
 
         # "utils/batches.h",
         "utils/ndn-limits.h",
+        "utils/ndn-rtt-estimator.h",
         # "utils/weights-path-stretch-tag.h",
 
         ]