32 #include <ndn-cxx/lp/tags.hpp> 50 , m_measurements(m_nameTree)
51 , m_strategyChoice(*this)
57 face.afterReceiveInterest.connect(
61 face.afterReceiveData.connect(
65 face.afterReceiveNack.connect(
69 face.onDroppedInterest.connect(
71 this->onDroppedInterest(
face, interest);
85 Forwarder::onIncomingInterest(
Face& inFace,
const Interest& interest)
89 " interest=" << interest.
getName());
90 interest.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.
getId()));
96 if (isViolatingLocalhost) {
98 " interest=" << interest.
getName() <<
" violates /localhost");
104 bool hasDuplicateNonceInDnl = m_deadNonceList.
has(interest.
getName(), interest.
getNonce());
105 if (hasDuplicateNonceInDnl) {
107 this->onInterestLoop(inFace, interest);
115 " interest=" << interest.
getName() <<
" reaching-producer-region");
116 const_cast<Interest&
>(interest).setForwardingHint({});
120 shared_ptr<pit::Entry> pitEntry = m_pit.
insert(interest).first;
129 if (hasDuplicateNonceInPit) {
131 this->onInterestLoop(inFace, interest);
136 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
139 bool isPending = inRecords.begin() != inRecords.end();
141 if (m_csFromNdnSim ==
nullptr) {
143 bind(&Forwarder::onContentStoreHit,
this, ref(inFace), pitEntry, _1, _2),
144 bind(&Forwarder::onContentStoreMiss,
this, ref(inFace), pitEntry, _1));
147 shared_ptr<Data> match = m_csFromNdnSim->Lookup(interest.shared_from_this());
148 if (match !=
nullptr) {
149 this->onContentStoreHit(inFace, pitEntry, interest, *match);
152 this->onContentStoreMiss(inFace, pitEntry, interest);
157 this->onContentStoreMiss(inFace, pitEntry, interest);
162 Forwarder::onInterestLoop(
Face& inFace,
const Interest& interest)
167 " interest=" << interest.getName() <<
173 " interest=" << interest.getName() <<
174 " send-Nack-duplicate");
179 nack.setReason(lp::NackReason::DUPLICATE);
180 inFace.sendNack(nack);
184 Forwarder::onContentStoreMiss(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
187 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.getName());
191 pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
194 this->setUnsatisfyTimer(pitEntry);
198 if (nextHopTag !=
nullptr) {
200 Face* nextHopFace = m_faceTable.
get(*nextHopTag);
201 if (nextHopFace !=
nullptr) {
202 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.getName() <<
" nexthop-faceid=" << nextHopFace->getId());
205 this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
211 this->dispatchToStrategy(*pitEntry,
212 [&] (
fw::Strategy& strategy) { strategy.afterReceiveInterest(inFace, interest, pitEntry); });
216 Forwarder::onContentStoreHit(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
219 NFD_LOG_DEBUG(
"onContentStoreHit interest=" << interest.getName());
223 this->dispatchToStrategy(*pitEntry,
224 [&] (
fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, *m_csFace, data); });
230 this->setStragglerTimer(pitEntry,
true, data.getFreshnessPeriod());
233 this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
237 Forwarder::onOutgoingInterest(
const shared_ptr<pit::Entry>& pitEntry,
Face& outFace,
const Interest& interest)
239 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
240 " interest=" << pitEntry->getName());
243 pitEntry->insertOrUpdateOutRecord(outFace, interest);
246 outFace.sendInterest(interest);
251 Forwarder::onInterestReject(
const shared_ptr<pit::Entry>& pitEntry)
254 NFD_LOG_ERROR(
"onInterestReject interest=" << pitEntry->getName() <<
255 " cannot reject forwarded Interest");
258 NFD_LOG_DEBUG(
"onInterestReject interest=" << pitEntry->getName());
261 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
264 this->setStragglerTimer(pitEntry,
false);
268 Forwarder::onInterestUnsatisfied(
const shared_ptr<pit::Entry>& pitEntry)
270 NFD_LOG_DEBUG(
"onInterestUnsatisfied interest=" << pitEntry->getName());
274 this->dispatchToStrategy(*pitEntry,
275 [&] (
fw::Strategy& strategy) { strategy.beforeExpirePendingInterest(pitEntry); });
278 this->onInterestFinalize(pitEntry,
false);
282 Forwarder::onInterestFinalize(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
285 NFD_LOG_DEBUG(
"onInterestFinalize interest=" << pitEntry->getName() <<
286 (isSatisfied ?
" satisfied" :
" unsatisfied"));
289 this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
292 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
293 m_pit.
erase(pitEntry.get());
297 Forwarder::onIncomingData(
Face& inFace,
const Data& data)
300 NFD_LOG_DEBUG(
"onIncomingData face=" << inFace.getId() <<
" data=" << data.getName());
301 data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
307 if (isViolatingLocalhost) {
309 " data=" << data.getName() <<
" violates /localhost");
316 if (pitMatches.begin() == pitMatches.end()) {
318 this->onDataUnsolicited(inFace, data);
322 shared_ptr<Data> dataCopyWithoutTag = make_shared<Data>(data);
326 if (m_csFromNdnSim ==
nullptr)
327 m_cs.
insert(*dataCopyWithoutTag);
329 m_csFromNdnSim->Add(dataCopyWithoutTag);
331 std::set<Face*> pendingDownstreams;
334 for (
const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
335 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
338 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
341 for (
const pit::InRecord& inRecord : pitEntry->getInRecords()) {
342 if (inRecord.getExpiry() > now) {
343 pendingDownstreams.insert(&inRecord.getFace());
349 this->dispatchToStrategy(*pitEntry,
350 [&] (
fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
353 this->insertDeadNonceList(*pitEntry,
true, data.getFreshnessPeriod(), &inFace);
356 pitEntry->clearInRecords();
357 pitEntry->deleteOutRecord(inFace);
360 this->setStragglerTimer(pitEntry,
true, data.getFreshnessPeriod());
364 for (
Face* pendingDownstream : pendingDownstreams) {
365 if (pendingDownstream->getId() == inFace.getId() &&
370 this->onOutgoingData(data, *pendingDownstream);
375 Forwarder::onDataUnsolicited(
Face& inFace,
const Data& data)
381 if (m_csFromNdnSim ==
nullptr)
384 m_csFromNdnSim->Add(data.shared_from_this());
388 " data=" << data.getName() <<
389 " decision=" << decision);
393 Forwarder::onOutgoingData(
const Data& data,
Face& outFace)
396 NFD_LOG_WARN(
"onOutgoingData face=invalid data=" << data.getName());
399 NFD_LOG_DEBUG(
"onOutgoingData face=" << outFace.getId() <<
" data=" << data.getName());
404 if (isViolatingLocalhost) {
406 " data=" << data.getName() <<
" violates /localhost");
414 outFace.sendData(data);
419 Forwarder::onIncomingNack(
Face& inFace,
const lp::Nack& nack)
422 nack.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
429 "~" << nack.
getReason() <<
" face-is-multi-access");
436 if (pitEntry ==
nullptr) {
439 "~" << nack.
getReason() <<
" no-PIT-entry");
446 if (outRecord == pitEntry->out_end()) {
449 "~" << nack.
getReason() <<
" no-out-record");
457 "~" << nack.
getReason() <<
" wrong-Nonce " <<
467 outRecord->setIncomingNack(nack);
470 this->dispatchToStrategy(*pitEntry,
471 [&] (
fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
475 Forwarder::onOutgoingNack(
const shared_ptr<pit::Entry>& pitEntry,
const Face& outFace,
480 " nack=" << pitEntry->getInterest().getName() <<
481 "~" << nack.
getReason() <<
" no-in-record");
489 if (inRecord == pitEntry->in_end()) {
491 " nack=" << pitEntry->getInterest().getName() <<
492 "~" << nack.
getReason() <<
" no-in-record");
499 " nack=" << pitEntry->getInterest().getName() <<
500 "~" << nack.
getReason() <<
" face-is-multi-access");
505 " nack=" << pitEntry->getInterest().getName() <<
509 lp::Nack nackPkt(inRecord->getInterest());
513 pitEntry->deleteInRecord(outFace);
516 const_cast<Face&
>(outFace).sendNack(nackPkt);
521 Forwarder::onDroppedInterest(
Face& outFace,
const Interest& interest)
533 Forwarder::setUnsatisfyTimer(
const shared_ptr<pit::Entry>& pitEntry)
540 if (lastExpiryFromNow <= time::seconds::zero()) {
546 bind(&Forwarder::onInterestUnsatisfied,
this, pitEntry));
550 Forwarder::setStragglerTimer(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
553 time::nanoseconds stragglerTime = time::milliseconds(100);
557 bind(&Forwarder::onInterestFinalize,
this, pitEntry, isSatisfied, dataFreshnessPeriod));
561 Forwarder::cancelUnsatisfyAndStragglerTimer(pit::Entry& pitEntry)
575 Forwarder::insertDeadNonceList(pit::Entry& pitEntry,
bool isSatisfied,
581 BOOST_ASSERT(dataFreshnessPeriod);
582 BOOST_ASSERT(*dataFreshnessPeriod >= time::milliseconds::zero());
583 needDnl =
static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
584 *dataFreshnessPeriod < m_deadNonceList.
getLifetime();
592 if (upstream ==
nullptr) {
595 std::for_each(outRecords.begin(), outRecords.end(),
601 if (outRecord != pitEntry.getOutRecords().end()) {
602 m_deadNonceList.
add(pitEntry.getName(), outRecord->getLastNonce());
signal::Signal< FaceTable, Face & > afterAdd
fires after a face is added
signal::Signal< Forwarder, pit::Entry, Face, Data > beforeSatisfyInterest
trigger before PIT entry is satisfied
void setTag(shared_ptr< T > tag) const
set a tag item
void erase(Entry *entry)
deletes an entry
void cleanupOnFaceRemoval(NameTree &nt, Fib &fib, Pit &pit, const Face &face)
cleanup tables when a face is destroyed
shared_ptr< Face > makeNullFace(const FaceUri &uri)
represents the Dead Nonce list
const Name LOCALHOST("ndn:/localhost")
ndn:/localhost
generalization of a network interface
void cancel(const EventId &eventId)
cancel a scheduled event
static time_point now() noexcept
contains information about an Interest from an incoming face
Nack & setHeader(const NackHeader &header)
bool isPrefixOf(const Name &other) const
Check if this name is a prefix of another name.
void startProcessInterest(Face &face, const Interest &interest)
start incoming Interest processing
signal::Signal< FaceTable, Face & > beforeRemove
fires before a face is removed
const time::nanoseconds & getLifetime() const
PacketCounter nInInterests
represents an Interest packet
#define NFD_LOG_DEBUG(expression)
static bool compare_InRecord_expiry(const pit::InRecord &a, const pit::InRecord &b)
DataMatchResult findAllDataMatches(const Data &data) const
performs a Data match
void add(const Name &name, uint32_t nonce)
records name+nonce
Face * get(FaceId id) const
get face by FaceId
std::list< InRecord > InRecordCollection
an unordered collection of in-records
represents a Network Nack
NackReason getReason() const
DropAllUnsolicitedDataPolicy DefaultUnsolicitedDataPolicy
the default UnsolicitedDataPolicy
provides a tag type for simple types
Table::const_iterator iterator
bool isInProducerRegion(const DelegationList &forwardingHint) const
determines whether an Interest has reached a producer region
FaceTable & getFaceTable()
#define NFD_LOG_ERROR(expression)
static void insertNonceToDnl(DeadNonceList &dnl, const pit::Entry &pitEntry, const pit::OutRecord &outRecord)
void insert(const Data &data, bool isUnsolicited=false)
inserts a Data packet
ndn::nfd::LinkType getLinkType() const
Copyright (c) 2011-2015 Regents of the University of California.
uint32_t getNonce() const
Get nonce.
signal::Signal< Forwarder, pit::Entry > beforeExpirePendingInterest
trigger before PIT entry expires
std::pair< shared_ptr< Entry >, bool > insert(const Interest &interest)
inserts a PIT entry for Interest
void startProcessData(Face &face, const Data &data)
start incoming Data processing
fw::Strategy & findEffectiveStrategy(const Name &prefix) const
get effective strategy for prefix
ndn::nfd::FaceScope getScope() const
Represents an absolute name.
void setDefaultStrategy(const Name &strategyName)
set the default strategy
PacketCounter nOutInterests
represents the underlying protocol and address used by a Face
void find(const Interest &interest, const HitCallback &hitCallback, const MissCallback &missCallback) const
finds the best matching Data packet
bool hasPendingOutRecords(const pit::Entry &pitEntry)
determine whether pitEntry has any pending out-records
uint32_t getLastNonce() const
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_WARN(expression)
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
static Name getDefaultStrategyName()
static const Name & getStrategyName()
This file contains common algorithms used by forwarding strategies.
bool has(const Name &name, uint32_t nonce) const
determines if name+nonce exists
bool empty() const noexcept
UnsolicitedDataDecision
a decision made by UnsolicitedDataPolicy
const Name & getName() const
EventId schedule(time::nanoseconds after, const EventCallback &event)
schedule an event
void addReserved(shared_ptr< Face > face, FaceId faceId)
add a special face with a reserved FaceId
contains information about an Interest toward an outgoing face
the Data should be cached in the ContentStore
const DelegationList & getForwardingHint() const
shared_ptr< Entry > find(const Interest &interest) const
finds a PIT entry for Interest
#define NFD_LOG_INIT(name)
Represents a Data packet.
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
void startProcessNack(Face &face, const lp::Nack &nack)
start incoming Nack processing
const Interest & getInterest() const
const Name & getName() const