fw: remove ncc strategy
Change-Id: I6de0acf51e965afcbda5cc943cb39daa78cabf2d
diff --git a/daemon/fw/ncc-strategy.cpp b/daemon/fw/ncc-strategy.cpp
deleted file mode 100644
index 060821a..0000000
--- a/daemon/fw/ncc-strategy.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2020, 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 "ncc-strategy.hpp"
-#include "algorithm.hpp"
-#include "common/global.hpp"
-
-#include <ndn-cxx/util/random.hpp>
-
-namespace nfd {
-namespace fw {
-
-NFD_REGISTER_STRATEGY(NccStrategy);
-
-const time::microseconds NccStrategy::DEFER_FIRST_WITHOUT_BEST_FACE = 4_ms;
-const time::microseconds NccStrategy::DEFER_RANGE_WITHOUT_BEST_FACE = 75_ms;
-const time::nanoseconds NccStrategy::MEASUREMENTS_LIFETIME = 16_s;
-
-NccStrategy::NccStrategy(Forwarder& forwarder, const Name& name)
- : Strategy(forwarder)
-{
- ParsedInstanceName parsed = parseInstanceName(name);
- if (!parsed.parameters.empty()) {
- NDN_THROW(std::invalid_argument("NccStrategy does not accept parameters"));
- }
- if (parsed.version && *parsed.version != getStrategyName()[-1].toVersion()) {
- NDN_THROW(std::invalid_argument(
- "NccStrategy does not support version " + to_string(*parsed.version)));
- }
- this->setInstanceName(makeInstanceName(name, getStrategyName()));
-}
-
-const Name&
-NccStrategy::getStrategyName()
-{
- static Name strategyName("/localhost/nfd/strategy/ncc/%FD%01");
- return strategyName;
-}
-
-void
-NccStrategy::afterReceiveInterest(const FaceEndpoint& ingress, const Interest& interest,
- const shared_ptr<pit::Entry>& pitEntry)
-{
- const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
- const fib::NextHopList& nexthops = fibEntry.getNextHops();
- if (nexthops.size() == 0) {
- this->rejectPendingInterest(pitEntry);
- return;
- }
-
- PitEntryInfo* pitEntryInfo = pitEntry->insertStrategyInfo<PitEntryInfo>().first;
- bool isNewPitEntry = !hasPendingOutRecords(*pitEntry);
- if (!isNewPitEntry) {
- return;
- }
-
- MeasurementsEntryInfo& meInfo = this->getMeasurementsEntryInfo(pitEntry);
-
- time::microseconds deferFirst = DEFER_FIRST_WITHOUT_BEST_FACE;
- time::microseconds deferRange = DEFER_RANGE_WITHOUT_BEST_FACE;
- size_t nUpstreams = nexthops.size();
-
- shared_ptr<Face> bestFace = meInfo.getBestFace();
- if (bestFace != nullptr && fibEntry.hasNextHop(*bestFace) &&
- !wouldViolateScope(ingress.face, interest, *bestFace) &&
- canForwardToLegacy(*pitEntry, *bestFace)) {
- // TODO Should we use `randlow = 100 + nrand48(h->seed) % 4096U;` ?
- deferFirst = meInfo.prediction;
- deferRange = time::microseconds((deferFirst.count() + 1) / 2);
- --nUpstreams;
- this->sendInterest(pitEntry, *bestFace, interest);
- pitEntryInfo->bestFaceTimeout = getScheduler().schedule(meInfo.prediction,
- bind(&NccStrategy::timeoutOnBestFace, this, weak_ptr<pit::Entry>(pitEntry)));
- }
- else {
- // use first eligible nexthop
- auto firstEligibleNexthop = std::find_if(nexthops.begin(), nexthops.end(),
- [&] (const fib::NextHop& nexthop) {
- Face& outFace = nexthop.getFace();
- return !wouldViolateScope(ingress.face, interest, outFace) &&
- canForwardToLegacy(*pitEntry, outFace);
- });
- if (firstEligibleNexthop != nexthops.end()) {
- this->sendInterest(pitEntry, firstEligibleNexthop->getFace(), interest);
- }
- else {
- this->rejectPendingInterest(pitEntry);
- return;
- }
- }
-
- shared_ptr<Face> previousFace = meInfo.previousFace.lock();
- if (previousFace != nullptr && fibEntry.hasNextHop(*previousFace) &&
- !wouldViolateScope(ingress.face, interest, *previousFace) &&
- canForwardToLegacy(*pitEntry, *previousFace)) {
- --nUpstreams;
- }
-
- if (nUpstreams > 0) {
- pitEntryInfo->maxInterval = std::max(1_us,
- time::microseconds((2 * deferRange.count() + nUpstreams - 1) / nUpstreams));
- }
- else {
- // Normally, maxInterval is unused if there aren't any face beyond best and previousBest.
- // However, in case FIB entry gains a new nexthop before doPropagate executes (bug 1853),
- // this maxInterval would be used to determine when the next doPropagate would happen.
- pitEntryInfo->maxInterval = deferFirst;
- }
- pitEntryInfo->propagateTimer = getScheduler().schedule(deferFirst,
- bind(&NccStrategy::doPropagate, this, ingress.face.getId(), weak_ptr<pit::Entry>(pitEntry)));
-}
-
-void
-NccStrategy::doPropagate(FaceId inFaceId, weak_ptr<pit::Entry> pitEntryWeak)
-{
- Face* inFace = this->getFace(inFaceId);
- if (inFace == nullptr) {
- return;
- }
- shared_ptr<pit::Entry> pitEntry = pitEntryWeak.lock();
- if (pitEntry == nullptr) {
- return;
- }
- auto inRecord = pitEntry->getInRecord(*inFace);
- if (inRecord == pitEntry->in_end()) {
- return;
- }
- const Interest& interest = inRecord->getInterest();
- const fib::Entry& fibEntry = this->lookupFib(*pitEntry);
-
- PitEntryInfo* pitEntryInfo = pitEntry->getStrategyInfo<PitEntryInfo>();
- // pitEntryInfo is guaranteed to exist here, because doPropagate is triggered
- // from a timer set by NccStrategy.
- BOOST_ASSERT(pitEntryInfo != nullptr);
-
- MeasurementsEntryInfo& meInfo = this->getMeasurementsEntryInfo(pitEntry);
-
- shared_ptr<Face> previousFace = meInfo.previousFace.lock();
- if (previousFace != nullptr && fibEntry.hasNextHop(*previousFace) &&
- !wouldViolateScope(*inFace, interest, *previousFace) &&
- canForwardToLegacy(*pitEntry, *previousFace)) {
- this->sendInterest(pitEntry, *previousFace, interest);
- }
-
- bool isForwarded = false;
- for (const auto& nexthop : fibEntry.getNextHops()) {
- Face& face = nexthop.getFace();
- if (!wouldViolateScope(*inFace, interest, face) &&
- canForwardToLegacy(*pitEntry, face)) {
- isForwarded = true;
- this->sendInterest(pitEntry, face, interest);
- break;
- }
- }
-
- if (isForwarded) {
- std::uniform_int_distribution<time::nanoseconds::rep> dist(0, pitEntryInfo->maxInterval.count() - 1);
- time::nanoseconds deferNext(dist(ndn::random::getRandomNumberEngine()));
- pitEntryInfo->propagateTimer = getScheduler().schedule(deferNext,
- bind(&NccStrategy::doPropagate, this, inFaceId, weak_ptr<pit::Entry>(pitEntry)));
- }
-}
-
-void
-NccStrategy::timeoutOnBestFace(weak_ptr<pit::Entry> pitEntryWeak)
-{
- shared_ptr<pit::Entry> pitEntry = pitEntryWeak.lock();
- if (pitEntry == nullptr) {
- return;
- }
- measurements::Entry* measurementsEntry = this->getMeasurements().get(*pitEntry);
-
- for (int i = 0; i < UPDATE_MEASUREMENTS_N_LEVELS; ++i) {
- if (measurementsEntry == nullptr) {
- // going out of this strategy's namespace
- break;
- }
- this->getMeasurements().extendLifetime(*measurementsEntry, MEASUREMENTS_LIFETIME);
-
- MeasurementsEntryInfo& meInfo = this->getMeasurementsEntryInfo(measurementsEntry);
- meInfo.adjustPredictUp();
-
- measurementsEntry = this->getMeasurements().getParent(*measurementsEntry);
- }
-}
-
-void
-NccStrategy::beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
- const FaceEndpoint& ingress, const Data& data)
-{
- if (!pitEntry->hasInRecords()) {
- // PIT entry has already been satisfied (and is now waiting for straggler timer to expire)
- // NCC does not collect measurements for non-best face
- return;
- }
-
- measurements::Entry* measurementsEntry = this->getMeasurements().get(*pitEntry);
-
- for (int i = 0; i < UPDATE_MEASUREMENTS_N_LEVELS; ++i) {
- if (measurementsEntry == nullptr) {
- // going out of this strategy's namespace
- return;
- }
- this->getMeasurements().extendLifetime(*measurementsEntry, MEASUREMENTS_LIFETIME);
-
- MeasurementsEntryInfo& meInfo = this->getMeasurementsEntryInfo(measurementsEntry);
- meInfo.updateBestFace(ingress.face);
-
- measurementsEntry = this->getMeasurements().getParent(*measurementsEntry);
- }
-
- PitEntryInfo* pitEntryInfo = pitEntry->getStrategyInfo<PitEntryInfo>();
- if (pitEntryInfo != nullptr) {
- pitEntryInfo->propagateTimer.cancel();
-
- // Verify that the best face satisfied the interest before canceling the timeout call
- MeasurementsEntryInfo& meInfo = this->getMeasurementsEntryInfo(pitEntry);
- shared_ptr<Face> bestFace = meInfo.getBestFace();
-
- if (bestFace.get() == &ingress.face)
- pitEntryInfo->bestFaceTimeout.cancel();
- }
-}
-
-NccStrategy::MeasurementsEntryInfo&
-NccStrategy::getMeasurementsEntryInfo(const shared_ptr<pit::Entry>& entry)
-{
- measurements::Entry* measurementsEntry = this->getMeasurements().get(*entry);
- return this->getMeasurementsEntryInfo(measurementsEntry);
-}
-
-NccStrategy::MeasurementsEntryInfo&
-NccStrategy::getMeasurementsEntryInfo(measurements::Entry* entry)
-{
- BOOST_ASSERT(entry != nullptr);
- MeasurementsEntryInfo* info = nullptr;
- bool isNew = false;
- std::tie(info, isNew) = entry->insertStrategyInfo<MeasurementsEntryInfo>();
- if (!isNew) {
- return *info;
- }
-
- measurements::Entry* parentEntry = this->getMeasurements().getParent(*entry);
- if (parentEntry != nullptr) {
- MeasurementsEntryInfo& parentInfo = this->getMeasurementsEntryInfo(parentEntry);
- info->inheritFrom(parentInfo);
- }
-
- return *info;
-}
-
-const time::microseconds NccStrategy::MeasurementsEntryInfo::INITIAL_PREDICTION = 8192_us;
-const time::microseconds NccStrategy::MeasurementsEntryInfo::MIN_PREDICTION = 127_us;
-const time::microseconds NccStrategy::MeasurementsEntryInfo::MAX_PREDICTION = 160_ms;
-
-NccStrategy::MeasurementsEntryInfo::MeasurementsEntryInfo()
- : prediction(INITIAL_PREDICTION)
-{
-}
-
-void
-NccStrategy::MeasurementsEntryInfo::inheritFrom(const MeasurementsEntryInfo& other)
-{
- this->operator=(other);
-}
-
-shared_ptr<Face>
-NccStrategy::MeasurementsEntryInfo::getBestFace()
-{
- shared_ptr<Face> best = this->bestFace.lock();
- if (best != nullptr) {
- return best;
- }
- this->bestFace = best = this->previousFace.lock();
- return best;
-}
-
-void
-NccStrategy::MeasurementsEntryInfo::updateBestFace(const Face& face)
-{
- if (this->bestFace.expired()) {
- this->bestFace = const_cast<Face&>(face).shared_from_this();
- return;
- }
- shared_ptr<Face> bestFace = this->bestFace.lock();
- if (bestFace.get() == &face) {
- this->adjustPredictDown();
- }
- else {
- this->previousFace = this->bestFace;
- this->bestFace = const_cast<Face&>(face).shared_from_this();
- }
-}
-
-void
-NccStrategy::MeasurementsEntryInfo::adjustPredictDown()
-{
- prediction = std::max(MIN_PREDICTION,
- time::microseconds(prediction.count() - (prediction.count() >> ADJUST_PREDICT_DOWN_SHIFT)));
-}
-
-void
-NccStrategy::MeasurementsEntryInfo::adjustPredictUp()
-{
- prediction = std::min(MAX_PREDICTION,
- time::microseconds(prediction.count() + (prediction.count() >> ADJUST_PREDICT_UP_SHIFT)));
-}
-
-void
-NccStrategy::MeasurementsEntryInfo::ageBestFace()
-{
- this->previousFace = this->bestFace;
- this->bestFace.reset();
-}
-
-NccStrategy::PitEntryInfo::~PitEntryInfo()
-{
- bestFaceTimeout.cancel();
- propagateTimer.cancel();
-}
-
-} // namespace fw
-} // namespace nfd
diff --git a/daemon/fw/ncc-strategy.hpp b/daemon/fw/ncc-strategy.hpp
deleted file mode 100644
index 3ba5019..0000000
--- a/daemon/fw/ncc-strategy.hpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2021, 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/>.
- */
-
-#ifndef NFD_DAEMON_FW_NCC_STRATEGY_HPP
-#define NFD_DAEMON_FW_NCC_STRATEGY_HPP
-
-#include "strategy.hpp"
-
-namespace nfd {
-namespace fw {
-
-/** \brief A forwarding strategy similar to CCNx 0.7.2
- */
-class NccStrategy : public Strategy
-{
-public:
- explicit
- NccStrategy(Forwarder& forwarder, const Name& name = getStrategyName());
-
- static const Name&
- getStrategyName();
-
- void
- afterReceiveInterest(const FaceEndpoint& ingress, const Interest& interest,
- const shared_ptr<pit::Entry>& pitEntry) override;
-
- void
- beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
- const FaceEndpoint& ingress, const Data& data) override;
-
-NFD_PUBLIC_WITH_TESTS_ELSE_PROTECTED:
- /// StrategyInfo on measurements::Entry
- class MeasurementsEntryInfo : public StrategyInfo
- {
- public:
- static constexpr int
- getTypeId()
- {
- return 1000;
- }
-
- MeasurementsEntryInfo();
-
- void
- inheritFrom(const MeasurementsEntryInfo& other);
-
- shared_ptr<Face>
- getBestFace();
-
- void
- updateBestFace(const Face& face);
-
- void
- adjustPredictUp();
-
- private:
- void
- adjustPredictDown();
-
- void
- ageBestFace();
-
- public:
- weak_ptr<Face> bestFace;
- weak_ptr<Face> previousFace;
- time::microseconds prediction;
-
- static const time::microseconds INITIAL_PREDICTION;
- static const time::microseconds MIN_PREDICTION;
- static const int ADJUST_PREDICT_DOWN_SHIFT = 7;
- static const time::microseconds MAX_PREDICTION;
- static const int ADJUST_PREDICT_UP_SHIFT = 3;
- };
-
- /// StrategyInfo on pit::Entry
- class PitEntryInfo : public StrategyInfo
- {
- public:
- static constexpr int
- getTypeId()
- {
- return 1001;
- }
-
- ~PitEntryInfo() override;
-
- public:
- /// timer that expires when best face does not respond within predicted time
- scheduler::EventId bestFaceTimeout;
- /// timer for propagating to another face
- scheduler::EventId propagateTimer;
- /// maximum interval between forwarding to two nexthops except best and previous
- time::microseconds maxInterval;
- };
-
-protected:
- MeasurementsEntryInfo&
- getMeasurementsEntryInfo(measurements::Entry* entry);
-
- MeasurementsEntryInfo&
- getMeasurementsEntryInfo(const shared_ptr<pit::Entry>& entry);
-
- /// propagate to another upstream
- void
- doPropagate(FaceId inFaceId, weak_ptr<pit::Entry> pitEntryWeak);
-
- /// best face did not reply within prediction
- void
- timeoutOnBestFace(weak_ptr<pit::Entry> pitEntryWeak);
-
-protected:
- static const time::microseconds DEFER_FIRST_WITHOUT_BEST_FACE;
- static const time::microseconds DEFER_RANGE_WITHOUT_BEST_FACE;
- static const int UPDATE_MEASUREMENTS_N_LEVELS = 2;
- static const time::nanoseconds MEASUREMENTS_LIFETIME;
-};
-
-} // namespace fw
-} // namespace nfd
-
-#endif // NFD_DAEMON_FW_NCC_STRATEGY_HPP
diff --git a/tests/daemon/fw/ncc-strategy.t.cpp b/tests/daemon/fw/ncc-strategy.t.cpp
deleted file mode 100644
index 3c3f4d4..0000000
--- a/tests/daemon/fw/ncc-strategy.t.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2019, 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 "fw/ncc-strategy.hpp"
-
-#include "tests/daemon/face/dummy-face.hpp"
-#include "strategy-tester.hpp"
-#include "topology-tester.hpp"
-
-namespace nfd {
-namespace fw {
-namespace tests {
-
-using NccStrategyTester = StrategyTester<NccStrategy>;
-NFD_REGISTER_STRATEGY(NccStrategyTester);
-
-BOOST_AUTO_TEST_SUITE(Fw)
-BOOST_FIXTURE_TEST_SUITE(TestNccStrategy, GlobalIoTimeFixture)
-
-BOOST_AUTO_TEST_CASE(FavorRespondingUpstream)
-{
- // NccStrategy is fairly complex.
- // The most important property is: it remembers which upstream is the fastest to return Data,
- // and favors this upstream in subsequent Interests.
-
- LimitedIo limitedIo(this);
- FaceTable faceTable;
- Forwarder forwarder(faceTable);
- NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
- strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
-
- shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
- shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
- shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
- faceTable.add(face1);
- faceTable.add(face2);
- faceTable.add(face3);
-
- Fib& fib = forwarder.getFib();
- fib::Entry& fibEntry = *fib.insert(Name()).first;
- fib.addOrUpdateNextHop(fibEntry, *face1, 10);
- fib.addOrUpdateNextHop(fibEntry, *face2, 20);
-
- Pit& pit = forwarder.getPit();
-
- // first Interest: strategy knows nothing and follows routing
- shared_ptr<Interest> interest1p = makeInterest("ndn:/0Jm1ajrW/%00");
- Interest& interest1 = *interest1p;
- interest1.setInterestLifetime(8_s);
- shared_ptr<pit::Entry> pitEntry1 = pit.insert(interest1).first;
-
- pitEntry1->insertOrUpdateInRecord(*face3, interest1);
- strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), interest1, pitEntry1);
-
- // forwards to face1 because routing says it's best
- // (no io run here: afterReceiveInterest has already sent the Interest)
- BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
-
- // forwards to face2 because face1 doesn't respond
- limitedIo.run(1, 500_ms, 10_ms);
- BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
-
- // face2 responds
- shared_ptr<Data> data1p = makeData("ndn:/0Jm1ajrW/%00");
- Data& data1 = *data1p;
- strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), data1);
- this->advanceClocks(10_ms, 500_ms);
-
- // second Interest: strategy knows face2 is best
- shared_ptr<Interest> interest2p = makeInterest("ndn:/0Jm1ajrW/%00%01");
- Interest& interest2 = *interest2p;
- interest2.setInterestLifetime(8_s);
- shared_ptr<pit::Entry> pitEntry2 = pit.insert(interest2).first;
-
- pitEntry2->insertOrUpdateInRecord(*face3, interest2);
- strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), interest2, pitEntry2);
-
- // forwards to face2 because it responds previously
- this->advanceClocks(1_ms);
- BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face2->getId());
-}
-
-BOOST_AUTO_TEST_CASE(Bug1853)
-{
- FaceTable faceTable;
- Forwarder forwarder(faceTable);
- NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
-
- shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
- shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
- shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
- faceTable.add(face1);
- faceTable.add(face2);
- faceTable.add(face3);
-
- Fib& fib = forwarder.getFib();
- fib::Entry& fibEntry = *fib.insert(Name()).first;
- fib.addOrUpdateNextHop(fibEntry, *face1, 10);
-
- Pit& pit = forwarder.getPit();
-
- // first Interest: strategy follows routing and forwards to face1
- shared_ptr<Interest> interest1 = makeInterest("ndn:/nztwIvHX/%00");
- interest1->setInterestLifetime(8_s);
- shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
-
- pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
- strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest1, pitEntry1);
-
- this->advanceClocks(1_ms);
- BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
-
- // face1 responds
- shared_ptr<Data> data1 = makeData("ndn:/nztwIvHX/%00");
- strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face1, 0), *data1);
- this->advanceClocks(10_ms, 500_ms);
-
- // second Interest: bestFace is face1, nUpstreams becomes 0,
- // therefore pitEntryInfo->maxInterval cannot be calculated from deferRange and nUpstreams
- shared_ptr<Interest> interest2 = makeInterest("ndn:/nztwIvHX/%01");
- interest2->setInterestLifetime(8_s);
- shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
-
- pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
- strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest2, pitEntry2);
-
- // FIB entry is changed before doPropagate executes
- fib.addOrUpdateNextHop(fibEntry, *face2, 20);
- this->advanceClocks(10_ms, 1_s);// should not crash
-}
-
-BOOST_AUTO_TEST_CASE(Bug1961)
-{
- LimitedIo limitedIo(this);
- FaceTable faceTable;
- Forwarder forwarder(faceTable);
- NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
- strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
-
- shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
- shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
- shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
- faceTable.add(face1);
- faceTable.add(face2);
- faceTable.add(face3);
-
- Fib& fib = forwarder.getFib();
- fib::Entry& fibEntry = *fib.insert(Name()).first;
- fib.addOrUpdateNextHop(fibEntry, *face1, 10);
- fib.addOrUpdateNextHop(fibEntry, *face2, 20);
-
- Pit& pit = forwarder.getPit();
-
- // first Interest: strategy forwards to face1 and face2
- shared_ptr<Interest> interest1 = makeInterest("ndn:/seRMz5a6/%00");
- interest1->setInterestLifetime(2_s);
- shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
-
- pitEntry1->insertOrUpdateInRecord(*face3, *interest1);
- strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest1, pitEntry1);
- limitedIo.run(2 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
- BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face1->getId());
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
-
- // face1 responds
- shared_ptr<Data> data1 = makeData("ndn:/seRMz5a6/%00");
- strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face1, 0), *data1);
- pitEntry1->clearInRecords();
- this->advanceClocks(10_ms);
- // face2 also responds
- strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), *data1);
- this->advanceClocks(10_ms);
-
- // second Interest: bestFace should be face 1
- shared_ptr<Interest> interest2 = makeInterest("ndn:/seRMz5a6/%01");
- interest2->setInterestLifetime(2_s);
- shared_ptr<pit::Entry> pitEntry2 = pit.insert(*interest2).first;
-
- pitEntry2->insertOrUpdateInRecord(*face3, *interest2);
- strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest2, pitEntry2);
- limitedIo.run(3 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
-
- BOOST_REQUIRE_GE(strategy.sendInterestHistory.size(), 3);
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[2].outFaceId, face1->getId());
-}
-
-BOOST_AUTO_TEST_CASE(Bug1971)
-{
- LimitedIo limitedIo(this);
- FaceTable faceTable;
- Forwarder forwarder(faceTable);
- NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
- strategy.afterAction.connect(bind(&LimitedIo::afterOp, &limitedIo));
-
- shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
- shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
- faceTable.add(face1);
- faceTable.add(face2);
-
- Fib& fib = forwarder.getFib();
- fib::Entry& fibEntry = *fib.insert(Name()).first;
- fib.addOrUpdateNextHop(fibEntry, *face2, 10);
-
- Pit& pit = forwarder.getPit();
-
- // first Interest: strategy forwards to face2
- shared_ptr<Interest> interest1 = makeInterest("ndn:/M4mBXCsd");
- interest1->setInterestLifetime(2_s);
- shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
-
- pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
- strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
- limitedIo.run(1 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
- BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
-
- // face2 responds
- shared_ptr<Data> data1 = makeData("ndn:/M4mBXCsd");
- data1->setFreshnessPeriod(5_ms);
- strategy.beforeSatisfyInterest(pitEntry1, FaceEndpoint(*face2, 0), *data1);
- pitEntry1->deleteOutRecord(*face2);
- pitEntry1->clearInRecords();
- this->advanceClocks(10_ms);
-
- // similar Interest: strategy should still forward it
- pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
- strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
- limitedIo.run(2 - strategy.sendInterestHistory.size(), 2_s, 10_ms);
- BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 2);
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[1].outFaceId, face2->getId());
-}
-
-BOOST_AUTO_TEST_CASE(Bug1998)
-{
- FaceTable faceTable;
- Forwarder forwarder(faceTable);
- NccStrategyTester& strategy = choose<NccStrategyTester>(forwarder);
-
- shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
- shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
- faceTable.add(face1);
- faceTable.add(face2);
-
- Fib& fib = forwarder.getFib();
- fib::Entry& fibEntry = *fib.insert(Name()).first;
- fib.addOrUpdateNextHop(fibEntry, *face1, 10); // face1 is top-ranked nexthop
- fib.addOrUpdateNextHop(fibEntry, *face2, 20);
-
- Pit& pit = forwarder.getPit();
-
- // Interest comes from face1, which is sole downstream
- shared_ptr<Interest> interest1 = makeInterest("ndn:/tFy5HzUzD4");
- shared_ptr<pit::Entry> pitEntry1 = pit.insert(*interest1).first;
- pitEntry1->insertOrUpdateInRecord(*face1, *interest1);
-
- strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest1, pitEntry1);
-
- // Interest shall go to face2, not loop back to face1
- BOOST_REQUIRE_EQUAL(strategy.sendInterestHistory.size(), 1);
- BOOST_CHECK_EQUAL(strategy.sendInterestHistory[0].outFaceId, face2->getId());
-}
-
-BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(PredictionAdjustment, 1)
-BOOST_AUTO_TEST_CASE(PredictionAdjustment) // Bug 3411
-{
- /*
- * /----------\
- * | consumer |
- * \----------/
- * |
- * |
- * +---+ 5ms +---+
- * | A |-------| B |
- * +---+ +---+
- * | |
- * | 5ms | 15ms/5ms
- * | |
- * +---+ +---+
- * | C |-------| D |
- * +---+ 15ms +---+
- * /5ms |
- * |
- * /----------\
- * | producer |
- * \----------/
- */
-
- TopologyTester topo;
- TopologyNode nodeA = topo.addForwarder("A"),
- nodeB = topo.addForwarder("B"),
- nodeC = topo.addForwarder("C"),
- nodeD = topo.addForwarder("D");
-
- for (TopologyNode node : {nodeA, nodeB, nodeC, nodeD}) {
- topo.setStrategy<NccStrategy>(node);
- }
-
- shared_ptr<TopologyLink> linkAB = topo.addLink("AB", 5_ms, {nodeA, nodeB}),
- linkAC = topo.addLink("AC", 5_ms, {nodeA, nodeC}),
- linkBD = topo.addLink("BD", 15_ms, {nodeB, nodeD}),
- linkCD = topo.addLink("CD", 15_ms, {nodeC, nodeD});
-
- topo.registerPrefix(nodeA, linkAB->getFace(nodeA), "ndn:/P");
- topo.registerPrefix(nodeA, linkAC->getFace(nodeA), "ndn:/P");
- topo.registerPrefix(nodeB, linkBD->getFace(nodeB), "ndn:/P");
- topo.registerPrefix(nodeC, linkCD->getFace(nodeC), "ndn:/P");
-
- shared_ptr<TopologyAppLink> producer = topo.addAppFace("producer", nodeD, "ndn:/P");
- topo.addEchoProducer(producer->getClientFace());
-
- shared_ptr<TopologyAppLink> consumer = topo.addAppFace("consumer", nodeA);
- topo.addIntervalConsumer(consumer->getClientFace(), "ndn:/P",
- 100_ms, 300);
-
- auto getMeInfo = [&] () -> NccStrategy::MeasurementsEntryInfo* {
- Measurements& measurements = topo.getForwarder(nodeA).getMeasurements();
- measurements::Entry* me = measurements.findExactMatch("ndn:/P");
- return me == nullptr ? nullptr : me->getStrategyInfo<NccStrategy::MeasurementsEntryInfo>();
- };
-
- // NccStrategy starts with an exploration period when the algorithm adjusts
- // its prediction to converge near the path RTT.
- bool isExplorationFinished = false;
- const time::milliseconds TRUE_RTT1(40);
- bool isLastPredictionUnder = true;
- int nPredictionCrossings = 0;
- for (int i = 0; i < 10000; ++i) {
- this->advanceClocks(5_ms);
- auto meInfo = getMeInfo();
- if (meInfo == nullptr) {
- continue;
- }
-
- if ((isLastPredictionUnder && meInfo->prediction > TRUE_RTT1) ||
- (!isLastPredictionUnder && meInfo->prediction < TRUE_RTT1)) {
- isLastPredictionUnder = !isLastPredictionUnder;
- if (++nPredictionCrossings > 6) {
- isExplorationFinished = true;
- BOOST_TEST_MESSAGE("exploration finishes after " << (i * 5) << "ms");
- break;
- }
- }
- }
- BOOST_REQUIRE_MESSAGE(isExplorationFinished, "exploration did not finish within 50s");
-
- // NccStrategy has selected one path as the best.
- // When we reduce the RTT of the other path, ideally it should be selected as the best face.
- // However, this won't happen due to a weakness in NccStrategy.
- // See https://redmine.named-data.net/issues/3411#note-4
- shared_ptr<Face> bestFace1 = getMeInfo()->bestFace.lock();
- if (bestFace1.get() == &linkAB->getFace(nodeA)) {
- linkCD->setDelay(5_ms);
- }
- else if (bestFace1.get() == &linkAC->getFace(nodeA)) {
- linkBD->setDelay(5_ms);
- }
- else {
- BOOST_FAIL("unexpected best face");
- }
-
- bool isNewBestChosen = false;
- for (int i = 0; i < 10000; ++i) {
- this->advanceClocks(5_ms);
- auto meInfo = getMeInfo();
- if (meInfo == nullptr) {
- continue;
- }
-
- if (meInfo->bestFace.lock() != bestFace1) {
- isNewBestChosen = true;
- BOOST_TEST_MESSAGE("new best face is found after " << (i * 5) << "ms");
- break;
- }
- }
- BOOST_CHECK_MESSAGE(isNewBestChosen, "new best face is not found in 50000ms"); // expected failure
-}
-
-BOOST_AUTO_TEST_SUITE_END() // TestNccStrategy
-BOOST_AUTO_TEST_SUITE_END() // Fw
-
-} // namespace tests
-} // namespace fw
-} // namespace nfd
diff --git a/tests/daemon/fw/strategy-instantiation.t.cpp b/tests/daemon/fw/strategy-instantiation.t.cpp
index 4ea9bb3..cd057bc 100644
--- a/tests/daemon/fw/strategy-instantiation.t.cpp
+++ b/tests/daemon/fw/strategy-instantiation.t.cpp
@@ -33,19 +33,17 @@
#include "fw/best-route-strategy.hpp"
#include "fw/best-route-strategy2.hpp"
#include "fw/multicast-strategy.hpp"
-#include "fw/ncc-strategy.hpp"
#include "fw/self-learning-strategy.hpp"
#include "fw/random-strategy.hpp"
#include "tests/test-common.hpp"
+
#include <boost/mpl/vector.hpp>
namespace nfd {
namespace fw {
namespace tests {
-using namespace nfd::tests;
-
BOOST_AUTO_TEST_SUITE(Fw)
BOOST_AUTO_TEST_SUITE(TestStrategyInstantiation)
@@ -80,7 +78,6 @@
Test<BestRouteStrategy, false, 1>,
Test<BestRouteStrategy2, false, 5>,
Test<MulticastStrategy, false, 4>,
- Test<NccStrategy, false, 1>,
Test<SelfLearningStrategy, false, 1>,
Test<RandomStrategy, false, 1>
>;
diff --git a/tests/daemon/fw/strategy-scope-control.t.cpp b/tests/daemon/fw/strategy-scope-control.t.cpp
index 123a4f8..a707a46 100644
--- a/tests/daemon/fw/strategy-scope-control.t.cpp
+++ b/tests/daemon/fw/strategy-scope-control.t.cpp
@@ -33,7 +33,6 @@
#include "fw/best-route-strategy.hpp"
#include "fw/best-route-strategy2.hpp"
#include "fw/multicast-strategy.hpp"
-#include "fw/ncc-strategy.hpp"
#include "fw/random-strategy.hpp"
#include "tests/test-common.hpp"
@@ -41,7 +40,6 @@
#include "choose-strategy.hpp"
#include "strategy-tester.hpp"
-#include <boost/mpl/copy_if.hpp>
#include <boost/mpl/vector.hpp>
namespace nfd {
@@ -87,7 +85,7 @@
BOOST_AUTO_TEST_SUITE(Fw)
BOOST_AUTO_TEST_SUITE(TestStrategyScopeControl)
-template<typename S, bool WillSendNackNoRoute, bool CanProcessNack, bool WillRejectPitEntry = true>
+template<typename S, bool WillSendNackNoRoute, bool CanProcessNack, bool WillRejectPitEntry>
class Test
{
public:
@@ -113,13 +111,12 @@
};
using Tests = boost::mpl::vector<
- Test<AccessStrategy, false, false>,
- Test<AsfStrategy, true, false>,
- Test<BestRouteStrategy, false, false>,
- Test<BestRouteStrategy2, true, true>,
+ Test<AccessStrategy, false, false, true>,
+ Test<AsfStrategy, true, false, true>,
+ Test<BestRouteStrategy, false, false, true>,
+ Test<BestRouteStrategy2, true, true, true>,
Test<MulticastStrategy, false, false, false>,
- Test<NccStrategy, false, false>,
- Test<RandomStrategy, true, true>
+ Test<RandomStrategy, true, true, true>
>;
BOOST_FIXTURE_TEST_CASE_TEMPLATE(LocalhostInterestToLocal,
@@ -259,7 +256,7 @@
this->fib.addOrUpdateNextHop(*fibEntry, *this->localFace4, 10);
this->fib.addOrUpdateNextHop(*fibEntry, *this->nonLocalFace2, 20);
- auto interest = makeInterest("/localhop/A/1", 1377);
+ auto interest = makeInterest("/localhop/A/1", false, nullopt, 1377);
shared_ptr<pit::Entry> pitEntry = this->pit.insert(*interest).first;
pitEntry->insertOrUpdateInRecord(*this->nonLocalFace1, *interest);
lp::Nack nack = makeNack(*interest, lp::NackReason::NO_ROUTE);