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;