Files
ndn-tools/tools/cc/client/ndn-rtt-mean-deviation.cpp
T
2024-01-20 22:16:50 +08:00

120 lines
4.5 KiB
C++

#include "ndn-rtt-mean-deviation.hpp"
namespace ndn
{
namespace cc
{
namespace client
{
RttMeanDeviation::RttMeanDeviation()
: m_gain(0.125),
m_gain2(0.25),
m_variance(0)
{
}
RttMeanDeviation::RttMeanDeviation(const RttMeanDeviation &c)
: RttEstimator(c), m_gain(c.m_gain), m_gain2(c.m_gain2), m_variance(c.m_variance)
{
}
void
RttMeanDeviation::Measurement(time::steady_clock::duration m)
{
if (m_nSamples)
{ // Not first
time::steady_clock::duration err(m - m_currentEstimatedRtt);
double gErr = duration_to_second_double(err) * m_gain;
m_currentEstimatedRtt += second_double_to_duration(gErr);
auto abs_err = err > time::steady_clock::duration::zero() ? err : -err;
time::steady_clock::duration difference = abs_err - m_variance;
m_variance += second_double_to_duration(m_gain2 * duration_to_second_double(difference));
}
else
{ // First sample
m_currentEstimatedRtt = m; // Set estimate to current
// variance = sample / 2; // And variance to current / 2
// m_variance = m; // try this why????
m_variance = second_double_to_duration(duration_to_second_double(m) / 2);
}
m_nSamples++;
}
time::steady_clock::duration
RttMeanDeviation::RetransmitTimeout()
{
// std::cout << "RTO -> m_currentEstimatedRtt:" << duration_to_second_double(m_currentEstimatedRtt) << ", m_variance:" << duration_to_second_double(m_variance) << std::endl;
double retval = std::min(
duration_to_second_double(m_maxRto),
std::max(
m_multiplier * duration_to_second_double(m_minRto),
m_multiplier * (duration_to_second_double(m_currentEstimatedRtt) + 4 * duration_to_second_double(m_variance))));
return second_double_to_duration(retval);
}
void
RttMeanDeviation::Reset()
{
// Reset to initial state
m_variance = time::steady_clock::duration::zero();
RttEstimator::Reset();
}
void
RttMeanDeviation::Gain(double g)
{
m_gain = g;
}
void
RttMeanDeviation::SentSeq(uint32_t seq, uint32_t size)
{
RttHistory_t::iterator i;
for (i = m_history.begin(); i != m_history.end(); ++i)
{
if (seq == i->seq)
{ // Found it
i->retx = true;
break;
}
}
// Note that a particular sequence has been sent
if (i == m_history.end())
m_history.push_back(RttHistory(seq, size, time::steady_clock::now()));
}
time::steady_clock::duration
RttMeanDeviation::AckSeq(uint32_t 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
auto m = time::steady_clock::duration::zero();
if (m_history.size() == 0)
return (m); // No pending history, just exit
for (RttHistory_t::iterator i = m_history.begin(); i != m_history.end(); ++i)
{
if (ackSeq == i->seq)
{ // Found it
if (!i->retx)
{
m = time::steady_clock::now() - i->time; // Elapsed time
Measurement(m); // Log the measurement
ResetMultiplier(); // Reset multiplier on valid measurement
}
m_history.erase(i);
break;
}
}
return m;
}
}
}
}