fw: add processing for afterNewNextHop signal
Refs: #4931
Change-Id: I08bddc0ae3ceca0ddb777392ea656876ad6fe701
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index f59963e..5c529a8 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -75,6 +75,10 @@
cleanupOnFaceRemoval(m_nameTree, m_fib, m_pit, face);
});
+ m_fib.afterNewNextHop.connect([&] (const Name& prefix, const fib::NextHop& nextHop) {
+ this->startProcessNewNextHop(prefix, nextHop);
+ });
+
m_strategyChoice.setDefaultStrategy(getDefaultStrategyName());
}
@@ -504,6 +508,46 @@
}
void
+Forwarder::onNewNextHop(const Name& prefix, const fib::NextHop& nextHop)
+{
+ const auto affectedEntries = this->getNameTree().partialEnumerate(prefix,
+ [&] (const name_tree::Entry& nte) -> std::pair<bool, bool> {
+ const fib::Entry* fibEntry = nte.getFibEntry();
+ const fw::Strategy* strategy = nullptr;
+ if (nte.getStrategyChoiceEntry() != nullptr) {
+ strategy = &nte.getStrategyChoiceEntry()->getStrategy();
+ }
+ // current nte has buffered Interests but no fibEntry (except for the root nte) and the strategy
+ // enables new nexthop behavior, we enumerate the current nte and keep visiting its children.
+ if (nte.getName().size() == 0 ||
+ (strategy != nullptr && strategy->wantNewNextHopTrigger() &&
+ fibEntry == nullptr && nte.hasPitEntries())) {
+ return {true, true};
+ }
+ // we don't need the current nte (no pitEntry or strategy doesn't support new nexthop), but
+ // if the current nte has no fibEntry, it's still possible that its children are affected by
+ // the new nexthop.
+ else if (fibEntry == nullptr) {
+ return {false, true};
+ }
+ // if the current nte has a fibEntry, we ignore the current nte and don't visit its
+ // children because they are already covered by the current nte's fibEntry.
+ else {
+ return {false, false};
+ }
+ });
+
+ for (const auto& nte : affectedEntries) {
+ for (const auto& pitEntry : nte.getPitEntries()) {
+ this->dispatchToStrategy(*pitEntry,
+ [&] (fw::Strategy& strategy) {
+ strategy.afterNewNextHop(nextHop, pitEntry);
+ });
+ }
+ }
+}
+
+void
Forwarder::setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
{
BOOST_ASSERT(pitEntry);
diff --git a/daemon/fw/forwarder.hpp b/daemon/fw/forwarder.hpp
index 3b14a61..2da7c87 100644
--- a/daemon/fw/forwarder.hpp
+++ b/daemon/fw/forwarder.hpp
@@ -107,6 +107,16 @@
this->onIncomingNack(ingress, nack);
}
+ /** \brief start new nexthop processing
+ * \param prefix the prefix of the FibEntry containing the new nexthop
+ * \param nextHop the new NextHop
+ */
+ void
+ startProcessNewNextHop(const Name& prefix, const fib::NextHop& nextHop)
+ {
+ this->onNewNextHop(prefix, nextHop);
+ }
+
NameTree&
getNameTree()
{
@@ -218,6 +228,9 @@
VIRTUAL_WITH_TESTS void
onDroppedInterest(const FaceEndpoint& egress, const Interest& interest);
+ VIRTUAL_WITH_TESTS void
+ onNewNextHop(const Name& prefix, const fib::NextHop& nextHop);
+
PROTECTED_WITH_TESTS_ELSE_PRIVATE:
/** \brief set a new expiry timer (now + \p duration) on a PIT entry
*/
diff --git a/daemon/fw/strategy.cpp b/daemon/fw/strategy.cpp
index f9f4106..d33ad9a 100644
--- a/daemon/fw/strategy.cpp
+++ b/daemon/fw/strategy.cpp
@@ -207,6 +207,13 @@
}
void
+Strategy::afterNewNextHop(const fib::NextHop& nextHop, const shared_ptr<pit::Entry>& pitEntry)
+{
+ NFD_LOG_DEBUG("afterNewNextHop pitEntry=" << pitEntry->getName()
+ << " nexthop=" << nextHop.getFace().getId());
+}
+
+void
Strategy::sendData(const shared_ptr<pit::Entry>& pitEntry, const Data& data,
const FaceEndpoint& egress)
{
diff --git a/daemon/fw/strategy.hpp b/daemon/fw/strategy.hpp
index 99e4826..37d98bb 100644
--- a/daemon/fw/strategy.hpp
+++ b/daemon/fw/strategy.hpp
@@ -82,7 +82,7 @@
static std::set<Name>
listRegistered();
-public: // constructor, destructor, strategy name
+public: // constructor, destructor, strategy info
/** \brief Construct a strategy instance.
* \param forwarder a reference to the forwarder, used to enable actions and accessors.
* \note Strategy subclass constructor must not retain a reference to \p forwarder.
@@ -114,6 +114,14 @@
return m_name;
}
+ /** \return whether the afterNewNextHop trigger should be invoked for this strategy.
+ */
+ bool
+ wantNewNextHopTrigger() const
+ {
+ return m_wantNewNextHopTrigger;
+ }
+
public: // triggers
/** \brief trigger after Interest is received
*
@@ -233,6 +241,14 @@
virtual void
onDroppedInterest(const FaceEndpoint& egress, const Interest& interest);
+ /** \brief trigger after new nexthop is added
+ *
+ * The strategy should decide whether to send the buffered Interests to the new nexthop.
+ * In the base class, this method does nothing.
+ */
+ virtual void
+ afterNewNextHop(const fib::NextHop& nextHop, const shared_ptr<pit::Entry>& pitEntry);
+
protected: // actions
/** \brief send Interest to egress
* \param pitEntry PIT entry
@@ -368,6 +384,15 @@
m_name = name;
}
+PUBLIC_WITH_TESTS_ELSE_PROTECTED: // setter
+ /** \brief set whether the afterNewNextHop trigger should be invoked for this strategy
+ */
+ void
+ enableNewNextHopTrigger(bool enabled)
+ {
+ m_wantNewNextHopTrigger = enabled;
+ }
+
private: // registry
typedef std::function<unique_ptr<Strategy>(Forwarder& forwarder, const Name& strategyName)> CreateFunc;
typedef std::map<Name, CreateFunc> Registry; // indexed by strategy name
@@ -392,6 +417,8 @@
Forwarder& m_forwarder;
MeasurementsAccessor m_measurements;
+
+ bool m_wantNewNextHopTrigger = false;
};
} // namespace fw