Add ASF measurement lifetime as strategy parameter
Refs: #5332
Change-Id: Iff42ca0870d4263f0ad8757a67b87e52dbfff9f5
diff --git a/daemon/fw/asf-measurements.cpp b/daemon/fw/asf-measurements.cpp
index 957e3a0..73b7cca 100644
--- a/daemon/fw/asf-measurements.cpp
+++ b/daemon/fw/asf-measurements.cpp
@@ -69,7 +69,7 @@
void
NamespaceInfo::extendFaceInfoLifetime(FaceInfo& info, FaceId faceId)
{
- info.m_measurementExpiration = getScheduler().schedule(AsfMeasurements::MEASUREMENTS_LIFETIME,
+ info.m_measurementExpiration = getScheduler().schedule(m_measurementLifetime,
[=] { m_fiMap.erase(faceId); });
}
@@ -105,7 +105,7 @@
// Set or update entry lifetime
extendLifetime(*me);
- NamespaceInfo* info = me->insertStrategyInfo<NamespaceInfo>(m_rttEstimatorOpts).first;
+ NamespaceInfo* info = me->insertStrategyInfo<NamespaceInfo>(m_rttEstimatorOpts, m_measurementsLifetime).first;
BOOST_ASSERT(info != nullptr);
return info;
}
@@ -129,7 +129,7 @@
// Set or update entry lifetime
extendLifetime(*me);
- NamespaceInfo* info = me->insertStrategyInfo<NamespaceInfo>(m_rttEstimatorOpts).first;
+ NamespaceInfo* info = me->insertStrategyInfo<NamespaceInfo>(m_rttEstimatorOpts, m_measurementsLifetime).first;
BOOST_ASSERT(info != nullptr);
return *info;
}
@@ -137,7 +137,7 @@
void
AsfMeasurements::extendLifetime(measurements::Entry& me)
{
- m_measurements.extendLifetime(me, MEASUREMENTS_LIFETIME);
+ m_measurements.extendLifetime(me, m_measurementsLifetime);
}
} // namespace nfd::fw::asf
diff --git a/daemon/fw/asf-measurements.hpp b/daemon/fw/asf-measurements.hpp
index 75a3c2b..77925b6 100644
--- a/daemon/fw/asf-measurements.hpp
+++ b/daemon/fw/asf-measurements.hpp
@@ -132,8 +132,9 @@
}
explicit
- NamespaceInfo(shared_ptr<const ndn::util::RttEstimator::Options> opts)
+ NamespaceInfo(shared_ptr<const ndn::util::RttEstimator::Options> opts, time::milliseconds measurementLifetime)
: m_rttEstimatorOpts(std::move(opts))
+ , m_measurementLifetime(measurementLifetime)
{
}
@@ -173,6 +174,7 @@
private:
std::unordered_map<FaceId, FaceInfo> m_fiMap;
shared_ptr<const ndn::util::RttEstimator::Options> m_rttEstimatorOpts;
+ time::milliseconds m_measurementLifetime;
bool m_isProbingDue = false;
bool m_isFirstProbeScheduled = false;
};
@@ -201,14 +203,29 @@
NamespaceInfo&
getOrCreateNamespaceInfo(const fib::Entry& fibEntry, const Name& prefix);
+ void
+ setMeasurementsLifetime(time::milliseconds measurementsLifetime)
+ {
+ // Measurement lifetime should not expire as soon as it is configured
+ BOOST_ASSERT(measurementsLifetime > 0_ms);
+ m_measurementsLifetime = measurementsLifetime;
+ }
+
+ time::milliseconds
+ getMeasurementsLifetime() const
+ {
+ return m_measurementsLifetime;
+ }
+
private:
void
extendLifetime(measurements::Entry& me);
public:
- static constexpr time::microseconds MEASUREMENTS_LIFETIME = 5_min;
+ static constexpr time::milliseconds DEFAULT_MEASUREMENTS_LIFETIME = 5_min;
private:
+ time::milliseconds m_measurementsLifetime = DEFAULT_MEASUREMENTS_LIFETIME;
MeasurementsAccessor& m_measurements;
shared_ptr<const ndn::util::RttEstimator::Options> m_rttEstimatorOpts;
};
diff --git a/daemon/fw/asf-probing-module.cpp b/daemon/fw/asf-probing-module.cpp
index a465a5b..27c493e 100644
--- a/daemon/fw/asf-probing-module.cpp
+++ b/daemon/fw/asf-probing-module.cpp
@@ -32,7 +32,7 @@
namespace nfd::fw::asf {
-static_assert(ProbingModule::DEFAULT_PROBING_INTERVAL < AsfMeasurements::MEASUREMENTS_LIFETIME);
+static_assert(ProbingModule::DEFAULT_PROBING_INTERVAL < AsfMeasurements::DEFAULT_MEASUREMENTS_LIFETIME);
ProbingModule::ProbingModule(AsfMeasurements& measurements)
: m_probingInterval(DEFAULT_PROBING_INTERVAL)
diff --git a/daemon/fw/asf-strategy.cpp b/daemon/fw/asf-strategy.cpp
index edb6ec1..8688729 100644
--- a/daemon/fw/asf-strategy.cpp
+++ b/daemon/fw/asf-strategy.cpp
@@ -26,6 +26,7 @@
#include "asf-strategy.hpp"
#include "algorithm.hpp"
#include "common/logger.hpp"
+#include <boost/lexical_cast.hpp>
namespace nfd::fw::asf {
@@ -48,12 +49,21 @@
m_probing.getProbingInterval().count());
m_probing.setProbingInterval(time::milliseconds(probingInterval));
m_nMaxTimeouts = params.getOrDefault<size_t>("max-timeouts", m_nMaxTimeouts);
+ auto measurementsLifetime = time::milliseconds(params.getOrDefault<time::milliseconds::rep>("measurements-lifetime",
+ AsfMeasurements::DEFAULT_MEASUREMENTS_LIFETIME.count()));
+ if (measurementsLifetime <= m_probing.getProbingInterval()) {
+ NDN_THROW(std::invalid_argument("Measurements lifetime (" + boost::lexical_cast<std::string>(measurementsLifetime) +
+ ") should be greater than the probing interval of " +
+ boost::lexical_cast<std::string>(m_probing.getProbingInterval())));
+ }
+ m_measurements.setMeasurementsLifetime(measurementsLifetime);
this->setInstanceName(makeInstanceName(name, getStrategyName()));
NDN_LOG_DEBUG(*m_retxSuppression);
NFD_LOG_DEBUG("probing-interval=" << m_probing.getProbingInterval()
- << " max-timeouts=" << m_nMaxTimeouts);
+ << " max-timeouts=" << m_nMaxTimeouts
+ << " measurements-lifetime=" << m_measurements.getMeasurementsLifetime());
}
const Name&
diff --git a/daemon/fw/asf-strategy.hpp b/daemon/fw/asf-strategy.hpp
index 83bff13..b41b4ab 100644
--- a/daemon/fw/asf-strategy.hpp
+++ b/daemon/fw/asf-strategy.hpp
@@ -85,9 +85,6 @@
void
sendNoRouteNack(Face& face, const shared_ptr<pit::Entry>& pitEntry);
-private:
- AsfMeasurements m_measurements{getMeasurements()};
-
NFD_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
struct FaceStatsForwardingCompare
{
@@ -96,6 +93,7 @@
};
using FaceStatsForwardingSet = std::set<FaceStats, FaceStatsForwardingCompare>;
+ AsfMeasurements m_measurements{getMeasurements()};
std::unique_ptr<RetxSuppressionExponential> m_retxSuppression;
ProbingModule m_probing{m_measurements};
size_t m_nMaxTimeouts = 3;
diff --git a/docs/manpages/nfd-asf-strategy.rst b/docs/manpages/nfd-asf-strategy.rst
index 45339b8..ff7079a 100644
--- a/docs/manpages/nfd-asf-strategy.rst
+++ b/docs/manpages/nfd-asf-strategy.rst
@@ -24,6 +24,14 @@
integer). Smaller values will result in higher overhead but faster reaction.
The default value is 1 minute and the minimum value is 1 second.
+.. option:: measurements-lifetime <LIFETIME>
+
+ This optional parameter tells ASF how long to retain NamespaceInfo and FaceInfo
+ measurements if they are not actively updated. If not specified, this value defaults
+ to 5 minutes. This value is specified in (non-negative integer) milliseconds and must
+ be greater than the probing interval, as otherwise there is negligible benefit gained
+ from the additional traffic generated by ASF.
+
.. option:: max-timeouts <TIMEOUTS>
This optional parameter makes ASF switch to another appropriate face (if available)
@@ -45,8 +53,11 @@
``nfdc strategy set prefix /ndn strategy /localhost/nfd/strategy/asf/v=5/max-timeouts~5``
Set the maximum number of timeouts to 5.
-``nfdc strategy set prefix /ndn strategy /localhost/nfd/strategy/asf/v=5/probing-interval~30000/max-timeouts~2``
- Set the probing interval to 30 seconds and the maximum number of timeouts to 2.
+``nfdc strategy set prefix /ndn strategy /localhost/nfd/strategy/asf/v=5/measurements-lifetime~120000``
+ Set the maximum measurement lifetime to 2 minutes.
+
+``nfdc strategy set prefix /ndn strategy /localhost/nfd/strategy/asf/v=5/probing-interval~30000/max-timeouts~2/measurements-lifetime~120000``
+ Set the probing interval to 30 seconds, the maximum number of timeouts to 2, and the maximum measurement lifetime to 2 minutes.
``nfdc strategy set prefix /ndn strategy /localhost/nfd/strategy/asf/v=5/retx-suppression-multiplier~2.5/probing-interval~45000``
Set the retransmission suppression multiplier to 2.5 and the probing interval
diff --git a/tests/daemon/fw/asf-measurements.t.cpp b/tests/daemon/fw/asf-measurements.t.cpp
index 4de0493..e44144b 100644
--- a/tests/daemon/fw/asf-measurements.t.cpp
+++ b/tests/daemon/fw/asf-measurements.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2022, Regents of the University of California,
+ * Copyright (c) 2014-2024, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -75,14 +75,14 @@
BOOST_FIXTURE_TEST_CASE(NamespaceInfo, GlobalIoTimeFixture)
{
using fw::asf::NamespaceInfo;
- NamespaceInfo info(nullptr);
+ NamespaceInfo info(nullptr, fw::asf::AsfMeasurements::DEFAULT_MEASUREMENTS_LIFETIME);
BOOST_CHECK(info.getFaceInfo(1234) == nullptr);
auto& faceInfo = info.getOrCreateFaceInfo(1234);
BOOST_CHECK(info.getFaceInfo(1234) == &faceInfo);
- this->advanceClocks(fw::asf::AsfMeasurements::MEASUREMENTS_LIFETIME + 1_s);
+ this->advanceClocks(fw::asf::AsfMeasurements::DEFAULT_MEASUREMENTS_LIFETIME + 1_s);
BOOST_CHECK(info.getFaceInfo(1234) == nullptr); // expired
}
diff --git a/tests/daemon/fw/asf-strategy.t.cpp b/tests/daemon/fw/asf-strategy.t.cpp
index dce7118..17a19a7 100644
--- a/tests/daemon/fw/asf-strategy.t.cpp
+++ b/tests/daemon/fw/asf-strategy.t.cpp
@@ -561,18 +561,33 @@
auto strategy = checkValidity("", true);
BOOST_TEST(strategy->m_probing.getProbingInterval() == 60_s);
BOOST_TEST(strategy->m_nMaxTimeouts == 3);
- strategy = checkValidity("/probing-interval~30000/max-timeouts~5", true);
+ BOOST_TEST(strategy->m_measurements.getMeasurementsLifetime() == 5_min);
+ strategy = checkValidity("/probing-interval~30000/max-timeouts~5/measurements-lifetime~120000", true);
BOOST_TEST(strategy->m_probing.getProbingInterval() == 30_s);
BOOST_TEST(strategy->m_nMaxTimeouts == 5);
+ BOOST_TEST(strategy->m_measurements.getMeasurementsLifetime() == 2_min);
strategy = checkValidity("/max-timeouts~5/probing-interval~30000", true);
BOOST_TEST(strategy->m_probing.getProbingInterval() == 30_s);
BOOST_TEST(strategy->m_nMaxTimeouts == 5);
+ BOOST_TEST(strategy->m_measurements.getMeasurementsLifetime() == 5_min);
+ strategy = checkValidity("/max-timeouts~5/measurements-lifetime~120000", true);
+ BOOST_TEST(strategy->m_nMaxTimeouts == 5);
+ BOOST_TEST(strategy->m_measurements.getMeasurementsLifetime() == 2_min);
+ strategy = checkValidity("/probing-interval~30000/measurements-lifetime~120000", true);
+ BOOST_TEST(strategy->m_probing.getProbingInterval() == 30_s);
+ BOOST_TEST(strategy->m_measurements.getMeasurementsLifetime() == 2_min);
strategy = checkValidity("/probing-interval~1000", true);
BOOST_TEST(strategy->m_probing.getProbingInterval() == 1_s);
BOOST_TEST(strategy->m_nMaxTimeouts == 3);
+ BOOST_TEST(strategy->m_measurements.getMeasurementsLifetime() == 5_min);
strategy = checkValidity("/max-timeouts~0", true);
BOOST_TEST(strategy->m_probing.getProbingInterval() == 60_s);
BOOST_TEST(strategy->m_nMaxTimeouts == 0);
+ BOOST_TEST(strategy->m_measurements.getMeasurementsLifetime() == 5_min);
+ strategy = checkValidity("/measurements-lifetime~120000", true);
+ BOOST_TEST(strategy->m_probing.getProbingInterval() == 60_s);
+ BOOST_TEST(strategy->m_nMaxTimeouts == 3);
+ BOOST_TEST(strategy->m_measurements.getMeasurementsLifetime() == 2_min);
BOOST_TEST(strategy->m_retxSuppression->m_initialInterval == fw::RetxSuppressionExponential::DEFAULT_INITIAL_INTERVAL);
BOOST_TEST(strategy->m_retxSuppression->m_maxInterval == fw::RetxSuppressionExponential::DEFAULT_MAX_INTERVAL);
BOOST_TEST(strategy->m_retxSuppression->m_multiplier == fw::RetxSuppressionExponential::DEFAULT_MULTIPLIER);
@@ -585,6 +600,15 @@
checkValidity("/max-timeouts~1/probing-interval~-30000", false);
checkValidity("/probing-interval~foo", false);
checkValidity("/max-timeouts~1~2", false);
+ checkValidity("/measurements-lifetime~1000", false); //Minimum is 60s by default
+ //Measurement lifetime must be greater than probing interval
+ checkValidity("/measurements-lifetime~1000/probing-interval~30000", false);
+ checkValidity("/measurements-lifetime~-120000", false);
+ checkValidity("/measurements-lifetime~ -120000", false);
+ checkValidity("/measurements-lifetime~0-120000", false);
+ checkValidity("/max-timeouts~1/measurements-lifetime~-120000", false);
+ checkValidity("/probing-interval~30000/measurements-lifetime~-120000", false);
+ checkValidity("/max-timeouts~1/probing-interval~30000/measurements-lifetime~-120000", false);
}
BOOST_AUTO_TEST_CASE(FaceRankingForForwarding)