Bug 1405 - RttEstimator improvements
authorTommaso Pecorella <tommaso.pecorella@unifi.it>
Fri, 30 Jan 2015 22:29:30 +0100
changeset 11190 f0458968b67d
parent 11189 c17091a7616e
child 11191 b3d1a0cd0aa2
Bug 1405 - RttEstimator improvements
RELEASE_NOTES
src/internet/bindings/modulegen__gcc_ILP32.py
src/internet/bindings/modulegen__gcc_LP64.py
src/internet/model/rtt-estimator.cc
src/internet/model/rtt-estimator.h
src/internet/model/tcp-newreno.cc
src/internet/model/tcp-reno.cc
src/internet/model/tcp-socket-base.cc
src/internet/model/tcp-socket-base.h
src/internet/model/tcp-tahoe.cc
src/internet/model/tcp-westwood.cc
src/internet/test/rtt-test.cc
--- a/RELEASE_NOTES	Fri Jan 30 11:52:16 2015 -0800
+++ b/RELEASE_NOTES	Fri Jan 30 22:29:30 2015 +0100
@@ -39,6 +39,7 @@
 
 Bugs fixed
 ----------
+- Bug 1405 - RttEstimator improvements
 - Bug 1551 - NS_LOG_COMPONENT_DEFINE inside or outside of ns3 namespace?
 - Bug 1726 - WiFi Minstrel rate control algorithm doesn't save state
 - Bug 1758 - Yans and Nist error rate models for 5/6 code rate 802.11n HT
@@ -74,7 +75,6 @@
 - Bug 2047 - Ipv6EndPointDemux::Lookup may crash
 - Bug 2049 - CQI feedback should always use the same calculation method
 
-
 Known issues
 ------------
 
--- a/src/internet/bindings/modulegen__gcc_ILP32.py	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/bindings/modulegen__gcc_ILP32.py	Fri Jan 30 22:29:30 2015 +0100
@@ -216,7 +216,7 @@
     module.add_class('RipNgRoutingTableEntry', parent=root_module['ns3::Ipv6RoutingTableEntry'])
     ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::Status_e [enumeration]
     module.add_enum('Status_e', ['RIPNG_VALID', 'RIPNG_INVALID'], outer_class=root_module['ns3::RipNgRoutingTableEntry'])
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory [class]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory [class]
     module.add_class('RttHistory')
     ## global-route-manager-impl.h (module 'internet'): ns3::SPFVertex [class]
     module.add_class('SPFVertex')
@@ -4513,17 +4513,17 @@
     return
 
 def register_Ns3RttHistory_methods(root_module, cls):
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::SequenceNumber32 s, uint32_t c, ns3::Time t) [constructor]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::SequenceNumber32 s, uint32_t c, ns3::Time t) [constructor]
     cls.add_constructor([param('ns3::SequenceNumber32', 's'), param('uint32_t', 'c'), param('ns3::Time', 't')])
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::RttHistory const & h) [copy constructor]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::RttHistory const & h) [copy constructor]
     cls.add_constructor([param('ns3::RttHistory const &', 'h')])
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::count [variable]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::count [variable]
     cls.add_instance_attribute('count', 'uint32_t', is_const=False)
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::retx [variable]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::retx [variable]
     cls.add_instance_attribute('retx', 'bool', is_const=False)
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::seq [variable]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::seq [variable]
     cls.add_instance_attribute('seq', 'ns3::SequenceNumber32', is_const=False)
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::time [variable]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::time [variable]
     cls.add_instance_attribute('time', 'ns3::Time', is_const=False)
     return
 
@@ -5328,7 +5328,6 @@
     return
 
 def register_Ns3Int64x64_t_methods(root_module, cls):
-    cls.add_binary_comparison_operator('<=')
     cls.add_binary_comparison_operator('!=')
     cls.add_inplace_numeric_operator('+=', param('ns3::int64x64_t const &', u'right'))
     cls.add_binary_numeric_operator('*', root_module['ns3::int64x64_t'], root_module['ns3::int64x64_t'], param('ns3::int64x64_t const &', u'right'))
@@ -5342,6 +5341,7 @@
     cls.add_inplace_numeric_operator('-=', param('ns3::int64x64_t const &', u'right'))
     cls.add_inplace_numeric_operator('/=', param('ns3::int64x64_t const &', u'right'))
     cls.add_output_stream_operator()
+    cls.add_binary_comparison_operator('<=')
     cls.add_binary_comparison_operator('==')
     cls.add_binary_comparison_operator('>=')
     ## int64x64-double.h (module 'core'): ns3::int64x64_t::int64x64_t() [constructor]
