32 #include <ndn-cxx/lp/tags.hpp>
33 #include <boost/random/uniform_int_distribution.hpp>
43 , m_measurements(m_nameTree)
48 m_faceTable.
afterAdd.connect([
this] (Face& face) {
49 face.afterReceiveInterest.connect(
50 [
this, &face] (
const Interest& interest) {
53 face.afterReceiveData.connect(
54 [
this, &face] (
const Data& data) {
57 face.afterReceiveNack.connect(
58 [
this, &face] (
const lp::Nack& nack) {
75 if (interest.hasLink()) {
79 catch (
const tlv::Error&) {
81 " interest=" << interest.getName() <<
" malformed");
86 this->onIncomingInterest(face, interest);
95 this->onIncomingData(face, data);
103 if (nack.getInterest().hasLink()) {
104 nack.getInterest().getLink();
107 catch (
const tlv::Error&) {
109 " nack=" << nack.getInterest().getName() <<
110 "~" << nack.getReason() <<
" malformed");
114 this->onIncomingNack(face, nack);
118 Forwarder::onIncomingInterest(Face& inFace,
const Interest& interest)
121 NFD_LOG_DEBUG(
"onIncomingInterest face=" << inFace.getId() <<
122 " interest=" << interest.getName());
123 interest.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
127 bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
129 if (isViolatingLocalhost) {
130 NFD_LOG_DEBUG(
"onIncomingInterest face=" << inFace.getId() <<
131 " interest=" << interest.getName() <<
" violates /localhost");
137 bool hasDuplicateNonceInDnl = m_deadNonceList.
has(interest.getName(), interest.getNonce());
138 if (hasDuplicateNonceInDnl) {
140 this->onInterestLoop(inFace, interest);
145 shared_ptr<pit::Entry> pitEntry = m_pit.insert(interest).first;
150 if (hasDuplicateNonceInPit) {
152 this->onInterestLoop(inFace, interest);
157 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
160 if (!pitEntry->hasInRecords()) {
162 bind(&Forwarder::onContentStoreHit,
this, ref(inFace), pitEntry, _1, _2),
163 bind(&Forwarder::onContentStoreMiss,
this, ref(inFace), pitEntry, _1));
166 this->onContentStoreMiss(inFace, pitEntry, interest);
171 Forwarder::onInterestLoop(Face& inFace,
const Interest& interest)
174 if (inFace.getLinkType() == ndn::nfd::LINK_TYPE_MULTI_ACCESS) {
176 " interest=" << interest.getName() <<
182 " interest=" << interest.getName() <<
183 " send-Nack-duplicate");
187 lp::Nack nack(interest);
188 nack.setReason(lp::NackReason::DUPLICATE);
189 inFace.sendNack(nack);
193 Forwarder::onContentStoreMiss(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
194 const Interest& interest)
196 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.getName());
199 pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
202 this->setUnsatisfyTimer(pitEntry);
205 shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
206 if (nextHopTag !=
nullptr) {
208 Face* nextHopFace = m_faceTable.
get(*nextHopTag);
209 if (nextHopFace !=
nullptr) {
211 this->onOutgoingInterest(pitEntry, *nextHopFace);
217 this->dispatchToStrategy(*pitEntry,
218 [&] (fw::Strategy& strategy) { strategy.afterReceiveInterest(inFace, interest, pitEntry); });
222 Forwarder::onContentStoreHit(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
223 const Interest& interest,
const Data& data)
225 NFD_LOG_DEBUG(
"onContentStoreHit interest=" << interest.getName());
231 this->setStragglerTimer(pitEntry,
true, data.getFreshnessPeriod());
234 this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
238 Forwarder::onOutgoingInterest(
const shared_ptr<pit::Entry>& pitEntry, Face& outFace,
242 NFD_LOG_WARN(
"onOutgoingInterest face=invalid interest=" << pitEntry->getName());
245 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
246 " interest=" << pitEntry->getName());
250 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
251 " interest=" << pitEntry->getName() <<
" violates scope");
261 pitEntry->in_begin(), pitEntry->in_end(),
262 [&outFace] (
const pit::InRecord& a,
const pit::InRecord& b) {
263 bool isOutFaceA = &a.getFace() == &outFace;
264 bool isOutFaceB = &b.getFace() == &outFace;
265 return (isOutFaceA > isOutFaceB) ||
266 (isOutFaceA == isOutFaceB && a.getLastRenewed() < b.getLastRenewed());
268 BOOST_ASSERT(pickedInRecord != pitEntry->in_end());
269 auto interest = const_pointer_cast<Interest>(pickedInRecord->getInterest().shared_from_this());
272 interest = make_shared<Interest>(*interest);
273 static boost::random::uniform_int_distribution<uint32_t> dist;
278 pitEntry->insertOrUpdateOutRecord(outFace, *interest);
281 outFace.sendInterest(*interest);
286 Forwarder::onInterestReject(
const shared_ptr<pit::Entry>& pitEntry)
289 NFD_LOG_ERROR(
"onInterestReject interest=" << pitEntry->getName() <<
290 " cannot reject forwarded Interest");
293 NFD_LOG_DEBUG(
"onInterestReject interest=" << pitEntry->getName());
296 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
299 this->setStragglerTimer(pitEntry,
false);
303 Forwarder::onInterestUnsatisfied(
const shared_ptr<pit::Entry>& pitEntry)
305 NFD_LOG_DEBUG(
"onInterestUnsatisfied interest=" << pitEntry->getName());
308 this->dispatchToStrategy(*pitEntry,
309 [&] (fw::Strategy& strategy) { strategy.beforeExpirePendingInterest(pitEntry); });
312 this->onInterestFinalize(pitEntry,
false);
316 Forwarder::onInterestFinalize(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
317 time::milliseconds dataFreshnessPeriod)
319 NFD_LOG_DEBUG(
"onInterestFinalize interest=" << pitEntry->getName() <<
320 (isSatisfied ?
" satisfied" :
" unsatisfied"));
323 this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
326 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
327 m_pit.erase(pitEntry.get());
331 Forwarder::onIncomingData(Face& inFace,
const Data& data)
334 NFD_LOG_DEBUG(
"onIncomingData face=" << inFace.getId() <<
" data=" << data.getName());
335 data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
339 bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
341 if (isViolatingLocalhost) {
343 " data=" << data.getName() <<
" violates /localhost");
350 if (pitMatches.begin() == pitMatches.end()) {
352 this->onDataUnsolicited(inFace, data);
359 std::set<Face*> pendingDownstreams;
361 auto now = time::steady_clock::now();
362 for (
const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
363 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
366 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
369 for (
const pit::InRecord& inRecord : pitEntry->getInRecords()) {
370 if (inRecord.getExpiry() > now) {
371 pendingDownstreams.insert(&inRecord.getFace());
376 this->dispatchToStrategy(*pitEntry,
377 [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
380 this->insertDeadNonceList(*pitEntry,
true, data.getFreshnessPeriod(), &inFace);
383 pitEntry->clearInRecords();
384 pitEntry->deleteOutRecord(inFace);
387 this->setStragglerTimer(pitEntry,
true, data.getFreshnessPeriod());
391 for (Face* pendingDownstream : pendingDownstreams) {
392 if (pendingDownstream == &inFace) {
396 this->onOutgoingData(data, *pendingDownstream);
401 Forwarder::onDataUnsolicited(Face& inFace,
const Data& data)
407 m_cs.insert(data,
true);
411 " data=" << data.getName() <<
412 " decision=" << decision);
416 Forwarder::onOutgoingData(
const Data& data, Face& outFace)
419 NFD_LOG_WARN(
"onOutgoingData face=invalid data=" << data.getName());
422 NFD_LOG_DEBUG(
"onOutgoingData face=" << outFace.getId() <<
" data=" << data.getName());
425 bool isViolatingLocalhost = outFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
427 if (isViolatingLocalhost) {
429 " data=" << data.getName() <<
" violates /localhost");
437 outFace.sendData(data);
442 Forwarder::onIncomingNack(Face& inFace,
const lp::Nack& nack)
445 nack.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
449 if (inFace.getLinkType() == ndn::nfd::LINK_TYPE_MULTI_ACCESS) {
451 " nack=" << nack.getInterest().getName() <<
452 "~" << nack.getReason() <<
" face-is-multi-access");
457 shared_ptr<pit::Entry> pitEntry = m_pit.find(nack.getInterest());
459 if (pitEntry ==
nullptr) {
461 " nack=" << nack.getInterest().getName() <<
462 "~" << nack.getReason() <<
" no-PIT-entry");
469 if (outRecord == pitEntry->out_end()) {
471 " nack=" << nack.getInterest().getName() <<
472 "~" << nack.getReason() <<
" no-out-record");
477 if (nack.getInterest().getNonce() != outRecord->getLastNonce()) {
479 " nack=" << nack.getInterest().getName() <<
480 "~" << nack.getReason() <<
" wrong-Nonce " <<
481 nack.getInterest().getNonce() <<
"!=" << outRecord->getLastNonce());
486 " nack=" << nack.getInterest().getName() <<
487 "~" << nack.getReason() <<
" OK");
490 outRecord->setIncomingNack(nack);
493 this->dispatchToStrategy(*pitEntry,
494 [&] (fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
498 Forwarder::onOutgoingNack(
const shared_ptr<pit::Entry>& pitEntry,
const Face& outFace,
499 const lp::NackHeader& nack)
503 " nack=" << pitEntry->getInterest().getName() <<
504 "~" << nack.getReason() <<
" no-in-record");
512 if (inRecord == pitEntry->in_end()) {
514 " nack=" << pitEntry->getInterest().getName() <<
515 "~" << nack.getReason() <<
" no-in-record");
520 if (outFace.getLinkType() == ndn::nfd::LINK_TYPE_MULTI_ACCESS) {
522 " nack=" << pitEntry->getInterest().getName() <<
523 "~" << nack.getReason() <<
" face-is-multi-access");
528 " nack=" << pitEntry->getInterest().getName() <<
529 "~" << nack.getReason() <<
" OK");
532 lp::Nack nackPkt(inRecord->getInterest());
533 nackPkt.setHeader(nack);
536 pitEntry->deleteInRecord(outFace);
539 const_cast<Face&
>(outFace).sendNack(nackPkt);
550 Forwarder::setUnsatisfyTimer(
const shared_ptr<pit::Entry>& pitEntry)
555 time::steady_clock::TimePoint lastExpiry = lastExpiring->getExpiry();
556 time::nanoseconds lastExpiryFromNow = lastExpiry - time::steady_clock::now();
557 if (lastExpiryFromNow <= time::seconds::zero()) {
563 bind(&Forwarder::onInterestUnsatisfied,
this, pitEntry));
567 Forwarder::setStragglerTimer(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
568 time::milliseconds dataFreshnessPeriod)
570 time::nanoseconds stragglerTime = time::milliseconds(100);
574 bind(&Forwarder::onInterestFinalize,
this, pitEntry, isSatisfied, dataFreshnessPeriod));
578 Forwarder::cancelUnsatisfyAndStragglerTimer(pit::Entry& pitEntry)
592 Forwarder::insertDeadNonceList(pit::Entry& pitEntry,
bool isSatisfied,
593 time::milliseconds dataFreshnessPeriod, Face* upstream)
596 bool needDnl =
false;
598 bool hasFreshnessPeriod = dataFreshnessPeriod >= time::milliseconds::zero();
600 needDnl =
static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
601 (hasFreshnessPeriod && dataFreshnessPeriod < m_deadNonceList.
getLifetime());
615 std::for_each(outRecords.begin(), outRecords.end(),
621 if (outRecord != pitEntry.getOutRecords().end()) {
622 m_deadNonceList.
add(pitEntry.getName(), outRecord->getLastNonce());
unique_ptr< Strategy > makeDefaultStrategy(Forwarder &forwarder)
void cleanupOnFaceRemoval(NameTree &nt, Fib &fib, Pit &pit, const Face &face)
cleanup tables when a face is destroyed
Copyright (c) 2014-2016, Regents of the University of California, Arizona Board of Regents...
#define NFD_LOG_DEBUG(expression)
PacketCounter nInInterests
void cancel(const EventId &eventId)
cancel a scheduled event
void installStrategies(Forwarder &forwarder)
contains information about an Interest toward an outgoing face
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
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)
bool violatesScope(const pit::Entry &pitEntry, const Face &outFace)
determine whether forwarding the Interest in pitEntry to outFace would violate scope ...
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
contains information about an Interest from an incoming face
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
boost::random::mt19937 & getGlobalRng()
bool hasPendingOutRecords(const pit::Entry &pitEntry)
determine whether pitEntry has any pending out-records
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
#define NFD_LOG_INIT(name)
EventId schedule(const time::nanoseconds &after, const Scheduler::Event &event)
schedule an event
UnsolicitedDataDecision
a decision made by UnsolicitedDataPolicy
the Data should be cached in the ContentStore
uint32_t getLastNonce() 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