52 , m_measurements(m_nameTree)
53 , m_strategyChoice(*this)
60 [
this, &face] (
const Interest& interest) {
64 [
this, &face] (
const Data& data) {
68 [
this, &face] (
const lp::Nack& nack) {
72 [
this, &face] (
const Interest& interest) {
73 this->onDroppedInterest(face, interest);
87 Forwarder::onIncomingInterest(
Face& inFace,
const Interest& interest)
91 " interest=" << interest.
getName());
92 interest.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.
getId()));
98 if (isViolatingLocalhost) {
100 " interest=" << interest.
getName() <<
" violates /localhost");
106 bool hasDuplicateNonceInDnl = m_deadNonceList.
has(interest.
getName(), interest.
getNonce());
107 if (hasDuplicateNonceInDnl) {
109 this->onInterestLoop(inFace, interest);
117 " interest=" << interest.
getName() <<
" reaching-producer-region");
118 const_cast<Interest&>(interest).setForwardingHint({});
122 shared_ptr<pit::Entry> pitEntry = m_pit.
insert(interest).first;
131 if (hasDuplicateNonceInPit) {
133 this->onInterestLoop(inFace, interest);
138 if (!pitEntry->hasInRecords()) {
139 if (m_csFromNdnSim ==
nullptr) {
141 bind(&Forwarder::onContentStoreHit,
this, std::ref(inFace), pitEntry, _1, _2),
142 bind(&Forwarder::onContentStoreMiss,
this, std::ref(inFace), pitEntry, _1));
145 shared_ptr<Data> match = m_csFromNdnSim->Lookup(interest.shared_from_this());
146 if (match !=
nullptr) {
147 this->onContentStoreHit(inFace, pitEntry, interest, *match);
150 this->onContentStoreMiss(inFace, pitEntry, interest);
155 this->onContentStoreMiss(inFace, pitEntry, interest);
160 Forwarder::onInterestLoop(
Face& inFace,
const Interest& interest)
165 " interest=" << interest.getName() <<
171 " interest=" << interest.getName() <<
172 " send-Nack-duplicate");
177 nack.setReason(lp::NackReason::DUPLICATE);
178 inFace.sendNack(nack);
188 Forwarder::onContentStoreMiss(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
191 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.getName());
195 pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
200 this->setExpiryTimer(pitEntry, time::duration_cast<time::milliseconds>(lastExpiryFromNow));
204 if (nextHopTag !=
nullptr) {
206 Face* nextHopFace = m_faceTable.
get(*nextHopTag);
207 if (nextHopFace !=
nullptr) {
208 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.getName() <<
" nexthop-faceid=" << nextHopFace->getId());
211 this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
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,
225 NFD_LOG_DEBUG(
"onContentStoreHit interest=" << interest.getName());
231 pitEntry->isSatisfied =
true;
232 pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
235 this->setExpiryTimer(pitEntry, 0_ms);
238 this->dispatchToStrategy(*pitEntry,
239 [&] (
fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, *m_csFace, data); });
242 this->dispatchToStrategy(*pitEntry,
243 [&] (
fw::Strategy& strategy) { strategy.afterContentStoreHit(pitEntry, inFace, data); });
247 Forwarder::onOutgoingInterest(
const shared_ptr<pit::Entry>& pitEntry,
Face& outFace,
const Interest& interest)
249 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
250 " interest=" << pitEntry->getName());
253 pitEntry->insertOrUpdateOutRecord(outFace, interest);
256 outFace.sendInterest(interest);
261 Forwarder::onInterestFinalize(
const shared_ptr<pit::Entry>& pitEntry)
263 NFD_LOG_DEBUG(
"onInterestFinalize interest=" << pitEntry->getName() <<
264 (pitEntry->isSatisfied ?
" satisfied" :
" unsatisfied"));
266 if (!pitEntry->isSatisfied) {
271 this->insertDeadNonceList(*pitEntry, 0);
274 if (pitEntry->isSatisfied) {
283 m_pit.
erase(pitEntry.get());
287 Forwarder::onIncomingData(
Face& inFace,
const Data& data)
290 NFD_LOG_DEBUG(
"onIncomingData face=" << inFace.getId() <<
" data=" << data.getName());
291 data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
297 if (isViolatingLocalhost) {
299 " data=" << data.getName() <<
" violates /localhost");
306 if (pitMatches.size() == 0) {
308 this->onDataUnsolicited(inFace, data);
312 shared_ptr<Data> dataCopyWithoutTag = make_shared<Data>(data);
316 if (m_csFromNdnSim ==
nullptr)
317 m_cs.
insert(*dataCopyWithoutTag);
319 m_csFromNdnSim->Add(dataCopyWithoutTag);
322 if (pitMatches.size() == 1) {
323 auto& pitEntry = pitMatches.front();
325 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
328 this->setExpiryTimer(pitEntry, 0_ms);
332 this->dispatchToStrategy(*pitEntry,
333 [&] (
fw::Strategy& strategy) { strategy.afterReceiveData(pitEntry, inFace, data); });
336 pitEntry->isSatisfied =
true;
337 pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
340 this->insertDeadNonceList(*pitEntry, &inFace);
343 pitEntry->deleteOutRecord(inFace);
348 std::set<Face*> pendingDownstreams;
351 for (
const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
352 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
355 for (
const pit::InRecord& inRecord : pitEntry->getInRecords()) {
356 if (inRecord.getExpiry() > now) {
357 pendingDownstreams.insert(&inRecord.getFace());
362 this->setExpiryTimer(pitEntry, 0_ms);
366 this->dispatchToStrategy(*pitEntry,
367 [&] (
fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
370 pitEntry->isSatisfied =
true;
371 pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
374 this->insertDeadNonceList(*pitEntry, &inFace);
377 pitEntry->clearInRecords();
378 pitEntry->deleteOutRecord(inFace);
382 for (
Face* pendingDownstream : pendingDownstreams) {
383 if (pendingDownstream->getId() == inFace.getId() &&
388 this->onOutgoingData(data, *pendingDownstream);
394 Forwarder::onDataUnsolicited(
Face& inFace,
const Data& data)
400 if (m_csFromNdnSim ==
nullptr)
403 m_csFromNdnSim->Add(data.shared_from_this());
407 " data=" << data.getName() <<
408 " decision=" << decision);
412 Forwarder::onOutgoingData(
const Data& data,
Face& outFace)
415 NFD_LOG_WARN(
"onOutgoingData face=invalid data=" << data.getName());
418 NFD_LOG_DEBUG(
"onOutgoingData face=" << outFace.getId() <<
" data=" << data.getName());
423 if (isViolatingLocalhost) {
425 " data=" << data.getName() <<
" violates /localhost");
433 outFace.sendData(data);
438 Forwarder::onIncomingNack(
Face& inFace,
const lp::Nack& nack)
441 nack.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
448 "~" << nack.
getReason() <<
" face-is-multi-access");
455 if (pitEntry ==
nullptr) {
458 "~" << nack.
getReason() <<
" no-PIT-entry");
465 if (outRecord == pitEntry->out_end()) {
468 "~" << nack.
getReason() <<
" no-out-record");
476 "~" << nack.
getReason() <<
" wrong-Nonce " <<
486 outRecord->setIncomingNack(nack);
490 this->setExpiryTimer(pitEntry, 0_ms);
494 this->dispatchToStrategy(*pitEntry,
495 [&] (
fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
499 Forwarder::onOutgoingNack(
const shared_ptr<pit::Entry>& pitEntry,
const Face& outFace,
504 " nack=" << pitEntry->getInterest().getName() <<
505 "~" << nack.
getReason() <<
" no-in-record");
513 if (inRecord == pitEntry->in_end()) {
515 " nack=" << pitEntry->getInterest().getName() <<
516 "~" << nack.
getReason() <<
" no-in-record");
523 " nack=" << pitEntry->getInterest().getName() <<
524 "~" << nack.
getReason() <<
" face-is-multi-access");
529 " nack=" << pitEntry->getInterest().getName() <<
533 lp::Nack nackPkt(inRecord->getInterest());
537 pitEntry->deleteInRecord(outFace);
540 const_cast<Face&>(outFace).sendNack(nackPkt);
545 Forwarder::onDroppedInterest(
Face& outFace,
const Interest& interest)
551 Forwarder::setExpiryTimer(
const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
553 BOOST_ASSERT(pitEntry);
554 BOOST_ASSERT(duration >= 0_ms);
558 pitEntry->expiryTimer =
scheduler::schedule(duration, [=] { onInterestFinalize(pitEntry); });
562 Forwarder::insertDeadNonceList(pit::Entry& pitEntry,
Face* upstream)
566 if (pitEntry.isSatisfied) {
567 BOOST_ASSERT(pitEntry.dataFreshnessPeriod >= 0_ms);
568 needDnl = static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
569 pitEntry.dataFreshnessPeriod < m_deadNonceList.
getLifetime();
577 if (upstream ==
nullptr) {
579 const auto& outRecords = pitEntry.getOutRecords();
580 std::for_each(outRecords.begin(), outRecords.end(), [&] (
const auto& outRecord) {
581 m_deadNonceList.
add(pitEntry.getName(), outRecord.getLastNonce());
586 auto outRecord = pitEntry.getOutRecord(*upstream);
587 if (outRecord != pitEntry.getOutRecords().end()) {
588 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
signal::Signal< LinkService, Interest > & onDroppedInterest
signals on Interest dropped by reliability system for exceeding allowed number of retx
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)
const Name LOCALHOST("ndn:/localhost")
ndn:/localhost
generalization of a network interface
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.
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
represents a Network Nack
NackReason getReason() const
DropAllUnsolicitedDataPolicy DefaultUnsolicitedDataPolicy
the default UnsolicitedDataPolicy
provides a tag type for simple types
Table::const_iterator iterator
std::vector< shared_ptr< Entry > > DataMatchResult
bool isInProducerRegion(const DelegationList &forwardingHint) const
determines whether an Interest has reached a producer region
FaceTable & getFaceTable()
void cancel(EventId eventId)
Cancel a scheduled event.
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 value.
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
signal::Signal< LinkService, Data > & afterReceiveData
signals on Data received
fw::Strategy & findEffectiveStrategy(const Name &prefix) const
get effective strategy for prefix
ndn::nfd::FaceScope getScope() const
Represents an absolute name.
signal::Signal< LinkService, Interest > & afterReceiveInterest
signals on Interest received
void setDefaultStrategy(const Name &strategyName)
set the default strategy
PacketCounter nOutInterests
represents the underlying protocol and address used by a Face
PacketCounter nSatisfiedInterests
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
no duplicate Nonce is found
int findDuplicateNonce(const pit::Entry &pitEntry, uint32_t nonce, const Face &face)
determine whether pitEntry has duplicate Nonce nonce
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
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
the Data should be cached in the ContentStore
const DelegationList & getForwardingHint() const
signal::Signal< LinkService, lp::Nack > & afterReceiveNack
signals on Nack received
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
const FaceId INVALID_FACEID
indicates an invalid FaceId
void startProcessNack(Face &face, const lp::Nack &nack)
start incoming Nack processing
PacketCounter nUnsatisfiedInterests
const Interest & getInterest() const
const Name & getName() const