@@ -7964,23 +7964,13 @@
     cls.add_constructor([])
     ## rtt-estimator.h (module 'internet'): ns3::RttEstimator::RttEstimator(ns3::RttEstimator const & r) [copy constructor]
     cls.add_constructor([param('ns3::RttEstimator const &', 'r')])
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::ClearSent() [member function]
-    cls.add_method('ClearSent', 
-                   'void', 
-                   [], 
-                   is_virtual=True)
     ## rtt-estimator.h (module 'internet'): ns3::Ptr<ns3::RttEstimator> ns3::RttEstimator::Copy() const [member function]
     cls.add_method('Copy', 
                    'ns3::Ptr< ns3::RttEstimator >', 
                    [], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::EstimateRttFromSeq(ns3::SequenceNumber32 ackSeq) [member function]
-    cls.add_method('EstimateRttFromSeq', 
-                   'ns3::Time', 
-                   [param('ns3::SequenceNumber32', 'ackSeq')], 
-                   is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetCurrentEstimate() const [member function]
-    cls.add_method('GetCurrentEstimate', 
+    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetEstimate() const [member function]
+    cls.add_method('GetEstimate', 
                    'ns3::Time', 
                    [], 
                    is_const=True)
@@ -7989,9 +7979,9 @@
                    'ns3::TypeId', 
                    [], 
                    is_const=True, is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetMinRto() const [member function]
-    cls.add_method('GetMinRto', 
-                   'ns3::Time', 
+    ## rtt-estimator.h (module 'internet'): uint32_t ns3::RttEstimator::GetNSamples() const [member function]
+    cls.add_method('GetNSamples', 
+                   'uint32_t', 
                    [], 
                    is_const=True)
     ## rtt-estimator.h (module 'internet'): static ns3::TypeId ns3::RttEstimator::GetTypeId() [member function]
@@ -7999,11 +7989,11 @@
                    'ns3::TypeId', 
                    [], 
                    is_static=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::IncreaseMultiplier() [member function]
-    cls.add_method('IncreaseMultiplier', 
-                   'void', 
-                   [], 
-                   is_virtual=True)
+    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetVariation() const [member function]
+    cls.add_method('GetVariation', 
+                   'ns3::Time', 
+                   [], 
+                   is_const=True)
     ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::Measurement(ns3::Time t) [member function]
     cls.add_method('Measurement', 
                    'void', 
@@ -8014,29 +8004,6 @@
                    'void', 
                    [], 
                    is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::ResetMultiplier() [member function]
-    cls.add_method('ResetMultiplier', 
-                   'void', 
-                   [], 
-                   is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::RetransmitTimeout() [member function]
-    cls.add_method('RetransmitTimeout', 
-                   'ns3::Time', 
-                   [], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::SentSeq(ns3::SequenceNumber32 seq, uint32_t size) [member function]
-    cls.add_method('SentSeq', 
-                   'void', 
-                   [param('ns3::SequenceNumber32', 'seq'), param('uint32_t', 'size')], 
-                   is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::SetCurrentEstimate(ns3::Time estimate) [member function]
-    cls.add_method('SetCurrentEstimate', 
-                   'void', 
-                   [param('ns3::Time', 'estimate')])
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::SetMinRto(ns3::Time minRto) [member function]
-    cls.add_method('SetMinRto', 
-                   'void', 
-                   [param('ns3::Time', 'minRto')])
     return
 
 def register_Ns3RttMeanDeviation_methods(root_module, cls):
@@ -8049,10 +8016,6 @@
                    'ns3::Ptr< ns3::RttEstimator >', 
                    [], 
                    is_const=True, is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttMeanDeviation::Gain(double g) [member function]
-    cls.add_method('Gain', 
-                   'void', 
-                   [param('double', 'g')])
     ## rtt-estimator.h (module 'internet'): ns3::TypeId ns3::RttMeanDeviation::GetInstanceTypeId() const [member function]
     cls.add_method('GetInstanceTypeId', 
                    'ns3::TypeId', 
@@ -8073,11 +8036,6 @@
                    'void', 
                    [], 
                    is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttMeanDeviation::RetransmitTimeout() [member function]
-    cls.add_method('RetransmitTimeout', 
-                   'ns3::Time', 
-                   [], 
-                   is_virtual=True)
     return
 
 def register_Ns3SequentialRandomVariable_methods(root_module, cls):
@@ -9389,11 +9347,21 @@
                    'int', 
                    [param('ns3::Address const &', 'address')], 
                    is_virtual=True)
+    ## tcp-socket-base.h (module 'internet'): ns3::Time ns3::TcpSocketBase::GetClockGranularity() const [member function]
+    cls.add_method('GetClockGranularity', 
+                   'ns3::Time', 
+                   [], 
+                   is_const=True)
     ## tcp-socket-base.h (module 'internet'): ns3::Socket::SocketErrno ns3::TcpSocketBase::GetErrno() const [member function]
     cls.add_method('GetErrno', 
                    'ns3::Socket::SocketErrno', 
                    [], 
                    is_const=True, is_virtual=True)
+    ## tcp-socket-base.h (module 'internet'): ns3::Time ns3::TcpSocketBase::GetMinRto() const [member function]
+    cls.add_method('GetMinRto', 
+                   'ns3::Time', 
+                   [], 
+                   is_const=True)
     ## tcp-socket-base.h (module 'internet'): ns3::Ptr<ns3::Node> ns3::TcpSocketBase::GetNode() const [member function]
     cls.add_method('GetNode', 
                    'ns3::Ptr< ns3::Node >', 
@@ -9449,6 +9417,14 @@
                    'int', 
                    [param('ns3::Ptr< ns3::Packet >', 'p'), param('uint32_t', 'flags'), param('ns3::Address const &', 'toAddress')], 
                    is_virtual=True)
+    ## tcp-socket-base.h (module 'internet'): void ns3::TcpSocketBase::SetClockGranularity(ns3::Time clockGranularity) [member function]
+    cls.add_method('SetClockGranularity', 
+                   'void', 
+                   [param('ns3::Time', 'clockGranularity')])
+    ## tcp-socket-base.h (module 'internet'): void ns3::TcpSocketBase::SetMinRto(ns3::Time minRto) [member function]
+    cls.add_method('SetMinRto', 
+                   'void', 
+                   [param('ns3::Time', 'minRto')])
     ## tcp-socket-base.h (module 'internet'): void ns3::TcpSocketBase::SetNode(ns3::Ptr<ns3::Node> node) [member function]
     cls.add_method('SetNode', 
                    'void', 
@@ -10110,7 +10086,6 @@
     return
 
 def register_Ns3Time_methods(root_module, cls):
-    cls.add_binary_comparison_operator('<=')
     cls.add_binary_comparison_operator('!=')
     cls.add_inplace_numeric_operator('+=', param('ns3::Time const &', u'right'))
     cls.add_binary_numeric_operator('*', root_module['ns3::Time'], root_module['ns3::Time'], param('int64_t const &', u'right'))
@@ -10121,6 +10096,7 @@
     cls.add_binary_comparison_operator('>')
     cls.add_inplace_numeric_operator('-=', param('ns3::Time const &', u'right'))
     cls.add_output_stream_operator()
+    cls.add_binary_comparison_operator('<=')
     cls.add_binary_comparison_operator('==')
     cls.add_binary_comparison_operator('>=')
     ## nstime.h (module 'core'): ns3::Time::Time() [constructor]
--- a/src/internet/bindings/modulegen__gcc_LP64.py	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/bindings/modulegen__gcc_LP64.py	Fri Jan 30 22:29:30 2015 +0100
@@ -216,7 +216,7 @@
     module.add_class('RipNgRoutingTableEntry', parent=root_module['ns3::Ipv6RoutingTableEntry'])
     ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::Status_e [enumeration]
     module.add_enum('Status_e', ['RIPNG_VALID', 'RIPNG_INVALID'], outer_class=root_module['ns3::RipNgRoutingTableEntry'])
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory [class]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory [class]
     module.add_class('RttHistory')
     ## global-route-manager-impl.h (module 'internet'): ns3::SPFVertex [class]
     module.add_class('SPFVertex')
@@ -4513,17 +4513,17 @@
     return
 
 def register_Ns3RttHistory_methods(root_module, cls):
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::SequenceNumber32 s, uint32_t c, ns3::Time t) [constructor]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::SequenceNumber32 s, uint32_t c, ns3::Time t) [constructor]
     cls.add_constructor([param('ns3::SequenceNumber32', 's'), param('uint32_t', 'c'), param('ns3::Time', 't')])
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::RttHistory const & h) [copy constructor]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::RttHistory const & h) [copy constructor]
     cls.add_constructor([param('ns3::RttHistory const &', 'h')])
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::count [variable]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::count [variable]
     cls.add_instance_attribute('count', 'uint32_t', is_const=False)
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::retx [variable]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::retx [variable]
     cls.add_instance_attribute('retx', 'bool', is_const=False)
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::seq [variable]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::seq [variable]
     cls.add_instance_attribute('seq', 'ns3::SequenceNumber32', is_const=False)
-    ## rtt-estimator.h (module 'internet'): ns3::RttHistory::time [variable]
+    ## tcp-socket-base.h (module 'internet'): ns3::RttHistory::time [variable]
     cls.add_instance_attribute('time', 'ns3::Time', is_const=False)
     return
 
@@ -5328,7 +5328,6 @@
     return
 
 def register_Ns3Int64x64_t_methods(root_module, cls):
-    cls.add_binary_comparison_operator('<=')
     cls.add_binary_comparison_operator('!=')
     cls.add_inplace_numeric_operator('+=', param('ns3::int64x64_t const &', u'right'))
     cls.add_binary_numeric_operator('*', root_module['ns3::int64x64_t'], root_module['ns3::int64x64_t'], param('ns3::int64x64_t const &', u'right'))
@@ -5342,6 +5341,7 @@
     cls.add_inplace_numeric_operator('-=', param('ns3::int64x64_t const &', u'right'))
     cls.add_inplace_numeric_operator('/=', param('ns3::int64x64_t const &', u'right'))
     cls.add_output_stream_operator()
+    cls.add_binary_comparison_operator('<=')
     cls.add_binary_comparison_operator('==')
     cls.add_binary_comparison_operator('>=')
     ## int64x64-double.h (module 'core'): ns3::int64x64_t::int64x64_t() [constructor]
@@ -7964,23 +7964,13 @@
     cls.add_constructor([])
     ## rtt-estimator.h (module 'internet'): ns3::RttEstimator::RttEstimator(ns3::RttEstimator const & r) [copy constructor]
     cls.add_constructor([param('ns3::RttEstimator const &', 'r')])
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::ClearSent() [member function]
-    cls.add_method('ClearSent', 
-                   'void', 
-                   [], 
-                   is_virtual=True)
     ## rtt-estimator.h (module 'internet'): ns3::Ptr<ns3::RttEstimator> ns3::RttEstimator::Copy() const [member function]
     cls.add_method('Copy', 
                    'ns3::Ptr< ns3::RttEstimator >', 
                    [], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::EstimateRttFromSeq(ns3::SequenceNumber32 ackSeq) [member function]
-    cls.add_method('EstimateRttFromSeq', 
-                   'ns3::Time', 
-                   [param('ns3::SequenceNumber32', 'ackSeq')], 
-                   is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetCurrentEstimate() const [member function]
-    cls.add_method('GetCurrentEstimate', 
+    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetEstimate() const [member function]
+    cls.add_method('GetEstimate', 
                    'ns3::Time', 
                    [], 
                    is_const=True)
@@ -7989,9 +7979,9 @@
                    'ns3::TypeId', 
                    [], 
                    is_const=True, is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetMinRto() const [member function]
-    cls.add_method('GetMinRto', 
-                   'ns3::Time', 
+    ## rtt-estimator.h (module 'internet'): uint32_t ns3::RttEstimator::GetNSamples() const [member function]
+    cls.add_method('GetNSamples', 
+                   'uint32_t', 
                    [], 
                    is_const=True)
     ## rtt-estimator.h (module 'internet'): static ns3::TypeId ns3::RttEstimator::GetTypeId() [member function]
@@ -7999,11 +7989,11 @@
                    'ns3::TypeId', 
                    [], 
                    is_static=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::IncreaseMultiplier() [member function]
-    cls.add_method('IncreaseMultiplier', 
-                   'void', 
-                   [], 
-                   is_virtual=True)
+    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetVariation() const [member function]
+    cls.add_method('GetVariation', 
+                   'ns3::Time', 
+                   [], 
+                   is_const=True)
     ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::Measurement(ns3::Time t) [member function]
     cls.add_method('Measurement', 
                    'void', 
@@ -8014,29 +8004,6 @@
                    'void', 
                    [], 
                    is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::ResetMultiplier() [member function]
-    cls.add_method('ResetMultiplier', 
-                   'void', 
-                   [], 
-                   is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::RetransmitTimeout() [member function]
-    cls.add_method('RetransmitTimeout', 
-                   'ns3::Time', 
-                   [], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::SentSeq(ns3::SequenceNumber32 seq, uint32_t size) [member function]
-    cls.add_method('SentSeq', 
-                   'void', 
-                   [param('ns3::SequenceNumber32', 'seq'), param('uint32_t', 'size')], 
-                   is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::SetCurrentEstimate(ns3::Time estimate) [member function]
-    cls.add_method('SetCurrentEstimate', 
-                   'void', 
-                   [param('ns3::Time', 'estimate')])
-    ## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::SetMinRto(ns3::Time minRto) [member function]
-    cls.add_method('SetMinRto', 
-                   'void', 
-                   [param('ns3::Time', 'minRto')])
     return
 
 def register_Ns3RttMeanDeviation_methods(root_module, cls):
@@ -8049,10 +8016,6 @@
                    'ns3::Ptr< ns3::RttEstimator >', 
                    [], 
                    is_const=True, is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): void ns3::RttMeanDeviation::Gain(double g) [member function]
-    cls.add_method('Gain', 
-                   'void', 
-                   [param('double', 'g')])
     ## rtt-estimator.h (module 'internet'): ns3::TypeId ns3::RttMeanDeviation::GetInstanceTypeId() const [member function]
     cls.add_method('GetInstanceTypeId', 
                    'ns3::TypeId', 
@@ -8073,11 +8036,6 @@
                    'void', 
                    [], 
                    is_virtual=True)
-    ## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttMeanDeviation::RetransmitTimeout() [member function]
-    cls.add_method('RetransmitTimeout', 
-                   'ns3::Time', 
-                   [], 
-                   is_virtual=True)
     return
 
 def register_Ns3SequentialRandomVariable_methods(root_module, cls):
@@ -9389,11 +9347,21 @@
                    'int', 
                    [param('ns3::Address const &', 'address')], 
                    is_virtual=True)
+    ## tcp-socket-base.h (module 'internet'): ns3::Time ns3::TcpSocketBase::GetClockGranularity() const [member function]
+    cls.add_method('GetClockGranularity', 
+                   'ns3::Time', 
+                   [], 
+                   is_const=True)
     ## tcp-socket-base.h (module 'internet'): ns3::Socket::SocketErrno ns3::TcpSocketBase::GetErrno() const [member function]
     cls.add_method('GetErrno', 
                    'ns3::Socket::SocketErrno', 
                    [], 
                    is_const=True, is_virtual=True)
+    ## tcp-socket-base.h (module 'internet'): ns3::Time ns3::TcpSocketBase::GetMinRto() const [member function]
+    cls.add_method('GetMinRto', 
+                   'ns3::Time', 
+                   [], 
+                   is_const=True)
     ## tcp-socket-base.h (module 'internet'): ns3::Ptr<ns3::Node> ns3::TcpSocketBase::GetNode() const [member function]
     cls.add_method('GetNode', 
                    'ns3::Ptr< ns3::Node >', 
@@ -9449,6 +9417,14 @@
                    'int', 
                    [param('ns3::Ptr< ns3::Packet >', 'p'), param('uint32_t', 'flags'), param('ns3::Address const &', 'toAddress')], 
                    is_virtual=True)
+    ## tcp-socket-base.h (module 'internet'): void ns3::TcpSocketBase::SetClockGranularity(ns3::Time clockGranularity) [member function]
+    cls.add_method('SetClockGranularity', 
+                   'void', 
+                   [param('ns3::Time', 'clockGranularity')])
+    ## tcp-socket-base.h (module 'internet'): void ns3::TcpSocketBase::SetMinRto(ns3::Time minRto) [member function]
+    cls.add_method('SetMinRto', 
+                   'void', 
+                   [param('ns3::Time', 'minRto')])
     ## tcp-socket-base.h (module 'internet'): void ns3::TcpSocketBase::SetNode(ns3::Ptr<ns3::Node> node) [member function]
     cls.add_method('SetNode', 
                    'void', 
@@ -10110,7 +10086,6 @@
     return
 
 def register_Ns3Time_methods(root_module, cls):
-    cls.add_binary_comparison_operator('<=')
     cls.add_binary_comparison_operator('!=')
     cls.add_inplace_numeric_operator('+=', param('ns3::Time const &', u'right'))
     cls.add_binary_numeric_operator('*', root_module['ns3::Time'], root_module['ns3::Time'], param('int64_t const &', u'right'))
@@ -10121,6 +10096,7 @@
     cls.add_binary_comparison_operator('>')
     cls.add_inplace_numeric_operator('-=', param('ns3::Time const &', u'right'))
     cls.add_output_stream_operator()
+    cls.add_binary_comparison_operator('<=')
     cls.add_binary_comparison_operator('==')
     cls.add_binary_comparison_operator('>=')
     ## nstime.h (module 'core'): ns3::Time::Time() [constructor]
--- a/src/internet/model/rtt-estimator.cc	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/model/rtt-estimator.cc	Fri Jan 30 22:29:30 2015 +0100
@@ -18,20 +18,18 @@
 // Author: Rajib Bhattacharjea<raj.b@gatech.edu>
 //
 
-
 // Ported from:
-// Georgia Tech Network Simulator - Round Trip Time Estimation Class
+// Georgia Tech Network Simulator - Round Trip Time Estimator Class
 // George F. Riley.  Georgia Tech, Spring 2002
 
-// Implements several variations of round trip time estimators
+// Base class allows variations of round trip time estimators to be
+// implemented
 
 #include <iostream>
+#include <cmath>
 
 #include "rtt-estimator.h"
-#include "ns3/simulator.h"
 #include "ns3/double.h"
-#include "ns3/integer.h"
-#include "ns3/uinteger.h"
 #include "ns3/log.h"
 
 namespace ns3 {
@@ -40,91 +38,56 @@
 
 NS_OBJECT_ENSURE_REGISTERED (RttEstimator);
 
+static const double TOLERANCE = 1e-6;
+
 TypeId 
 RttEstimator::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::RttEstimator")
     .SetParent<Object> ()
-    .AddAttribute ("MaxMultiplier", 
-                   "Maximum RTO Multiplier",
-                   UintegerValue (64),
-                   MakeUintegerAccessor (&RttEstimator::m_maxMultiplier),
-                   MakeUintegerChecker<uint16_t> ())
     .AddAttribute ("InitialEstimation", 
-                   "Initial RTT estimation",
+                   "Initial RTT estimate",
                    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 ())
   ;
   return tid;
 }
 
-void 
-RttEstimator::SetMinRto (Time minRto)
-{
-  NS_LOG_FUNCTION (this << minRto);
-  m_minRto = minRto;
-}
-Time 
-RttEstimator::GetMinRto (void) const
+Time
+RttEstimator::GetEstimate (void) const
 {
-  return m_minRto;
-}
-void 
-RttEstimator::SetCurrentEstimate (Time estimate)
-{
-  NS_LOG_FUNCTION (this << estimate);
-  m_currentEstimatedRtt = estimate;
-}
-Time 
-RttEstimator::GetCurrentEstimate (void) const
-{
-  return m_currentEstimatedRtt;
+  return m_estimatedRtt;
 }
 
-
-//RttHistory methods
-RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t)
-  : seq (s), count (c), time (t), retx (false)
+Time 
+RttEstimator::GetVariation (void) const
 {
-  NS_LOG_FUNCTION (this);
+  return m_estimatedVariation;
 }
 
-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_history (),
-    m_nSamples (0),
-    m_multiplier (1)
+  : m_nSamples (0)
 { 
   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.");
+  m_estimatedRtt = m_initialEstimatedRtt;
+  m_estimatedVariation = Time (0);
+  NS_LOG_DEBUG ("Initialize m_estimatedRtt to " << m_estimatedRtt.GetSeconds () << " sec.");
 }
 
 RttEstimator::RttEstimator (const RttEstimator& c)
-  : Object (c), m_next (c.m_next), m_history (c.m_history), 
-    m_maxMultiplier (c.m_maxMultiplier), 
+  : Object (c),
     m_initialEstimatedRtt (c.m_initialEstimatedRtt),
-    m_currentEstimatedRtt (c.m_currentEstimatedRtt), m_minRto (c.m_minRto),
-    m_nSamples (c.m_nSamples), m_multiplier (c.m_multiplier)
+    m_estimatedRtt (c.m_estimatedRtt),
+    m_estimatedVariation (c.m_estimatedVariation),
+    m_nSamples (c.m_nSamples)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -140,92 +103,20 @@
   return GetTypeId ();
 }
 
-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::EstimateRttFromSeq (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_estimatedRtt = m_initialEstimatedRtt;
+  m_estimatedVariation = Time (0);
   m_nSamples = 0;
-  ResetMultiplier ();
 }
 
-
+uint32_t 
+RttEstimator::GetNSamples (void) const
+{
+  return m_nSamples;
+}
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -239,23 +130,27 @@
   static TypeId tid = TypeId ("ns3::RttMeanDeviation")
     .SetParent<RttEstimator> ()
     .AddConstructor<RttMeanDeviation> ()
-    .AddAttribute ("Gain",
-                   "Gain used in estimating the RTT, must be 0 < Gain < 1",
-                   DoubleValue (0.1),
-                   MakeDoubleAccessor (&RttMeanDeviation::m_gain),
-                   MakeDoubleChecker<double> ())
+    .AddAttribute ("Alpha",
+                   "Gain used in estimating the RTT, must be 0 <= alpha <= 1",
+                   DoubleValue (0.125),
+                   MakeDoubleAccessor (&RttMeanDeviation::m_alpha),
+                   MakeDoubleChecker<double> (0, 1))
+    .AddAttribute ("Beta",
+                   "Gain used in estimating the RTT variation, must be 0 <= beta <= 1",
+                   DoubleValue (0.25),
+                   MakeDoubleAccessor (&RttMeanDeviation::m_beta),
+                   MakeDoubleChecker<double> (0, 1))
   ;
   return tid;
 }
 
-RttMeanDeviation::RttMeanDeviation() :
-  m_variance (0) 
-{ 
+RttMeanDeviation::RttMeanDeviation()
+{
   NS_LOG_FUNCTION (this);
 }
 
 RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c)
-  : RttEstimator (c), m_gain (c.m_gain), m_variance (c.m_variance)
+  : RttEstimator (c), m_alpha (c.m_alpha), m_beta (c.m_beta)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -266,62 +161,120 @@
   return GetTypeId ();
 }
 
-void RttMeanDeviation::Measurement (Time m)
+uint32_t
+RttMeanDeviation::CheckForReciprocalPowerOfTwo (double val) const
+{
+  NS_LOG_FUNCTION (this << val);
+  if (val < TOLERANCE)
+    {
+      return 0;
+    }
+  // supports 1/32, 1/16, 1/8, 1/4, 1/2
+  if (abs (1/val - 8) < TOLERANCE)
+    {
+      return 3;
+    }
+  if (abs (1/val - 4) < TOLERANCE)
+    {
+      return 2;
+    }
+  if (abs (1/val - 32) < TOLERANCE)
+    {
+      return 5;
+    }
+  if (abs (1/val - 16) < TOLERANCE)
+    {
+      return 4;
+    }
+  if (abs (1/val - 2) < TOLERANCE)
+    {
+      return 1;
+    }
+  return 0;
+}
+
+void
+RttMeanDeviation::FloatingPointUpdate (Time m)
+{
+  NS_LOG_FUNCTION (this << m);
+
+  // EWMA formulas are implemented as suggested in
+  // Jacobson/Karels paper appendix A.2
+
+  // SRTT <- (1 - alpha) * SRTT + alpha *  R'
+  Time err (m - m_estimatedRtt);
+  double gErr = err.ToDouble (Time::S) * m_alpha;
+  m_estimatedRtt += Time::FromDouble (gErr, Time::S);
+
+  // RTTVAR <- (1 - beta) * RTTVAR + beta * |SRTT - R'|
+  Time difference = Abs (err) - m_estimatedVariation;
+  m_estimatedVariation += Time::FromDouble (difference.ToDouble (Time::S) * m_beta, Time::S);
+
+  return;
+}
+
+void
+RttMeanDeviation::IntegerUpdate (Time m, uint32_t rttShift, uint32_t variationShift)
+{
+  NS_LOG_FUNCTION (this << m << rttShift << variationShift);
+  // Jacobson/Karels paper appendix A.2
+  int64_t meas = m.GetInteger ();
+  int64_t delta = meas - m_estimatedRtt.GetInteger ();
+  int64_t srtt = (m_estimatedRtt.GetInteger () << rttShift) + delta;
+  m_estimatedRtt = Time::From (srtt >> rttShift);
+  if (delta < 0)
+    {
+      delta = -delta;
+    }
+  delta -= m_estimatedVariation.GetInteger ();
+  int64_t rttvar = m_estimatedVariation.GetInteger () << variationShift;
+  rttvar += delta;
+  m_estimatedVariation = Time::From (rttvar >> variationShift);
+  return;
+}
+
+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_gain, Time::S));
-      m_variance += Time::FromDouble (difference.ToDouble (Time::S) * m_gain, Time::S);
+    { 
+      // If both alpha and beta are reciprocal powers of two, updating can
+      // be done with integer arithmetic according to Jacobson/Karels paper.
+      // If not, since class Time only supports integer multiplication,
+      // must convert Time to floating point and back again
+      uint32_t rttShift = CheckForReciprocalPowerOfTwo (m_alpha);
+      uint32_t variationShift = CheckForReciprocalPowerOfTwo (m_beta);
+      if (rttShift && variationShift)
+        {
+          IntegerUpdate (m, rttShift, variationShift);
+        }
+      else
+        {
+          FloatingPointUpdate (m);
+        }
     }
   else
     { // First sample
-      m_currentEstimatedRtt = m;             // Set estimate to current
-      //variance = sample / 2;               // And variance to current / 2
-      m_variance = m; // try this
-      NS_LOG_DEBUG ("(first sample) m_variance += " << m);
+      m_estimatedRtt = m;               // Set estimate to current
+      m_estimatedVariation = m / 2;  // And variation to current / 2
+      NS_LOG_DEBUG ("(first sample) m_estimatedVariation += " << m);
     }
   m_nSamples++;
 }
 
-Time RttMeanDeviation::RetransmitTimeout ()
-{
-  NS_LOG_FUNCTION (this);
-  NS_LOG_DEBUG ("RetransmitTimeout:  var " << m_variance.GetSeconds () << " est " << m_currentEstimatedRtt.GetSeconds () << " multiplier " << m_multiplier);
-  // RTO = srtt + 4* rttvar
-  int64_t temp = m_currentEstimatedRtt.ToInteger (Time::MS) + 4 * m_variance.ToInteger (Time::MS);
-  if (temp < m_minRto.ToInteger (Time::MS))
-    {
-      temp = m_minRto.ToInteger (Time::MS);
-    } 
-  temp = temp * m_multiplier; // Apply backoff
-  Time retval = Time::FromInteger (temp, Time::MS);
-  NS_LOG_DEBUG ("RetransmitTimeout:  return " << retval.GetSeconds ());
-  return (retval);  
-}
-
-Ptr<RttEstimator> RttMeanDeviation::Copy () const
+Ptr<RttEstimator> 
+RttMeanDeviation::Copy () const
 {
   NS_LOG_FUNCTION (this);
   return CopyObject<RttMeanDeviation> (this);
 }
 
-void RttMeanDeviation::Reset ()
+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;
-}
 
 } //namespace ns3
--- a/src/internet/model/rtt-estimator.h	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/model/rtt-estimator.h	Fri Jan 30 22:29:30 2015 +0100
@@ -25,8 +25,6 @@
 #ifndef RTT_ESTIMATOR_H
 #define RTT_ESTIMATOR_H
 
-#include <deque>
-#include "ns3/sequence-number.h"
 #include "ns3/nstime.h"
 #include "ns3/object.h"
 
@@ -35,36 +33,12 @@
 /**
  * \ingroup tcp
  *
- * \brief Helper class to store RTT measurements
- */
-class RttHistory {
-public:
-  /**
-   * \brief Constructor - builds an RttHistory with the given parameters
-   * \param s First sequence number in packet sent
-   * \param c Number of bytes sent
-   * \param t Time this one was sent
-   */
-  RttHistory (SequenceNumber32 s, uint32_t c, Time t);
-  /**
-   * \brief Copy constructor
-   * \param h the object to copy
-   */
-  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
-};
-
-/// Container for RttHistory objects
-typedef std::deque<RttHistory> RttHistory_t;
-
-/**
- * \ingroup tcp
+ * \brief Base class for all RTT Estimators
  *
- * \brief Base class for all RTT Estimators
+ * The RTT Estimator class computes an estimate of the round trip time
+ * observed in a series of Time measurements.  The estimate is provided in
+ * the form of an estimate and a sample variation.  Subclasses can implement
+ * different algorithms to provide values for the estimate and variation.  
  */
 class RttEstimator : public Object {
 public:
@@ -86,92 +60,51 @@
   virtual TypeId GetInstanceTypeId (void) const;
 
   /**
-   * \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 EstimateRttFromSeq (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;
-
-  /**
-   * \brief Copy object
+   * \brief Copy object (including current internal state)
    * \returns a copy of itself
    */
   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.
+   * \brief gets the RTT estimate.
+   * \return The RTT estimate.
    */
-  void SetMinRto (Time minRto);
-
-  /**
-   * \brief Get the Minimum RTO.
-   * \return The minimum RTO returned by the estimator.
-   */
-  Time GetMinRto (void) const;
+  Time GetEstimate (void) const;
 
   /**
-   * \brief Sets the current RTT estimate (forcefully).
-   * \param estimate The current RTT estimate.
+   * Note that this is not a formal statistical variance; it has the
+   * the same units as the estimate.  Mean deviation or standard deviation 
+   * are example quantities that could be provided here.
+   *
+   * \brief gets the RTT estimate variation.
+   * \return The RTT estimate variation.
    */
-  void SetCurrentEstimate (Time estimate);
+  Time GetVariation (void) const;
 
   /**
-   * \brief gets the current RTT estimate.
-   * \return The current RTT estimate.
+   * \brief gets the number of samples used in the estimates
+   * \return the number of samples used in the estimates
    */
-  Time GetCurrentEstimate (void) const;
+  uint32_t GetNSamples (void) const;
 
 private:
-  SequenceNumber32 m_next;    //!< Next expected sequence to be sent
-  RttHistory_t m_history;     //!< List of sent packet
-  uint16_t m_maxMultiplier;   //!< Maximum RTO Multiplier
   Time m_initialEstimatedRtt; //!< Initial RTT estimation
 
 protected:
-  Time         m_currentEstimatedRtt;     //!< Current estimate
-  Time         m_minRto;                  //!< minimum value of the timeout
+  Time         m_estimatedRtt;            //!< Current estimate
+  Time         m_estimatedVariation;   //!< Current estimate variation
   uint32_t     m_nSamples;                //!< Number of samples
-  uint16_t     m_multiplier;              //!< RTO Multiplier
 };
 
 /**
@@ -183,6 +116,9 @@
  * by Van Jacobson and Michael J. Karels, in
  * "Congestion Avoidance and Control", SIGCOMM 88, Appendix A
  *
+ * The default values for the gain (alpha and beta) are set as documented
+ * in RFC 6298.
+ *
  */
 class RttMeanDeviation : public RttEstimator {
 public:
@@ -208,12 +144,6 @@
    */
   void Measurement (Time measure);
 
-  /**
-   * \brief Returns the estimated RTO.
-   * \return the estimated RTO.
-   */
-  Time RetransmitTimeout ();
-
   Ptr<RttEstimator> Copy () const;
 
   /**
@@ -221,16 +151,41 @@
    */
   void Reset ();
 
-  /**
-   * \brief Sets the estimator Gain.
-   * \param g the gain, where 0 < g < 1.
+private:
+  /** 
+   * Utility function to check for possible conversion
+   * of a double value (0 < value < 1) to a reciprocal power of two
+   *
+   * Values of 1/32, 1/16, 1/8, 1/4, and 1/2 (i.e., within the possible
+   * range of experimentation for this estimator) are supported.
+   * 
+   * \param val value to check 
+   * \return log base 2 (1/val) if reciprocal power of 2, or zero if not
    */
-  void Gain (double g);
+  uint32_t CheckForReciprocalPowerOfTwo (double val) const;
+  /**
+   * Method to update the rtt and variation estimates using integer
+   * arithmetic, used when the values of Alpha and Beta support the
+   * integer conversion.
+   *
+   * \param m time measurement
+   * \param rttShift value corresponding to log base 2 (1/alpha)
+   * \param variationShift value corresponding to log base 2 (1/beta)
+   */
+  void IntegerUpdate (Time m, uint32_t rttShift, uint32_t variationShift);
+  /**
+   * Method to update the rtt and variation estimates using floating
+   * point arithmetic, used when the values of Alpha and Beta are not
+   * both a reciprocal power of two.
+   *
+   * \param m time measurement
+   */
+  void FloatingPointUpdate (Time m);
+  double       m_alpha;       //!< Filter gain for average
+  double       m_beta;        //!< Filter gain for variation
 
-private:
-  double       m_gain;       //!< Filter gain
-  Time         m_variance;   //!< Current variance
 };
+
 } // namespace ns3
 
 #endif /* RTT_ESTIMATOR_H */
--- a/src/internet/model/tcp-newreno.cc	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/model/tcp-newreno.cc	Fri Jan 30 22:29:30 2015 +0100
@@ -213,7 +213,6 @@
   m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
   NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
                ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
-  m_rtt->IncreaseMultiplier ();             // Double the next RTO
   DoRetransmit ();                          // Retransmit the packet
 }
 
--- a/src/internet/model/tcp-reno.cc	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/model/tcp-reno.cc	Fri Jan 30 22:29:30 2015 +0100
@@ -188,7 +188,6 @@
   m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
   NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
                ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
-  m_rtt->IncreaseMultiplier ();             // Double the next RTO
   DoRetransmit ();                          // Retransmit the packet
 }
 
