fw: replace straggler timer with per-strategy decision
remove onInterestReject pipeline refs: #4200 Change-Id: I184d7ef7f732efda3d1066eef6cd89e36a6a8802
This commit is contained in:
1 parent
3cf75dc10b
commit
7003e0bc66
5 files changed
+353
-103
No files matched your search
+25
-64
@@ -127,9 +127,6 @@ Forwarder::onIncomingInterest(Face& inFace, const Interest& interest)
|
||||
return;
|
||||
}
|
||||
|
||||
// cancel unsatisfy & straggler timer
|
||||
this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
|
||||
|
||||
// is pending?
|
||||
if (!pitEntry->hasInRecords()) {
|
||||
m_cs.find(interest,
|
||||
@@ -163,6 +160,12 @@ Forwarder::onInterestLoop(Face& inFace, const Interest& interest)
|
||||
inFace.sendNack(nack);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
compare_InRecord_expiry(const pit::InRecord& a, const pit::InRecord& b)
|
||||
{
|
||||
return a.getExpiry() < b.getExpiry();
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::onContentStoreMiss(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
|
||||
const Interest& interest)
|
||||
@@ -173,8 +176,10 @@ Forwarder::onContentStoreMiss(const Face& inFace, const shared_ptr<pit::Entry>&
|
||||
// insert in-record
|
||||
pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
|
||||
|
||||
// set PIT unsatisfy timer
|
||||
this->setUnsatisfyTimer(pitEntry);
|
||||
// set PIT expiry timer to the time that the last PIT in-record expires
|
||||
auto lastExpiring = std::max_element(pitEntry->in_begin(), pitEntry->in_end(), &compare_InRecord_expiry);
|
||||
auto lastExpiryFromNow = lastExpiring->getExpiry() - time::steady_clock::now();
|
||||
this->setExpiryTimer(pitEntry, time::duration_cast<time::milliseconds>(lastExpiryFromNow));
|
||||
|
||||
// has NextHopFaceId?
|
||||
shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
|
||||
@@ -208,8 +213,8 @@ Forwarder::onContentStoreHit(const Face& inFace, const shared_ptr<pit::Entry>& p
|
||||
pitEntry->isSatisfied = true;
|
||||
pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
|
||||
|
||||
// set PIT straggler timer
|
||||
this->setStragglerTimer(pitEntry);
|
||||
// finalize Interest
|
||||
this->onInterestFinalize(pitEntry);
|
||||
|
||||
// goto outgoing Data pipeline
|
||||
this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
|
||||
@@ -229,23 +234,6 @@ Forwarder::onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outF
|
||||
++m_counters.nOutInterests;
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::onInterestReject(const shared_ptr<pit::Entry>& pitEntry)
|
||||
{
|
||||
if (fw::hasPendingOutRecords(*pitEntry)) {
|
||||
NFD_LOG_ERROR("onInterestReject interest=" << pitEntry->getName() <<
|
||||
" cannot reject forwarded Interest");
|
||||
return;
|
||||
}
|
||||
NFD_LOG_DEBUG("onInterestReject interest=" << pitEntry->getName());
|
||||
|
||||
// cancel unsatisfy & straggler timer
|
||||
this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
|
||||
|
||||
// set PIT straggler timer
|
||||
this->setStragglerTimer(pitEntry);
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry)
|
||||
{
|
||||
@@ -256,7 +244,7 @@ Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry)
|
||||
this->insertDeadNonceList(*pitEntry, 0);
|
||||
|
||||
// PIT delete
|
||||
this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
|
||||
scheduler::cancel(pitEntry->expiryTimer);
|
||||
m_pit.erase(pitEntry.get());
|
||||
}
|
||||
|
||||
@@ -295,9 +283,6 @@ Forwarder::onIncomingData(Face& inFace, const Data& data)
|
||||
for (const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
|
||||
NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
|
||||
|
||||
// cancel unsatisfy & straggler timer
|
||||
this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
|
||||
|
||||
// remember pending downstreams
|
||||
for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
|
||||
if (inRecord.getExpiry() > now) {
|
||||
@@ -305,6 +290,9 @@ Forwarder::onIncomingData(Face& inFace, const Data& data)
|
||||
}
|
||||
}
|
||||
|
||||
// set PIT expiry timer to now
|
||||
this->setExpiryTimer(pitEntry, 0_ms);
|
||||
|
||||
// invoke PIT satisfy callback
|
||||
this->dispatchToStrategy(*pitEntry,
|
||||
[&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
|
||||
@@ -318,9 +306,6 @@ Forwarder::onIncomingData(Face& inFace, const Data& data)
|
||||
// mark PIT satisfied
|
||||
pitEntry->clearInRecords();
|
||||
pitEntry->deleteOutRecord(inFace);
|
||||
|
||||
// set PIT straggler timer
|
||||
this->setStragglerTimer(pitEntry);
|
||||
}
|
||||
|
||||
// foreach pending downstream
|
||||
@@ -426,6 +411,11 @@ Forwarder::onIncomingNack(Face& inFace, const lp::Nack& nack)
|
||||
// record Nack on out-record
|
||||
outRecord->setIncomingNack(nack);
|
||||
|
||||
// set PIT expiry timer to now when all out-record receive Nack
|
||||
if (!fw::hasPendingOutRecords(*pitEntry)) {
|
||||
this->setExpiryTimer(pitEntry, 0_ms);
|
||||
}
|
||||
|
||||
// trigger strategy: after receive NACK
|
||||
this->dispatchToStrategy(*pitEntry,
|
||||
[&] (fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
|
||||
@@ -483,46 +473,17 @@ Forwarder::onDroppedInterest(Face& outFace, const Interest& interest)
|
||||
m_strategyChoice.findEffectiveStrategy(interest.getName()).onDroppedInterest(outFace, interest);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
compare_InRecord_expiry(const pit::InRecord& a, const pit::InRecord& b)
|
||||
{
|
||||
return a.getExpiry() < b.getExpiry();
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::setUnsatisfyTimer(const shared_ptr<pit::Entry>& pitEntry)
|
||||
Forwarder::setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
|
||||
{
|
||||
pit::InRecordCollection::iterator lastExpiring =
|
||||
std::max_element(pitEntry->in_begin(), pitEntry->in_end(), &compare_InRecord_expiry);
|
||||
BOOST_ASSERT(duration >= 0_ms);
|
||||
|
||||
time::steady_clock::TimePoint lastExpiry = lastExpiring->getExpiry();
|
||||
time::nanoseconds lastExpiryFromNow = lastExpiry - time::steady_clock::now();
|
||||
if (lastExpiryFromNow <= time::seconds::zero()) {
|
||||
// TODO all in-records are already expired; will this happen?
|
||||
}
|
||||
scheduler::cancel(pitEntry->expiryTimer);
|
||||
|
||||
scheduler::cancel(pitEntry->m_unsatisfyTimer);
|
||||
pitEntry->m_unsatisfyTimer = scheduler::schedule(lastExpiryFromNow,
|
||||
pitEntry->expiryTimer = scheduler::schedule(duration,
|
||||
bind(&Forwarder::onInterestFinalize, this, pitEntry));
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::setStragglerTimer(const shared_ptr<pit::Entry>& pitEntry)
|
||||
{
|
||||
time::nanoseconds stragglerTime = time::milliseconds(100);
|
||||
|
||||
scheduler::cancel(pitEntry->m_stragglerTimer);
|
||||
pitEntry->m_stragglerTimer = scheduler::schedule(stragglerTime,
|
||||
bind(&Forwarder::onInterestFinalize, this, pitEntry));
|
||||
}
|
||||
|
||||
void
|
||||
Forwarder::cancelUnsatisfyAndStragglerTimer(pit::Entry& pitEntry)
|
||||
{
|
||||
scheduler::cancel(pitEntry.m_unsatisfyTimer);
|
||||
scheduler::cancel(pitEntry.m_stragglerTimer);
|
||||
}
|
||||
|
||||
static inline void
|
||||
insertNonceToDnl(DeadNonceList& dnl, const pit::Entry& pitEntry,
|
||||
const pit::OutRecord& outRecord)
|
||||
|
||||
+4
-13
@@ -209,11 +209,6 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
|
||||
VIRTUAL_WITH_TESTS void
|
||||
onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outFace, const Interest& interest);
|
||||
|
||||
/** \brief Interest reject pipeline
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
onInterestReject(const shared_ptr<pit::Entry>& pitEntry);
|
||||
|
||||
/** \brief Interest finalize pipeline
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
@@ -248,14 +243,10 @@ PUBLIC_WITH_TESTS_ELSE_PRIVATE: // pipelines
|
||||
onDroppedInterest(Face& outFace, const Interest& interest);
|
||||
|
||||
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
|
||||
VIRTUAL_WITH_TESTS void
|
||||
setUnsatisfyTimer(const shared_ptr<pit::Entry>& pitEntry);
|
||||
|
||||
VIRTUAL_WITH_TESTS void
|
||||
setStragglerTimer(const shared_ptr<pit::Entry>& pitEntry);
|
||||
|
||||
VIRTUAL_WITH_TESTS void
|
||||
cancelUnsatisfyAndStragglerTimer(pit::Entry& pitEntry);
|
||||
/** \brief set a new expiry timer (now + \p duration) on a PIT entry
|
||||
*/
|
||||
void
|
||||
setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration);
|
||||
|
||||
/** \brief insert Nonce to Dead Nonce List if necessary
|
||||
* \param upstream if null, insert Nonces from all out-records;
|
||||
|
||||
+38
-9
@@ -121,11 +121,18 @@ public: // triggers
|
||||
* - cannot be satisfied by ContentStore
|
||||
* - is under a namespace managed by this strategy
|
||||
*
|
||||
* The PIT entry is set to expire after InterestLifetime has elapsed at each downstream.
|
||||
*
|
||||
* The strategy should decide whether and where to forward this Interest.
|
||||
* - If the strategy decides to forward this Interest,
|
||||
* invoke this->sendInterest one or more times, either now or shortly after
|
||||
* - If strategy concludes that this Interest cannot be forwarded,
|
||||
* invoke this->rejectPendingInterest so that PIT entry will be deleted shortly
|
||||
* invoke \c sendInterest for each upstream, either now or shortly after via a scheduler event,
|
||||
* but before PIT entry expires.
|
||||
* Optionally, the strategy can invoke \c setExpiryTimer to adjust how long it would wait for a response.
|
||||
* - If the strategy has already forwarded this Interest previously and decides to continue waiting,
|
||||
* do nothing.
|
||||
* Optionally, the strategy can invoke \c setExpiryTimer to adjust how long it would wait for a response.
|
||||
* - If the strategy concludes that this Interest cannot be satisfied,
|
||||
* invoke \c rejectPendingInterest to erase the PIT entry.
|
||||
*
|
||||
* \warning The strategy must not retain shared_ptr<pit::Entry>, otherwise undefined behavior
|
||||
* may occur. However, the strategy is allowed to store weak_ptr<pit::Entry>.
|
||||
@@ -137,7 +144,13 @@ public: // triggers
|
||||
/** \brief trigger before PIT entry is satisfied
|
||||
*
|
||||
* This trigger is invoked when an incoming Data satisfies the PIT entry.
|
||||
* It can be invoked even if the PIT entry has already been satisfied.
|
||||
* Normally, only the first incoming Data would satisfy the PIT entry and invoke this trigger,
|
||||
* after which the PIT entry is erased.
|
||||
*
|
||||
* If the strategy wishes to collect responses from additional upstream nodes,
|
||||
* it should invoke \c setExpiryTimer within this function to retain the PIT entry.
|
||||
* If a Data arrives from another upstream during the extended PIT entry lifetime, this trigger will be invoked again.
|
||||
* At that time, this function must invoke \c setExpiryTimer again to continue collecting more responses.
|
||||
*
|
||||
* In this base class this method does nothing.
|
||||
*
|
||||
@@ -156,6 +169,14 @@ public: // triggers
|
||||
* to that upstream, i.e. the PIT out-record exists and has a matching Nonce.
|
||||
* The NackHeader has been recorded in the PIT out-record.
|
||||
*
|
||||
* If the PIT entry is not yet satisfied, its expiry timer remains unchanged.
|
||||
* Otherwise, the PIT entry normally would expire immediately after this function returns.
|
||||
*
|
||||
* If the strategy wishes to collect responses from additional upstream nodes,
|
||||
* it should invoke \c setExpiryTimer within this function to retain the PIT entry.
|
||||
* If a Nack arrives from another upstream during the extended PIT entry lifetime, this trigger will be invoked again.
|
||||
* At that time, this function must invoke \c setExpiryTimer again to continue collecting more responses.
|
||||
*
|
||||
* In this base class this method does nothing.
|
||||
*
|
||||
* \warning The strategy must not retain shared_ptr<pit::Entry>, otherwise undefined behavior
|
||||
@@ -185,16 +206,16 @@ protected: // actions
|
||||
m_forwarder.onOutgoingInterest(pitEntry, outFace, interest);
|
||||
}
|
||||
|
||||
/** \brief decide that a pending Interest cannot be forwarded
|
||||
* \param pitEntry PIT entry
|
||||
/** \brief schedule the PIT entry for immediate deletion
|
||||
*
|
||||
* This shall not be called if the pending Interest has been
|
||||
* forwarded earlier, and does not need to be resent now.
|
||||
* This helper function sets the PIT entry expiry time to zero.
|
||||
* The strategy should invoke this function when it concludes that the Interest cannot
|
||||
* be forwarded and it does not want to wait for responses from existing upstream nodes.
|
||||
*/
|
||||
VIRTUAL_WITH_TESTS void
|
||||
rejectPendingInterest(const shared_ptr<pit::Entry>& pitEntry)
|
||||
{
|
||||
m_forwarder.onInterestReject(pitEntry);
|
||||
this->setExpiryTimer(pitEntry, 0_ms);
|
||||
}
|
||||
|
||||
/** \brief send Nack to outFace
|
||||
@@ -222,6 +243,14 @@ protected: // actions
|
||||
sendNacks(const shared_ptr<pit::Entry>& pitEntry, const lp::NackHeader& header,
|
||||
std::initializer_list<const Face*> exceptFaces = std::initializer_list<const Face*>());
|
||||
|
||||
/** \brief Schedule the PIT entry to be erased after \p duration
|
||||
*/
|
||||
void
|
||||
setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
|
||||
{
|
||||
m_forwarder.setExpiryTimer(pitEntry, duration);
|
||||
}
|
||||
|
||||
protected: // accessors
|
||||
/** \brief performs a FIB lookup, considering Link object if present
|
||||
*/
|
||||
|
||||
@@ -215,26 +215,11 @@ public: // out-record
|
||||
deleteOutRecord(const Face& face);
|
||||
|
||||
public:
|
||||
/** \brief unsatisfy timer
|
||||
/** \brief expiry timer
|
||||
*
|
||||
* This timer is used in forwarding pipelines to delete the entry
|
||||
* when it expires without being satisfied.
|
||||
* It fires when the last InterestLifetime among in-records expires.
|
||||
*
|
||||
* Either this or the straggler timer should be set at all times,
|
||||
* except when this entry is being processed in a pipeline.
|
||||
*/
|
||||
scheduler::EventId m_unsatisfyTimer;
|
||||
|
||||
/** \brief straggler timer
|
||||
*
|
||||
* This timer is used in forwarding pipelines to delete the entry when it has been satisfied
|
||||
* and is no longer needed for measurement collection purpose.
|
||||
*
|
||||
* Either this or the unsatisfy timer should be set at all times,
|
||||
* except when this entry is being processed in a pipeline.
|
||||
*/
|
||||
scheduler::EventId m_stragglerTimer;
|
||||
scheduler::EventId expiryTimer;
|
||||
|
||||
/** \brief indicate if PIT entry is satisfied
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2014-2018, Regents of the University of California,
|
||||
* Arizona Board of Regents,
|
||||
* Colorado State University,
|
||||
* University Pierre & Marie Curie, Sorbonne University,
|
||||
* Washington University in St. Louis,
|
||||
* Beijing Institute of Technology,
|
||||
* The University of Memphis.
|
||||
*
|
||||
* This file is part of NFD (Named Data Networking Forwarding Daemon).
|
||||
* See AUTHORS.md for complete list of NFD authors and contributors.
|
||||
*
|
||||
* NFD 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.
|
||||
*
|
||||
* NFD 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
|
||||
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dummy-strategy.hpp"
|
||||
#include "choose-strategy.hpp"
|
||||
#include "tests/daemon/face/dummy-face.hpp"
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
|
||||
namespace nfd {
|
||||
namespace fw {
|
||||
namespace tests {
|
||||
|
||||
using namespace nfd::tests;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Fw)
|
||||
BOOST_FIXTURE_TEST_SUITE(TestPitExpiry, UnitTestTimeFixture)
|
||||
|
||||
class PitExpiryTestStrategy : public DummyStrategy
|
||||
{
|
||||
public:
|
||||
static Name
|
||||
getStrategyName(uint64_t version)
|
||||
{
|
||||
return Name("/PitExpiryTestStrategy").appendVersion(version);
|
||||
}
|
||||
|
||||
static void
|
||||
registerAs(const Name& strategyName)
|
||||
{
|
||||
registerAsImpl<PitExpiryTestStrategy>(strategyName);
|
||||
}
|
||||
|
||||
explicit
|
||||
PitExpiryTestStrategy(Forwarder& forwarder, const Name& name = getStrategyName(1))
|
||||
: DummyStrategy(forwarder, name)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
afterReceiveInterest(const Face& inFace, const Interest& interest,
|
||||
const shared_ptr<pit::Entry>& pitEntry) override
|
||||
{
|
||||
++afterReceiveInterest_count;
|
||||
|
||||
if (afterReceiveInterest_count <= 1) {
|
||||
setExpiryTimer(pitEntry, 190_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
|
||||
const Face& inFace, const Data& data) override
|
||||
{
|
||||
++beforeSatisfyInterest_count;
|
||||
|
||||
if (beforeSatisfyInterest_count <= 1 ) {
|
||||
setExpiryTimer(pitEntry, 190_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
afterReceiveNack(const Face& inFace, const lp::Nack& nack,
|
||||
const shared_ptr<pit::Entry>& pitEntry) override
|
||||
{
|
||||
++afterReceiveNack_count;
|
||||
|
||||
if (afterReceiveNack_count <= 1) {
|
||||
setExpiryTimer(pitEntry, 50_ms);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(UnsatisfiedInterest)
|
||||
{
|
||||
Forwarder forwarder;
|
||||
|
||||
auto face1 = make_shared<DummyFace>();
|
||||
auto face2 = make_shared<DummyFace>();
|
||||
forwarder.addFace(face1);
|
||||
forwarder.addFace(face2);
|
||||
|
||||
Pit& pit = forwarder.getPit();
|
||||
|
||||
shared_ptr<Interest> interest1 = makeInterest("/A/0");
|
||||
shared_ptr<Interest> interest2 = makeInterest("/A/1");
|
||||
interest1->setInterestLifetime(90_ms);
|
||||
interest2->setInterestLifetime(90_ms);
|
||||
|
||||
face1->receiveInterest(*interest1);
|
||||
face2->receiveInterest(*interest2);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 2);
|
||||
|
||||
this->advanceClocks(100_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SatisfiedInterest)
|
||||
{
|
||||
Forwarder forwarder;
|
||||
|
||||
auto face1 = make_shared<DummyFace>();
|
||||
auto face2 = make_shared<DummyFace>();
|
||||
forwarder.addFace(face1);
|
||||
forwarder.addFace(face2);
|
||||
|
||||
Pit& pit = forwarder.getPit();
|
||||
|
||||
shared_ptr<Interest> interest = makeInterest("/A/0");
|
||||
interest->setInterestLifetime(90_ms);
|
||||
shared_ptr<Data> data = makeData("/A/0");
|
||||
|
||||
face1->receiveInterest(*interest);
|
||||
|
||||
this->advanceClocks(30_ms);
|
||||
face2->receiveData(*data);
|
||||
|
||||
this->advanceClocks(1_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ReceiveNack)
|
||||
{
|
||||
Forwarder forwarder;
|
||||
|
||||
auto face1 = make_shared<DummyFace>();
|
||||
auto face2 = make_shared<DummyFace>();
|
||||
auto face3 = make_shared<DummyFace>();
|
||||
forwarder.addFace(face1);
|
||||
forwarder.addFace(face2);
|
||||
forwarder.addFace(face3);
|
||||
|
||||
Name strategyA("/strategyA/%FD%01");
|
||||
PitExpiryTestStrategy::registerAs(strategyA);
|
||||
choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
|
||||
|
||||
Pit& pit = forwarder.getPit();
|
||||
|
||||
shared_ptr<Interest> interest = makeInterest("/A/0", 562);
|
||||
interest->setInterestLifetime(90_ms);
|
||||
lp::Nack nack = makeNack("/A/0", 562, lp::NackReason::CONGESTION);
|
||||
|
||||
face1->receiveInterest(*interest);
|
||||
auto entry = pit.find(*interest);
|
||||
entry->insertOrUpdateOutRecord(*face2, *interest);
|
||||
entry->insertOrUpdateOutRecord(*face3, *interest);
|
||||
|
||||
this->advanceClocks(10_ms);
|
||||
face2->receiveNack(nack);
|
||||
|
||||
this->advanceClocks(1_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 1);
|
||||
|
||||
this->advanceClocks(50_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ResetTimerAfterReceiveInterest)
|
||||
{
|
||||
Forwarder forwarder;
|
||||
|
||||
auto face = make_shared<DummyFace>();
|
||||
forwarder.addFace(face);
|
||||
|
||||
Name strategyA("/strategyA/%FD%01");
|
||||
PitExpiryTestStrategy::registerAs(strategyA);
|
||||
choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
|
||||
|
||||
Pit& pit = forwarder.getPit();
|
||||
|
||||
shared_ptr<Interest> interest = makeInterest("/A/0");
|
||||
interest->setInterestLifetime(90_ms);
|
||||
|
||||
face->receiveInterest(*interest);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 1);
|
||||
|
||||
this->advanceClocks(100_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 1);
|
||||
|
||||
this->advanceClocks(100_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ResetTimerBeforeSatisfyInterest)
|
||||
{
|
||||
Forwarder forwarder;
|
||||
|
||||
auto face1 = make_shared<DummyFace>();
|
||||
auto face2 = make_shared<DummyFace>();
|
||||
forwarder.addFace(face1);
|
||||
forwarder.addFace(face2);
|
||||
|
||||
Name strategyA("/strategyA/%FD%01");
|
||||
PitExpiryTestStrategy::registerAs(strategyA);
|
||||
choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
|
||||
|
||||
Pit& pit = forwarder.getPit();
|
||||
|
||||
shared_ptr<Interest> interest = makeInterest("/A/0");
|
||||
interest->setInterestLifetime(90_ms);
|
||||
shared_ptr<Data> data = makeData("/A/0");
|
||||
|
||||
face1->receiveInterest(*interest);
|
||||
|
||||
this->advanceClocks(30_ms);
|
||||
face2->receiveData(*data);
|
||||
|
||||
this->advanceClocks(1_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 1);
|
||||
|
||||
this->advanceClocks(30_ms);
|
||||
face2->receiveData(*data);
|
||||
|
||||
this->advanceClocks(1_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ReceiveNackAfterResetTimer)
|
||||
{
|
||||
Forwarder forwarder;
|
||||
|
||||
auto face1 = make_shared<DummyFace>();
|
||||
auto face2 = make_shared<DummyFace>();
|
||||
auto face3 = make_shared<DummyFace>();
|
||||
forwarder.addFace(face1);
|
||||
forwarder.addFace(face2);
|
||||
forwarder.addFace(face3);
|
||||
|
||||
Name strategyA("/strategyA/%FD%01");
|
||||
PitExpiryTestStrategy::registerAs(strategyA);
|
||||
choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
|
||||
|
||||
Pit& pit = forwarder.getPit();
|
||||
|
||||
shared_ptr<Interest> interest = makeInterest("/A/0", 562);
|
||||
interest->setInterestLifetime(90_ms);
|
||||
lp::Nack nack = makeNack("/A/0", 562, lp::NackReason::CONGESTION);
|
||||
|
||||
face1->receiveInterest(*interest);
|
||||
auto entry = pit.find(*interest);
|
||||
entry->insertOrUpdateOutRecord(*face2, *interest);
|
||||
entry->insertOrUpdateOutRecord(*face3, *interest);
|
||||
|
||||
//pitEntry is not erased after receiving the first Nack
|
||||
this->advanceClocks(10_ms);
|
||||
face2->receiveNack(nack);
|
||||
this->advanceClocks(1_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 1);
|
||||
|
||||
//pitEntry is erased after receiving the second Nack
|
||||
this->advanceClocks(10_ms);
|
||||
face3->receiveNack(nack);
|
||||
this->advanceClocks(1_ms);
|
||||
BOOST_CHECK_EQUAL(pit.size(), 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // TestPitExpiry
|
||||
BOOST_AUTO_TEST_SUITE_END() // Fw
|
||||
|
||||
} // namespace tests
|
||||
} // namespace fw
|
||||
} // namespace nfd
|
||||
Reference in new issue
Block a user