Bug 1405 - RttEstimator improvements

This commit is contained in:
Tommaso Pecorella
2015-01-30 22:29:30 +01:00
parent 7b3b202b10
commit 2ab35569ae
12 changed files with 593 additions and 522 deletions

View File

@@ -39,6 +39,7 @@ New user-visible features
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 @@ Bugs fixed
- Bug 2047 - Ipv6EndPointDemux::Lookup may crash
- Bug 2049 - CQI feedback should always use the same calculation method
Known issues
------------

View File

@@ -216,7 +216,7 @@ def register_types(module):
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 @@ def register_Ns3RipNgRoutingTableEntry_methods(root_module, cls):
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 @@ def register_Ns3Empty_methods(root_module, cls):
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 @@ def register_Ns3Int64x64_t_methods(root_module, cls):
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 @@ def register_Ns3RttEstimator_methods(root_module, cls):
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 @@ def register_Ns3RttEstimator_methods(root_module, cls):
'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 @@ def register_Ns3RttEstimator_methods(root_module, cls):
'ns3::TypeId',
[],
is_static=True)
## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::IncreaseMultiplier() [member function]
cls.add_method('IncreaseMultiplier',
'void',
## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetVariation() const [member function]
cls.add_method('GetVariation',
'ns3::Time',
[],
is_virtual=True)
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 @@ def register_Ns3RttEstimator_methods(root_module, cls):
'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 @@ def register_Ns3RttMeanDeviation_methods(root_module, cls):
'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 @@ def register_Ns3RttMeanDeviation_methods(root_module, cls):
'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 @@ def register_Ns3TcpSocketBase_methods(root_module, cls):
'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 @@ def register_Ns3TcpSocketBase_methods(root_module, cls):
'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 @@ def register_Ns3TcpWestwood_methods(root_module, cls):
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 @@ def register_Ns3Time_methods(root_module, cls):
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]

View File

@@ -216,7 +216,7 @@ def register_types(module):
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 @@ def register_Ns3RipNgRoutingTableEntry_methods(root_module, cls):
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 @@ def register_Ns3Empty_methods(root_module, cls):
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 @@ def register_Ns3Int64x64_t_methods(root_module, cls):
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 @@ def register_Ns3RttEstimator_methods(root_module, cls):
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 @@ def register_Ns3RttEstimator_methods(root_module, cls):
'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 @@ def register_Ns3RttEstimator_methods(root_module, cls):
'ns3::TypeId',
[],
is_static=True)
## rtt-estimator.h (module 'internet'): void ns3::RttEstimator::IncreaseMultiplier() [member function]
cls.add_method('IncreaseMultiplier',
'void',
## rtt-estimator.h (module 'internet'): ns3::Time ns3::RttEstimator::GetVariation() const [member function]
cls.add_method('GetVariation',
'ns3::Time',
[],
is_virtual=True)
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 @@ def register_Ns3RttEstimator_methods(root_module, cls):
'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 @@ def register_Ns3RttMeanDeviation_methods(root_module, cls):
'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 @@ def register_Ns3RttMeanDeviation_methods(root_module, cls):
'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 @@ def register_Ns3TcpSocketBase_methods(root_module, cls):
'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 @@ def register_Ns3TcpSocketBase_methods(root_module, cls):
'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 @@ def register_Ns3TcpWestwood_methods(root_module, cls):
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 @@ def register_Ns3Time_methods(root_module, cls):
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]

View File

@@ -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_LOG_COMPONENT_DEFINE ("RttEstimator");
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)
Time
RttEstimator::GetEstimate (void) const
{
NS_LOG_FUNCTION (this << minRto);
m_minRto = minRto;
return m_estimatedRtt;
}
Time
RttEstimator::GetMinRto (void) const
RttEstimator::GetVariation (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_estimatedVariation;
}
//RttHistory methods
RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t)
: seq (s), count (c), time (t), retx (false)
{
NS_LOG_FUNCTION (this);
}
RttHistory::RttHistory (const RttHistory& h)
: seq (h.seq), count (h.count), time (h.time), retx (h.retx)
{
NS_LOG_FUNCTION (this);
}
// Base class methods
RttEstimator::RttEstimator ()
: m_next (1), m_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 @@ RttEstimator::GetInstanceTypeId (void) const
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 @@ RttMeanDeviation::GetTypeId (void)
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 @@ RttMeanDeviation::GetInstanceTypeId (void) const
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

View File