--- a/src/internet/model/tcp-socket-base.cc	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/model/tcp-socket-base.cc	Fri Jan 30 22:29:30 2015 +0100
@@ -94,6 +94,18 @@
                    BooleanValue (true),
                    MakeBooleanAccessor (&TcpSocketBase::m_timestampEnabled),
                    MakeBooleanChecker ())
+    .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 (&TcpSocketBase::SetMinRto,
+                                     &TcpSocketBase::GetMinRto),
+                                     MakeTimeChecker ())
+    .AddAttribute ("ClockGranularity",
+                   "Clock Granularity used in RTO calculations",
+                   TimeValue (MilliSeconds (1)), // RFC6298 suggest to use fine clock granularity
+                   MakeTimeAccessor (&TcpSocketBase::SetClockGranularity,
+                                     &TcpSocketBase::GetClockGranularity),
+                                     MakeTimeChecker ())
     .AddTraceSource ("RTO",
                      "Retransmission timeout",
                      MakeTraceSourceAccessor (&TcpSocketBase::m_rto),
@@ -148,8 +160,7 @@
     m_sndScaleFactor (0),
     m_rcvScaleFactor (0),
     m_timestampEnabled (true),
-    m_timestampToEcho (0),
-    m_lastEchoedTime (0)
+    m_timestampToEcho (0)
 
 {
   NS_LOG_FUNCTION (this);
@@ -190,8 +201,7 @@
     m_sndScaleFactor (sock.m_sndScaleFactor),
     m_rcvScaleFactor (sock.m_rcvScaleFactor),
     m_timestampEnabled (sock.m_timestampEnabled),
-    m_timestampToEcho (sock.m_timestampToEcho),
-    m_lastEchoedTime (sock.m_lastEchoedTime)
+    m_timestampToEcho (sock.m_timestampToEcho)
 
 {
   NS_LOG_FUNCTION (this);
@@ -1568,8 +1578,8 @@
   if (m_state == LAST_ACK)
     {
       NS_LOG_LOGIC ("TcpSocketBase " << this << " scheduling LATO1");
-      m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (),
-                                            &TcpSocketBase::LastAckTimeout, this);
+      Time lastRto = m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation ()*4);
+      m_lastAckEvent = Simulator::Schedule (lastRto, &TcpSocketBase::LastAckTimeout, this);
     }
 }
 
