catchunks: use ndn-cxx's RttEstimator
Refs: #4887
Change-Id: If24bea40a22909bf0fd9e49ec7b18330dbe336f2
diff --git a/tools/chunks/catchunks/main.cpp b/tools/chunks/catchunks/main.cpp
index af345cf..9ec1973 100644
--- a/tools/chunks/catchunks/main.cpp
+++ b/tools/chunks/catchunks/main.cpp
@@ -35,7 +35,6 @@
#include "pipeline-interests-aimd.hpp"
#include "pipeline-interests-cubic.hpp"
#include "pipeline-interests-fixed.hpp"
-#include "rtt-estimator.hpp"
#include "statistics-collector.hpp"
#include "core/version.hpp"
@@ -207,9 +206,7 @@
try {
Face face;
-
auto discover = make_unique<DiscoverVersion>(Name(uri), face, options);
-
unique_ptr<PipelineInterests> pipeline;
unique_ptr<StatisticsCollector> statsCollector;
unique_ptr<RttEstimator> rttEstimator;
@@ -223,20 +220,29 @@
}
else if (pipelineType == "aimd" || pipelineType == "cubic") {
RttEstimator::Options optionsRttEst;
- optionsRttEst.isVerbose = options.isVerbose;
optionsRttEst.alpha = rtoAlpha;
optionsRttEst.beta = rtoBeta;
optionsRttEst.k = k;
- optionsRttEst.minRto = Milliseconds(minRto);
- optionsRttEst.maxRto = Milliseconds(maxRto);
-
+ optionsRttEst.minRto = RttEstimator::MillisecondsDouble(minRto);
+ optionsRttEst.maxRto = RttEstimator::MillisecondsDouble(maxRto);
rttEstimator = make_unique<RttEstimator>(optionsRttEst);
+ if (options.isVerbose) {
+ std::cerr << "RTT estimator parameters:\n"
+ << "\tAlpha = " << optionsRttEst.alpha << "\n"
+ << "\tBeta = " << optionsRttEst.beta << "\n"
+ << "\tK = " << optionsRttEst.k << "\n"
+ << "\tInitial RTO = " << optionsRttEst.initialRto << "\n"
+ << "\tMin RTO = " << optionsRttEst.minRto << "\n"
+ << "\tMax RTO = " << optionsRttEst.maxRto << "\n"
+ << "\tBackoff multiplier = " << optionsRttEst.rtoBackoffMultiplier << "\n";
+ }
+
PipelineInterestsAdaptive::Options optionsPipeline(options);
optionsPipeline.disableCwa = disableCwa;
optionsPipeline.resetCwndToInit = resetCwndToInit;
- optionsPipeline.initCwnd = static_cast<double>(initCwnd);
- optionsPipeline.initSsthresh = static_cast<double>(initSsthresh);
+ optionsPipeline.initCwnd = initCwnd;
+ optionsPipeline.initSsthresh = initSsthresh;
optionsPipeline.aiStep = aiStep;
optionsPipeline.mdCoef = aimdBeta;
optionsPipeline.ignoreCongMarks = ignoreCongMarks;
diff --git a/tools/chunks/catchunks/pipeline-interests-adaptive.cpp b/tools/chunks/catchunks/pipeline-interests-adaptive.cpp
index 93cd30d..fd28829 100644
--- a/tools/chunks/catchunks/pipeline-interests-adaptive.cpp
+++ b/tools/chunks/catchunks/pipeline-interests-adaptive.cpp
@@ -101,8 +101,8 @@
for (auto& entry : m_segmentInfo) {
SegmentInfo& segInfo = entry.second;
if (segInfo.state != SegmentState::InRetxQueue) { // skip segments already in the retx queue
- Milliseconds timeElapsed = time::steady_clock::now() - segInfo.timeSent;
- if (timeElapsed.count() > segInfo.rto.count()) { // timer expired?
+ auto timeElapsed = time::steady_clock::now() - segInfo.timeSent;
+ if (timeElapsed > segInfo.rto) { // timer expired?
m_nTimeouts++;
hasTimeout = true;
enqueueForRetransmission(entry.first);
@@ -235,7 +235,7 @@
}
SegmentInfo& segInfo = segIt->second;
- Milliseconds rtt = time::steady_clock::now() - segInfo.timeSent;
+ RttEstimator::MillisecondsDouble rtt = time::steady_clock::now() - segInfo.timeSent;
if (m_options.isVerbose) {
std::cerr << "Received segment #" << recvSegNo
<< ", rtt=" << rtt.count() << "ms"
@@ -285,7 +285,7 @@
m_retxCount.count(recvSegNo) == 0) {
auto nExpectedSamples = std::max<int64_t>((m_nInFlight + 1) >> 1, 1);
BOOST_ASSERT(nExpectedSamples > 0);
- m_rttEstimator.addMeasurement(recvSegNo, rtt, static_cast<size_t>(nExpectedSamples));
+ m_rttEstimator.addMeasurement(rtt, static_cast<size_t>(nExpectedSamples), recvSegNo);
}
// remove the entry associated with the received segment
@@ -422,15 +422,15 @@
<< ", skipped: " << m_nSkippedRetx << "\n"
<< "RTT ";
- if (m_rttEstimator.getMinRtt() == std::numeric_limits<double>::max() ||
- m_rttEstimator.getMaxRtt() == std::numeric_limits<double>::min()) {
- std::cerr << "stats unavailable\n";
- }
- else {
- std::cerr << "min/avg/max = " << std::fixed << std::setprecision(3)
- << m_rttEstimator.getMinRtt() << "/"
- << m_rttEstimator.getAvgRtt() << "/"
- << m_rttEstimator.getMaxRtt() << " ms\n";
+ if (m_rttEstimator.getMinRtt().count() == std::numeric_limits<double>::max() ||
+ m_rttEstimator.getMaxRtt().count() == std::numeric_limits<double>::min()) {
+ std::cerr << "stats unavailable\n";
+ }
+ else {
+ std::cerr << "min/avg/max = " << std::fixed << std::setprecision(3)
+ << m_rttEstimator.getMinRtt().count() << "/"
+ << m_rttEstimator.getAvgRtt().count() << "/"
+ << m_rttEstimator.getMaxRtt().count() << " ms\n";
}
}
diff --git a/tools/chunks/catchunks/pipeline-interests-adaptive.hpp b/tools/chunks/catchunks/pipeline-interests-adaptive.hpp
index 0c4f889..8ecc45b 100644
--- a/tools/chunks/catchunks/pipeline-interests-adaptive.hpp
+++ b/tools/chunks/catchunks/pipeline-interests-adaptive.hpp
@@ -30,15 +30,18 @@
#define NDN_TOOLS_CHUNKS_CATCHUNKS_PIPELINE_INTERESTS_ADAPTIVE_HPP
#include "options.hpp"
-#include "rtt-estimator.hpp"
#include "pipeline-interests.hpp"
+#include <ndn-cxx/util/rtt-estimator.hpp>
+
#include <queue>
#include <unordered_map>
namespace ndn {
namespace chunks {
+using util::RttEstimator;
+
class PipelineInterestsAdaptiveOptions : public Options
{
public:
@@ -81,7 +84,7 @@
{
ScopedPendingInterestHandle interestHdl;
time::steady_clock::TimePoint timeSent;
- Milliseconds rto;
+ RttEstimator::MillisecondsDouble rto;
SegmentState state;
};
@@ -116,10 +119,10 @@
/**
* @brief Signals when the congestion window changes.
*
- * The callback function should be: void(Milliseconds age, double cwnd) where age is the
- * duration since pipeline starts, and cwnd is the new congestion window size (in segments).
+ * The callback function should be: `void(nanoseconds age, double cwnd)`, where `age` is the
+ * time since the pipeline started and `cwnd` is the new congestion window size (in segments).
*/
- signal::Signal<PipelineInterestsAdaptive, Milliseconds, double> afterCwndChange;
+ signal::Signal<PipelineInterestsAdaptive, time::nanoseconds, double> afterCwndChange;
protected:
DECLARE_SIGNAL_EMIT(afterCwndChange)
diff --git a/tools/chunks/catchunks/rtt-estimator.cpp b/tools/chunks/catchunks/rtt-estimator.cpp
deleted file mode 100644
index fd3a592..0000000
--- a/tools/chunks/catchunks/rtt-estimator.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2016-2019, Arizona Board of Regents.
- *
- * This file is part of ndn-tools (Named Data Networking Essential Tools).
- * See AUTHORS.md for complete list of ndn-tools authors and contributors.
- *
- * ndn-tools is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Shuo Yang
- * @author Weiwei Liu
- * @author Chavoosh Ghasemi
- */
-
-#include "rtt-estimator.hpp"
-
-#include <cmath>
-
-namespace ndn {
-namespace chunks {
-
-RttEstimator::RttEstimator(const Options& options)
- : m_options(options)
- , m_sRtt(std::numeric_limits<double>::quiet_NaN())
- , m_rttVar(std::numeric_limits<double>::quiet_NaN())
- , m_rto(m_options.initialRto.count())
- , m_rttMin(std::numeric_limits<double>::max())
- , m_rttMax(std::numeric_limits<double>::min())
- , m_rttAvg(0.0)
- , m_nRttSamples(0)
-{
- if (m_options.isVerbose) {
- std::cerr << m_options;
- }
-}
-
-void
-RttEstimator::addMeasurement(uint64_t segNo, Milliseconds rtt, size_t nExpectedSamples)
-{
- BOOST_ASSERT(nExpectedSamples > 0);
-
- if (m_nRttSamples == 0) { // first measurement
- m_sRtt = rtt;
- m_rttVar = m_sRtt / 2;
- m_rto = m_sRtt + m_options.k * m_rttVar;
- }
- else {
- double alpha = m_options.alpha / nExpectedSamples;
- double beta = m_options.beta / nExpectedSamples;
- m_rttVar = (1 - beta) * m_rttVar + beta * time::abs(m_sRtt - rtt);
- m_sRtt = (1 - alpha) * m_sRtt + alpha * rtt;
- m_rto = m_sRtt + m_options.k * m_rttVar;
- }
-
- m_rto = ndn::clamp(m_rto, m_options.minRto, m_options.maxRto);
- afterRttMeasurement({segNo, rtt, m_sRtt, m_rttVar, m_rto});
-
- m_rttAvg = (m_nRttSamples * m_rttAvg + rtt.count()) / (m_nRttSamples + 1);
- m_rttMax = std::max(rtt.count(), m_rttMax);
- m_rttMin = std::min(rtt.count(), m_rttMin);
- m_nRttSamples++;
-}
-
-void
-RttEstimator::backoffRto()
-{
- m_rto = ndn::clamp(m_rto * m_options.rtoBackoffMultiplier,
- m_options.minRto, m_options.maxRto);
-}
-
-std::ostream&
-operator<<(std::ostream& os, const RttEstimator::Options& options)
-{
- os << "RTT estimator parameters:\n"
- << "\tAlpha = " << options.alpha << "\n"
- << "\tBeta = " << options.beta << "\n"
- << "\tK = " << options.k << "\n"
- << "\tInitial RTO = " << options.initialRto << "\n"
- << "\tMin RTO = " << options.minRto << "\n"
- << "\tMax RTO = " << options.maxRto << "\n";
- return os;
-}
-
-} // namespace chunks
-} // namespace ndn
diff --git a/tools/chunks/catchunks/rtt-estimator.hpp b/tools/chunks/catchunks/rtt-estimator.hpp
deleted file mode 100644
index 47f2ac8..0000000
--- a/tools/chunks/catchunks/rtt-estimator.hpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2016-2019, Arizona Board of Regents.
- *
- * This file is part of ndn-tools (Named Data Networking Essential Tools).
- * See AUTHORS.md for complete list of ndn-tools authors and contributors.
- *
- * ndn-tools is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- *
- * @author Shuo Yang
- * @author Weiwei Liu
- * @author Chavoosh Ghasemi
- */
-
-#ifndef NDN_TOOLS_CHUNKS_CATCHUNKS_RTT_ESTIMATOR_HPP
-#define NDN_TOOLS_CHUNKS_CATCHUNKS_RTT_ESTIMATOR_HPP
-
-#include "core/common.hpp"
-
-namespace ndn {
-namespace chunks {
-
-typedef time::duration<double, time::milliseconds::period> Milliseconds;
-
-struct RttRtoSample
-{
- uint64_t segNo;
- Milliseconds rtt; ///< measured RTT
- Milliseconds sRtt; ///< smoothed RTT
- Milliseconds rttVar; ///< RTT variation
- Milliseconds rto; ///< retransmission timeout
-};
-
-/**
- * @brief RTT Estimator.
- *
- * This class implements the "Mean-Deviation" RTT estimator, as discussed in RFC 6298,
- * with the modifications to RTO calculation described in RFC 7323 Appendix G.
- */
-class RttEstimator
-{
-public:
- class Options
- {
- public:
- Options()
- : isVerbose(false)
- , alpha(0.125)
- , beta(0.25)
- , k(8)
- , initialRto(1000.0)
- , minRto(200.0)
- , maxRto(20000.0)
- , rtoBackoffMultiplier(2)
- {
- }
-
- public:
- bool isVerbose;
- double alpha; ///< parameter for RTT estimation
- double beta; ///< parameter for RTT variation calculation
- int k; ///< factor of RTT variation when calculating RTO
- Milliseconds initialRto; ///< initial RTO value
- Milliseconds minRto; ///< lower bound of RTO
- Milliseconds maxRto; ///< upper bound of RTO
- int rtoBackoffMultiplier;
- };
-
- /**
- * @brief Create a RTT Estimator
- *
- * Configures the RTT Estimator with the default parameters if an instance of Options
- * is not passed to the constructor.
- */
- explicit
- RttEstimator(const Options& options = Options());
-
- /**
- * @brief Add a new RTT measurement to the estimator for the given received segment.
- *
- * @param segNo the segment number of the received segmented Data
- * @param rtt the sampled rtt
- * @param nExpectedSamples number of expected samples, must be greater than 0.
- * It should be set to current number of in-flight Interests. Please
- * refer to Appendix G of RFC 7323 for details.
- * @note Don't take RTT measurement for retransmitted segments
- */
- void
- addMeasurement(uint64_t segNo, Milliseconds rtt, size_t nExpectedSamples);
-
- /**
- * @brief Returns the estimated RTO value
- */
- Milliseconds
- getEstimatedRto() const
- {
- return m_rto;
- }
-
- /**
- * @brief Returns the minimum RTT observed
- */
- double
- getMinRtt() const
- {
- return m_rttMin;
- }
-
- /**
- * @brief Returns the maximum RTT observed
- */
- double
- getMaxRtt() const
- {
- return m_rttMax;
- }
-
- /**
- * @brief Returns the average RTT
- */
- double
- getAvgRtt() const
- {
- return m_rttAvg;
- }
-
- /**
- * @brief Backoff RTO by a factor of Options::rtoBackoffMultiplier
- */
- void
- backoffRto();
-
- /**
- * @brief Signals after rtt is measured
- */
- signal::Signal<RttEstimator, RttRtoSample> afterRttMeasurement;
-
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
- const Options m_options;
- Milliseconds m_sRtt; ///< smoothed round-trip time
- Milliseconds m_rttVar; ///< round-trip time variation
- Milliseconds m_rto; ///< retransmission timeout
-
- double m_rttMin;
- double m_rttMax;
- double m_rttAvg;
- int64_t m_nRttSamples; ///< number of RTT samples
-};
-
-std::ostream&
-operator<<(std::ostream& os, const RttEstimator::Options& options);
-
-} // namespace chunks
-} // namespace ndn
-
-#endif // NDN_TOOLS_CHUNKS_CATCHUNKS_RTT_ESTIMATOR_HPP
diff --git a/tools/chunks/catchunks/statistics-collector.cpp b/tools/chunks/catchunks/statistics-collector.cpp
index 44c342c..8984e78 100644
--- a/tools/chunks/catchunks/statistics-collector.cpp
+++ b/tools/chunks/catchunks/statistics-collector.cpp
@@ -27,7 +27,8 @@
namespace ndn {
namespace chunks {
-StatisticsCollector::StatisticsCollector(PipelineInterestsAdaptive& pipeline, RttEstimator& rttEstimator,
+StatisticsCollector::StatisticsCollector(PipelineInterestsAdaptive& pipeline,
+ RttEstimator& rttEstimator,
std::ostream& osCwnd, std::ostream& osRtt)
: m_osCwnd(osCwnd)
, m_osRtt(osRtt)
@@ -35,18 +36,18 @@
m_osCwnd << "time\tcwndsize\n";
m_osRtt << "segment\trtt\trttvar\tsrtt\trto\n";
pipeline.afterCwndChange.connect(
- [this] (Milliseconds timeElapsed, double cwnd) {
- m_osCwnd << timeElapsed.count() / 1000 << '\t' << cwnd << '\n';
+ [this] (time::nanoseconds timeElapsed, double cwnd) {
+ m_osCwnd << timeElapsed.count() / 1e9 << '\t' << cwnd << '\n';
});
- rttEstimator.afterRttMeasurement.connect(
- [this] (const RttRtoSample& rttSample) {
- m_osRtt << rttSample.segNo << '\t'
- << rttSample.rtt.count() << '\t'
- << rttSample.rttVar.count() << '\t'
- << rttSample.sRtt.count() << '\t'
- << rttSample.rto.count() << '\n';
+ rttEstimator.afterMeasurement.connect(
+ [this] (const RttEstimator::Sample& sample) {
+ m_osRtt << *sample.segNum << '\t'
+ << sample.rtt.count() << '\t'
+ << sample.rttVar.count() << '\t'
+ << sample.sRtt.count() << '\t'
+ << sample.rto.count() << '\n';
});
}
} // namespace chunks
-} // namespace ndn
\ No newline at end of file
+} // namespace ndn
diff --git a/tools/chunks/catchunks/statistics-collector.hpp b/tools/chunks/catchunks/statistics-collector.hpp
index cd71018..35a0846 100644
--- a/tools/chunks/catchunks/statistics-collector.hpp
+++ b/tools/chunks/catchunks/statistics-collector.hpp
@@ -26,7 +26,6 @@
#define NDN_TOOLS_CHUNKS_CATCHUNKS_STATISTICS_COLLECTOR_HPP
#include "pipeline-interests-adaptive.hpp"
-#include "rtt-estimator.hpp"
namespace ndn {
namespace chunks {