forwarder.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2017, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "forwarder.hpp"
27 #include "algorithm.hpp"
28 #include "best-route-strategy2.hpp"
29 #include "strategy.hpp"
30 #include "core/logger.hpp"
31 #include "table/cleanup.hpp"
32 #include <ndn-cxx/lp/tags.hpp>
33 
34 namespace nfd {
35 
36 NFD_LOG_INIT("Forwarder");
37 
38 static Name
40 {
42 }
43 
45  : m_unsolicitedDataPolicy(new fw::DefaultUnsolicitedDataPolicy())
46  , m_fib(m_nameTree)
47  , m_pit(m_nameTree)
48  , m_measurements(m_nameTree)
49  , m_strategyChoice(*this)
50 {
51  m_faceTable.afterAdd.connect([this] (Face& face) {
52  face.afterReceiveInterest.connect(
53  [this, &face] (const Interest& interest) {
54  this->startProcessInterest(face, interest);
55  });
56  face.afterReceiveData.connect(
57  [this, &face] (const Data& data) {
58  this->startProcessData(face, data);
59  });
60  face.afterReceiveNack.connect(
61  [this, &face] (const lp::Nack& nack) {
62  this->startProcessNack(face, nack);
63  });
64  });
65 
66  m_faceTable.beforeRemove.connect([this] (Face& face) {
67  cleanupOnFaceRemoval(m_nameTree, m_fib, m_pit, face);
68  });
69 
70  m_strategyChoice.setDefaultStrategy(getDefaultStrategyName());
71 }
72 
73 Forwarder::~Forwarder() = default;
74 
75 void
76 Forwarder::onIncomingInterest(Face& inFace, const Interest& interest)
77 {
78  // receive Interest
79  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
80  " interest=" << interest.getName());
81  interest.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
82  ++m_counters.nInInterests;
83 
84  // /localhost scope control
85  bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
86  scope_prefix::LOCALHOST.isPrefixOf(interest.getName());
87  if (isViolatingLocalhost) {
88  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
89  " interest=" << interest.getName() << " violates /localhost");
90  // (drop)
91  return;
92  }
93 
94  // detect duplicate Nonce with Dead Nonce List
95  bool hasDuplicateNonceInDnl = m_deadNonceList.has(interest.getName(), interest.getNonce());
96  if (hasDuplicateNonceInDnl) {
97  // goto Interest loop pipeline
98  this->onInterestLoop(inFace, interest);
99  return;
100  }
101 
102  // strip forwarding hint if Interest has reached producer region
103  if (!interest.getForwardingHint().empty() &&
104  m_networkRegionTable.isInProducerRegion(interest.getForwardingHint())) {
105  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
106  " interest=" << interest.getName() << " reaching-producer-region");
107  const_cast<Interest&>(interest).setForwardingHint({});
108  }
109 
110  // PIT insert
111  shared_ptr<pit::Entry> pitEntry = m_pit.insert(interest).first;
112 
113  // detect duplicate Nonce in PIT entry
114  int dnw = fw::findDuplicateNonce(*pitEntry, interest.getNonce(), inFace);
115  bool hasDuplicateNonceInPit = dnw != fw::DUPLICATE_NONCE_NONE;
116  if (inFace.getLinkType() == ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
117  // for p2p face: duplicate Nonce from same incoming face is not loop
118  hasDuplicateNonceInPit = hasDuplicateNonceInPit && !(dnw & fw::DUPLICATE_NONCE_IN_SAME);
119  }
120  if (hasDuplicateNonceInPit) {
121  // goto Interest loop pipeline
122  this->onInterestLoop(inFace, interest);
123  return;
124  }
125 
126  // cancel unsatisfy & straggler timer
127  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
128 
129  // is pending?
130  if (!pitEntry->hasInRecords()) {
131  m_cs.find(interest,
132  bind(&Forwarder::onContentStoreHit, this, ref(inFace), pitEntry, _1, _2),
133  bind(&Forwarder::onContentStoreMiss, this, ref(inFace), pitEntry, _1));
134  }
135  else {
136  this->onContentStoreMiss(inFace, pitEntry, interest);
137  }
138 }
139 
140 void
141 Forwarder::onInterestLoop(Face& inFace, const Interest& interest)
142 {
143  // if multi-access or ad hoc face, drop
144  if (inFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
145  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
146  " interest=" << interest.getName() <<
147  " drop");
148  return;
149  }
150 
151  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
152  " interest=" << interest.getName() <<
153  " send-Nack-duplicate");
154 
155  // send Nack with reason=DUPLICATE
156  // note: Don't enter outgoing Nack pipeline because it needs an in-record.
157  lp::Nack nack(interest);
158  nack.setReason(lp::NackReason::DUPLICATE);
159  inFace.sendNack(nack);
160 }
161 
162 void
163 Forwarder::onContentStoreMiss(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
164  const Interest& interest)
165 {
166  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName());
167  ++m_counters.nCsMisses;
168 
169  // insert in-record
170  pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
171 
172  // set PIT unsatisfy timer
173  this->setUnsatisfyTimer(pitEntry);
174 
175  // has NextHopFaceId?
176  shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
177  if (nextHopTag != nullptr) {
178  // chosen NextHop face exists?
179  Face* nextHopFace = m_faceTable.get(*nextHopTag);
180  if (nextHopFace != nullptr) {
181  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName() << " nexthop-faceid=" << nextHopFace->getId());
182  // go to outgoing Interest pipeline
183  // scope control is unnecessary, because privileged app explicitly wants to forward
184  this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
185  }
186  return;
187  }
188 
189  // dispatch to strategy: after incoming Interest
190  this->dispatchToStrategy(*pitEntry,
191  [&] (fw::Strategy& strategy) { strategy.afterReceiveInterest(inFace, interest, pitEntry); });
192 }
193 
194 void
195 Forwarder::onContentStoreHit(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
196  const Interest& interest, const Data& data)
197 {
198  NFD_LOG_DEBUG("onContentStoreHit interest=" << interest.getName());
199  ++m_counters.nCsHits;
200 
201  data.setTag(make_shared<lp::IncomingFaceIdTag>(face::FACEID_CONTENT_STORE));
202  // XXX should we lookup PIT for other Interests that also match csMatch?
203 
204  // set PIT straggler timer
205  this->setStragglerTimer(pitEntry, true, data.getFreshnessPeriod());
206 
207  // goto outgoing Data pipeline
208  this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
209 }
210 
211 void
212 Forwarder::onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outFace, const Interest& interest)
213 {
214  NFD_LOG_DEBUG("onOutgoingInterest face=" << outFace.getId() <<
215  " interest=" << pitEntry->getName());
216 
217  // insert out-record
218  pitEntry->insertOrUpdateOutRecord(outFace, interest);
219 
220  // send Interest
221  outFace.sendInterest(interest);
222  ++m_counters.nOutInterests;
223 }
224 
225 void
226 Forwarder::onInterestReject(const shared_ptr<pit::Entry>& pitEntry)
227 {
228  if (fw::hasPendingOutRecords(*pitEntry)) {
229  NFD_LOG_ERROR("onInterestReject interest=" << pitEntry->getName() <<
230  " cannot reject forwarded Interest");
231  return;
232  }
233  NFD_LOG_DEBUG("onInterestReject interest=" << pitEntry->getName());
234 
235  // cancel unsatisfy & straggler timer
236  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
237 
238  // set PIT straggler timer
239  this->setStragglerTimer(pitEntry, false);
240 }
241 
242 void
243 Forwarder::onInterestUnsatisfied(const shared_ptr<pit::Entry>& pitEntry)
244 {
245  NFD_LOG_DEBUG("onInterestUnsatisfied interest=" << pitEntry->getName());
246 
247  // invoke PIT unsatisfied callback
248  this->dispatchToStrategy(*pitEntry,
249  [&] (fw::Strategy& strategy) { strategy.beforeExpirePendingInterest(pitEntry); });
250 
251  // goto Interest Finalize pipeline
252  this->onInterestFinalize(pitEntry, false);
253 }
254 
255 void
256 Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
257  ndn::optional<time::milliseconds> dataFreshnessPeriod)
258 {
259  NFD_LOG_DEBUG("onInterestFinalize interest=" << pitEntry->getName() <<
260  (isSatisfied ? " satisfied" : " unsatisfied"));
261 
262  // Dead Nonce List insert if necessary
263  this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
264 
265  // PIT delete
266  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
267  m_pit.erase(pitEntry.get());
268 }
269 
270 void
271 Forwarder::onIncomingData(Face& inFace, const Data& data)
272 {
273  // receive Data
274  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() << " data=" << data.getName());
275  data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
276  ++m_counters.nInData;
277 
278  // /localhost scope control
279  bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
280  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
281  if (isViolatingLocalhost) {
282  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() <<
283  " data=" << data.getName() << " violates /localhost");
284  // (drop)
285  return;
286  }
287 
288  // PIT match
289  pit::DataMatchResult pitMatches = m_pit.findAllDataMatches(data);
290  if (pitMatches.begin() == pitMatches.end()) {
291  // goto Data unsolicited pipeline
292  this->onDataUnsolicited(inFace, data);
293  return;
294  }
295 
296  // CS insert
297  m_cs.insert(data);
298 
299  std::set<Face*> pendingDownstreams;
300  // foreach PitEntry
301  auto now = time::steady_clock::now();
302  for (const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
303  NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
304 
305  // cancel unsatisfy & straggler timer
306  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
307 
308  // remember pending downstreams
309  for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
310  if (inRecord.getExpiry() > now) {
311  pendingDownstreams.insert(&inRecord.getFace());
312  }
313  }
314 
315  // invoke PIT satisfy callback
316  this->dispatchToStrategy(*pitEntry,
317  [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
318 
319  // Dead Nonce List insert if necessary (for out-record of inFace)
320  this->insertDeadNonceList(*pitEntry, true, data.getFreshnessPeriod(), &inFace);
321 
322  // mark PIT satisfied
323  pitEntry->clearInRecords();
324  pitEntry->deleteOutRecord(inFace);
325 
326  // set PIT straggler timer
327  this->setStragglerTimer(pitEntry, true, data.getFreshnessPeriod());
328  }
329 
330  // foreach pending downstream
331  for (Face* pendingDownstream : pendingDownstreams) {
332  if (pendingDownstream->getId() == inFace.getId() &&
333  pendingDownstream->getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
334  continue;
335  }
336  // goto outgoing Data pipeline
337  this->onOutgoingData(data, *pendingDownstream);
338  }
339 }
340 
341 void
342 Forwarder::onDataUnsolicited(Face& inFace, const Data& data)
343 {
344  // accept to cache?
345  fw::UnsolicitedDataDecision decision = m_unsolicitedDataPolicy->decide(inFace, data);
346  if (decision == fw::UnsolicitedDataDecision::CACHE) {
347  // CS insert
348  m_cs.insert(data, true);
349  }
350 
351  NFD_LOG_DEBUG("onDataUnsolicited face=" << inFace.getId() <<
352  " data=" << data.getName() <<
353  " decision=" << decision);
354 }
355 
356 void
357 Forwarder::onOutgoingData(const Data& data, Face& outFace)
358 {
359  if (outFace.getId() == face::INVALID_FACEID) {
360  NFD_LOG_WARN("onOutgoingData face=invalid data=" << data.getName());
361  return;
362  }
363  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() << " data=" << data.getName());
364 
365  // /localhost scope control
366  bool isViolatingLocalhost = outFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
367  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
368  if (isViolatingLocalhost) {
369  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() <<
370  " data=" << data.getName() << " violates /localhost");
371  // (drop)
372  return;
373  }
374 
375  // TODO traffic manager
376 
377  // send Data
378  outFace.sendData(data);
379  ++m_counters.nOutData;
380 }
381 
382 void
383 Forwarder::onIncomingNack(Face& inFace, const lp::Nack& nack)
384 {
385  // receive Nack
386  nack.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
387  ++m_counters.nInNacks;
388 
389  // if multi-access or ad hoc face, drop
390  if (inFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
391  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
392  " nack=" << nack.getInterest().getName() <<
393  "~" << nack.getReason() << " face-is-multi-access");
394  return;
395  }
396 
397  // PIT match
398  shared_ptr<pit::Entry> pitEntry = m_pit.find(nack.getInterest());
399  // if no PIT entry found, drop
400  if (pitEntry == nullptr) {
401  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
402  " nack=" << nack.getInterest().getName() <<
403  "~" << nack.getReason() << " no-PIT-entry");
404  return;
405  }
406 
407  // has out-record?
408  pit::OutRecordCollection::iterator outRecord = pitEntry->getOutRecord(inFace);
409  // if no out-record found, drop
410  if (outRecord == pitEntry->out_end()) {
411  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
412  " nack=" << nack.getInterest().getName() <<
413  "~" << nack.getReason() << " no-out-record");
414  return;
415  }
416 
417  // if out-record has different Nonce, drop
418  if (nack.getInterest().getNonce() != outRecord->getLastNonce()) {
419  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
420  " nack=" << nack.getInterest().getName() <<
421  "~" << nack.getReason() << " wrong-Nonce " <<
422  nack.getInterest().getNonce() << "!=" << outRecord->getLastNonce());
423  return;
424  }
425 
426  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
427  " nack=" << nack.getInterest().getName() <<
428  "~" << nack.getReason() << " OK");
429 
430  // record Nack on out-record
431  outRecord->setIncomingNack(nack);
432 
433  // trigger strategy: after receive NACK
434  this->dispatchToStrategy(*pitEntry,
435  [&] (fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
436 }
437 
438 void
439 Forwarder::onOutgoingNack(const shared_ptr<pit::Entry>& pitEntry, const Face& outFace,
440  const lp::NackHeader& nack)
441 {
442  if (outFace.getId() == face::INVALID_FACEID) {
443  NFD_LOG_WARN("onOutgoingNack face=invalid" <<
444  " nack=" << pitEntry->getInterest().getName() <<
445  "~" << nack.getReason() << " no-in-record");
446  return;
447  }
448 
449  // has in-record?
450  pit::InRecordCollection::iterator inRecord = pitEntry->getInRecord(outFace);
451 
452  // if no in-record found, drop
453  if (inRecord == pitEntry->in_end()) {
454  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
455  " nack=" << pitEntry->getInterest().getName() <<
456  "~" << nack.getReason() << " no-in-record");
457  return;
458  }
459 
460  // if multi-access or ad hoc face, drop
461  if (outFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
462  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
463  " nack=" << pitEntry->getInterest().getName() <<
464  "~" << nack.getReason() << " face-is-multi-access");
465  return;
466  }
467 
468  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
469  " nack=" << pitEntry->getInterest().getName() <<
470  "~" << nack.getReason() << " OK");
471 
472  // create Nack packet with the Interest from in-record
473  lp::Nack nackPkt(inRecord->getInterest());
474  nackPkt.setHeader(nack);
475 
476  // erase in-record
477  pitEntry->deleteInRecord(outFace);
478 
479  // send Nack on face
480  const_cast<Face&>(outFace).sendNack(nackPkt);
481  ++m_counters.nOutNacks;
482 }
483 
484 static inline bool
486 {
487  return a.getExpiry() < b.getExpiry();
488 }
489 
490 void
491 Forwarder::setUnsatisfyTimer(const shared_ptr<pit::Entry>& pitEntry)
492 {
493  pit::InRecordCollection::iterator lastExpiring =
494  std::max_element(pitEntry->in_begin(), pitEntry->in_end(), &compare_InRecord_expiry);
495 
496  time::steady_clock::TimePoint lastExpiry = lastExpiring->getExpiry();
497  time::nanoseconds lastExpiryFromNow = lastExpiry - time::steady_clock::now();
498  if (lastExpiryFromNow <= time::seconds::zero()) {
499  // TODO all in-records are already expired; will this happen?
500  }
501 
502  scheduler::cancel(pitEntry->m_unsatisfyTimer);
503  pitEntry->m_unsatisfyTimer = scheduler::schedule(lastExpiryFromNow,
504  bind(&Forwarder::onInterestUnsatisfied, this, pitEntry));
505 }
506 
507 void
508 Forwarder::setStragglerTimer(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
509  ndn::optional<time::milliseconds> dataFreshnessPeriod)
510 {
511  time::nanoseconds stragglerTime = time::milliseconds(100);
512 
513  scheduler::cancel(pitEntry->m_stragglerTimer);
514  pitEntry->m_stragglerTimer = scheduler::schedule(stragglerTime,
515  bind(&Forwarder::onInterestFinalize, this, pitEntry, isSatisfied, dataFreshnessPeriod));
516 }
517 
518 void
519 Forwarder::cancelUnsatisfyAndStragglerTimer(pit::Entry& pitEntry)
520 {
523 }
524 
525 static inline void
527  const pit::OutRecord& outRecord)
528 {
529  dnl.add(pitEntry.getName(), outRecord.getLastNonce());
530 }
531 
532 void
533 Forwarder::insertDeadNonceList(pit::Entry& pitEntry, bool isSatisfied,
534  ndn::optional<time::milliseconds> dataFreshnessPeriod, Face* upstream)
535 {
536  // need Dead Nonce List insert?
537  bool needDnl = true;
538  if (isSatisfied) {
539  BOOST_ASSERT(dataFreshnessPeriod);
540  BOOST_ASSERT(*dataFreshnessPeriod >= time::milliseconds::zero());
541  needDnl = static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
542  *dataFreshnessPeriod < m_deadNonceList.getLifetime();
543  }
544 
545  if (!needDnl) {
546  return;
547  }
548 
549  // Dead Nonce List insert
550  if (upstream == nullptr) {
551  // insert all outgoing Nonces
552  const pit::OutRecordCollection& outRecords = pitEntry.getOutRecords();
553  std::for_each(outRecords.begin(), outRecords.end(),
554  bind(&insertNonceToDnl, ref(m_deadNonceList), cref(pitEntry), _1));
555  }
556  else {
557  // insert outgoing Nonce of a specific face
558  pit::OutRecordCollection::iterator outRecord = pitEntry.getOutRecord(*upstream);
559  if (outRecord != pitEntry.getOutRecords().end()) {
560  m_deadNonceList.add(pitEntry.getName(), outRecord->getLastNonce());
561  }
562  }
563 }
564 
565 } // namespace nfd
OutRecordCollection::iterator getOutRecord(const Face &face)
get the out-record for face
Definition: pit-entry.cpp:90
void cleanupOnFaceRemoval(NameTree &nt, Fib &fib, Pit &pit, const Face &face)
cleanup tables when a face is destroyed
Definition: cleanup.cpp:31
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:161
void cancel(const EventId &eventId)
cancel a scheduled event
Definition: scheduler.cpp:53
virtual void afterReceiveInterest(const Face &inFace, const Interest &interest, const shared_ptr< pit::Entry > &pitEntry)=0
trigger after Interest is received
contains information about an Interest toward an outgoing face
static const Name & getStrategyName()
scheduler::EventId m_unsatisfyTimer
unsatisfy timer
Definition: pit-entry.hpp:227
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
scheduler::EventId m_stragglerTimer
straggler timer
Definition: pit-entry.hpp:237
virtual void beforeSatisfyInterest(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data)
trigger before PIT entry is satisfied
Definition: strategy.cpp:152
Face * get(FaceId id) const
get face by FaceId
Definition: face-table.cpp:44
#define NFD_LOG_ERROR(expression)
Definition: logger.hpp:164
const time::nanoseconds & getLifetime() const
void add(const Name &name, uint32_t nonce)
records name+nonce
static bool compare_InRecord_expiry(const pit::InRecord &a, const pit::InRecord &b)
Definition: forwarder.cpp:485
bool has(const Name &name, uint32_t nonce) const
determines if name+nonce exists
DropAllUnsolicitedDataPolicy DefaultUnsolicitedDataPolicy
the default UnsolicitedDataPolicy
Table::const_iterator iterator
Definition: cs-internal.hpp:41
in-record of same face
Definition: algorithm.hpp:93
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:163
an Interest table entry
Definition: pit-entry.hpp:57
static void insertNonceToDnl(DeadNonceList &dnl, const pit::Entry &pitEntry, const pit::OutRecord &outRecord)
Definition: forwarder.cpp:526
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
Definition: algorithm.hpp:32
contains information about an Interest from an incoming face
virtual void afterReceiveNack(const Face &inFace, const lp::Nack &nack, const shared_ptr< pit::Entry > &pitEntry)
trigger after Nack is received
Definition: strategy.cpp:166
signal::Signal< FaceTable, Face & > beforeRemove
fires before a face is removed
Definition: face-table.hpp:90
void startProcessInterest(Face &face, const Interest &interest)
start incoming Interest processing
Definition: forwarder.hpp:112
represents the Dead Nonce list
signal::Signal< FaceTable, Face & > afterAdd
fires after a face is added
Definition: face-table.hpp:84
bool hasPendingOutRecords(const pit::Entry &pitEntry)
determine whether pitEntry has any pending out-records
Definition: algorithm.cpp:113
const Interest & getInterest() const
Definition: pit-entry.hpp:69
const Name LOCALHOST
ndn:/localhost
no duplicate Nonce is found
Definition: algorithm.hpp:92
int findDuplicateNonce(const pit::Entry &pitEntry, uint32_t nonce, const Face &face)
determine whether pitEntry has duplicate Nonce nonce
Definition: algorithm.cpp:83
std::list< OutRecord > OutRecordCollection
an unordered collection of out-records
Definition: pit-entry.hpp:47
static Name getDefaultStrategyName()
Definition: forwarder.cpp:39
represents a forwarding strategy
Definition: strategy.hpp:37
This file contains common algorithms used by forwarding strategies.
#define NFD_LOG_INIT(name)
Definition: logger.hpp:122
UnsolicitedDataDecision
a decision made by UnsolicitedDataPolicy
EventId schedule(time::nanoseconds after, const EventCallback &event)
schedule an event
Definition: scheduler.cpp:47
the Data should be cached in the ContentStore
bool isInProducerRegion(const DelegationList &forwardingHint) const
determines whether an Interest has reached a producer region
uint32_t getLastNonce() const
virtual void beforeExpirePendingInterest(const shared_ptr< pit::Entry > &pitEntry)
trigger before PIT entry expires
Definition: strategy.cpp:160
const OutRecordCollection & getOutRecords() const
Definition: pit-entry.hpp:159
void startProcessData(Face &face, const Data &data)
start incoming Data processing
Definition: forwarder.hpp:122
const FaceId FACEID_CONTENT_STORE
identifies a packet comes from the ContentStore
Definition: face.hpp:46
std::vector< shared_ptr< Entry > > DataMatchResult
Definition: pit.hpp:42
const FaceId INVALID_FACEID
indicates an invalid FaceId
Definition: face.hpp:42
const Name & getName() const
Definition: pit-entry.hpp:77
void startProcessNack(Face &face, const lp::Nack &nack)
start incoming Nack processing
Definition: forwarder.hpp:132