@@ -1687,7 +1697,10 @@
     }
   AddOptions (header);
   header.SetWindowSize (AdvertisedWindowSize ());
-  m_rto = m_rtt->RetransmitTimeout ();
+
+  // RFC 6298, clause 2.4
+  m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation ()*4), Time::FromDouble (1,  Time::S));
+
   bool hasSyn = flags & TcpHeader::SYN;
   bool hasFin = flags & TcpHeader::FIN;
   bool isAck = flags == TcpHeader::ACK;
@@ -1696,6 +1709,7 @@
       if (m_cnCount == 0)
         { // No more connection retries, give up
           NS_LOG_LOGIC ("Connection failed.");
+          m_rtt->Reset (); //According to recommendation -> RFC 6298
           CloseAndNotify ();
           return;
         }
@@ -1891,6 +1905,12 @@
 {
   NS_LOG_FUNCTION (this << seq << maxSize << withAck);
 
+  bool isRetransmission = false;
+  if ( seq == m_txBuffer.HeadSequence () )
+    {
+      isRetransmission = true;
+    }
+
   Ptr<Packet> p = m_txBuffer.CopyFromSequence (maxSize, seq);
   uint32_t sz = p->GetSize (); // Size of packet
   uint8_t flags = withAck ? TcpHeader::ACK : 0;
@@ -1960,9 +1980,15 @@
     }
   header.SetWindowSize (AdvertisedWindowSize ());
   AddOptions (header);
