fw: Add ASF strategy parameters n-silent-timeouts & probing-interval
refs: #4193
Change-Id: I9572425a2fdcbf67b9886c2a5b6b50a10a0856e2
diff --git a/daemon/fw/asf-measurements.cpp b/daemon/fw/asf-measurements.cpp
index e8bc8fd..e85ec3f 100644
--- a/daemon/fw/asf-measurements.cpp
+++ b/daemon/fw/asf-measurements.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -66,6 +66,7 @@
FaceInfo::FaceInfo()
: m_isTimeoutScheduled(false)
+ , m_nSilentTimeouts(0)
{
}
@@ -147,9 +148,9 @@
}
FaceInfo*
-NamespaceInfo::getFaceInfo(const fib::Entry& fibEntry, const Face& face)
+NamespaceInfo::getFaceInfo(const fib::Entry& fibEntry, FaceId faceId)
{
- FaceInfoTable::iterator it = m_fit.find(face.getId());
+ FaceInfoTable::iterator it = m_fit.find(faceId);
if (it != m_fit.end()) {
return &it->second;
@@ -160,17 +161,17 @@
}
FaceInfo&
-NamespaceInfo::getOrCreateFaceInfo(const fib::Entry& fibEntry, const Face& face)
+NamespaceInfo::getOrCreateFaceInfo(const fib::Entry& fibEntry, FaceId faceId)
{
- FaceInfoTable::iterator it = m_fit.find(face.getId());
+ FaceInfoTable::iterator it = m_fit.find(faceId);
FaceInfo* info = nullptr;
if (it == m_fit.end()) {
- const auto& pair = m_fit.insert(std::make_pair(face.getId(), FaceInfo()));
+ const auto& pair = m_fit.insert(std::make_pair(faceId, FaceInfo()));
info = &pair.first->second;
- extendFaceInfoLifetime(*info, face);
+ extendFaceInfoLifetime(*info, faceId);
}
else {
info = &it->second;
@@ -180,20 +181,20 @@
}
void
-NamespaceInfo::expireFaceInfo(nfd::face::FaceId faceId)
+NamespaceInfo::expireFaceInfo(FaceId faceId)
{
m_fit.erase(faceId);
}
void
-NamespaceInfo::extendFaceInfoLifetime(FaceInfo& info, const Face& face)
+NamespaceInfo::extendFaceInfoLifetime(FaceInfo& info, FaceId faceId)
{
// Cancel previous expiration
scheduler::cancel(info.getMeasurementExpirationEventId());
// Refresh measurement
scheduler::EventId id = scheduler::schedule(AsfMeasurements::MEASUREMENTS_LIFETIME,
- bind(&NamespaceInfo::expireFaceInfo, this, face.getId()));
+ bind(&NamespaceInfo::expireFaceInfo, this, faceId));
info.setMeasurementExpirationEventId(id);
}
@@ -209,17 +210,18 @@
}
FaceInfo*
-AsfMeasurements::getFaceInfo(const fib::Entry& fibEntry, const Interest& interest, const Face& face)
+AsfMeasurements::getFaceInfo(const fib::Entry& fibEntry, const Interest& interest, FaceId faceId)
{
NamespaceInfo& info = getOrCreateNamespaceInfo(fibEntry, interest);
- return info.getFaceInfo(fibEntry, face);
+ return info.getFaceInfo(fibEntry, faceId);
}
FaceInfo&
-AsfMeasurements::getOrCreateFaceInfo(const fib::Entry& fibEntry, const Interest& interest, const Face& face)
+AsfMeasurements::getOrCreateFaceInfo(const fib::Entry& fibEntry, const Interest& interest,
+ FaceId faceId)
{
NamespaceInfo& info = getOrCreateNamespaceInfo(fibEntry, interest);
- return info.getOrCreateFaceInfo(fibEntry, face);
+ return info.getOrCreateFaceInfo(fibEntry, faceId);
}
NamespaceInfo*
diff --git a/daemon/fw/asf-measurements.hpp b/daemon/fw/asf-measurements.hpp
index ba858df..ee5885d 100644
--- a/daemon/fw/asf-measurements.hpp
+++ b/daemon/fw/asf-measurements.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017, Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -166,6 +166,18 @@
return getSrtt() != RttStats::RTT_NO_MEASUREMENT;
}
+ size_t
+ getNSilentTimeouts() const
+ {
+ return m_nSilentTimeouts;
+ }
+
+ void
+ setNSilentTimeouts(size_t nSilentTimeouts)
+ {
+ m_nSilentTimeouts = nSilentTimeouts;
+ }
+
private:
void
cancelTimeoutEvent();
@@ -183,9 +195,10 @@
// RTO associated with Interest
scheduler::EventId m_timeoutEventId;
bool m_isTimeoutScheduled;
+ size_t m_nSilentTimeouts;
};
-typedef std::unordered_map<face::FaceId, FaceInfo> FaceInfoTable;
+typedef std::unordered_map<FaceId, FaceInfo> FaceInfoTable;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@@ -204,19 +217,19 @@
}
FaceInfo&
- getOrCreateFaceInfo(const fib::Entry& fibEntry, const Face& face);
+ getOrCreateFaceInfo(const fib::Entry& fibEntry, FaceId faceId);
FaceInfo*
- getFaceInfo(const fib::Entry& fibEntry, const Face& face);
+ getFaceInfo(const fib::Entry& fibEntry, FaceId faceId);
void
- expireFaceInfo(nfd::face::FaceId faceId);
+ expireFaceInfo(FaceId faceId);
void
- extendFaceInfoLifetime(FaceInfo& info, const Face& face);
+ extendFaceInfoLifetime(FaceInfo& info, FaceId faceId);
FaceInfo*
- get(nfd::face::FaceId faceId)
+ get(FaceId faceId)
{
if (m_fit.find(faceId) != m_fit.end()) {
return &m_fit.at(faceId);
@@ -227,7 +240,7 @@
}
FaceInfoTable::iterator
- find(nfd::face::FaceId faceId)
+ find(FaceId faceId)
{
return m_fit.find(faceId);
}
@@ -239,7 +252,7 @@
}
const FaceInfoTable::iterator
- insert(nfd::face::FaceId faceId)
+ insert(FaceId faceId)
{
const auto& pair = m_fit.insert(std::make_pair(faceId, FaceInfo()));
return pair.first;
@@ -288,10 +301,10 @@
AsfMeasurements(MeasurementsAccessor& measurements);
FaceInfo*
- getFaceInfo(const fib::Entry& fibEntry, const Interest& interest, const Face& face);
+ getFaceInfo(const fib::Entry& fibEntry, const Interest& interest, FaceId faceId);
FaceInfo&
- getOrCreateFaceInfo(const fib::Entry& fibEntry, const Interest& interest, const Face& face);
+ getOrCreateFaceInfo(const fib::Entry& fibEntry, const Interest& interest, FaceId faceId);
NamespaceInfo*
getNamespaceInfo(const Name& prefix);
diff --git a/daemon/fw/asf-probing-module.cpp b/daemon/fw/asf-probing-module.cpp
index f29d0e7..24b4577 100644
--- a/daemon/fw/asf-probing-module.cpp
+++ b/daemon/fw/asf-probing-module.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -31,7 +31,8 @@
namespace fw {
namespace asf {
-constexpr time::seconds ProbingModule::DEFAULT_PROBING_INTERVAL;
+constexpr time::milliseconds ProbingModule::DEFAULT_PROBING_INTERVAL;
+constexpr time::milliseconds ProbingModule::MIN_PROBING_INTERVAL;
static_assert(ProbingModule::DEFAULT_PROBING_INTERVAL < AsfMeasurements::MEASUREMENTS_LIFETIME,
"ProbingModule::DEFAULT_PROBING_INTERVAL must be less than AsfMeasurements::MEASUREMENTS_LIFETIME");
@@ -91,7 +92,7 @@
continue;
}
- FaceInfo* info = m_measurements.getFaceInfo(fibEntry, interest, hopFace);
+ FaceInfo* info = m_measurements.getFaceInfo(fibEntry, interest, hopFace.getId());
// If no RTT has been recorded, probe this face
if (info == nullptr || !info->hasSrttMeasurement()) {
@@ -189,6 +190,19 @@
return dist(getGlobalRng());
}
+void
+ProbingModule::setProbingInterval(size_t probingInterval)
+{
+ if (time::milliseconds(probingInterval) >= MIN_PROBING_INTERVAL) {
+ m_probingInterval = time::milliseconds(probingInterval);
+ }
+ else {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Probing interval should be >= "
+ + to_string(MIN_PROBING_INTERVAL.count())
+ + " milliseconds"));
+ }
+}
+
} // namespace asf
} // namespace fw
} // namespace nfd
diff --git a/daemon/fw/asf-probing-module.hpp b/daemon/fw/asf-probing-module.hpp
index 055adb0..785abd8 100644
--- a/daemon/fw/asf-probing-module.hpp
+++ b/daemon/fw/asf-probing-module.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -55,6 +55,15 @@
void
afterForwardingProbe(const fib::Entry& fibEntry, const Interest& interest);
+ void
+ setProbingInterval(size_t probingInterval);
+
+ time::milliseconds
+ getProbingInterval() const
+ {
+ return m_probingInterval;
+ }
+
private:
// Used to associate FaceInfo with the face in a NextHop
typedef std::pair<FaceInfo*, Face*> FaceInfoFacePair;
@@ -71,10 +80,11 @@
getRandomNumber(double start, double end);
public:
- static constexpr time::seconds DEFAULT_PROBING_INTERVAL = time::seconds(60);
+ static constexpr time::milliseconds DEFAULT_PROBING_INTERVAL = time::milliseconds(60000);
+ static constexpr time::milliseconds MIN_PROBING_INTERVAL = time::milliseconds(1000);
private:
- time::seconds m_probingInterval;
+ time::milliseconds m_probingInterval;
AsfMeasurements& m_measurements;
};
diff --git a/daemon/fw/asf-strategy.cpp b/daemon/fw/asf-strategy.cpp
index 5e14e37..ab629f9 100644
--- a/daemon/fw/asf-strategy.cpp
+++ b/daemon/fw/asf-strategy.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2017, Regents of the University of California,
+ * Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -42,29 +42,72 @@
: Strategy(forwarder)
, m_measurements(getMeasurements())
, m_probing(m_measurements)
+ , m_maxSilentTimeouts(0)
, m_retxSuppression(RETX_SUPPRESSION_INITIAL,
RetxSuppressionExponential::DEFAULT_MULTIPLIER,
RETX_SUPPRESSION_MAX)
{
ParsedInstanceName parsed = parseInstanceName(name);
if (!parsed.parameters.empty()) {
- BOOST_THROW_EXCEPTION(std::invalid_argument("AsfStrategy does not accept parameters"));
+ processParams(parsed.parameters);
}
+
if (parsed.version && *parsed.version != getStrategyName()[-1].toVersion()) {
BOOST_THROW_EXCEPTION(std::invalid_argument(
"AsfStrategy does not support version " + to_string(*parsed.version)));
}
this->setInstanceName(makeInstanceName(name, getStrategyName()));
+
+ NFD_LOG_DEBUG("Probing interval=" << m_probing.getProbingInterval()
+ << ", Num silent timeouts=" << m_maxSilentTimeouts);
}
const Name&
AsfStrategy::getStrategyName()
{
- static Name strategyName("/localhost/nfd/strategy/asf/%FD%02");
+ static Name strategyName("/localhost/nfd/strategy/asf/%FD%03");
return strategyName;
}
void
+AsfStrategy::processParams(const PartialName& parsed)
+{
+ for (const auto& component : parsed) {
+ std::string parsedStr(reinterpret_cast<const char*>(component.value()), component.value_size());
+ auto n = parsedStr.find("~");
+ if (n == std::string::npos) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Format is <parameter>~<value>"));
+ }
+
+ auto f = parsedStr.substr(0, n);
+ auto s = parsedStr.substr(n + 1);
+ if (f == "probing-interval") {
+ m_probing.setProbingInterval(getParamValue(f, s));
+ }
+ else if (f == "n-silent-timeouts") {
+ m_maxSilentTimeouts = getParamValue(f, s);
+ }
+ else {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Parameter should be probing-interval or n-silent-timeouts"));
+ }
+ }
+}
+
+uint64_t
+AsfStrategy::getParamValue(const std::string& param, const std::string& value)
+{
+ try {
+ if (!value.empty() && value[0] == '-')
+ BOOST_THROW_EXCEPTION(boost::bad_lexical_cast());
+
+ return boost::lexical_cast<uint64_t>(value);
+ }
+ catch (const boost::bad_lexical_cast&) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Value of " + param + " must be a non-negative integer"));
+ }
+}
+
+void
AsfStrategy::afterReceiveInterest(const Face& inFace, const Interest& interest,
const shared_ptr<pit::Entry>& pitEntry)
{
@@ -132,7 +175,7 @@
faceInfo->recordRtt(pitEntry, inFace);
// Extend lifetime for measurements associated with Face
- namespaceInfo->extendFaceInfoLifetime(*faceInfo, inFace);
+ namespaceInfo->extendFaceInfoLifetime(*faceInfo, inFace.getId());
if (faceInfo->isTimeoutScheduled()) {
faceInfo->cancelTimeoutEvent(data.getName());
@@ -169,11 +212,11 @@
this->sendInterest(pitEntry, outFace, interest);
}
- FaceInfo& faceInfo = m_measurements.getOrCreateFaceInfo(fibEntry, interest, outFace);
+ FaceInfo& faceInfo = m_measurements.getOrCreateFaceInfo(fibEntry, interest, outFace.getId());
// Refresh measurements since Face is being used for forwarding
NamespaceInfo& namespaceInfo = m_measurements.getOrCreateNamespaceInfo(fibEntry, interest);
- namespaceInfo.extendFaceInfoLifetime(faceInfo, outFace);
+ namespaceInfo.extendFaceInfoLifetime(faceInfo, outFace.getId());
if (!faceInfo.isTimeoutScheduled()) {
// Estimate and schedule timeout
@@ -251,7 +294,7 @@
continue;
}
- FaceInfo* info = m_measurements.getFaceInfo(fibEntry, interest, hopFace);
+ FaceInfo* info = m_measurements.getFaceInfo(fibEntry, interest, hopFace.getId());
if (info == nullptr) {
FaceStats stats = {&hopFace,
@@ -278,10 +321,8 @@
}
void
-AsfStrategy::onTimeout(const Name& interestName, face::FaceId faceId)
+AsfStrategy::onTimeout(const Name& interestName, const face::FaceId faceId)
{
- NFD_LOG_TRACE("FaceId: " << faceId << " for " << interestName << " has timed-out");
-
NamespaceInfo* namespaceInfo = m_measurements.getNamespaceInfo(interestName);
if (namespaceInfo == nullptr) {
@@ -296,7 +337,23 @@
}
FaceInfo& faceInfo = it->second;
- faceInfo.recordTimeout(interestName);
+
+ faceInfo.setNSilentTimeouts(faceInfo.getNSilentTimeouts() + 1);
+
+ if (faceInfo.getNSilentTimeouts() <= m_maxSilentTimeouts) {
+ NFD_LOG_TRACE("FaceId " << faceId << " for " << interestName << " has timed-out "
+ << faceInfo.getNSilentTimeouts() << " time(s), ignoring");
+ // Extend lifetime for measurements associated with Face
+ namespaceInfo->extendFaceInfoLifetime(faceInfo, faceId);
+
+ if (faceInfo.isTimeoutScheduled()) {
+ faceInfo.cancelTimeoutEvent(interestName);
+ }
+ }
+ else {
+ NFD_LOG_TRACE("FaceId " << faceId << " for " << interestName << " has timed-out");
+ faceInfo.recordTimeout(interestName);
+ }
}
void
diff --git a/daemon/fw/asf-strategy.hpp b/daemon/fw/asf-strategy.hpp
index eb1c65c..b58e656 100644
--- a/daemon/fw/asf-strategy.hpp
+++ b/daemon/fw/asf-strategy.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -51,15 +51,15 @@
getStrategyName();
public: // triggers
- virtual void
+ void
afterReceiveInterest(const Face& inFace, const Interest& interest,
const shared_ptr<pit::Entry>& pitEntry) override;
- virtual void
+ void
beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
const Face& inFace, const Data& data) override;
- virtual void
+ void
afterReceiveNack(const Face& inFace, const lp::Nack& nack,
const shared_ptr<pit::Entry>& pitEntry) override;
@@ -75,14 +75,21 @@
getBestFaceForForwarding(const fib::Entry& fibEntry, const Interest& interest, const Face& inFace);
void
- onTimeout(const Name& interestName, face::FaceId faceId);
+ onTimeout(const Name& interestName, const FaceId faceId);
void
sendNoRouteNack(const Face& inFace, const Interest& interest, const shared_ptr<pit::Entry>& pitEntry);
+ void
+ processParams(const PartialName& parsed);
+
+ static uint64_t
+ getParamValue(const std::string& param, const std::string& value);
+
private:
AsfMeasurements m_measurements;
ProbingModule m_probing;
+ size_t m_maxSilentTimeouts;
private:
RetxSuppressionExponential m_retxSuppression;