NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
forwarder.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "forwarder.hpp"
27 #include "algorithm.hpp"
28 #include "core/logger.hpp"
29 #include "strategy.hpp"
30 #include "table/cleanup.hpp"
31 #include <ndn-cxx/lp/tags.hpp>
32 #include "face/null-face.hpp"
33 #include <boost/random/uniform_int_distribution.hpp>
34 
35 namespace nfd {
36 
37 NFD_LOG_INIT("Forwarder");
38 
40  : m_unsolicitedDataPolicy(new fw::DefaultUnsolicitedDataPolicy())
41  , m_fib(m_nameTree)
42  , m_pit(m_nameTree)
43  , m_measurements(m_nameTree)
44  , m_strategyChoice(m_nameTree, fw::makeDefaultStrategy(*this))
45  , m_csFace(face::makeNullFace(FaceUri("contentstore://")))
46 {
47  fw::installStrategies(*this);
49 
50  m_faceTable.afterAdd.connect([this] (Face& face) {
51  face.afterReceiveInterest.connect(
52  [this, &face] (const Interest& interest) {
53  this->startProcessInterest(face, interest);
54  });
55  face.afterReceiveData.connect(
56  [this, &face] (const Data& data) {
57  this->startProcessData(face, data);
58  });
59  face.afterReceiveNack.connect(
60  [this, &face] (const lp::Nack& nack) {
61  this->startProcessNack(face, nack);
62  });
63  });
64 
65  m_faceTable.beforeRemove.connect([this] (Face& face) {
66  cleanupOnFaceRemoval(m_nameTree, m_fib, m_pit, face);
67  });
68 }
69 
70 Forwarder::~Forwarder() = default;
71 
72 void
74 {
75  // check fields used by forwarding are well-formed
76  try {
77  if (interest.hasLink()) {
78  interest.getLink();
79  }
80  }
81  catch (const tlv::Error&) {
82  NFD_LOG_DEBUG("startProcessInterest face=" << face.getId() <<
83  " interest=" << interest.getName() << " malformed");
84  // It's safe to call interest.getName() because Name has been fully parsed
85  return;
86  }
87 
88  this->onIncomingInterest(face, interest);
89 }
90 
91 void
93 {
94  // check fields used by forwarding are well-formed
95  // (none needed)
96 
97  this->onIncomingData(face, data);
98 }
99 
100 void
102 {
103  // check fields used by forwarding are well-formed
104  try {
105  if (nack.getInterest().hasLink()) {
106  nack.getInterest().getLink();
107  }
108  }
109  catch (const tlv::Error&) {
110  NFD_LOG_DEBUG("startProcessNack face=" << face.getId() <<
111  " nack=" << nack.getInterest().getName() <<
112  "~" << nack.getReason() << " malformed");
113  return;
114  }
115 
116  this->onIncomingNack(face, nack);
117 }
118 
119 void
120 Forwarder::onIncomingInterest(Face& inFace, const Interest& interest)
121 {
122  // receive Interest
123  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
124  " interest=" << interest.getName());
125  interest.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
126  ++m_counters.nInInterests;
127 
128  // /localhost scope control
129  bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
131  if (isViolatingLocalhost) {
132  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
133  " interest=" << interest.getName() << " violates /localhost");
134  // (drop)
135  return;
136  }
137 
138  // detect duplicate Nonce with Dead Nonce List
139  bool hasDuplicateNonceInDnl = m_deadNonceList.has(interest.getName(), interest.getNonce());
140  if (hasDuplicateNonceInDnl) {
141  // goto Interest loop pipeline
142  this->onInterestLoop(inFace, interest);
143  return;
144  }
145 
146  // PIT insert
147  shared_ptr<pit::Entry> pitEntry = m_pit.insert(interest).first;
148 
149  // detect duplicate Nonce in PIT entry
150  bool hasDuplicateNonceInPit = fw::findDuplicateNonce(*pitEntry, interest.getNonce(), inFace) !=
152  if (hasDuplicateNonceInPit) {
153  // goto Interest loop pipeline
154  this->onInterestLoop(inFace, interest);
155  return;
156  }
157 
158  // cancel unsatisfy & straggler timer
159  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
160 
161  const pit::InRecordCollection& inRecords = pitEntry->getInRecords();
162  bool isPending = inRecords.begin() != inRecords.end();
163  if (!isPending) {
164  if (m_csFromNdnSim == nullptr) {
165  m_cs.find(interest,
166  bind(&Forwarder::onContentStoreHit, this, ref(inFace), pitEntry, _1, _2),
167  bind(&Forwarder::onContentStoreMiss, this, ref(inFace), pitEntry, _1));
168  }
169  else {
170  shared_ptr<Data> match = m_csFromNdnSim->Lookup(interest.shared_from_this());
171  if (match != nullptr) {
172  this->onContentStoreHit(inFace, pitEntry, interest, *match);
173  }
174  else {
175  this->onContentStoreMiss(inFace, pitEntry, interest);
176  }
177  }
178  }
179  else {
180  this->onContentStoreMiss(inFace, pitEntry, interest);
181  }
182 }
183 
184 void
185 Forwarder::onInterestLoop(Face& inFace, const Interest& interest)
186 {
187  // if multi-access face, drop
189  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
190  " interest=" << interest.getName() <<
191  " drop");
192  return;
193  }
194 
195  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
196  " interest=" << interest.getName() <<
197  " send-Nack-duplicate");
198 
199  // send Nack with reason=DUPLICATE
200  // note: Don't enter outgoing Nack pipeline because it needs an in-record.
201  lp::Nack nack(interest);
202  nack.setReason(lp::NackReason::DUPLICATE);
203  inFace.sendNack(nack);
204 }
205 
206 void
207 Forwarder::onContentStoreMiss(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
208  const Interest& interest)
209 {
210  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName());
211 
212  // insert in-record
213  pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
214 
215  // set PIT unsatisfy timer
216  this->setUnsatisfyTimer(pitEntry);
217 
218  // has NextHopFaceId?
219  shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
220  if (nextHopTag != nullptr) {
221  // chosen NextHop face exists?
222  Face* nextHopFace = m_faceTable.get(*nextHopTag);
223  if (nextHopFace != nullptr) {
224  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName() << " nexthop-faceid=" << nextHopFace->getId());
225  // go to outgoing Interest pipeline
226  // scope control is unnecessary, because privileged app explicitly wants to forward
227  this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
228  }
229  return;
230  }
231 
232  // dispatch to strategy: after incoming Interest
233  this->dispatchToStrategy(*pitEntry,
234  [&] (fw::Strategy& strategy) { strategy.afterReceiveInterest(inFace, interest, pitEntry); });
235 }
236 
237 void
238 Forwarder::onContentStoreHit(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
239  const Interest& interest, const Data& data)
240 {
241  NFD_LOG_DEBUG("onContentStoreHit interest=" << interest.getName());
242 
243  beforeSatisfyInterest(*pitEntry, *m_csFace, data);
244  this->dispatchToStrategy(*pitEntry,
245  [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, *m_csFace, data); });
246 
247  data.setTag(make_shared<lp::IncomingFaceIdTag>(face::FACEID_CONTENT_STORE));
248  // XXX should we lookup PIT for other Interests that also match csMatch?
249 
250  // set PIT straggler timer
251  this->setStragglerTimer(pitEntry, true, data.getFreshnessPeriod());
252 
253  // goto outgoing Data pipeline
254  this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
255 }
256 
257 void
258 Forwarder::onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outFace, const Interest& interest)
259 {
260  NFD_LOG_DEBUG("onOutgoingInterest face=" << outFace.getId() <<
261  " interest=" << pitEntry->getName());
262 
263  // insert out-record
264  pitEntry->insertOrUpdateOutRecord(outFace, interest);
265 
266  // send Interest
267  outFace.sendInterest(interest);
268  ++m_counters.nOutInterests;
269 }
270 
271 void
272 Forwarder::onInterestReject(const shared_ptr<pit::Entry>& pitEntry)
273 {
274  if (fw::hasPendingOutRecords(*pitEntry)) {
275  NFD_LOG_ERROR("onInterestReject interest=" << pitEntry->getName() <<
276  " cannot reject forwarded Interest");
277  return;
278  }
279  NFD_LOG_DEBUG("onInterestReject interest=" << pitEntry->getName());
280 
281  // cancel unsatisfy & straggler timer
282  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
283 
284  // set PIT straggler timer
285  this->setStragglerTimer(pitEntry, false);
286 }
287 
288 void
289 Forwarder::onInterestUnsatisfied(const shared_ptr<pit::Entry>& pitEntry)
290 {
291  NFD_LOG_DEBUG("onInterestUnsatisfied interest=" << pitEntry->getName());
292 
293  // invoke PIT unsatisfied callback
294  beforeExpirePendingInterest(*pitEntry);
295  this->dispatchToStrategy(*pitEntry,
296  [&] (fw::Strategy& strategy) { strategy.beforeExpirePendingInterest(pitEntry); });
297 
298  // goto Interest Finalize pipeline
299  this->onInterestFinalize(pitEntry, false);
300 }
301 
302 void
303 Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
304  time::milliseconds dataFreshnessPeriod)
305 {
306  NFD_LOG_DEBUG("onInterestFinalize interest=" << pitEntry->getName() <<
307  (isSatisfied ? " satisfied" : " unsatisfied"));
308 
309  // Dead Nonce List insert if necessary
310  this->insertDeadNonceList(*pitEntry, isSatisfied, dataFreshnessPeriod, 0);
311 
312  // PIT delete
313  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
314  m_pit.erase(pitEntry.get());
315 }
316 
317 void
318 Forwarder::onIncomingData(Face& inFace, const Data& data)
319 {
320  // receive Data
321  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() << " data=" << data.getName());
322  data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
323  ++m_counters.nInData;
324 
325  // /localhost scope control
326  bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
328  if (isViolatingLocalhost) {
329  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() <<
330  " data=" << data.getName() << " violates /localhost");
331  // (drop)
332  return;
333  }
334 
335  // PIT match
336  pit::DataMatchResult pitMatches = m_pit.findAllDataMatches(data);
337  if (pitMatches.begin() == pitMatches.end()) {
338  // goto Data unsolicited pipeline
339  this->onDataUnsolicited(inFace, data);
340  return;
341  }
342 
343  shared_ptr<Data> dataCopyWithoutTag = make_shared<Data>(data);
344  dataCopyWithoutTag->removeTag<lp::HopCountTag>();
345 
346  // CS insert
347  if (m_csFromNdnSim == nullptr)
348  m_cs.insert(*dataCopyWithoutTag);
349  else
350  m_csFromNdnSim->Add(dataCopyWithoutTag);
351 
352  std::set<Face*> pendingDownstreams;
353  // foreach PitEntry
354  auto now = time::steady_clock::now();
355  for (const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
356  NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
357 
358  // cancel unsatisfy & straggler timer
359  this->cancelUnsatisfyAndStragglerTimer(*pitEntry);
360 
361  // remember pending downstreams
362  for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
363  if (inRecord.getExpiry() > now) {
364  pendingDownstreams.insert(&inRecord.getFace());
365  }
366  }
367 
368  // invoke PIT satisfy callback
369  beforeSatisfyInterest(*pitEntry, inFace, data);
370  this->dispatchToStrategy(*pitEntry,
371  [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
372 
373  // Dead Nonce List insert if necessary (for out-record of inFace)
374  this->insertDeadNonceList(*pitEntry, true, data.getFreshnessPeriod(), &inFace);
375 
376  // mark PIT satisfied
377  pitEntry->clearInRecords();
378  pitEntry->deleteOutRecord(inFace);
379 
380  // set PIT straggler timer
381  this->setStragglerTimer(pitEntry, true, data.getFreshnessPeriod());
382  }
383 
384  // foreach pending downstream
385  for (Face* pendingDownstream : pendingDownstreams) {
386  if (pendingDownstream == &inFace) {
387  continue;
388  }
389  // goto outgoing Data pipeline
390  this->onOutgoingData(data, *pendingDownstream);
391  }
392 }
393 
394 void
395 Forwarder::onDataUnsolicited(Face& inFace, const Data& data)
396 {
397  // accept to cache?
398  fw::UnsolicitedDataDecision decision = m_unsolicitedDataPolicy->decide(inFace, data);
399  if (decision == fw::UnsolicitedDataDecision::CACHE) {
400  // CS insert
401  if (m_csFromNdnSim == nullptr)
402  m_cs.insert(data, true);
403  else
404  m_csFromNdnSim->Add(data.shared_from_this());
405  }
406 
407  NFD_LOG_DEBUG("onDataUnsolicited face=" << inFace.getId() <<
408  " data=" << data.getName() <<
409  " decision=" << decision);
410 }
411 
412 void
413 Forwarder::onOutgoingData(const Data& data, Face& outFace)
414 {
415  if (outFace.getId() == face::INVALID_FACEID) {
416  NFD_LOG_WARN("onOutgoingData face=invalid data=" << data.getName());
417  return;
418  }
419  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() << " data=" << data.getName());
420 
421  // /localhost scope control
422  bool isViolatingLocalhost = outFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
424  if (isViolatingLocalhost) {
425  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() <<
426  " data=" << data.getName() << " violates /localhost");
427  // (drop)
428  return;
429  }
430 
431  // TODO traffic manager
432 
433  // send Data
434  outFace.sendData(data);
435  ++m_counters.nOutData;
436 }
437 
438 void
439 Forwarder::onIncomingNack(Face& inFace, const lp::Nack& nack)
440 {
441  // receive Nack
442  nack.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
443  ++m_counters.nInNacks;
444 
445  // if multi-access face, drop
447  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
448  " nack=" << nack.getInterest().getName() <<
449  "~" << nack.getReason() << " face-is-multi-access");
450  return;
451  }
452 
453  // PIT match
454  shared_ptr<pit::Entry> pitEntry = m_pit.find(nack.getInterest());
455  // if no PIT entry found, drop
456  if (pitEntry == nullptr) {
457  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
458  " nack=" << nack.getInterest().getName() <<
459  "~" << nack.getReason() << " no-PIT-entry");
460  return;
461  }
462 
463  // has out-record?
464  pit::OutRecordCollection::iterator outRecord = pitEntry->getOutRecord(inFace);
465  // if no out-record found, drop
466  if (outRecord == pitEntry->out_end()) {
467  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
468  " nack=" << nack.getInterest().getName() <<
469  "~" << nack.getReason() << " no-out-record");
470  return;
471  }
472 
473  // if out-record has different Nonce, drop
474  if (nack.getInterest().getNonce() != outRecord->getLastNonce()) {
475  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
476  " nack=" << nack.getInterest().getName() <<
477  "~" << nack.getReason() << " wrong-Nonce " <<
478  nack.getInterest().getNonce() << "!=" << outRecord->getLastNonce());
479  return;
480  }
481 
482  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
483  " nack=" << nack.getInterest().getName() <<
484  "~" << nack.getReason() << " OK");
485 
486  // record Nack on out-record
487  outRecord->setIncomingNack(nack);
488 
489  // trigger strategy: after receive NACK
490  this->dispatchToStrategy(*pitEntry,
491  [&] (fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
492 }
493 
494 void
495 Forwarder::onOutgoingNack(const shared_ptr<pit::Entry>& pitEntry, const Face& outFace,
496  const lp::NackHeader& nack)
497 {
498  if (outFace.getId() == face::INVALID_FACEID) {
499  NFD_LOG_WARN("onOutgoingNack face=invalid" <<
500  " nack=" << pitEntry->getInterest().getName() <<
501  "~" << nack.getReason() << " no-in-record");
502  return;
503  }
504 
505  // has in-record?
506  pit::InRecordCollection::iterator inRecord = pitEntry->getInRecord(outFace);
507 
508  // if no in-record found, drop
509  if (inRecord == pitEntry->in_end()) {
510  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
511  " nack=" << pitEntry->getInterest().getName() <<
512  "~" << nack.getReason() << " no-in-record");
513  return;
514  }
515 
516  // if multi-access face, drop
518  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
519  " nack=" << pitEntry->getInterest().getName() <<
520  "~" << nack.getReason() << " face-is-multi-access");
521  return;
522  }
523 
524  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
525  " nack=" << pitEntry->getInterest().getName() <<
526  "~" << nack.getReason() << " OK");
527 
528  // create Nack packet with the Interest from in-record
529  lp::Nack nackPkt(inRecord->getInterest());
530  nackPkt.setHeader(nack);
531 
532  // erase in-record
533  pitEntry->deleteInRecord(outFace);
534 
535  // send Nack on face
536  const_cast<Face&>(outFace).sendNack(nackPkt);
537  ++m_counters.nOutNacks;
538 }
539 
540 static inline bool
542 {
543  return a.getExpiry() < b.getExpiry();
544 }
545 
546 void
547 Forwarder::setUnsatisfyTimer(const shared_ptr<pit::Entry>& pitEntry)
548 {
549  pit::InRecordCollection::iterator lastExpiring =
550  std::max_element(pitEntry->in_begin(), pitEntry->in_end(), &compare_InRecord_expiry);
551 
552  time::steady_clock::TimePoint lastExpiry = lastExpiring->getExpiry();
553  time::nanoseconds lastExpiryFromNow = lastExpiry - time::steady_clock::now();
554  if (lastExpiryFromNow <= time::seconds::zero()) {
555  // TODO all in-records are already expired; will this happen?
556  }
557 
558  scheduler::cancel(pitEntry->m_unsatisfyTimer);
559  pitEntry->m_unsatisfyTimer = scheduler::schedule(lastExpiryFromNow,
560  bind(&Forwarder::onInterestUnsatisfied, this, pitEntry));
561 }
562 
563 void
564 Forwarder::setStragglerTimer(const shared_ptr<pit::Entry>& pitEntry, bool isSatisfied,
565  time::milliseconds dataFreshnessPeriod)
566 {
567  time::nanoseconds stragglerTime = time::milliseconds(100);
568 
569  scheduler::cancel(pitEntry->m_stragglerTimer);
570  pitEntry->m_stragglerTimer = scheduler::schedule(stragglerTime,
571  bind(&Forwarder::onInterestFinalize, this, pitEntry, isSatisfied, dataFreshnessPeriod));
572 }
573 
574 void
575 Forwarder::cancelUnsatisfyAndStragglerTimer(pit::Entry& pitEntry)
576 {
579 }
580 
581 static inline void
583  const pit::OutRecord& outRecord)
584 {
585  dnl.add(pitEntry.getName(), outRecord.getLastNonce());
586 }
587 
588 void
589 Forwarder::insertDeadNonceList(pit::Entry& pitEntry, bool isSatisfied,
590  time::milliseconds dataFreshnessPeriod, Face* upstream)
591 {
592  // need Dead Nonce List insert?
593  bool needDnl = false;
594  if (isSatisfied) {
595  bool hasFreshnessPeriod = dataFreshnessPeriod >= time::milliseconds::zero();
596  // Data never becomes stale if it doesn't have FreshnessPeriod field
597  needDnl = static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
598  (hasFreshnessPeriod && dataFreshnessPeriod < m_deadNonceList.getLifetime());
599  }
600  else {
601  needDnl = true;
602  }
603 
604  if (!needDnl) {
605  return;
606  }
607 
608  // Dead Nonce List insert
609  if (upstream == 0) {
610  // insert all outgoing Nonces
611  const pit::OutRecordCollection& outRecords = pitEntry.getOutRecords();
612  std::for_each(outRecords.begin(), outRecords.end(),
613  bind(&insertNonceToDnl, ref(m_deadNonceList), cref(pitEntry), _1));
614  }
615  else {
616  // insert outgoing Nonce of a specific face
617  pit::OutRecordCollection::iterator outRecord = pitEntry.getOutRecord(*upstream);
618  if (outRecord != pitEntry.getOutRecords().end()) {
619  m_deadNonceList.add(pitEntry.getName(), outRecord->getLastNonce());
620  }
621  }
622 }
623 
624 } // namespace nfd
signal::Signal< FaceTable, Face & > afterAdd
fires after a face is added
Definition: face-table.hpp:85
signal::Signal< Forwarder, pit::Entry, Face, Data > beforeSatisfyInterest
trigger before PIT entry is satisfied
Definition: forwarder.hpp:189
void setTag(shared_ptr< T > tag) const
set a tag item
Definition: tag-host.hpp:80
time_point TimePoint
Definition: time.hpp:120
unique_ptr< Strategy > makeDefaultStrategy(Forwarder &forwarder)
void erase(Entry *entry)
deletes an entry
Definition: pit.hpp:90
void cleanupOnFaceRemoval(NameTree &nt, Fib &fib, Pit &pit, const Face &face)
cleanup tables when a face is destroyed
Definition: cleanup.cpp:31
shared_ptr< Face > makeNullFace(const FaceUri &uri)
Definition: null-face.cpp:37
shared_ptr< T > getTag() const
get a tag item
Definition: tag-host.hpp:67
represents the Dead Nonce list
OutRecordCollection::iterator getOutRecord(const Face &face)
get the out-record for face
Definition: pit-entry.cpp:90
const Name LOCALHOST("ndn:/localhost")
ndn:/localhost
Definition: algorithm.hpp:50
const Link & getLink() const
Get the link object for this interest.
Definition: interest.cpp:370
generalization of a network interface
Definition: face.hpp:67
int getMustBeFresh() const
Definition: interest.hpp:370
void cancel(const EventId &eventId)
cancel a scheduled event
Definition: scheduler.cpp:53
void installStrategies(Forwarder &forwarder)
static time_point now() noexcept
Definition: time.cpp:79
scheduler::EventId m_stragglerTimer
straggler timer
Definition: pit-entry.hpp:237
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:44
const Name & getName() const
Get name of the Data packet.
Definition: data.hpp:318
contains information about an Interest from an incoming face
Nack & setHeader(const NackHeader &header)
Definition: nack.hpp:77
virtual void beforeExpirePendingInterest(const shared_ptr< pit::Entry > &pitEntry)
trigger before PIT entry expires
Definition: strategy.cpp:57
void startProcessInterest(Face &face, const Interest &interest)
start incoming Interest processing
Definition: forwarder.cpp:73
signal::Signal< FaceTable, Face & > beforeRemove
fires before a face is removed
Definition: face-table.hpp:91
const time::nanoseconds & getLifetime() const
represents an Interest packet
Definition: interest.hpp:42
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:55
static bool compare_InRecord_expiry(const pit::InRecord &a, const pit::InRecord &b)
Definition: forwarder.cpp:541
DataMatchResult findAllDataMatches(const Data &data) const
performs a Data match
Definition: pit.cpp:88
void sendInterest(const Interest &interest)
sends Interest on Face
Definition: face.hpp:211
void add(const Name &name, uint32_t nonce)
records name+nonce
Face * get(FaceId id) const
get face by FaceId
Definition: face-table.cpp:42
std::list< InRecord > InRecordCollection
an unordered collection of in-records
Definition: pit-entry.hpp:43
NackReason getReason() const
represents a Network Nack
Definition: nack.hpp:40
NackReason getReason() const
Definition: nack.hpp:92
DropAllUnsolicitedDataPolicy DefaultUnsolicitedDataPolicy
the default UnsolicitedDataPolicy
provides a tag type for simple types
Definition: tag.hpp:58
Table::const_iterator iterator
Definition: cs-internal.hpp:41
virtual void afterReceiveNack(const Face &inFace, const lp::Nack &nack, const shared_ptr< pit::Entry > &pitEntry)
trigger after Nack is received
Definition: strategy.cpp:63
void sendData(const Data &data)
sends Data on Face
Definition: face.hpp:217
FaceTable & getFaceTable()
Definition: forwarder.hpp:70
#define NFD_LOG_ERROR(expression)
Definition: logger.hpp:57
static void insertNonceToDnl(DeadNonceList &dnl, const pit::Entry &pitEntry, const pit::OutRecord &outRecord)
Definition: forwarder.cpp:582
void insert(const Data &data, bool isUnsolicited=false)
inserts a Data packet
Definition: cs.cpp:83
ndn::nfd::LinkType getLinkType() const
Definition: face.hpp:283
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
uint32_t getNonce() const
Get Interest&#39;s nonce.
Definition: interest.cpp:62
an Interest table entry
Definition: pit-entry.hpp:57
signal::Signal< Forwarder, pit::Entry > beforeExpirePendingInterest
trigger before PIT entry expires
Definition: forwarder.hpp:194
FaceId getId() const
Definition: face.hpp:229
std::pair< shared_ptr< Entry >, bool > insert(const Interest &interest)
inserts a PIT entry for Interest
Definition: pit.hpp:76
void startProcessData(Face &face, const Data &data)
start incoming Data processing
Definition: forwarder.cpp:92
signal::Signal< LinkService, Data > & afterReceiveData
signals on Data received
Definition: face.hpp:104
ndn::nfd::FaceScope getScope() const
Definition: face.hpp:265
virtual void beforeSatisfyInterest(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data)
trigger before PIT entry is satisfied
Definition: strategy.cpp:49
signal::Signal< LinkService, Interest > & afterReceiveInterest
signals on Interest received
Definition: face.hpp:100
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...
Definition: name.cpp:308
void find(const Interest &interest, const HitCallback &hitCallback, const MissCallback &missCallback) const
finds the best matching Data packet
Definition: cs.cpp:123
bool hasPendingOutRecords(const pit::Entry &pitEntry)
determine whether pitEntry has any pending out-records
Definition: algorithm.cpp:136
const Interest & getInterest() const
Definition: pit-entry.hpp:69
uint32_t getLastNonce() const
no duplicate Nonce is found
Definition: algorithm.hpp:100
represents a forwarding strategy
Definition: strategy.hpp:38
int findDuplicateNonce(const pit::Entry &pitEntry, uint32_t nonce, const Face &face)
determine whether pitEntry has duplicate Nonce nonce
Definition: algorithm.cpp:106
std::list< OutRecord > OutRecordCollection
an unordered collection of out-records
Definition: pit-entry.hpp:47
#define NFD_LOG_WARN(expression)
Definition: logger.hpp:58
const time::milliseconds & getFreshnessPeriod() const
Definition: data.hpp:336
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
Definition: scheduler.cpp:47
UnsolicitedDataDecision
a decision made by UnsolicitedDataPolicy
const Name & getName() const
Definition: pit-entry.hpp:77
void addReserved(shared_ptr< Face > face, FaceId faceId)
add a special face with a reserved FaceId
Definition: face-table.cpp:71
void sendNack(const lp::Nack &nack)
sends Nack on Face
Definition: face.hpp:223
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.
Definition: interest.cpp:364
signal::Signal< LinkService, lp::Nack > & afterReceiveNack
signals on Nack received
Definition: face.hpp:108
shared_ptr< Entry > find(const Interest &interest) const
finds a PIT entry for Interest
Definition: pit.hpp:65
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)
Definition: logger.hpp:34
represents a Data packet
Definition: data.hpp:37
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
represents a Network NACK header
Definition: nack-header.hpp:52
const FaceId INVALID_FACEID
indicates an invalid FaceId
Definition: face.hpp:42
void startProcessNack(Face &face, const lp::Nack &nack)
start incoming Nack processing
Definition: forwarder.cpp:101
const Interest & getInterest() const
Definition: nack.hpp:53
const OutRecordCollection & getOutRecords() const
Definition: pit-entry.hpp:159
scheduler::EventId m_unsatisfyTimer
unsatisfy timer
Definition: pit-entry.hpp:227
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50
const Name & getName() const
Definition: interest.hpp:215