+
   if (m_retxEvent.IsExpired () )
-    { // Schedule retransmit
-      m_rto = m_rtt->RetransmitTimeout ();
+    {
+      // RFC 6298, clause 2.5
+      Time doubledRto = m_rto + m_rto;
+      m_rto = Min (doubledRto, Time::FromDouble (60,  Time::S));
+
+      // Schedules retransmit
+
       NS_LOG_LOGIC (this << " SendDataPacket Schedule ReTxTimeout at time " <<
                     Simulator::Now ().GetSeconds () << " to expire at time " <<
                     (Simulator::Now () + m_rto.Get ()).GetSeconds () );
@@ -1979,7 +2005,25 @@
       m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
                          m_endPoint6->GetPeerAddress (), m_boundnetdevice);
     }
-  m_rtt->SentSeq (seq, sz);       // notify the RTT
+
+  // update the history of sequence numbers used to calculate the RTT
+  if (isRetransmission == false)
+    { // This is the next expected one, just log at end
+      m_history.push_back (RttHistory (seq, sz, Simulator::Now () ));
+    }
+  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;
+              i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist
+              break;
+            }
+        }
+    }
+
   // Notify the application of the data being sent unless this is a retransmit
   if (seq == m_nextTxSequence)
     {
@@ -2155,27 +2199,46 @@
 void
 TcpSocketBase::EstimateRtt (const TcpHeader& tcpHeader)
 {
-  Time nextRtt;
+  SequenceNumber32 ackSeq = tcpHeader.GetAckNumber();
+  Time m = Time (0.0);
 
-  if (m_timestampEnabled)
+  // 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
+  if (!m_history.empty ())
     {
-      nextRtt = TcpOptionTS::ElapsedTimeFromTsValue (m_lastEchoedTime);
-    }
-  else
-    {
-      // Use m_rtt for the estimation. Note, RTT of duplicated acknowledgement
-      // (which should be ignored) is handled by m_rtt.
-      nextRtt =  m_rtt->EstimateRttFromSeq (tcpHeader.GetAckNumber () );
+      RttHistory& h = m_history.front ();
+      if (!h.retx && ackSeq >= (h.seq + SequenceNumber32 (h.count)))
+        { // Ok to use this sample
+          if (m_timestampEnabled && tcpHeader.HasOption (TcpOption::TS))
+            {
+              Ptr<TcpOptionTS> ts;
+              ts = DynamicCast<TcpOptionTS> (tcpHeader.GetOption (TcpOption::TS));
+              m = TcpOptionTS::ElapsedTimeFromTsValue (ts->GetEcho ());
+            }
+          else
+            {
+              m = Simulator::Now () - h.time; // Elapsed time
+            }
+        }
     }
 
-  //nextRtt will be zero for dup acks.  Don't want to update lastRtt in that case
-  //but still needed to do list clearing that is done in EstimateRttFromSeq.
-  if(nextRtt != Time (0))
-  {
-    m_lastRtt = nextRtt;
-    NS_LOG_FUNCTION(this << m_lastRtt);
-  }
-  
+  // Now delete all ack history with seq <= ack
+  while(!m_history.empty ())
+    {
+      RttHistory& h = m_history.front ();
+      if ((h.seq + SequenceNumber32 (h.count)) > ackSeq) break;               // Done removing
+      m_history.pop_front (); // Remove
+    }
+
+  if (!m.IsZero ())
+    {
+      m_rtt->Measurement (m);                // Log the measurement
+      // RFC 6298, clause 2.4
+      m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation ()*4), Time::FromDouble (1,  Time::S));
+      m_lastRtt = m_rtt->GetEstimate ();
+      NS_LOG_FUNCTION(this << m_lastRtt);
+    }
 }
 
 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
