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/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
+