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