@@ -2191,8 +2254,10 @@
       NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
                     (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
       m_retxEvent.Cancel ();
-      // On recieving a "New" ack we restart retransmission timer .. RFC 2988
-      m_rto = m_rtt->RetransmitTimeout ();
+      // On receiving a "New" ack we restart retransmission timer .. RFC 6298
+      // RFC 6298, clause 2.4
+      m_rto = Max (m_rtt->GetEstimate () + Max (m_clockGranularity, m_rtt->GetVariation ()*4), Time::FromDouble (1,  Time::S));
+
       NS_LOG_LOGIC (this << " Schedule ReTxTimeout at time " <<
                     Simulator::Now ().GetSeconds () << " to expire at time " <<
                     (Simulator::Now () + m_rto.Get ()).GetSeconds ());
@@ -2320,7 +2385,6 @@
 TcpSocketBase::Retransmit ()
 {
   m_nextTxSequence = m_txBuffer.HeadSequence (); // Start from highest Ack
-  m_rtt->IncreaseMultiplier (); // Double the timeout value for next retx timer
   m_dupAckCount = 0;
   DoRetransmit (); // Retransmit the packet
 }
@@ -2526,6 +2590,7 @@
     }
 
   m_timestampEnabled = false;
+
   if (header.HasOption (TcpOption::TS))
     {
       m_timestampEnabled = true;
@@ -2622,10 +2687,9 @@
 
   Ptr<const TcpOptionTS> ts = DynamicCast<const TcpOptionTS> (option);
   m_timestampToEcho = ts->GetTimestamp ();
-  m_lastEchoedTime = ts->GetEcho ();
 
   NS_LOG_INFO (m_node->GetId () << " Got timestamp=" <<
-               m_timestampToEcho << " and Echo="     << m_lastEchoedTime);
+               m_timestampToEcho << " and Echo="     << ts->GetEcho ());
 }
 
 void
@@ -2643,4 +2707,41 @@
                option->GetTimestamp () << " echo=" << m_timestampToEcho);
 }
 
+void
+TcpSocketBase::SetMinRto (Time minRto)
+{
+  NS_LOG_FUNCTION (this << minRto);
+  m_minRto = minRto;
+}
+
+Time
+TcpSocketBase::GetMinRto (void) const
+{
+  return m_minRto;
+}
+
+void
+TcpSocketBase::SetClockGranularity (Time clockGranularity)
+{
+  NS_LOG_FUNCTION (this << clockGranularity);
+  m_clockGranularity = clockGranularity;
+}
+
+Time
+TcpSocketBase::GetClockGranularity (void) const
+{
+  return m_clockGranularity;
+}
+
+//RttHistory methods
+RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t)
+  : seq (s), count (c), time (t), retx (false)
+{
+}
+
+RttHistory::RttHistory (const RttHistory& h)
+  : seq (h.seq), count (h.count), time (h.time), retx (h.retx)
+{
+}
+
 } // namespace ns3
