32 #include <ndn-cxx/lp/tags.hpp> 50 , m_measurements(m_nameTree)
51 , m_strategyChoice(*this)
57 face.afterReceiveInterest.connect(
58 [
this, &face] (
const Interest& interest) {
61 face.afterReceiveData.connect(
62 [
this, &face] (
const Data& data) {
65 face.afterReceiveNack.connect(
66 [
this, &face] (
const lp::Nack& nack) {
81 Forwarder::onIncomingInterest(
Face& inFace,
const Interest& interest)
85 " interest=" << interest.
getName());
86 interest.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
92 if (isViolatingLocalhost) {
94 " interest=" << interest.
getName() <<
" violates /localhost");
100 bool hasDuplicateNonceInDnl = m_deadNonceList.
has(interest.
getName(), interest.
getNonce());
101 if (hasDuplicateNonceInDnl) {
103 this->onInterestLoop(inFace, interest);
110 NFD_LOG_DEBUG(
"onIncomingInterest face=" << inFace.getId() <<
111 " interest=" << interest.
getName() <<
" reaching-producer-region");
112 const_cast<Interest&
>(interest).setForwardingHint({});
116 shared_ptr<pit::Entry> pitEntry = m_pit.insert(interest).first;
125 if (hasDuplicateNonceInPit) {
127 this->onInterestLoop(inFace, interest);
132 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
135 bool isPending = inRecords.begin() != inRecords.end();
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);
180 Forwarder::onContentStoreMiss(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
187 pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
190 this->setUnsatisfyTimer(pitEntry);
194 if (nextHopTag !=
nullptr) {
196 Face* nextHopFace = m_faceTable.
get(*nextHopTag);
197 if (nextHopFace !=
nullptr) {
198 NFD_LOG_DEBUG(
"onContentStoreMiss interest=" << interest.
getName() <<
" nexthop-faceid=" << nextHopFace->getId());
201 this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
207 this->dispatchToStrategy(*pitEntry,
212 Forwarder::onContentStoreHit(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
219 this->dispatchToStrategy(*pitEntry,
229 this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
233 Forwarder::onOutgoingInterest(
const shared_ptr<pit::Entry>& pitEntry,
Face& outFace,
const Interest& interest)
235 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
236 " interest=" << pitEntry->getName());
239 pitEntry->insertOrUpdateOutRecord(outFace, interest);
242 outFace.sendInterest(interest);
247 Forwarder::onInterestReject(
const shared_ptr<pit::Entry>& pitEntry)
250 NFD_LOG_ERROR(
"onInterestReject interest=" << pitEntry->getName() <<
251 " cannot reject forwarded Interest");
254 NFD_LOG_DEBUG(
"onInterestReject interest=" << pitEntry->getName());
257 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
260 this->setStragglerTimer(pitEntry,
false);
264 Forwarder::onInterestUnsatisfied(
const shared_ptr<pit::Entry>& pitEntry)
266 NFD_LOG_DEBUG(
"onInterestUnsatisfied interest=" << pitEntry->getName());
270 this->dispatchToStrategy(*pitEntry,
274 this->onInterestFinalize(pitEntry,
false);
278 Forwarder::onInterestFinalize(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
281 NFD_LOG_DEBUG(
"onInterestFinalize interest=" << pitEntry->getName() <<
282 (isSatisfied ?
" satisfied" :
" unsatisfied"));
285 this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
288 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
289 m_pit.erase(pitEntry.get());
293 Forwarder::onIncomingData(
Face& inFace,
const Data& data)
297 data.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
303 if (isViolatingLocalhost) {
305 " data=" << data.
getName() <<
" violates /localhost");
312 if (pitMatches.begin() == pitMatches.end()) {
314 this->onDataUnsolicited(inFace, data);
318 shared_ptr<Data> dataCopyWithoutTag = make_shared<Data>(data);
322 if (m_csFromNdnSim ==
nullptr)
323 m_cs.insert(*dataCopyWithoutTag);
325 m_csFromNdnSim->Add(dataCopyWithoutTag);
327 std::set<Face*> pendingDownstreams;
330 for (
const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
331 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
334 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
337 for (
const pit::InRecord& inRecord : pitEntry->getInRecords()) {
338 if (inRecord.getExpiry() > now) {
339 pendingDownstreams.insert(&inRecord.getFace());
345 this->dispatchToStrategy(*pitEntry,
352 pitEntry->clearInRecords();
353 pitEntry->deleteOutRecord(inFace);
360 for (
Face* pendingDownstream : pendingDownstreams) {
361 if (pendingDownstream->getId() == inFace.getId() &&
366 this->onOutgoingData(data, *pendingDownstream);
371 Forwarder::onDataUnsolicited(
Face& inFace,
const Data& data)
377 if (m_csFromNdnSim ==
nullptr)
378 m_cs.insert(data,
true);
380 m_csFromNdnSim->Add(data.shared_from_this());
385 " decision=" << decision);
389 Forwarder::onOutgoingData(
const Data& data,
Face& outFace)
400 if (isViolatingLocalhost) {
402 " data=" << data.
getName() <<
" violates /localhost");
410 outFace.sendData(data);
415 Forwarder::onIncomingNack(
Face& inFace,
const lp::Nack& nack)
418 nack.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
425 "~" << nack.
getReason() <<
" face-is-multi-access");
430 shared_ptr<pit::Entry> pitEntry = m_pit.find(nack.
getInterest());
432 if (pitEntry ==
nullptr) {
435 "~" << nack.
getReason() <<
" no-PIT-entry");
442 if (outRecord == pitEntry->out_end()) {
445 "~" << nack.
getReason() <<
" no-out-record");
453 "~" << nack.
getReason() <<
" wrong-Nonce " <<
463 outRecord->setIncomingNack(nack);
466 this->dispatchToStrategy(*pitEntry,
471 Forwarder::onOutgoingNack(
const shared_ptr<pit::Entry>& pitEntry,
const Face& outFace,
476 " nack=" << pitEntry->getInterest().getName() <<
477 "~" << nack.
getReason() <<
" no-in-record");
485 if (inRecord == pitEntry->in_end()) {
487 " nack=" << pitEntry->getInterest().getName() <<
488 "~" << nack.
getReason() <<
" no-in-record");
495 " nack=" << pitEntry->getInterest().getName() <<
496 "~" << nack.
getReason() <<
" face-is-multi-access");
501 " nack=" << pitEntry->getInterest().getName() <<
505 lp::Nack nackPkt(inRecord->getInterest());
509 pitEntry->deleteInRecord(outFace);
512 const_cast<Face&
>(outFace).sendNack(nackPkt);
523 Forwarder::setUnsatisfyTimer(
const shared_ptr<pit::Entry>& pitEntry)
530 if (lastExpiryFromNow <= time::seconds::zero()) {
536 bind(&Forwarder::onInterestUnsatisfied,
this, pitEntry));
540 Forwarder::setStragglerTimer(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
547 bind(&Forwarder::onInterestFinalize,
this, pitEntry, isSatisfied, dataFreshnessPeriod));
551 Forwarder::cancelUnsatisfyAndStragglerTimer(
pit::Entry& pitEntry)
565 Forwarder::insertDeadNonceList(
pit::Entry& pitEntry,
bool isSatisfied,
571 BOOST_ASSERT(dataFreshnessPeriod);
572 BOOST_ASSERT(*dataFreshnessPeriod >= time::milliseconds::zero());
574 *dataFreshnessPeriod < m_deadNonceList.
getLifetime();
582 if (upstream ==
nullptr) {
585 std::for_each(outRecords.begin(), outRecords.end(),
592 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
const Name & getName() const
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
bool has(const Name &name, uint32_t nonce) const
determines if name+nonce exists
OutRecordCollection::iterator getOutRecord(const Face &face)
get the out-record for face
const Name LOCALHOST("ndn:/localhost")
ndn:/localhost
const time::milliseconds & getFreshnessPeriod() const
void cancel(const EventId &eventId)
cancel a scheduled event
static time_point now() noexcept
scheduler::EventId m_stragglerTimer
straggler timer
contains information about an Interest from an incoming face
Nack & setHeader(const NackHeader &header)
uint32_t getLastNonce() const
boost::posix_time::time_duration milliseconds(long duration)
virtual void beforeExpirePendingInterest(const shared_ptr< pit::Entry > &pitEntry)
trigger before PIT entry expires
const Interest & getInterest() const
void startProcessInterest(Face &face, const Interest &interest)
start incoming Interest processing
signal::Signal< FaceTable, Face & > beforeRemove
fires before a face is removed
PacketCounter nInInterests
represents an Interest packet
#define NFD_LOG_DEBUG(expression)
static bool compare_InRecord_expiry(const pit::InRecord &a, const pit::InRecord &b)
void setTag(shared_ptr< T > tag) const
set a tag item
void add(const Name &name, uint32_t nonce)
records name+nonce
std::list< InRecord > InRecordCollection
an unordered collection of in-records
uint32_t getNonce() const
Get nonce.
represents a Network Nack
DropAllUnsolicitedDataPolicy DefaultUnsolicitedDataPolicy
the default UnsolicitedDataPolicy
provides a tag type for simple types
Table::const_iterator iterator
NackReason getReason() const
virtual void afterReceiveNack(const Face &inFace, const lp::Nack &nack, const shared_ptr< pit::Entry > &pitEntry)
trigger after Nack is received
FaceTable & getFaceTable()
#define NFD_LOG_ERROR(expression)
static void insertNonceToDnl(DeadNonceList &dnl, const pit::Entry &pitEntry, const pit::OutRecord &outRecord)
int getMustBeFresh() const
Copyright (c) 2011-2015 Regents of the University of California.
const Interest & getInterest() const
const time::nanoseconds & getLifetime() const
signal::Signal< Forwarder, pit::Entry > beforeExpirePendingInterest
trigger before PIT entry expires
void startProcessData(Face &face, const Data &data)
start incoming Data processing
virtual void beforeSatisfyInterest(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data)
trigger before PIT entry is satisfied
Represents an absolute name.
bool isPrefixOf(const Name &other) const
Check if this name is a prefix of another name.
PacketCounter nOutInterests
represents the underlying protocol and address used by a Face
bool hasPendingOutRecords(const pit::Entry &pitEntry)
determine whether pitEntry has any pending out-records
no duplicate Nonce is found
represents a forwarding strategy
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)
const DelegationList & getForwardingHint() const
const Name & getName() const
Get name.
static Name getDefaultStrategyName()
static const Name & getStrategyName()
This file contains common algorithms used by forwarding strategies.
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
const Name & getName() const
contains information about an Interest toward an outgoing face
the Data should be cached in the ContentStore
shared_ptr< T > getTag() const
get a tag item
virtual void afterReceiveInterest(const Face &inFace, const Interest &interest, const shared_ptr< pit::Entry > &pitEntry)=0
trigger after Interest is received
#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
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
Face * get(FaceId id) const
get face by FaceId
const FaceId INVALID_FACEID
indicates an invalid FaceId
bool isInProducerRegion(const DelegationList &forwardingHint) const
determines whether an Interest has reached a producer region
void startProcessNack(Face &face, const lp::Nack &nack)
start incoming Nack processing
const OutRecordCollection & getOutRecords() const
scheduler::EventId m_unsatisfyTimer
unsatisfy timer