31 #include <ndn-cxx/lp/tags.hpp> 33 #include <boost/random/uniform_int_distribution.hpp> 43 , m_measurements(m_nameTree)
52 [
this, &face] (
const Interest& interest) {
56 [
this, &face] (
const Data& data) {
60 [
this, &face] (
const lp::Nack& nack) {
83 " interest=" << interest.
getName() <<
" malformed");
88 this->onIncomingInterest(face, interest);
97 this->onIncomingData(face, data);
112 "~" << nack.
getReason() <<
" malformed");
116 this->onIncomingNack(face, nack);
120 Forwarder::onIncomingInterest(
Face& inFace,
const Interest& interest)
124 " interest=" << interest.
getName());
125 interest.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.
getId()));
131 if (isViolatingLocalhost) {
133 " interest=" << interest.
getName() <<
" violates /localhost");
139 bool hasDuplicateNonceInDnl = m_deadNonceList.
has(interest.
getName(), interest.
getNonce());
140 if (hasDuplicateNonceInDnl) {
142 this->onInterestLoop(inFace, interest);
147 shared_ptr<pit::Entry> pitEntry = m_pit.
insert(interest).first;
152 if (hasDuplicateNonceInPit) {
154 this->onInterestLoop(inFace, interest);
159 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
162 bool isPending = inRecords.begin() != inRecords.end();
164 if (m_csFromNdnSim ==
nullptr) {
166 bind(&Forwarder::onContentStoreHit,
this, ref(inFace), pitEntry, _1, _2),
167 bind(&Forwarder::onContentStoreMiss,
this, ref(inFace), pitEntry, _1));
170 shared_ptr<Data> match = m_csFromNdnSim->Lookup(interest.shared_from_this());
171 if (match !=
nullptr) {
172 this->onContentStoreHit(inFace, pitEntry, interest, *match);
175 this->onContentStoreMiss(inFace, pitEntry, interest);
180 this->onContentStoreMiss(inFace, pitEntry, interest);
185 Forwarder::onInterestLoop(
Face& inFace,
const Interest& interest)
190 " interest=" << interest.
getName() <<
196 " interest=" << interest.
getName() <<
197 " send-Nack-duplicate");
202 nack.setReason(lp::NackReason::DUPLICATE);
207 Forwarder::onContentStoreMiss(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
213 pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
216 this->setUnsatisfyTimer(pitEntry);
220 if (nextHopTag !=
nullptr) {
222 Face* nextHopFace = m_faceTable.
get(*nextHopTag);
223 if (nextHopFace !=
nullptr) {
227 this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
233 this->dispatchToStrategy(*pitEntry,
238 Forwarder::onContentStoreHit(
const Face& inFace,
const shared_ptr<pit::Entry>& pitEntry,
244 this->dispatchToStrategy(*pitEntry,
254 this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
258 Forwarder::onOutgoingInterest(
const shared_ptr<pit::Entry>& pitEntry,
Face& outFace,
const Interest& interest)
261 " interest=" << pitEntry->getName());
264 pitEntry->insertOrUpdateOutRecord(outFace, interest);
272 Forwarder::onInterestReject(
const shared_ptr<pit::Entry>& pitEntry)
275 NFD_LOG_ERROR(
"onInterestReject interest=" << pitEntry->getName() <<
276 " cannot reject forwarded Interest");
279 NFD_LOG_DEBUG(
"onInterestReject interest=" << pitEntry->getName());
282 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
285 this->setStragglerTimer(pitEntry,
false);
289 Forwarder::onInterestUnsatisfied(
const shared_ptr<pit::Entry>& pitEntry)
291 NFD_LOG_DEBUG(
"onInterestUnsatisfied interest=" << pitEntry->getName());
295 this->dispatchToStrategy(*pitEntry,
299 this->onInterestFinalize(pitEntry,
false);
303 Forwarder::onInterestFinalize(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
304 time::milliseconds dataFreshnessPeriod)
306 NFD_LOG_DEBUG(
"onInterestFinalize interest=" << pitEntry->getName() <<
307 (isSatisfied ?
" satisfied" :
" unsatisfied"));
310 this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
313 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
314 m_pit.
erase(pitEntry.get());
318 Forwarder::onIncomingData(
Face& inFace,
const Data& data)
322 data.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.
getId()));
328 if (isViolatingLocalhost) {
330 " data=" << data.
getName() <<
" violates /localhost");
337 if (pitMatches.begin() == pitMatches.end()) {
339 this->onDataUnsolicited(inFace, data);
343 shared_ptr<Data> dataCopyWithoutTag = make_shared<Data>(data);
347 if (m_csFromNdnSim ==
nullptr)
348 m_cs.
insert(*dataCopyWithoutTag);
350 m_csFromNdnSim->Add(dataCopyWithoutTag);
352 std::set<Face*> pendingDownstreams;
355 for (
const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
356 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
359 this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
362 for (
const pit::InRecord& inRecord : pitEntry->getInRecords()) {
363 if (inRecord.getExpiry() > now) {
364 pendingDownstreams.insert(&inRecord.getFace());
370 this->dispatchToStrategy(*pitEntry,
377 pitEntry->clearInRecords();
378 pitEntry->deleteOutRecord(inFace);
385 for (
Face* pendingDownstream : pendingDownstreams) {
386 if (pendingDownstream == &inFace) {
390 this->onOutgoingData(data, *pendingDownstream);
395 Forwarder::onDataUnsolicited(
Face& inFace,
const Data& data)
401 if (m_csFromNdnSim ==
nullptr)
404 m_csFromNdnSim->Add(data.shared_from_this());
409 " decision=" << decision);
413 Forwarder::onOutgoingData(
const Data& data,
Face& outFace)
424 if (isViolatingLocalhost) {
426 " data=" << data.
getName() <<
" violates /localhost");
439 Forwarder::onIncomingNack(
Face& inFace,
const lp::Nack& nack)
442 nack.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.
getId()));
449 "~" << nack.
getReason() <<
" face-is-multi-access");
456 if (pitEntry ==
nullptr) {
459 "~" << nack.
getReason() <<
" no-PIT-entry");
466 if (outRecord == pitEntry->out_end()) {
469 "~" << nack.
getReason() <<
" no-out-record");
477 "~" << nack.
getReason() <<
" wrong-Nonce " <<
487 outRecord->setIncomingNack(nack);
490 this->dispatchToStrategy(*pitEntry,
495 Forwarder::onOutgoingNack(
const shared_ptr<pit::Entry>& pitEntry,
const Face& outFace,
500 " nack=" << pitEntry->getInterest().getName() <<
501 "~" << nack.
getReason() <<
" no-in-record");
509 if (inRecord == pitEntry->in_end()) {
511 " nack=" << pitEntry->getInterest().getName() <<
512 "~" << nack.
getReason() <<
" no-in-record");
519 " nack=" << pitEntry->getInterest().getName() <<
520 "~" << nack.
getReason() <<
" face-is-multi-access");
525 " nack=" << pitEntry->getInterest().getName() <<
529 lp::Nack nackPkt(inRecord->getInterest());
533 pitEntry->deleteInRecord(outFace);
536 const_cast<Face&
>(outFace).sendNack(nackPkt);
547 Forwarder::setUnsatisfyTimer(
const shared_ptr<pit::Entry>& pitEntry)
554 if (lastExpiryFromNow <= time::seconds::zero()) {
560 bind(&Forwarder::onInterestUnsatisfied,
this, pitEntry));
564 Forwarder::setStragglerTimer(
const shared_ptr<pit::Entry>& pitEntry,
bool isSatisfied,
565 time::milliseconds dataFreshnessPeriod)
567 time::nanoseconds stragglerTime = time::milliseconds(100);
571 bind(&Forwarder::onInterestFinalize,
this, pitEntry, isSatisfied, dataFreshnessPeriod));
575 Forwarder::cancelUnsatisfyAndStragglerTimer(
pit::Entry& pitEntry)
589 Forwarder::insertDeadNonceList(
pit::Entry& pitEntry,
bool isSatisfied,
590 time::milliseconds dataFreshnessPeriod,
Face* upstream)
593 bool needDnl =
false;
595 bool hasFreshnessPeriod = dataFreshnessPeriod >= time::milliseconds::zero();
598 (hasFreshnessPeriod && dataFreshnessPeriod < m_deadNonceList.
getLifetime());
612 std::for_each(outRecords.begin(), outRecords.end(),
619 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
unique_ptr< Strategy > makeDefaultStrategy(Forwarder &forwarder)
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)
shared_ptr< T > getTag() const
get a tag item
represents the Dead Nonce list
OutRecordCollection::iterator getOutRecord(const Face &face)
get the out-record for face
const Name LOCALHOST("ndn:/localhost")
ndn:/localhost
const Link & getLink() const
Get the link object for this interest.
generalization of a network interface
int getMustBeFresh() const
void cancel(const EventId &eventId)
cancel a scheduled event
void installStrategies(Forwarder &forwarder)
static time_point now() noexcept
scheduler::EventId m_stragglerTimer
straggler timer
represents the underlying protocol and address used by a Face
const Name & getName() const
Get name of the Data packet.
contains information about an Interest from an incoming face
Nack & setHeader(const NackHeader &header)
virtual void beforeExpirePendingInterest(const shared_ptr< pit::Entry > &pitEntry)
trigger before PIT entry expires
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 sendInterest(const Interest &interest)
sends Interest on Face
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
virtual void afterReceiveNack(const Face &inFace, const lp::Nack &nack, const shared_ptr< pit::Entry > &pitEntry)
trigger after Nack is received
void sendData(const Data &data)
sends Data on Face
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 Interest's 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
signal::Signal< LinkService, Data > & afterReceiveData
signals on Data received
ndn::nfd::FaceScope getScope() const
virtual void beforeSatisfyInterest(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data)
trigger before PIT entry is satisfied
signal::Signal< LinkService, Interest > & afterReceiveInterest
signals on Interest received
bool isPrefixOf(const Name &name) const
Check if the N components of this name are the same as the first N components of the given name...
PacketCounter nOutInterests
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
const Interest & getInterest() const
uint32_t getLastNonce() const
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 time::milliseconds & getFreshnessPeriod() const
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
Copyright (c) 2014-2016, Regents of the University of California, Arizona Board of Regents...
bool has(const Name &name, uint32_t nonce) const
determines if name+nonce exists
EventId schedule(const time::nanoseconds &after, const Scheduler::Event &event)
schedule an event
UnsolicitedDataDecision
a decision made by UnsolicitedDataPolicy
const Name & getName() const
void addReserved(shared_ptr< Face > face, FaceId faceId)
add a special face with a reserved FaceId
void sendNack(const lp::Nack &nack)
sends Nack on Face
contains information about an Interest toward an outgoing face
the Data should be cached in the ContentStore
bool hasLink() const
Check whether the Interest contains a Link object.
signal::Signal< LinkService, lp::Nack > & afterReceiveNack
signals on Nack received
shared_ptr< Entry > find(const Interest &interest) const
finds a PIT entry for Interest
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)
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 OutRecordCollection & getOutRecords() const
scheduler::EventId m_unsatisfyTimer
unsatisfy timer
represents an error in TLV encoding or decoding
const Name & getName() const