fw: Nack in pipelines and best-route strategy
* in PIT out-record, add last incoming Nack field
* create incoming Nack pipeline
* create outgoing Nack pipeline
* modify Interest loop pipeline to send Nack upon duplicate Nonce
* in strategy API, add after receive Nack trigger and send Nack action
* in best-route strategy, send Nack-NoRoute before rejecting pending Interest
* in best-route strategy, process incoming Nack
Other changes include:
* Pit::find
* StrategyTester saved arguments structs
* TopologyTester transmit at Transport level
refs #3156
Change-Id: I7868561c0838231083d471261200aeb280cc6e9d
diff --git a/daemon/fw/strategy.cpp b/daemon/fw/strategy.cpp
index 4f439db..7b0504e 100644
--- a/daemon/fw/strategy.cpp
+++ b/daemon/fw/strategy.cpp
@@ -60,23 +60,36 @@
NFD_LOG_DEBUG("beforeExpirePendingInterest pitEntry=" << pitEntry->getName());
}
-//void
-//Strategy::afterAddFibEntry(shared_ptr<fib::Entry> fibEntry)
-//{
-// NFD_LOG_DEBUG("afterAddFibEntry fibEntry=" << fibEntry->getPrefix());
-//}
-//
-//void
-//Strategy::afterUpdateFibEntry(shared_ptr<fib::Entry> fibEntry)
-//{
-// NFD_LOG_DEBUG("afterUpdateFibEntry fibEntry=" << fibEntry->getPrefix());
-//}
-//
-//void
-//Strategy::beforeRemoveFibEntry(shared_ptr<fib::Entry> fibEntry)
-//{
-// NFD_LOG_DEBUG("beforeRemoveFibEntry fibEntry=" << fibEntry->getPrefix());
-//}
+void
+Strategy::afterReceiveNack(const Face& inFace, const lp::Nack& nack,
+ shared_ptr<fib::Entry> fibEntry, shared_ptr<pit::Entry> pitEntry)
+{
+ NFD_LOG_DEBUG("afterReceiveNack inFace=" << inFace.getId() <<
+ " pitEntry=" << pitEntry->getName());
+}
+
+void
+Strategy::sendNacks(shared_ptr<pit::Entry> pitEntry, const lp::NackHeader& header,
+ std::initializer_list<const Face*> exceptFaces)
+{
+ // populate downstreams with all downstreams faces
+ std::unordered_set<const Face*> downstreams;
+ const pit::InRecordCollection& inRecords = pitEntry->getInRecords();
+ std::transform(inRecords.begin(), inRecords.end(), std::inserter(downstreams, downstreams.end()),
+ [] (const pit::InRecord& inR) { return inR.getFace().get(); });
+
+ // delete excluded faces
+ // .erase in a loop is more efficient than std::set_difference between that requires sorted range
+ for (const Face* exceptFace : exceptFaces) {
+ downstreams.erase(exceptFace);
+ }
+
+ // send Nacks
+ for (const Face* downstream : downstreams) {
+ this->sendNack(pitEntry, *downstream, header);
+ }
+ // warning: don't loop on pitEntry->getInRecords(), because InRecord is erased when sending Nack
+}
} // namespace fw
} // namespace nfd