--- a/src/internet/model/tcp-socket-base.h	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/model/tcp-socket-base.h	Fri Jan 30 22:29:30 2015 +0100
@@ -47,6 +47,35 @@
 class TcpHeader;
 
 /**
+ * \ingroup tcp
+ *
+ * \brief Helper class to store RTT measurements
+ */
+class RttHistory {
+public:
+  /**
+   * \brief Constructor - builds an RttHistory with the given parameters
+   * \param s First sequence number in packet sent
+   * \param c Number of bytes sent
+   * \param t Time this one was sent
+   */
+  RttHistory (SequenceNumber32 s, uint32_t c, Time t);
+  /**
+   * \brief Copy constructor
+   * \param h the object to copy
+   */
+  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
+};
+
+/// Container for RttHistory objects
+typedef std::deque<RttHistory> RttHistory_t;
+
+/**
  * \ingroup socket
  * \ingroup tcp
  *
@@ -101,6 +130,31 @@
    */
   virtual void SetRtt (Ptr<RttEstimator> rtt);
 
+  /**
+   * \brief Sets the Minimum RTO.
+   * \param minRto The minimum RTO.
+   */
+  void SetMinRto (Time minRto);
+
+  /**
+   * \brief Get the Minimum RTO.
+   * \return The minimum RTO.
+   */
+  Time GetMinRto (void) const;
+
+  /**
+   * \brief Sets the Clock Granularity (used in RTO calcs).
+   * \param clockGranularity The Clock Granularity
+   */
+  void SetClockGranularity (Time clockGranularity);
+
+  /**
+   * \brief Get the Clock Granularity (used in RTO calcs).
+   * \return The Clock Granularity.
+   */
+  Time GetClockGranularity (void) const;
+
+
   // Necessary implementations of null functions from ns3::Socket
   virtual enum SocketErrno GetErrno (void) const;    // returns m_errno
   virtual enum SocketType GetSocketType (void) const; // returns socket type
@@ -624,10 +678,13 @@
   uint32_t          m_cnCount;         //!< Count of remaining connection retries
   uint32_t          m_cnRetries;       //!< Number of connection retries before giving up
   TracedValue<Time> m_rto;             //!< Retransmit timeout
+  Time              m_minRto;          //!< minimum value of the Retransmit timeout
+  Time              m_clockGranularity; //!< Clock Granularity used in RTO calcs
   TracedValue<Time> m_lastRtt;         //!< Last RTT sample collected
   Time              m_delAckTimeout;   //!< Time to delay an ACK
   Time              m_persistTimeout;  //!< Time between sending 1-byte probes
   Time              m_cnTimeout;       //!< Timeout for connection retry
+  RttHistory_t      m_history;         //!< List of sent packet
 
   // Connections to other layers of TCP/IP
   Ipv4EndPoint*       m_endPoint;   //!< the IPv4 endpoint
@@ -667,7 +724,6 @@
 
   bool     m_timestampEnabled;    //!< Timestamp option enabled
   uint32_t m_timestampToEcho;     //!< Timestamp to echo
-  uint32_t m_lastEchoedTime;      //!< Last echoed timestamp
 };
 
 } // namespace ns3
--- a/src/internet/model/tcp-tahoe.cc	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/model/tcp-tahoe.cc	Fri Jan 30 22:29:30 2015 +0100
@@ -166,7 +166,6 @@
   m_ssThresh = std::max (static_cast<unsigned> (m_cWnd / 2), m_segmentSize * 2);  // Half ssthresh
   m_cWnd = m_segmentSize;                   // Set cwnd to 1 segSize (RFC2001, sec.2)
   m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack
-  m_rtt->IncreaseMultiplier ();             // Double the next RTO
   DoRetransmit ();                          // Retransmit the packet
 }
 
--- a/src/internet/model/tcp-westwood.cc	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/model/tcp-westwood.cc	Fri Jan 30 22:29:30 2015 +0100
@@ -307,23 +307,20 @@
   if (m_state == CLOSED || m_state == TIME_WAIT)
     return;
   // If all data are received, just return
-  if (m_txBuffer.HeadSequence() >= m_nextTxSequence)
+  if (m_txBuffer.HeadSequence () >= m_nextTxSequence)
     return;
 
   // Upon an RTO, adjust cwnd and ssthresh based on the estimated BW
-  m_ssThresh = std::max (static_cast<double> (2 * m_segmentSize), m_currentBW.Get() * static_cast<double> (m_minRtt.GetSeconds()));
+  m_ssThresh = std::max (static_cast<double> (2 * m_segmentSize), m_currentBW.Get () * static_cast<double> (m_minRtt.GetSeconds ()));
   m_cWnd = m_segmentSize;
 
   // Restart from highest ACK
-  m_nextTxSequence = m_txBuffer.HeadSequence();
+  m_nextTxSequence = m_txBuffer.HeadSequence ();
   NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd <<
       ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
 
-  // Double the next RTO
-  m_rtt->IncreaseMultiplier();
-
   // Retransmit the packet
-  DoRetransmit();
+  DoRetransmit ();
 }
 
 void
--- a/src/internet/test/rtt-test.cc	Fri Jan 30 11:52:16 2015 -0800
+++ b/src/internet/test/rtt-test.cc	Fri Jan 30 22:29:30 2015 +0100
@@ -16,93 +16,153 @@
  */
 
 #include "ns3/test.h"
-#include "ns3/core-module.h"
-#include "ns3/internet-module.h"
 #include "ns3/rtt-estimator.h"
+#include "ns3/attribute.h"
+#include "ns3/nstime.h"
+#include "ns3/config.h"
 #include "ns3/log.h"
+#include "ns3/double.h"
 
 using namespace ns3;
 
-NS_LOG_COMPONENT_DEFINE ("RttTestSuite");
+NS_LOG_COMPONENT_DEFINE ("RttEstimatorTestSuite");
 
-class RttTestCase : public TestCase
+class RttEstimatorTestCase : public TestCase
 {
 public:
-  RttTestCase (double mean,
-               double variance,
-               double gain);
+  RttEstimatorTestCase ();
 
 private:
   virtual void DoRun (void);
   virtual void DoTeardown (void);
 
-  double m_mean;
-  double m_variance;
-  double m_gain;
-
+  void CheckValues (Ptr<RttEstimator> rtt, Time m, Time e, Time v);
+  void CheckValuesWithTolerance (Ptr<RttEstimator> rtt, Time m, Time e, Time v);
 };
 
-RttTestCase::RttTestCase (double mean,
-                          double variance,
-                          double gain)
-  : TestCase ("Rtt Estimate Test"),
-    m_mean (mean),
-    m_variance (variance),
-    m_gain (gain)
+RttEstimatorTestCase::RttEstimatorTestCase ()
+  : TestCase ("Rtt Estimator Test")
 {
 }
 
 void
