32 #include <ndn-cxx/lp/tags.hpp> 48 , m_measurements(m_nameTree)
49 , m_strategyChoice(*this)
51 m_faceTable.
afterAdd.connect([
this] (Face& face) {
52 face.afterReceiveInterest.connect(
53 [
this, &face] (
const Interest& interest) {
56 face.afterReceiveData.connect(
57 [
this, &face] (
const Data& data) {
60 face.afterReceiveNack.connect(
61 [
this, &face] (
const lp::Nack& nack) {
76 Forwarder::onIncomingInterest(Face& inFace,
const Interest& interest)
80 " interest=" << interest.getName());
81 interest.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
85 bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
87 if (isViolatingLocalhost) {
89 " interest=" << interest.getName() <<
" violates /localhost");
95 bool hasDuplicateNonceInDnl = m_deadNonceList.
has(interest.getName(), interest.getNonce());
96 if (hasDuplicateNonceInDnl) {
98 this->onInterestLoop(inFace, interest);
103 if (!interest.getForwardingHint().empty() &&
105 NFD_LOG_DEBUG(
"onIncomingInterest face=" << inFace.getId() <<
106 " interest=" << interest.getName() <<
" reaching-producer-region");
107 const_cast<Interest&
>(interest).setForwardingHint({});
111 shared_ptr<pit::Entry> pitEntry = m_pit.insert(interest).first;
116 if (inFace.getLinkType() == ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
120 if (hasDuplicateNonceInPit) {
122 this->onInterestLoop(inFace, interest);
127 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
130 if (!pitEntry->hasInRecords()) {
132 bind(&Forwarder::onContentStoreHit,
this, ref(inFace), pitEntry, _1, _2),
133 bind(&Forwarder::onContentStoreMiss,
this, ref(inFace), pitEntry, _1));
136 this->onContentStoreMiss(inFace, pitEntry, interest);
141 Forwarder::onInterestLoop(Face& inFace,
const Interest& interest)
144 if (inFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
146 " interest=" << interest.getName() <<
152 " interest=" << interest.getName() <<
153 " send-Nack-duplicate");
157 lp::Nack nack(interest);
158 nack.setReason(lp::NackReason::DUPLICATE);
159 inFace.sendNack(nack);
163 Forwarder::onContentStoreMiss(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
164 const Interest& interest)
166 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.getName());
170 pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
173 this->setUnsatisfyTimer(pitEntry);
176 shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
177 if (nextHopTag !=
nullptr) {
179 Face* nextHopFace = m_faceTable.
get(*nextHopTag);
180 if (nextHopFace !=
nullptr) {
181 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.getName() <<
" nexthop-faceid=" << nextHopFace->getId());
184 this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
190 this->dispatchToStrategy(*pitEntry,
195 Forwarder::onContentStoreHit(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
196 const Interest& interest,
const Data& data)
198 NFD_LOG_DEBUG(
"onContentStoreHit interest=" << interest.getName());
205 this->setStragglerTimer(pitEntry,
true, data.getFreshnessPeriod());
208 this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
212 Forwarder::onOutgoingInterest(
const shared_ptr<pit::Entry>& pitEntry, Face& outFace,
const Interest& interest)
214 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
215 " interest=" << pitEntry->getName());
218 pitEntry->insertOrUpdateOutRecord(outFace, interest);
221 outFace.sendInterest(interest);
226 Forwarder::onInterestReject(
const shared_ptr<pit::Entry>& pitEntry)
229 NFD_LOG_ERROR(
"onInterestReject interest=" << pitEntry->getName() <<
230 " cannot reject forwarded Interest");
233 NFD_LOG_DEBUG(
"onInterestReject interest=" << pitEntry->getName());
236 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
239 this->setStragglerTimer(pitEntry,
false);
243 Forwarder::onInterestUnsatisfied(
const shared_ptr<pit::Entry>& pitEntry)
245 NFD_LOG_DEBUG(
"onInterestUnsatisfied interest=" << pitEntry->getName());
248 this->dispatchToStrategy(*pitEntry,
252 this->onInterestFinalize(pitEntry,
false);
256 Forwarder::onInterestFinalize(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
257 ndn::optional<time::milliseconds> dataFreshnessPeriod)
259 NFD_LOG_DEBUG(
"onInterestFinalize interest=" << pitEntry->getName() <<
260 (isSatisfied ?
" satisfied" :
" unsatisfied"));
263 this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
266 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
267 m_pit.erase(pitEntry.get());
271 Forwarder::onIncomingData(Face& inFace,
const Data& data)
274 NFD_LOG_DEBUG(
"onIncomingData face=" << inFace.getId() <<
" data=" << data.getName());
275 data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
279 bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
281 if (isViolatingLocalhost) {
283 " data=" << data.getName() <<
" violates /localhost");
290 if (pitMatches.begin() == pitMatches.end()) {
292 this->onDataUnsolicited(inFace, data);
299 std::set<Face*> pendingDownstreams;
301 auto now = time::steady_clock::now();
302 for (
const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
303 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
306 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
309 for (
const pit::InRecord& inRecord : pitEntry->getInRecords()) {
310 if (inRecord.getExpiry() > now) {
311 pendingDownstreams.insert(&inRecord.getFace());
316 this->dispatchToStrategy(*pitEntry,
320 this->insertDeadNonceList(*pitEntry,
true, data.getFreshnessPeriod(), &inFace);
323 pitEntry->clearInRecords();
324 pitEntry->deleteOutRecord(inFace);
327 this->setStragglerTimer(pitEntry,
true, data.getFreshnessPeriod());
331 for (Face* pendingDownstream : pendingDownstreams) {
332 if (pendingDownstream->getId() == inFace.getId() &&
333 pendingDownstream->getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
337 this->onOutgoingData(data, *pendingDownstream);
342 Forwarder::onDataUnsolicited(Face& inFace,
const Data& data)
348 m_cs.insert(data,
true);
352 " data=" << data.getName() <<
353 " decision=" << decision);
357 Forwarder::onOutgoingData(
const Data& data, Face& outFace)
360 NFD_LOG_WARN(
"onOutgoingData face=invalid data=" << data.getName());
363 NFD_LOG_DEBUG(
"onOutgoingData face=" << outFace.getId() <<
" data=" << data.getName());
366 bool isViolatingLocalhost = outFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
368 if (isViolatingLocalhost) {
370 " data=" << data.getName() <<
" violates /localhost");
378 outFace.sendData(data);
383 Forwarder::onIncomingNack(Face& inFace,
const lp::Nack& nack)
386 nack.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
390 if (inFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
392 " nack=" << nack.getInterest().getName() <<
393 "~" << nack.getReason() <<
" face-is-multi-access");
398 shared_ptr<pit::Entry> pitEntry = m_pit.find(nack.getInterest());
400 if (pitEntry ==
nullptr) {
402 " nack=" << nack.getInterest().getName() <<
403 "~" << nack.getReason() <<
" no-PIT-entry");
410 if (outRecord == pitEntry->out_end()) {
412 " nack=" << nack.getInterest().getName() <<
413 "~" << nack.getReason() <<
" no-out-record");
418 if (nack.getInterest().getNonce() != outRecord->getLastNonce()) {
420 " nack=" << nack.getInterest().getName() <<
421 "~" << nack.getReason() <<
" wrong-Nonce " <<
422 nack.getInterest().getNonce() <<
"!=" << outRecord->getLastNonce());
427 " nack=" << nack.getInterest().getName() <<
428 "~" << nack.getReason() <<
" OK");
431 outRecord->setIncomingNack(nack);
434 this->dispatchToStrategy(*pitEntry,
439 Forwarder::onOutgoingNack(
const shared_ptr<pit::Entry>& pitEntry,
const Face& outFace,
440 const lp::NackHeader& nack)
444 " nack=" << pitEntry->getInterest().getName() <<
445 "~" << nack.getReason() <<
" no-in-record");
453 if (inRecord == pitEntry->in_end()) {
455 " nack=" << pitEntry->getInterest().getName() <<
456 "~" << nack.getReason() <<
" no-in-record");
461 if (outFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
463 " nack=" << pitEntry->getInterest().getName() <<
464 "~" << nack.getReason() <<
" face-is-multi-access");
469 " nack=" << pitEntry->getInterest().getName() <<
470 "~" << nack.getReason() <<
" OK");
473 lp::Nack nackPkt(inRecord->getInterest());
474 nackPkt.setHeader(nack);
477 pitEntry->deleteInRecord(outFace);
480 const_cast<Face&
>(outFace).sendNack(nackPkt);
491 Forwarder::setUnsatisfyTimer(
const shared_ptr<pit::Entry>& pitEntry)
496 time::steady_clock::TimePoint lastExpiry = lastExpiring->getExpiry();
497 time::nanoseconds lastExpiryFromNow = lastExpiry - time::steady_clock::now();
498 if (lastExpiryFromNow <= time::seconds::zero()) {
504 bind(&Forwarder::onInterestUnsatisfied,
this, pitEntry));
508 Forwarder::setStragglerTimer(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
509 ndn::optional<time::milliseconds> dataFreshnessPeriod)
511 time::nanoseconds stragglerTime = time::milliseconds(100);
515 bind(&Forwarder::onInterestFinalize,
this, pitEntry, isSatisfied, dataFreshnessPeriod));
519 Forwarder::cancelUnsatisfyAndStragglerTimer(
pit::Entry& pitEntry)
533 Forwarder::insertDeadNonceList(
pit::Entry& pitEntry,
bool isSatisfied,
534 ndn::optional<time::milliseconds> dataFreshnessPeriod, Face* upstream)
539 BOOST_ASSERT(dataFreshnessPeriod);
540 BOOST_ASSERT(*dataFreshnessPeriod >= time::milliseconds::zero());
541 needDnl =
static_cast<bool>(pitEntry.
getInterest().getMustBeFresh()) &&
542 *dataFreshnessPeriod < m_deadNonceList.
getLifetime();
550 if (upstream ==
nullptr) {
553 std::for_each(outRecords.begin(), outRecords.end(),
560 m_deadNonceList.
add(pitEntry.
getName(), outRecord->getLastNonce());
OutRecordCollection::iterator getOutRecord(const Face &face)
get the out-record for face
void cleanupOnFaceRemoval(NameTree &nt, Fib &fib, Pit &pit, const Face &face)
cleanup tables when a face is destroyed
#define NFD_LOG_DEBUG(expression)
PacketCounter nInInterests
void cancel(const EventId &eventId)
cancel a scheduled event
virtual void afterReceiveInterest(const Face &inFace, const Interest &interest, const shared_ptr< pit::Entry > &pitEntry)=0
trigger after Interest is received
contains information about an Interest toward an outgoing face
static const Name & getStrategyName()
scheduler::EventId m_unsatisfyTimer
unsatisfy timer
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
scheduler::EventId m_stragglerTimer
straggler timer
virtual void beforeSatisfyInterest(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data)
trigger before PIT entry is satisfied
Face * get(FaceId id) const
get face by FaceId
#define NFD_LOG_ERROR(expression)
const time::nanoseconds & getLifetime() const
void add(const Name &name, uint32_t nonce)
records name+nonce
static bool compare_InRecord_expiry(const pit::InRecord &a, const pit::InRecord &b)
PacketCounter nOutInterests
bool has(const Name &name, uint32_t nonce) const
determines if name+nonce exists
DropAllUnsolicitedDataPolicy DefaultUnsolicitedDataPolicy
the default UnsolicitedDataPolicy
Table::const_iterator iterator
#define NFD_LOG_WARN(expression)
static void insertNonceToDnl(DeadNonceList &dnl, const pit::Entry &pitEntry, const pit::OutRecord &outRecord)
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
contains information about an Interest from an incoming face
virtual void afterReceiveNack(const Face &inFace, const lp::Nack &nack, const shared_ptr< pit::Entry > &pitEntry)
trigger after Nack is received
signal::Signal< FaceTable, Face & > beforeRemove
fires before a face is removed
void startProcessInterest(Face &face, const Interest &interest)
start incoming Interest processing
represents the Dead Nonce list
signal::Signal< FaceTable, Face & > afterAdd
fires after a face is added
bool hasPendingOutRecords(const pit::Entry &pitEntry)
determine whether pitEntry has any pending out-records
const Interest & getInterest() const
const Name LOCALHOST
ndn:/localhost
no duplicate Nonce is found
int findDuplicateNonce(const pit::Entry &pitEntry, uint32_t nonce, const Face &face)
determine whether pitEntry has duplicate Nonce nonce
std::list< OutRecord > OutRecordCollection
an unordered collection of out-records
static Name getDefaultStrategyName()
represents a forwarding strategy
This file contains common algorithms used by forwarding strategies.
#define NFD_LOG_INIT(name)
UnsolicitedDataDecision
a decision made by UnsolicitedDataPolicy
EventId schedule(time::nanoseconds after, const EventCallback &event)
schedule an event
the Data should be cached in the ContentStore
bool isInProducerRegion(const DelegationList &forwardingHint) const
determines whether an Interest has reached a producer region
uint32_t getLastNonce() const
virtual void beforeExpirePendingInterest(const shared_ptr< pit::Entry > &pitEntry)
trigger before PIT entry expires
const OutRecordCollection & getOutRecords() const
void startProcessData(Face &face, const Data &data)
start incoming Data processing
const FaceId FACEID_CONTENT_STORE
identifies a packet comes from the ContentStore
std::vector< shared_ptr< Entry > > DataMatchResult
const FaceId INVALID_FACEID
indicates an invalid FaceId
const Name & getName() const
void startProcessNack(Face &face, const lp::Nack &nack)
start incoming Nack processing