43 , m_measurements(getMeasurements())
44 , m_probing(m_measurements)
45 , m_retxSuppression(RETX_SUPPRESSION_INITIAL,
61 <<
" max-timeouts=" << m_nMaxTimeouts);
67 static const auto strategyName =
Name(
"/localhost/nfd/strategy/asf").appendVersion(4);
75 if (!value.empty() && value[0] ==
'-')
78 return boost::lexical_cast<uint64_t>(
value);
80 catch (
const boost::bad_lexical_cast&) {
81 NDN_THROW(std::invalid_argument(
"Value of " + param +
" must be a non-negative integer"));
86 AsfStrategy::processParams(
const PartialName& parsed)
88 for (
const auto& component : parsed) {
89 std::string parsedStr(reinterpret_cast<const char*>(component.value()), component.value_size());
90 auto n = parsedStr.find(
"~");
91 if (n == std::string::npos) {
92 NDN_THROW(std::invalid_argument(
"Format is <parameter>~<value>"));
95 auto f = parsedStr.substr(0, n);
96 auto s = parsedStr.substr(n + 1);
97 if (f ==
"probing-interval") {
100 else if (f ==
"max-timeouts") {
102 if (m_nMaxTimeouts <= 0)
103 NDN_THROW(std::invalid_argument(
"max-timeouts should be greater than 0"));
106 NDN_THROW(std::invalid_argument(
"Parameter should be probing-interval or max-timeouts"));
113 const shared_ptr<pit::Entry>& pitEntry)
115 const auto& fibEntry = this->
lookupFib(*pitEntry);
119 auto* faceToUse = getBestFaceForForwarding(interest, ingress.
face, fibEntry, pitEntry);
120 if (faceToUse ==
nullptr) {
121 NFD_LOG_DEBUG(interest <<
" new-interest from=" << ingress <<
" no-nexthop");
122 sendNoRouteNack(ingress.
face, pitEntry);
125 NFD_LOG_DEBUG(interest <<
" new-interest from=" << ingress <<
" forward-to=" << faceToUse->getId());
126 forwardInterest(interest, *faceToUse, fibEntry, pitEntry);
127 sendProbe(interest, ingress, *faceToUse, fibEntry, pitEntry);
132 auto* faceToUse = getBestFaceForForwarding(interest, ingress.
face, fibEntry, pitEntry,
false);
133 if (faceToUse !=
nullptr) {
134 auto suppressResult = m_retxSuppression.
decidePerUpstream(*pitEntry, *faceToUse);
138 <<
" forward-to=" << faceToUse->getId() <<
" suppressed");
143 NFD_LOG_DEBUG(interest <<
" retx-interest from=" << ingress <<
" forward-to=" << faceToUse->getId());
144 auto* outRecord = forwardInterest(interest, *faceToUse, fibEntry, pitEntry);
154 const auto& nexthops = fibEntry.getNextHops();
156 if (it == nexthops.end()) {
157 NFD_LOG_DEBUG(interest <<
" retx-interest from=" << ingress <<
" no eligible nexthop");
160 auto& outFace = it->getFace();
164 <<
" retry-to=" << outFace.getId() <<
" suppressed");
167 NFD_LOG_DEBUG(interest <<
" retx-interest from=" << ingress <<
" retry-to=" << outFace.getId());
170 auto* outRecord =
sendInterest(interest, outFace, pitEntry);
179 const shared_ptr<pit::Entry>& pitEntry)
182 if (namespaceInfo ==
nullptr) {
183 NFD_LOG_DEBUG(pitEntry->getName() <<
" data from=" << ingress <<
" no-measurements");
189 if (faceInfo ==
nullptr) {
190 NFD_LOG_DEBUG(pitEntry->getName() <<
" data from=" << ingress <<
" no-face-info");
194 auto outRecord = pitEntry->getOutRecord(ingress.
face);
195 if (outRecord == pitEntry->out_end()) {
196 NFD_LOG_DEBUG(pitEntry->getName() <<
" data from=" << ingress <<
" no-out-record");
200 NFD_LOG_DEBUG(pitEntry->getName() <<
" data from=" << ingress
213 const shared_ptr<pit::Entry>& pitEntry)
216 onTimeoutOrNack(pitEntry->getName(), ingress.
face.getId(),
true);
221 const shared_ptr<pit::Entry>& pitEntry)
223 const auto& interestName = interest.
getName();
224 auto faceId = outFace.getId();
226 auto* outRecord =
sendInterest(interest, outFace, pitEntry);
236 [
this,
name = interestName, faceId] {
237 onTimeoutOrNack(
name, faceId,
false);
248 const fib::Entry& fibEntry,
const shared_ptr<pit::Entry>& pitEntry)
254 if (faceToProbe ==
nullptr)
259 NFD_LOG_TRACE(
"Sending probe " << probeInterest <<
" to=" << faceToProbe->getId());
260 forwardInterest(probeInterest, *faceToProbe, fibEntry, pitEntry);
282 return std::tie(lhsValue, lhs.
cost) < std::tie(rhsValue, rhs.
cost);
287 getValueForSorting(
const FaceStats& stats)
292 return time::nanoseconds::max();
295 return time::nanoseconds::max() / 2;
304 AsfStrategy::getBestFaceForForwarding(
const Interest& interest,
const Face& inFace,
305 const fib::Entry& fibEntry,
const shared_ptr<pit::Entry>& pitEntry,
308 std::set<FaceStats, FaceStatsCompare> rankedFaces;
316 const FaceInfo*
info = m_measurements.getFaceInfo(fibEntry, interest.
getName(), nh.getFace().getId());
317 if (info ==
nullptr) {
322 rankedFaces.insert({&nh.getFace(), info->
getLastRtt(), info->
getSrtt(), nh.getCost()});
326 auto it = rankedFaces.begin();
327 return it != rankedFaces.end() ? it->face :
nullptr;
331 AsfStrategy::onTimeoutOrNack(
const Name& interestName,
FaceId faceId,
bool isNack)
333 NamespaceInfo* namespaceInfo = m_measurements.getNamespaceInfo(interestName);
334 if (namespaceInfo ==
nullptr) {
335 NFD_LOG_TRACE(interestName <<
" FibEntry has been removed since timeout scheduling");
340 if (fiPtr ==
nullptr) {
341 NFD_LOG_TRACE(interestName <<
" FaceInfo id=" << faceId <<
" has been removed since timeout scheduling");
345 auto& faceInfo = *fiPtr;
347 faceInfo.setNTimeouts(nTimeouts);
349 if (nTimeouts < m_nMaxTimeouts && !isNack) {
350 NFD_LOG_TRACE(interestName <<
" face=" << faceId <<
" timeout-count=" << nTimeouts <<
" ignoring");
353 faceInfo.cancelTimeout(interestName);
356 NFD_LOG_TRACE(interestName <<
" face=" << faceId <<
" timeout-count=" << nTimeouts);
357 faceInfo.recordTimeout(interestName);
362 AsfStrategy::sendNoRouteNack(
Face& face,
const shared_ptr<pit::Entry>& pitEntry)
365 nackHeader.
setReason(lp::NackReason::NO_ROUTE);
366 this->
sendNack(nackHeader, face, pitEntry);
Interest is retransmission and should be forwarded.
const Name & getPrefix() const
void afterForwardingProbe(const fib::Entry &fibEntry, const Name &interestName)
static ParsedInstanceName parseInstanceName(const Name &input)
Parse a strategy instance name.
time::nanoseconds scheduleTimeout(const Name &interestName, scheduler::EventCallback cb)
#define NFD_LOG_INIT(name)
void afterReceiveNack(const lp::Nack &nack, const FaceEndpoint &ingress, const shared_ptr< pit::Entry > &pitEntry) override
Trigger after a Nack is received.
static const time::nanoseconds RTT_TIMEOUT
std::string to_string(const T &val)
void afterReceiveInterest(const Interest &interest, const FaceEndpoint &ingress, const shared_ptr< pit::Entry > &pitEntry) override
Trigger after an Interest is received.
void beforeSatisfyInterest(const Data &data, const FaceEndpoint &ingress, const shared_ptr< pit::Entry > &pitEntry) override
trigger before PIT entry is satisfied
bool isProbingNeeded(const fib::Entry &fibEntry, const Name &interestName)
Represents a face-endpoint pair in the forwarder.
PartialName parameters
parameter components
static time_point now() noexcept
void refreshNonce()
Change nonce value.
fib::NextHopList::const_iterator findEligibleNextHopWithEarliestOutRecord(const Face &inFace, const Interest &interest, const fib::NextHopList &nexthops, const shared_ptr< pit::Entry > &pitEntry)
pick an eligible NextHop with earliest out-record
NFD_REGISTER_STRATEGY(AsfStrategy)
void extendFaceInfoLifetime(FaceInfo &info, FaceId faceId)
bool operator()(const FaceStats &lhs, const FaceStats &rhs) const
static const Name & getStrategyName()
Main class of NFD's forwarding engine.
RetxSuppressionResult decidePerUpstream(pit::Entry &pitEntry, Face &outFace)
determines whether Interest is a retransmission per upstream and if so, whether it shall be forwarded...
Interest is retransmission and should be suppressed.
static uint64_t getParamValue(const std::string ¶m, const std::string &value)
void setInstanceName(const Name &name)
Set strategy instance name.
Represents an Interest packet.
Stores strategy information about each face in this namespace.
void recordRtt(time::nanoseconds rtt)
NFD_VIRTUAL_WITH_TESTS void rejectPendingInterest(const shared_ptr< pit::Entry > &pitEntry)
Schedule the PIT entry for immediate deletion.
FaceInfo & getOrCreateFaceInfo(const fib::Entry &fibEntry, const Name &interestName, FaceId faceId)
represents a Network Nack
void setProbingInterval(size_t probingInterval)
NackReason getReason() const
time::nanoseconds getLastRtt() const
NamespaceInfo & getOrCreateNamespaceInfo(const fib::Entry &fibEntry, const Name &prefix)
void cancelTimeout(const Name &prefix)
time::milliseconds getProbingInterval() const
Copyright (c) 2011-2015 Regents of the University of California.
void incrementIntervalForOutRecord(pit::OutRecord &outRecord)
Increment the suppression interval for out record.
size_t getNTimeouts() const
Name PartialName
Represents an arbitrary sequence of name components.
const Name & getName() const noexcept
Get name.
Represents an absolute name.
Face * getFaceToProbe(const Face &inFace, const Interest &interest, const fib::Entry &fibEntry, const Face &faceUsed)
bool hasPendingOutRecords(const pit::Entry &pitEntry)
determine whether pitEntry has any pending out-records
NFD_VIRTUAL_WITH_TESTS bool sendNack(const lp::NackHeader &header, Face &egress, const shared_ptr< pit::Entry > &pitEntry)
Send a Nack packet.
Strategy information for each face in a namespace.
Represents a forwarding strategy.
FaceInfo * getFaceInfo(FaceId faceId)
optional< uint64_t > version
whether strategyName contains a version component
NamespaceInfo * getNamespaceInfo(const Name &prefix)
This file contains common algorithms used by forwarding strategies.
const fib::Entry & lookupFib(const pit::Entry &pitEntry) const
Performs a FIB lookup, considering Link object if present.
const Name & getName() const noexcept
Contains information about an Interest toward an outgoing face.
bool isNextHopEligible(const Face &inFace, const Interest &interest, const fib::NextHop &nexthop, const shared_ptr< pit::Entry > &pitEntry, bool wantUnused, time::steady_clock::time_point now)
time::nanoseconds getSrtt() const
static Name makeInstanceName(const Name &input, const Name &strategyName)
Construct a strategy instance name.
void setExpiryTimer(const shared_ptr< pit::Entry > &pitEntry, time::milliseconds duration)
Schedule the PIT entry to be erased after duration.
const NextHopList & getNextHops() const
NFD_VIRTUAL_WITH_TESTS pit::OutRecord * sendInterest(const Interest &interest, Face &egress, const shared_ptr< pit::Entry > &pitEntry)
Send an Interest packet.
Represents a Data packet.
a retransmission suppression decision algorithm that suppresses retransmissions using exponential bac...
AsfStrategy(Forwarder &forwarder, const Name &name=getStrategyName())
Adaptive SRTT-based Forwarding Strategy.
uint64_t FaceId
Identifies a face.
bool isTimeoutScheduled() const
const Interest & getInterest() const
boost::chrono::nanoseconds nanoseconds
static const time::nanoseconds RTT_NO_MEASUREMENT
boost::chrono::milliseconds milliseconds