-RttTestCase::DoRun (void)
+RttEstimatorTestCase::CheckValues (Ptr<RttEstimator> rtt, Time m, Time e, Time v)
+{
+  rtt->Measurement (m);
+  NS_TEST_EXPECT_MSG_EQ (rtt->GetEstimate (), e, "Estimate not correct");
+  NS_TEST_EXPECT_MSG_EQ (rtt->GetVariation (), v, "Estimate not correct");
+}
+
+void
+RttEstimatorTestCase::CheckValuesWithTolerance (Ptr<RttEstimator> rtt, Time m, Time e, Time v)
 {
-  Config::SetDefault ("ns3::RttEstimator::InitialEstimation", TimeValue (MilliSeconds (m_mean)));
-  Config::SetDefault ("ns3::RttMeanDeviation::Gain", DoubleValue (m_gain));
-  Config::SetDefault ("ns3::RttEstimator::MinRTO", TimeValue (Seconds (0)));
+  rtt->Measurement (m);
+  NS_TEST_EXPECT_MSG_EQ_TOL (rtt->GetEstimate (), e, Time (NanoSeconds (1)), "Estimate not correct");
+  NS_TEST_EXPECT_MSG_EQ_TOL (rtt->GetVariation (), v, Time (NanoSeconds (1)), "Estimate not correct");
+}
+
+
+void
+RttEstimatorTestCase::DoRun (void)
+{
+  // Set to a non-default value
+  Config::SetDefault ("ns3::RttEstimator::InitialEstimation", TimeValue (MilliSeconds (500)));
+  Config::SetDefault ("ns3::RttMeanDeviation::Alpha", DoubleValue (0.5));
+  Config::SetDefault ("ns3::RttMeanDeviation::Beta", DoubleValue (0.6));
 
   Ptr<RttMeanDeviation> rtt = CreateObject<RttMeanDeviation> ();
-  Ptr<NormalRandomVariable> nv = CreateObject<NormalRandomVariable> ();
-  nv->SetAttribute ("Mean", DoubleValue (m_mean));
-  nv->SetAttribute ("Variance", DoubleValue (m_variance));
+
+  bool ok;
+  TimeValue timeval;
+  DoubleValue doubleval;
+  ok = rtt->GetAttributeFailSafe ("InitialEstimation", timeval);
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be gettable");
+  NS_TEST_EXPECT_MSG_EQ (timeval.Get (), MilliSeconds (500), "Initial estimate should match");
+  ok = rtt->GetAttributeFailSafe ("Alpha", doubleval);
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be gettable");
+  NS_TEST_ASSERT_MSG_EQ_TOL (doubleval.Get (), 0.5, 0.001, "Alpha not set");
+  ok = rtt->GetAttributeFailSafe ("Beta", doubleval);
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be gettable");
+  NS_TEST_ASSERT_MSG_EQ_TOL (doubleval.Get (), 0.6, 0.001, "Beta not set");
 
-  NS_TEST_EXPECT_MSG_EQ (m_mean, rtt->GetCurrentEstimate ().GetMilliSeconds (), "Initial estimate should match mean");
+  // Reset to default values
+  ok = rtt->SetAttributeFailSafe ("InitialEstimation", TimeValue (Seconds (1)));
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be settable");
+  ok = rtt->SetAttributeFailSafe ("Alpha", DoubleValue (0.125));
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be settable");
+  ok = rtt->SetAttributeFailSafe ("Beta", DoubleValue (0.25));
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be settable");
+  rtt->Reset ();
 
-  double a, v, g;
-  a = v = m_mean;
-  g = m_gain;
+  Time t (Seconds (1));
+  Time t2 (MilliSeconds (125));
+  NS_TEST_EXPECT_MSG_EQ (t2, Time::From (t.GetInteger () >> 3), "X");
+  NS_TEST_EXPECT_MSG_EQ (rtt->GetEstimate (), Time (Seconds (1)), "Incorrect initial estimate");
+  NS_TEST_EXPECT_MSG_EQ (rtt->GetVariation (), Time (Seconds (0)), "Incorrect initial variance");
+  NS_TEST_EXPECT_MSG_EQ (rtt->GetNSamples (), 0, "Incorrect initial estimate");
+
+  // CheckValues (rtt, measurement, new estimate, new variance);
+  // Initial value:  SRTT <- measurement; RTTVAR <- measurement/2
+  CheckValues (rtt, Time (Seconds (1)), Time (Seconds (1)), Time (MilliSeconds (500)));
+  // Subsequent values:  according to RFC 6298
+  CheckValues (rtt, Time (MilliSeconds (1200)), Time (MilliSeconds (1025)), Time (MilliSeconds (425)));
+  Ptr<RttEstimator> copy = rtt->Copy ();
+  CheckValues (rtt, Time (MilliSeconds (900)), Time (MicroSeconds (1009375)), Time (MilliSeconds (350)));
 
-  for (uint32_t i = 0; i < 10000; ++i)
-    {
-      int measurement = nv->GetInteger ();
-      rtt->Measurement (Time::FromInteger (measurement, Time::MS));
-      double err = (measurement - a);
-      a = a + g * err;
-      v = v + g * (std::abs (err) - v);
-    }
+  // Check behavior of copy; should have inherited state
+  CheckValues (copy, Time (MilliSeconds (900)), Time (MicroSeconds (1009375)), Time (MilliSeconds (350)));
+
+  // Floating point arithmetic due to alpha and beta settings
+  rtt->Reset ();
+  ok = rtt->SetAttributeFailSafe ("Alpha", DoubleValue (0.1));
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be settable");
+  ok = rtt->SetAttributeFailSafe ("Beta", DoubleValue (0.1));
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be settable");
+  CheckValuesWithTolerance (rtt, Time (Seconds (1.2)), Time (Seconds (1.2)), Time (Seconds (0.6)));
+  CheckValuesWithTolerance (rtt, Time (MilliSeconds (950)), Time (MilliSeconds (1175)), Time (MilliSeconds (565)));
+  CheckValuesWithTolerance (rtt, Time (MilliSeconds (1400)), Time (MicroSeconds (1197500)), Time (MilliSeconds (531)));
 
-  //5% tolerance
-  double tolerance = m_mean * .05;
-
-  NS_TEST_ASSERT_MSG_EQ_TOL (m_mean, rtt->GetCurrentEstimate ().GetMilliSeconds (), tolerance, "Unexpected estimate");
+  // Check boundary values; 0 will not update, 1 will use most recent value
+  rtt->Reset ();
+  ok = rtt->SetAttributeFailSafe ("Alpha", DoubleValue (0));
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be settable");
+  ok = rtt->SetAttributeFailSafe ("Beta", DoubleValue (0));
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be settable");
+  CheckValues (rtt, Time (Seconds (1)), Time (Seconds (1)), Time (MilliSeconds (500)));
+  CheckValues (rtt, Time (Seconds (2)), Time (Seconds (1)), Time (MilliSeconds (500)));
+  CheckValues (rtt, Time (Seconds (3)), Time (Seconds (1)), Time (MilliSeconds (500)));
+  rtt->Reset ();
+  ok = rtt->SetAttributeFailSafe ("Alpha", DoubleValue (1));
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be settable");
+  ok = rtt->SetAttributeFailSafe ("Beta", DoubleValue (1));
+  NS_TEST_EXPECT_MSG_EQ (ok, true, "Attribute should be settable");
+  CheckValues (rtt, Time (Seconds (1)), Time (Seconds (1)), Time (MilliSeconds (500)));
+  CheckValues (rtt, Time (Seconds (2.5)), Time (Seconds (2.5)), Time (Seconds (1.5)));
+  CheckValues (rtt, Time (Seconds (7)), Time (Seconds (7)), Time (Seconds (4.5)));
+  
+  // recheck initial values
+  rtt->Reset ();
+  NS_TEST_EXPECT_MSG_EQ (rtt->GetEstimate (), Time (Seconds (1)), "Incorrect initial estimate");
+  NS_TEST_EXPECT_MSG_EQ (rtt->GetVariation (), Time (Seconds (0)), "Incorrect initial variation");
+  NS_TEST_EXPECT_MSG_EQ (rtt->GetNSamples (), 0, "Incorrect initial estimate");
+}
 
-  int expectedTimeout = (int)a + 4 * (int)v;
-
-  NS_TEST_EXPECT_MSG_EQ (rtt->RetransmitTimeout ().GetMilliSeconds (), expectedTimeout, "Timeout values do not match");
-}
 void
-RttTestCase::DoTeardown (void)
+RttEstimatorTestCase::DoTeardown (void)
 {
 }
 
-
-static class RttTestSuite : public TestSuite
+class RttEstimatorTestSuite : public TestSuite
 {
 public:
-  RttTestSuite ()
-    : TestSuite ("rtt", UNIT)
+  RttEstimatorTestSuite ()
+    : TestSuite ("rtt-estimator", UNIT)
   {
-    AddTestCase (new RttTestCase (150.0, 10.0, .1), TestCase::QUICK);
-    AddTestCase (new RttTestCase (5000.0, 5.0, .5), TestCase::QUICK);
-    AddTestCase (new RttTestCase (200.0, 25.0, .7), TestCase::QUICK);
+    AddTestCase (new RttEstimatorTestCase, TestCase::QUICK);
   }
 
-} g_tcpTestSuite;
+};
+
+static RttEstimatorTestSuite  g_rttEstimatorTestSuite;
+
+