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 if (!pitEntry->hasInRecords()) {
137 if (m_csFromNdnSim ==
nullptr) {
139 bind(&Forwarder::onContentStoreHit,
this, ref(inFace), pitEntry, _1, _2),
140 bind(&Forwarder::onContentStoreMiss,
this, ref(inFace), pitEntry, _1));
143 shared_ptr<Data> match = m_csFromNdnSim->Lookup(interest.shared_from_this());
144 if (match !=
nullptr) {
145 this->onContentStoreHit(inFace, pitEntry, interest, *match);
148 this->onContentStoreMiss(inFace, pitEntry, interest);
153 this->onContentStoreMiss(inFace, pitEntry, interest);
158 Forwarder::onInterestLoop(
Face& inFace,
const Interest& interest)
163 " interest=" << interest.getName() <<
169 " interest=" << interest.getName() <<
170 " send-Nack-duplicate");
175 nack.setReason(lp::NackReason::DUPLICATE);
176 inFace.sendNack(nack);
186 Forwarder::onContentStoreMiss(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
189 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.getName());
193 pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
198 this->setExpiryTimer(pitEntry, time::duration_cast<time::milliseconds>(lastExpiryFromNow));
202 if (nextHopTag !=
nullptr) {
204 Face* nextHopFace = m_faceTable.
get(*nextHopTag);
205 if (nextHopFace !=
nullptr) {
206 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.getName() <<
" nexthop-faceid=" << nextHopFace->getId());
209 this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
215 this->dispatchToStrategy(*pitEntry,
216 [&] (
fw::Strategy& strategy) { strategy.afterReceiveInterest(inFace, interest, pitEntry); });
220 Forwarder::onContentStoreHit(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
223 NFD_LOG_DEBUG(
"onContentStoreHit interest=" << interest.getName());
229 pitEntry->isSatisfied =
true;
230 pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
233 this->setExpiryTimer(pitEntry, 0_ms);
236 this->dispatchToStrategy(*pitEntry,
237 [&] (
fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, *m_csFace, data); });
240 this->dispatchToStrategy(*pitEntry,
241 [&] (
fw::Strategy& strategy) { strategy.afterContentStoreHit(pitEntry, inFace, data); });
245 Forwarder::onOutgoingInterest(
const shared_ptr<pit::Entry>& pitEntry,
Face& outFace,
const Interest& interest)
247 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
248 " interest=" << pitEntry->getName());
251 pitEntry->insertOrUpdateOutRecord(outFace, interest);
254 outFace.sendInterest(interest);
259 Forwarder::onInterestFinalize(
const shared_ptr<pit::Entry>& pitEntry)
261 NFD_LOG_DEBUG(
"onInterestFinalize interest=" << pitEntry->getName() <<
262 (pitEntry->isSatisfied ?
" satisfied" :
" unsatisfied"));
264 if (!pitEntry->isSatisfied) {
269 this->insertDeadNonceList(*pitEntry, 0);
273 m_pit.
erase(pitEntry.get());
277 Forwarder::onIncomingData(
Face& inFace,
const Data& data)
280 NFD_LOG_DEBUG(
"onIncomingData face=" << inFace.getId() <<
" data=" << data.getName());
281 data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
287 if (isViolatingLocalhost) {
289 " data=" << data.getName() <<
" violates /localhost");
296 if (pitMatches.size() == 0) {
298 this->onDataUnsolicited(inFace, data);
302 shared_ptr<Data> dataCopyWithoutTag = make_shared<Data>(data);
306 if (m_csFromNdnSim ==
nullptr)
307 m_cs.
insert(*dataCopyWithoutTag);
309 m_csFromNdnSim->Add(dataCopyWithoutTag);
312 if (pitMatches.size() == 1) {
313 auto& pitEntry = pitMatches.front();
315 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
318 this->setExpiryTimer(pitEntry, 0_ms);
322 this->dispatchToStrategy(*pitEntry,
323 [&] (
fw::Strategy& strategy) { strategy.afterReceiveData(pitEntry, inFace, data); });
326 pitEntry->isSatisfied =
true;
327 pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
330 this->insertDeadNonceList(*pitEntry, &inFace);
333 pitEntry->deleteOutRecord(inFace);
338 std::set<Face*> pendingDownstreams;
341 for (
const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
342 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
345 for (
const pit::InRecord& inRecord : pitEntry->getInRecords()) {
346 if (inRecord.getExpiry() > now) {
347 pendingDownstreams.insert(&inRecord.getFace());
352 this->setExpiryTimer(pitEntry, 0_ms);
356 this->dispatchToStrategy(*pitEntry,
357 [&] (
fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
360 pitEntry->isSatisfied =
true;
361 pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
364 this->insertDeadNonceList(*pitEntry, &inFace);
367 pitEntry->clearInRecords();
368 pitEntry->deleteOutRecord(inFace);
372 for (
Face* pendingDownstream : pendingDownstreams) {
373 if (pendingDownstream->getId() == inFace.getId() &&
378 this->onOutgoingData(data, *pendingDownstream);
384 Forwarder::onDataUnsolicited(
Face& inFace,
const Data& data)
390 if (m_csFromNdnSim ==
nullptr)
393 m_csFromNdnSim->Add(data.shared_from_this());
397 " data=" << data.getName() <<
398 " decision=" << decision);
402 Forwarder::onOutgoingData(
const Data& data,
Face& outFace)
405 NFD_LOG_WARN(
"onOutgoingData face=invalid data=" << data.getName());
408 NFD_LOG_DEBUG(
"onOutgoingData face=" << outFace.getId() <<
" data=" << data.getName());
413 if (isViolatingLocalhost) {
415 " data=" << data.getName() <<
" violates /localhost");
423 outFace.sendData(data);
428 Forwarder::onIncomingNack(
Face& inFace,
const lp::Nack& nack)
431 nack.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
438 "~" << nack.
getReason() <<
" face-is-multi-access");
445 if (pitEntry ==
nullptr) {
448 "~" << nack.
getReason() <<
" no-PIT-entry");
455 if (outRecord == pitEntry->out_end()) {
458 "~" << nack.
getReason() <<
" no-out-record");
466 "~" << nack.
getReason() <<
" wrong-Nonce " <<
476 outRecord->setIncomingNack(nack);
480 this->setExpiryTimer(pitEntry, 0_ms);
484 this->dispatchToStrategy(*pitEntry,
485 [&] (
fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
489 Forwarder::onOutgoingNack(
const shared_ptr<pit::Entry>& pitEntry,
const Face& outFace,
494 " nack=" << pitEntry->getInterest().getName() <<
495 "~" << nack.
getReason() <<
" no-in-record");
503 if (inRecord == pitEntry->in_end()) {
505 " nack=" << pitEntry->getInterest().getName() <<
506 "~" << nack.
getReason() <<
" no-in-record");
513 " nack=" << pitEntry->getInterest().getName() <<
514 "~" << nack.
getReason() <<
" face-is-multi-access");
519 " nack=" << pitEntry->getInterest().getName() <<
523 lp::Nack nackPkt(inRecord->getInterest());
527 pitEntry->deleteInRecord(outFace);
530 const_cast<Face&
>(outFace).sendNack(nackPkt);
535 Forwarder::onDroppedInterest(
Face& outFace,
const Interest& interest)
541 Forwarder::setExpiryTimer(
const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
543 BOOST_ASSERT(duration >= 0_ms);
548 bind(&Forwarder::onInterestFinalize,
this, pitEntry));
559 Forwarder::insertDeadNonceList(pit::Entry& pitEntry,
Face* upstream)
563 if (pitEntry.isSatisfied) {
564 BOOST_ASSERT(pitEntry.dataFreshnessPeriod >= 0_ms);
565 needDnl =
static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
566 pitEntry.dataFreshnessPeriod < m_deadNonceList.
getLifetime();
574 if (upstream ==
nullptr) {
577 std::for_each(outRecords.begin(), outRecords.end(),
583 if (outRecord != pitEntry.getOutRecords().end()) {
584 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
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()
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 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
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
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