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