@@ -25,46 +25,20 @@
#ifndef RTT_ESTIMATOR_H
#define RTT_ESTIMATOR_H
#include <deque>
#include "ns3/sequence-number.h"
#include "ns3/nstime.h"
#include "ns3/object.h"
namespace ns3 {
/**
* \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
*
* 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:
@@ -85,25 +59,6 @@ public:
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.
@@ -111,67 +66,45 @@ public:
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);
Time GetEstimate (void) const;
/**
* \brief Get the Minimum RTO.
* \return The minimum RTO returned by the estimator.
* 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.
*/
Time GetMinRto (void) const;
Time GetVariation (void) const;
/**
* \brief Sets the current RTT estimate (forcefully).
* \param estimate The current RTT estimate.
* \brief gets the number of samples used in the estimates
* \return the number of samples used in the estimates
*/
void SetCurrentEstimate (Time estimate);
/**
* \brief gets the current RTT estimate.
* \return The current RTT estimate.
*/
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 @@ protected:
* 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 @@ public:
*/
void Measurement (Time measure);
/**
* \brief Returns the estimated RTO.
* \return the estimated RTO.
*/
Time RetransmitTimeout ();
Ptr<RttEstimator> Copy () const;
/**
@@ -221,16 +151,41 @@ public:
*/
void Reset ();
/**
* \brief Sets the estimator Gain.
* \param g the gain, where 0 < g < 1.
*/
void Gain (double g);
private:
double m_gain; //!< Filter gain
Time m_variance; //!< Current variance
/**
* 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
*/
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
};
} // namespace ns3
#endif /* RTT_ESTIMATOR_H */

View File

@@ -213,7 +213,6 @@ TcpNewReno::Retransmit (void)
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
}

View File

@@ -188,7 +188,6 @@ void TcpReno::Retransmit (void)
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
}

View File

@@ -94,6 +94,18 @@ TcpSocketBase::GetTypeId (void)
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 @@ TcpSocketBase::TcpSocketBase (void)
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 @@ TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock)
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 @@ TcpSocketBase::DoPeerClose (void)
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 @@ TcpSocketBase::SendEmptyPacket (uint8_t flags)
}
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 @@ TcpSocketBase::SendEmptyPacket (uint8_t flags)
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 @@ TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool with
{
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 @@ TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool with
}
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 @@ TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool with
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 @@ TcpSocketBase::ReceivedData (Ptr<Packet> p, const TcpHeader& tcpHeader)
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 @@ TcpSocketBase::NewAck (SequenceNumber32 const& ack)
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 @@ void
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 @@ TcpSocketBase::ReadOptions (const TcpHeader& header)
}
m_timestampEnabled = false;
if (header.HasOption (TcpOption::TS))
{
m_timestampEnabled = true;
@@ -2622,10 +2687,9 @@ TcpSocketBase::ProcessOptionTimestamp (const Ptr<const TcpOption> option)
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 @@ TcpSocketBase::AddOptionTimestamp (TcpHeader& header)
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

View File

@@ -46,6 +46,35 @@ class Packet;
class TcpL4Protocol;
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 @@ public:
*/
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 @@ protected:
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 @@ protected:
bool m_timestampEnabled; //!< Timestamp option enabled
uint32_t m_timestampToEcho; //!< Timestamp to echo
uint32_t m_lastEchoedTime; //!< Last echoed timestamp
};
} // namespace ns3

View File

@@ -166,7 +166,6 @@ void TcpTahoe::Retransmit (void)
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
}

View File

@@ -307,23 +307,20 @@ TcpWestwood::Retransmit (void)
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

View File

@@ -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);
};
RttEstimatorTestCase::RttEstimatorTestCase ()
: TestCase ("Rtt Estimator Test")
{
}
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)
{
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> ();
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");
// 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 ();
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)));
// 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)));
// 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");
}
void
RttEstimatorTestCase::DoTeardown (void)
{
}
class RttEstimatorTestSuite : public TestSuite
{
public:
RttEstimatorTestSuite ()
: TestSuite ("rtt-estimator", UNIT)
{
AddTestCase (new RttEstimatorTestCase, TestCase::QUICK);
}
};
RttTestCase::RttTestCase (double mean,
double variance,
double gain)
: TestCase ("Rtt Estimate Test"),
m_mean (mean),
m_variance (variance),
m_gain (gain)
{
}
void
RttTestCase::DoRun (void)
{
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)));
Ptr<RttMeanDeviation> rtt = CreateObject<RttMeanDeviation> ();
Ptr<NormalRandomVariable> nv = CreateObject<NormalRandomVariable> ();
nv->SetAttribute ("Mean", DoubleValue (m_mean));
nv->SetAttribute ("Variance", DoubleValue (m_variance));
NS_TEST_EXPECT_MSG_EQ (m_mean, rtt->GetCurrentEstimate ().GetMilliSeconds (), "Initial estimate should match mean");
double a, v, g;
a = v = m_mean;
g = m_gain;
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);
}
//5% tolerance
double tolerance = m_mean * .05;
NS_TEST_ASSERT_MSG_EQ_TOL (m_mean, rtt->GetCurrentEstimate ().GetMilliSeconds (), tolerance, "Unexpected 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)
{
}
static RttEstimatorTestSuite g_rttEstimatorTestSuite;
static class RttTestSuite : public TestSuite
{
public:
RttTestSuite ()
: TestSuite ("rtt", 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);
}
} g_tcpTestSuite;