34 #include <boost/random/uniform_int_distribution.hpp> 42 const Name Forwarder::LOCALHOST_NAME(
"ndn:/localhost");
48 , m_measurements(m_nameTree)
71 " interest=" << interest.
getName() <<
" malformed");
76 this->onIncomingInterest(face, interest);
85 this->onIncomingData(face, data);
100 "~" << nack.
getReason() <<
" malformed");
104 this->onIncomingNack(face, nack);
108 Forwarder::onIncomingInterest(Face& inFace,
const Interest& interest)
111 NFD_LOG_DEBUG(
"onIncomingInterest face=" << inFace.getId() <<
112 " interest=" << interest.
getName());
113 interest.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
119 if (isViolatingLocalhost) {
120 NFD_LOG_DEBUG(
"onIncomingInterest face=" << inFace.getId() <<
121 " interest=" << interest.
getName() <<
" violates /localhost");
127 bool hasDuplicateNonceInDnl = m_deadNonceList.
has(interest.
getName(), interest.
getNonce());
128 if (hasDuplicateNonceInDnl) {
130 this->onInterestLoop(inFace, interest);
135 shared_ptr<pit::Entry> pitEntry = m_pit.
insert(interest).first;
138 bool hasDuplicateNonceInPit = pitEntry->findNonce(interest.
getNonce(), inFace) !=
140 if (hasDuplicateNonceInPit) {
142 this->onInterestLoop(inFace, interest);
147 this->cancelUnsatisfyAndStragglerTimer(pitEntry);
151 bool isPending = inRecords.begin() != inRecords.end();
153 if (m_csFromNdnSim ==
nullptr) {
155 bind(&Forwarder::onContentStoreHit,
this, ref(inFace), pitEntry, _1, _2),
156 bind(&Forwarder::onContentStoreMiss,
this, ref(inFace), pitEntry, _1));
159 shared_ptr<Data> match = m_csFromNdnSim->Lookup(interest.shared_from_this());
160 if (match !=
nullptr) {
161 this->onContentStoreHit(inFace, pitEntry, interest, *match);
164 this->onContentStoreMiss(inFace, pitEntry, interest);
169 this->onContentStoreMiss(inFace, pitEntry, interest);
174 Forwarder::onInterestLoop(Face& inFace,
const Interest& interest)
179 " interest=" << interest.
getName() <<
185 " interest=" << interest.
getName() <<
186 " send-Nack-duplicate");
191 nack.setReason(lp::NackReason::DUPLICATE);
192 inFace.sendNack(nack);
196 Forwarder::onContentStoreMiss(
const Face& inFace,
197 shared_ptr<pit::Entry> pitEntry,
202 shared_ptr<Face>
face = const_pointer_cast<Face>(inFace.shared_from_this());
204 pitEntry->insertOrUpdateInRecord(face, interest);
207 this->setUnsatisfyTimer(pitEntry);
209 shared_ptr<fib::Entry> fibEntry;
236 bool isDefaultFreeZone = !(fibEntry->getPrefix().size() == 0 && fibEntry->hasNextHops());
237 if (isDefaultFreeZone) {
239 for (
const std::pair<uint32_t, Name>& delegation : link.
getDelegations()) {
240 const Name& delegationName = delegation.second;
242 if (fibEntry->hasNextHops()) {
243 const_cast<Interest&
>(interest).setSelectedDelegation(delegationName);
245 <<
" setSelectedDelegation=" << delegationName);
257 BOOST_ASSERT(fibEntry !=
nullptr);
259 cref(inFace), cref(interest), fibEntry, pitEntry));
263 Forwarder::onContentStoreHit(
const Face& inFace,
264 shared_ptr<pit::Entry> pitEntry,
272 pitEntry, cref(*m_csFace), cref(data)));
281 this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
285 Forwarder::onOutgoingInterest(shared_ptr<pit::Entry> pitEntry, Face& outFace,
289 NFD_LOG_WARN(
"onOutgoingInterest face=invalid interest=" << pitEntry->getName());
292 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
293 " interest=" << pitEntry->getName());
296 if (pitEntry->violatesScope(outFace)) {
297 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
298 " interest=" << pitEntry->getName() <<
" violates scope");
308 pit::InRecordCollection::const_iterator pickedInRecord = std::max_element(
309 pitEntry->getInRecords().begin(), pitEntry->getInRecords().end(),
311 bool isOutFaceA = a.
getFace().get() == &outFace;
312 bool isOutFaceB = b.getFace().get() == &outFace;
313 return (isOutFaceA > isOutFaceB) ||
314 (isOutFaceA == isOutFaceB && a.
getLastRenewed() < b.getLastRenewed());
316 BOOST_ASSERT(pickedInRecord != pitEntry->getInRecords().end());
317 auto interest = const_pointer_cast<
Interest>(pickedInRecord->getInterest().shared_from_this());
320 interest = make_shared<Interest>(*interest);
321 static boost::random::uniform_int_distribution<uint32_t> dist;
326 pitEntry->insertOrUpdateOutRecord(outFace.shared_from_this(), *interest);
329 outFace.sendInterest(*interest);
334 Forwarder::onInterestReject(shared_ptr<pit::Entry> pitEntry)
336 if (pitEntry->hasUnexpiredOutRecords()) {
337 NFD_LOG_ERROR(
"onInterestReject interest=" << pitEntry->getName() <<
338 " cannot reject forwarded Interest");
341 NFD_LOG_DEBUG(
"onInterestReject interest=" << pitEntry->getName());
344 this->cancelUnsatisfyAndStragglerTimer(pitEntry);
347 this->setStragglerTimer(pitEntry,
false);
351 Forwarder::onInterestUnsatisfied(shared_ptr<pit::Entry> pitEntry)
353 NFD_LOG_DEBUG(
"onInterestUnsatisfied interest=" << pitEntry->getName());
361 this->onInterestFinalize(pitEntry,
false);
365 Forwarder::onInterestFinalize(shared_ptr<pit::Entry> pitEntry,
bool isSatisfied,
366 const time::milliseconds& dataFreshnessPeriod)
368 NFD_LOG_DEBUG(
"onInterestFinalize interest=" << pitEntry->getName() <<
369 (isSatisfied ?
" satisfied" :
" unsatisfied"));
372 this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
375 this->cancelUnsatisfyAndStragglerTimer(pitEntry);
376 m_pit.
erase(pitEntry);
380 Forwarder::onIncomingData(Face& inFace,
const Data& data)
384 data.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
390 if (isViolatingLocalhost) {
392 " data=" << data.
getName() <<
" violates /localhost");
399 if (pitMatches.begin() == pitMatches.end()) {
401 this->onDataUnsolicited(inFace, data);
411 shared_ptr<Data> dataCopyWithoutPacket = make_shared<Data>(data);
415 if (m_csFromNdnSim ==
nullptr)
416 m_cs.
insert(*dataCopyWithoutPacket);
418 m_csFromNdnSim->Add(dataCopyWithoutPacket);
420 std::set<Face*> pendingDownstreams;
422 for (
const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
423 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
426 this->cancelUnsatisfyAndStragglerTimer(pitEntry);
432 pendingDownstreams.insert(inRecord.getFace().get());
439 pitEntry, cref(inFace), cref(data)));
445 pitEntry->deleteInRecords();
446 pitEntry->deleteOutRecord(inFace);
453 for (Face* pendingDownstream : pendingDownstreams) {
454 if (pendingDownstream == &inFace) {
458 this->onOutgoingData(data, *pendingDownstream);
463 Forwarder::onDataUnsolicited(Face& inFace,
const Data& data)
469 if (m_csFromNdnSim ==
nullptr)
472 m_csFromNdnSim->Add(data.shared_from_this());
477 (acceptToCache ?
" cached" :
" not cached"));
481 Forwarder::onOutgoingData(
const Data& data, Face& outFace)
492 if (isViolatingLocalhost) {
494 " data=" << data.
getName() <<
" violates /localhost");
502 outFace.sendData(data);
507 Forwarder::onIncomingNack(Face& inFace,
const lp::Nack& nack)
510 nack.
setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
517 "~" << nack.
getReason() <<
" face-is-multi-access");
524 if (pitEntry ==
nullptr) {
527 "~" << nack.
getReason() <<
" no-PIT-entry");
534 if (outRecord == pitEntry->getOutRecords().end()) {
537 "~" << nack.
getReason() <<
" no-out-record");
545 "~" << nack.
getReason() <<
" wrong-Nonce " <<
555 outRecord->setIncomingNack(nack);
560 cref(inFace), cref(nack), fibEntry, pitEntry));
564 Forwarder::onOutgoingNack(shared_ptr<pit::Entry> pitEntry,
const Face& outFace,
569 " nack=" << pitEntry->getInterest().getName() <<
570 "~" << nack.
getReason() <<
" no-in-record");
575 pit::InRecordCollection::const_iterator inRecord = pitEntry->getInRecord(outFace);
578 if (inRecord == pitEntry->getInRecords().end()) {
580 " nack=" << pitEntry->getInterest().getName() <<
581 "~" << nack.
getReason() <<
" no-in-record");
588 " nack=" << pitEntry->getInterest().getName() <<
589 "~" << nack.
getReason() <<
" face-is-multi-access");
594 " nack=" << pitEntry->getInterest().getName() <<
598 lp::Nack nackPkt(inRecord->getInterest());
602 pitEntry->deleteInRecord(outFace);
605 const_cast<Face&
>(outFace).sendNack(nackPkt);
616 Forwarder::setUnsatisfyTimer(shared_ptr<pit::Entry> pitEntry)
619 pit::InRecordCollection::const_iterator lastExpiring =
620 std::max_element(inRecords.begin(), inRecords.end(),
625 if (lastExpiryFromNow <= time::seconds(0)) {
631 bind(&Forwarder::onInterestUnsatisfied,
this, pitEntry));
635 Forwarder::setStragglerTimer(shared_ptr<pit::Entry> pitEntry,
bool isSatisfied,
636 const time::milliseconds& dataFreshnessPeriod)
638 time::nanoseconds stragglerTime = time::milliseconds(100);
642 bind(&Forwarder::onInterestFinalize,
this, pitEntry, isSatisfied, dataFreshnessPeriod));
646 Forwarder::cancelUnsatisfyAndStragglerTimer(shared_ptr<pit::Entry> pitEntry)
660 Forwarder::insertDeadNonceList(
pit::Entry& pitEntry,
bool isSatisfied,
661 const time::milliseconds& dataFreshnessPeriod,
665 bool needDnl =
false;
667 bool hasFreshnessPeriod = dataFreshnessPeriod >= time::milliseconds::zero();
670 (hasFreshnessPeriod && dataFreshnessPeriod < m_deadNonceList.
getLifetime());
684 std::for_each(outRecords.begin(), outRecords.end(),
689 pit::OutRecordCollection::const_iterator outRecord = pitEntry.
getOutRecord(*upstream);
691 m_deadNonceList.
add(pitEntry.
getName(), outRecord->getLastNonce());
signal::Signal< Forwarder, pit::Entry, Face, Data > beforeSatisfyInterest
trigger before PIT entry is satisfied
std::list< InRecord > InRecordCollection
represents an unordered collection of InRecords
void setTag(shared_ptr< T > tag) const
set a tag item
void erase(shared_ptr< pit::Entry > pitEntry)
erases a PIT Entry
shared_ptr< Face > makeNullFace(const FaceUri &uri)
represents the Dead Nonce list
#define NFD_LOG_DEBUG(expression)
shared_ptr< Face > getFace() const
OutRecordCollection::iterator getOutRecord(const Face &face)
get the OutRecord for face
const Link & getLink() const
Get the link object for this interest.
int getMustBeFresh() const
void cancel(const EventId &eventId)
cancel a scheduled event
void installStrategies(Forwarder &forwarder)
static time_point now() noexcept
represents the underlying protocol and address used by a Face
const Name & getName() const
Get name of the Data packet.
FaceTable & getFaceTable()
contains information about an Interest from an incoming face
Nack & setHeader(const NackHeader &header)
shared_ptr< fib::Entry > findLongestPrefixMatch(const Name &prefix) const
performs a longest prefix match
void startProcessInterest(Face &face, const Interest &interest)
start incoming Interest processing
virtual void beforeSatisfyInterest(shared_ptr< pit::Entry > pitEntry, const Face &inFace, const Data &data)
trigger before PIT entry is satisfied
const time::nanoseconds & getLifetime() const
PacketCounter nInInterests
represents an Interest packet
#define NFD_LOG_ERROR(expression)
pit::DataMatchResult findAllDataMatches(const Data &data) const
performs a Data match
shared_ptr< pit::Entry > find(const Interest &interest) const
finds a PIT entry for Interest
static bool compare_InRecord_expiry(const pit::InRecord &a, const pit::InRecord &b)
shared_ptr< Strategy > makeDefaultStrategy(Forwarder &forwarder)
void add(const Name &name, uint32_t nonce)
records name+nonce
const Name & getName() const
represents a Network Nack
NackReason getReason() const
Table::const_iterator iterator
virtual void beforeExpirePendingInterest(shared_ptr< pit::Entry > pitEntry)
trigger before PIT entry expires
#define NFD_LOG_WARN(expression)
Name getSelectedDelegation() const
Get the name of the selected delegation.
static void insertNonceToDnl(DeadNonceList &dnl, const pit::Entry &pitEntry, const pit::OutRecord &outRecord)
represents a Link instance
void insert(const Data &data, bool isUnsolicited=false)
inserts a Data packet
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
Interest & setNonce(uint32_t nonce)
Set Interest's nonce.
void startProcessData(Face &face, const Data &data)
start incoming Data processing
bool isInProducerRegion(const Link &link) const
determines whether an Interest has reached a producer region
Name abstraction to represent an absolute name.
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...
boost::random::mt19937 & getGlobalRng()
std::pair< shared_ptr< pit::Entry >, bool > insert(const Interest &interest)
inserts a PIT entry for Interest
PacketCounter nOutInterests
void find(const Interest &interest, const HitCallback &hitCallback, const MissCallback &missCallback) const
finds the best matching Data packet
const OutRecordCollection & getOutRecords() const
uint32_t getLastNonce() const
std::list< OutRecord > OutRecordCollection
represents an unordered collection of OutRecords
const time::milliseconds & getFreshnessPeriod() const
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
bool has(const Name &name, uint32_t nonce) const
determines if name+nonce exists
const Interest & getInterest() const
#define NFD_LOG_INIT(name)
EventId schedule(const time::nanoseconds &after, const Scheduler::Event &event)
schedule an event
#define NFD_LOG_TRACE(expression)
const DelegationSet & getDelegations() const
Get the pairs of <Name, Preference>
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
bool hasLink() const
Check whether the Interest contains a Link object.
virtual void afterReceiveInterest(const Face &inFace, const Interest &interest, shared_ptr< fib::Entry > fibEntry, shared_ptr< pit::Entry > pitEntry)=0
trigger after Interest is received
virtual void afterReceiveNack(const Face &inFace, const lp::Nack &nack, shared_ptr< fib::Entry > fibEntry, shared_ptr< pit::Entry > pitEntry)
trigger after Nack is received
bool hasSelectedDelegation() const
Check whether the Interest includes a selected delegation.
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
represents an error in TLV encoding or decoding
const Name & getName() const
time::steady_clock::TimePoint getLastRenewed() const
std::vector< shared_ptr< pit::Entry > > DataMatchResult