32 #include <boost/random/uniform_int_distribution.hpp>
40 const Name Forwarder::LOCALHOST_NAME(
"ndn:/localhost");
46 , m_measurements(m_nameTree)
48 , m_csFace(make_shared<
NullFace>(FaceUri(
"contentstore://")))
60 Forwarder::onIncomingInterest(
Face& inFace,
const Interest& interest)
64 " interest=" << interest.getName());
65 const_cast<Interest&
>(interest).setIncomingFaceId(inFace.
getId());
69 bool isViolatingLocalhost = !inFace.
isLocal() &&
70 LOCALHOST_NAME.isPrefixOf(interest.getName());
71 if (isViolatingLocalhost) {
73 " interest=" << interest.getName() <<
" violates /localhost");
79 shared_ptr<pit::Entry> pitEntry = m_pit.
insert(interest).first;
82 int dnw = pitEntry->findNonce(interest.getNonce(), inFace);
84 m_deadNonceList.
has(interest.getName(), interest.getNonce());
85 if (hasDuplicateNonce) {
87 this->onInterestLoop(inFace, interest, pitEntry);
92 this->cancelUnsatisfyAndStragglerTimer(pitEntry);
96 bool isPending = inRecords.begin() != inRecords.end();
100 shared_ptr<Data> match;
101 if (m_csFromNdnSim ==
nullptr)
102 csMatch = m_cs.
find(interest);
104 match = m_csFromNdnSim->Lookup(interest.shared_from_this());
105 csMatch = match.get();
113 this->dispatchToStrategy(pitEntry, bind(&Strategy::beforeSatisfyInterest, _1,
114 pitEntry, cref(*m_csFace), cref(*csMatch)));
116 this->setStragglerTimer(pitEntry,
true, csMatch->getFreshnessPeriod());
119 this->onOutgoingData(*csMatch, inFace);
125 pitEntry->insertOrUpdateInRecord(inFace.shared_from_this(), interest);
128 this->setUnsatisfyTimer(pitEntry);
134 this->dispatchToStrategy(pitEntry, bind(&Strategy::afterReceiveInterest, _1,
135 cref(inFace), cref(interest), fibEntry, pitEntry));
139 Forwarder::onInterestLoop(Face& inFace,
const Interest& interest,
140 shared_ptr<pit::Entry> pitEntry)
143 " interest=" << interest.getName());
161 bool isOutFaceA = a.
getFace().get() == outFace;
162 bool isOutFaceB = b.
getFace().get() == outFace;
164 if (!isOutFaceA && isOutFaceB) {
167 if (isOutFaceA && !isOutFaceB) {
175 Forwarder::onOutgoingInterest(shared_ptr<pit::Entry> pitEntry, Face& outFace,
179 NFD_LOG_WARN(
"onOutgoingInterest face=invalid interest=" << pitEntry->getName());
182 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
183 " interest=" << pitEntry->getName());
186 if (pitEntry->violatesScope(outFace)) {
187 NFD_LOG_DEBUG(
"onOutgoingInterest face=" << outFace.getId() <<
188 " interest=" << pitEntry->getName() <<
" violates scope");
194 pit::InRecordCollection::const_iterator pickedInRecord = std::max_element(
196 BOOST_ASSERT(pickedInRecord != inRecords.end());
197 shared_ptr<Interest> interest = const_pointer_cast<Interest>(
198 pickedInRecord->getInterest().shared_from_this());
201 interest = make_shared<Interest>(*interest);
202 static boost::random::uniform_int_distribution<uint32_t> dist;
207 pitEntry->insertOrUpdateOutRecord(outFace.shared_from_this(), *interest);
210 outFace.sendInterest(*interest);
215 Forwarder::onInterestReject(shared_ptr<pit::Entry> pitEntry)
217 if (pitEntry->hasUnexpiredOutRecords()) {
218 NFD_LOG_ERROR(
"onInterestReject interest=" << pitEntry->getName() <<
219 " cannot reject forwarded Interest");
222 NFD_LOG_DEBUG(
"onInterestReject interest=" << pitEntry->getName());
225 this->cancelUnsatisfyAndStragglerTimer(pitEntry);
228 this->setStragglerTimer(pitEntry,
false);
232 Forwarder::onInterestUnsatisfied(shared_ptr<pit::Entry> pitEntry)
234 NFD_LOG_DEBUG(
"onInterestUnsatisfied interest=" << pitEntry->getName());
238 this->dispatchToStrategy(pitEntry, bind(&Strategy::beforeExpirePendingInterest, _1,
242 this->onInterestFinalize(pitEntry,
false);
246 Forwarder::onInterestFinalize(shared_ptr<pit::Entry> pitEntry,
bool isSatisfied,
247 const time::milliseconds& dataFreshnessPeriod)
249 NFD_LOG_DEBUG(
"onInterestFinalize interest=" << pitEntry->getName() <<
250 (isSatisfied ?
" satisfied" :
" unsatisfied"));
253 this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
256 this->cancelUnsatisfyAndStragglerTimer(pitEntry);
257 m_pit.
erase(pitEntry);
261 Forwarder::onIncomingData(Face& inFace,
const Data& data)
264 NFD_LOG_DEBUG(
"onIncomingData face=" << inFace.getId() <<
" data=" << data.getName());
265 const_cast<Data&
>(data).setIncomingFaceId(inFace.getId());
269 bool isViolatingLocalhost = !inFace.isLocal() &&
270 LOCALHOST_NAME.isPrefixOf(data.getName());
271 if (isViolatingLocalhost) {
273 " data=" << data.getName() <<
" violates /localhost");
280 if (pitMatches.begin() == pitMatches.end()) {
282 this->onDataUnsolicited(inFace, data);
287 if (m_csFromNdnSim ==
nullptr)
290 m_csFromNdnSim->Add(data.shared_from_this());
292 std::set<shared_ptr<Face> > pendingDownstreams;
294 for (
const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
295 NFD_LOG_DEBUG(
"onIncomingData matching=" << pitEntry->getName());
298 this->cancelUnsatisfyAndStragglerTimer(pitEntry);
302 for (pit::InRecordCollection::const_iterator it = inRecords.begin();
303 it != inRecords.end(); ++it) {
304 if (it->getExpiry() > time::steady_clock::now()) {
305 pendingDownstreams.insert(it->getFace());
311 this->dispatchToStrategy(pitEntry, bind(&Strategy::beforeSatisfyInterest, _1,
312 pitEntry, cref(inFace), cref(data)));
315 this->insertDeadNonceList(*pitEntry,
true, data.getFreshnessPeriod(), &inFace);
318 pitEntry->deleteInRecords();
319 pitEntry->deleteOutRecord(inFace);
322 this->setStragglerTimer(pitEntry,
true, data.getFreshnessPeriod());
326 for (std::set<shared_ptr<Face> >::iterator it = pendingDownstreams.begin();
327 it != pendingDownstreams.end(); ++it) {
328 shared_ptr<Face> pendingDownstream = *it;
329 if (pendingDownstream.get() == &inFace) {
333 this->onOutgoingData(data, *pendingDownstream);
338 Forwarder::onDataUnsolicited(Face& inFace,
const Data& data)
341 bool acceptToCache = inFace.isLocal();
344 if (m_csFromNdnSim ==
nullptr)
347 m_csFromNdnSim->Add(data.shared_from_this());
351 " data=" << data.getName() <<
352 (acceptToCache ?
" cached" :
" not cached"));
356 Forwarder::onOutgoingData(
const Data& data, Face& outFace)
359 NFD_LOG_WARN(
"onOutgoingData face=invalid data=" << data.getName());
362 NFD_LOG_DEBUG(
"onOutgoingData face=" << outFace.getId() <<
" data=" << data.getName());
365 bool isViolatingLocalhost = !outFace.isLocal() &&
366 LOCALHOST_NAME.isPrefixOf(data.getName());
367 if (isViolatingLocalhost) {
369 " data=" << data.getName() <<
" violates /localhost");
377 outFace.sendData(data);
388 Forwarder::setUnsatisfyTimer(shared_ptr<pit::Entry> pitEntry)
391 pit::InRecordCollection::const_iterator lastExpiring =
392 std::max_element(inRecords.begin(), inRecords.end(),
395 time::steady_clock::TimePoint lastExpiry = lastExpiring->getExpiry();
396 time::nanoseconds lastExpiryFromNow = lastExpiry - time::steady_clock::now();
397 if (lastExpiryFromNow <= time::seconds(0)) {
403 bind(&Forwarder::onInterestUnsatisfied,
this, pitEntry));
407 Forwarder::setStragglerTimer(shared_ptr<pit::Entry> pitEntry,
bool isSatisfied,
408 const time::milliseconds& dataFreshnessPeriod)
410 time::nanoseconds stragglerTime = time::milliseconds(100);
414 bind(&Forwarder::onInterestFinalize,
this, pitEntry, isSatisfied, dataFreshnessPeriod));
418 Forwarder::cancelUnsatisfyAndStragglerTimer(shared_ptr<pit::Entry> pitEntry)
432 Forwarder::insertDeadNonceList(pit::Entry& pitEntry,
bool isSatisfied,
433 const time::milliseconds& dataFreshnessPeriod,
437 bool needDnl =
false;
439 bool hasFreshnessPeriod = dataFreshnessPeriod >= time::milliseconds::zero();
441 needDnl =
static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
442 (hasFreshnessPeriod && dataFreshnessPeriod < m_deadNonceList.
getLifetime());
456 std::for_each(outRecords.begin(), outRecords.end(),
461 pit::OutRecordCollection::const_iterator outRecord = pitEntry.getOutRecord(*upstream);
462 if (outRecord != pitEntry.getOutRecords().end()) {
463 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 erase(shared_ptr< pit::Entry > pitEntry)
erases a PIT Entry
represents the Dead Nonce list
#define NFD_LOG_DEBUG(expression)
bool has(const Name &name, uint32_t nonce) const
determines if name+nonce exists
shared_ptr< fib::Entry > findLongestPrefixMatch(const Name &prefix) const
performs a longest prefix match
time::steady_clock::TimePoint getLastRenewed() const
void cancel(const EventId &eventId)
cancel a scheduled event
void installStrategies(Forwarder &forwarder)
FaceTable & getFaceTable()
contains information about an Interest from an incoming face
uint32_t getLastNonce() const
#define NFD_LOG_ERROR(expression)
pit::DataMatchResult findAllDataMatches(const Data &data) const
performs a Data match
const PacketCounter & getNOutDatas() const
outgoing Data
static bool compare_InRecord_expiry(const pit::InRecord &a, const pit::InRecord &b)
const PacketCounter & getNOutInterests() const
outgoing Interest
shared_ptr< Strategy > makeDefaultStrategy(Forwarder &forwarder)
const Data * find(const Interest &interest) const
finds the best match Data for an Interest
void add(const Name &name, uint32_t nonce)
records name+nonce
#define NFD_LOG_WARN(expression)
bool insert(const Data &data, bool isUnsolicited=false)
inserts a Data packet This method does not consider the payload of the Data packet.
static void insertNonceToDnl(DeadNonceList &dnl, const pit::Entry &pitEntry, const pit::OutRecord &outRecord)
const time::nanoseconds & getLifetime() const
signal::Signal< Forwarder, pit::Entry > beforeExpirePendingInterest
trigger before PIT entry expires
const Name & getName() const
EventId schedule(const time::nanoseconds &after, const std::function< void()> &event)
schedule an event
boost::random::mt19937 & getGlobalRng()
const PacketCounter & getNInDatas() const
incoming Data
std::pair< shared_ptr< pit::Entry >, bool > insert(const Interest &interest)
inserts a PIT entry for Interest
a Face that has no underlying transport and drops every packet
std::list< OutRecord > OutRecordCollection
represents an unordered collection of OutRecords
static bool compare_pickInterest(const pit::InRecord &a, const pit::InRecord &b, const Face *outFace)
compare two InRecords for picking outgoing Interest
shared_ptr< Face > getFace() const
#define NFD_LOG_INIT(name)
const FaceId FACEID_CONTENT_STORE
identifies a packet comes from the ContentStore, in LocalControlHeader incomingFaceId ...
const FaceId INVALID_FACEID
indicates an invalid FaceId
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
const PacketCounter & getNInInterests() const
incoming Interest
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
bool isLocal() const
Get whether face is connected to a local app.
std::vector< shared_ptr< pit::Entry > > DataMatchResult