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-2018, 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  face.onDroppedInterest.connect(
65  [this, &face] (const Interest& interest) {
66  this->onDroppedInterest(face, interest);
67  });
68  });
69 
70  m_faceTable.beforeRemove.connect([this] (Face& face) {
71  cleanupOnFaceRemoval(m_nameTree, m_fib, m_pit, face);
72  });
73 
74  m_strategyChoice.setDefaultStrategy(getDefaultStrategyName());
75 }
76 
77 Forwarder::~Forwarder() = default;
78 
79 void
80 Forwarder::onIncomingInterest(Face& inFace, const Interest& interest)
81 {
82  // receive Interest
83  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
84  " interest=" << interest.getName());
85  interest.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
86  ++m_counters.nInInterests;
87 
88  // /localhost scope control
89  bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
90  scope_prefix::LOCALHOST.isPrefixOf(interest.getName());
91  if (isViolatingLocalhost) {
92  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
93  " interest=" << interest.getName() << " violates /localhost");
94  // (drop)
95  return;
96  }
97 
98  // detect duplicate Nonce with Dead Nonce List
99  bool hasDuplicateNonceInDnl = m_deadNonceList.has(interest.getName(), interest.getNonce());
100  if (hasDuplicateNonceInDnl) {
101  // goto Interest loop pipeline
102  this->onInterestLoop(inFace, interest);
103  return;
104  }
105 
106  // strip forwarding hint if Interest has reached producer region
107  if (!interest.getForwardingHint().empty() &&
108  m_networkRegionTable.isInProducerRegion(interest.getForwardingHint())) {
109  NFD_LOG_DEBUG("onIncomingInterest face=" << inFace.getId() <<
110  " interest=" << interest.getName() << " reaching-producer-region");
111  const_cast<Interest&>(interest).setForwardingHint({});
112  }
113 
114  // PIT insert
115  shared_ptr<pit::Entry> pitEntry = m_pit.insert(interest).first;
116 
117  // detect duplicate Nonce in PIT entry
118  int dnw = fw::findDuplicateNonce(*pitEntry, interest.getNonce(), inFace);
119  bool hasDuplicateNonceInPit = dnw != fw::DUPLICATE_NONCE_NONE;
120  if (inFace.getLinkType() == ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
121  // for p2p face: duplicate Nonce from same incoming face is not loop
122  hasDuplicateNonceInPit = hasDuplicateNonceInPit && !(dnw & fw::DUPLICATE_NONCE_IN_SAME);
123  }
124  if (hasDuplicateNonceInPit) {
125  // goto Interest loop pipeline
126  this->onInterestLoop(inFace, interest);
127  return;
128  }
129 
130  // is pending?
131  if (!pitEntry->hasInRecords()) {
132  m_cs.find(interest,
133  bind(&Forwarder::onContentStoreHit, this, ref(inFace), pitEntry, _1, _2),
134  bind(&Forwarder::onContentStoreMiss, this, ref(inFace), pitEntry, _1));
135  }
136  else {
137  this->onContentStoreMiss(inFace, pitEntry, interest);
138  }
139 }
140 
141 void
142 Forwarder::onInterestLoop(Face& inFace, const Interest& interest)
143 {
144  // if multi-access or ad hoc face, drop
145  if (inFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
146  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
147  " interest=" << interest.getName() <<
148  " drop");
149  return;
150  }
151 
152  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
153  " interest=" << interest.getName() <<
154  " send-Nack-duplicate");
155 
156  // send Nack with reason=DUPLICATE
157  // note: Don't enter outgoing Nack pipeline because it needs an in-record.
158  lp::Nack nack(interest);
159  nack.setReason(lp::NackReason::DUPLICATE);
160  inFace.sendNack(nack);
161 }
162 
163 static inline bool
165 {
166  return a.getExpiry() < b.getExpiry();
167 }
168 
169 void
170 Forwarder::onContentStoreMiss(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
171  const Interest& interest)
172 {
173  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName());
174  ++m_counters.nCsMisses;
175 
176  // insert in-record
177  pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
178 
179  // set PIT expiry timer to the time that the last PIT in-record expires
180  auto lastExpiring = std::max_element(pitEntry->in_begin(), pitEntry->in_end(), &compare_InRecord_expiry);
181  auto lastExpiryFromNow = lastExpiring->getExpiry() - time::steady_clock::now();
182  this->setExpiryTimer(pitEntry, time::duration_cast<time::milliseconds>(lastExpiryFromNow));
183 
184  // has NextHopFaceId?
185  shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
186  if (nextHopTag != nullptr) {
187  // chosen NextHop face exists?
188  Face* nextHopFace = m_faceTable.get(*nextHopTag);
189  if (nextHopFace != nullptr) {
190  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName() << " nexthop-faceid=" << nextHopFace->getId());
191  // go to outgoing Interest pipeline
192  // scope control is unnecessary, because privileged app explicitly wants to forward
193  this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
194  }
195  return;
196  }
197 
198  // dispatch to strategy: after incoming Interest
199  this->dispatchToStrategy(*pitEntry,
200  [&] (fw::Strategy& strategy) { strategy.afterReceiveInterest(inFace, interest, pitEntry); });
201 }
202 
203 void
204 Forwarder::onContentStoreHit(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
205  const Interest& interest, const Data& data)
206 {
207  NFD_LOG_DEBUG("onContentStoreHit interest=" << interest.getName());
208  ++m_counters.nCsHits;
209 
210  data.setTag(make_shared<lp::IncomingFaceIdTag>(face::FACEID_CONTENT_STORE));
211  // XXX should we lookup PIT for other Interests that also match csMatch?
212 
213  pitEntry->isSatisfied = true;
214  pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
215 
216  // set PIT expiry timer to now
217  this->setExpiryTimer(pitEntry, 0_ms);
218 
219  // dispatch to strategy: after Content Store hit
220  this->dispatchToStrategy(*pitEntry,
221  [&] (fw::Strategy& strategy) { strategy.afterContentStoreHit(pitEntry, inFace, data); });
222 }
223 
224 void
225 Forwarder::onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outFace, const Interest& interest)
226 {
227  NFD_LOG_DEBUG("onOutgoingInterest face=" << outFace.getId() <<
228  " interest=" << pitEntry->getName());
229 
230  // insert out-record
231  pitEntry->insertOrUpdateOutRecord(outFace, interest);
232 
233  // send Interest
234  outFace.sendInterest(interest);
235  ++m_counters.nOutInterests;
236 }
237 
238 void
239 Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry)
240 {
241  NFD_LOG_DEBUG("onInterestFinalize interest=" << pitEntry->getName() <<
242  (pitEntry->isSatisfied ? " satisfied" : " unsatisfied"));
243 
244  // Dead Nonce List insert if necessary
245  this->insertDeadNonceList(*pitEntry, 0);
246 
247  // PIT delete
248  scheduler::cancel(pitEntry->expiryTimer);
249  m_pit.erase(pitEntry.get());
250 }
251 
252 void
253 Forwarder::onIncomingData(Face& inFace, const Data& data)
254 {
255  // receive Data
256  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() << " data=" << data.getName());
257  data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
258  ++m_counters.nInData;
259 
260  // /localhost scope control
261  bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
262  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
263  if (isViolatingLocalhost) {
264  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() <<
265  " data=" << data.getName() << " violates /localhost");
266  // (drop)
267  return;
268  }
269 
270  // PIT match
271  pit::DataMatchResult pitMatches = m_pit.findAllDataMatches(data);
272  if (pitMatches.size() == 0) {
273  // goto Data unsolicited pipeline
274  this->onDataUnsolicited(inFace, data);
275  return;
276  }
277 
278  // CS insert
279  m_cs.insert(data);
280 
281  // when only one PIT entry is matched, trigger strategy: after receive Data
282  if (pitMatches.size() == 1) {
283  auto& pitEntry = pitMatches.front();
284 
285  NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
286 
287  // set PIT expiry timer to now
288  this->setExpiryTimer(pitEntry, 0_ms);
289 
290  // trigger strategy: after receive Data
291  this->dispatchToStrategy(*pitEntry,
292  [&] (fw::Strategy& strategy) { strategy.afterReceiveData(pitEntry, inFace, data); });
293 
294  // mark PIT satisfied
295  pitEntry->isSatisfied = true;
296  pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
297 
298  // Dead Nonce List insert if necessary (for out-record of inFace)
299  this->insertDeadNonceList(*pitEntry, &inFace);
300 
301  // delete PIT entry's out-record
302  pitEntry->deleteOutRecord(inFace);
303  }
304  // when more than one PIT entry is matched, trigger strategy: before satisfy Interest,
305  // and send Data to all matched out faces
306  else {
307  std::set<Face*> pendingDownstreams;
308  auto now = time::steady_clock::now();
309 
310  for (const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
311  NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
312 
313  // remember pending downstreams
314  for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
315  if (inRecord.getExpiry() > now) {
316  pendingDownstreams.insert(&inRecord.getFace());
317  }
318  }
319 
320  // set PIT expiry timer to now
321  this->setExpiryTimer(pitEntry, 0_ms);
322 
323  // invoke PIT satisfy callback
324  this->dispatchToStrategy(*pitEntry,
325  [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
326 
327  // mark PIT satisfied
328  pitEntry->isSatisfied = true;
329  pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
330 
331  // Dead Nonce List insert if necessary (for out-record of inFace)
332  this->insertDeadNonceList(*pitEntry, &inFace);
333 
334  // clear PIT entry's in and out records
335  pitEntry->clearInRecords();
336  pitEntry->deleteOutRecord(inFace);
337  }
338 
339  // foreach pending downstream
340  for (Face* pendingDownstream : pendingDownstreams) {
341  if (pendingDownstream->getId() == inFace.getId() &&
342  pendingDownstream->getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
343  continue;
344  }
345  // goto outgoing Data pipeline
346  this->onOutgoingData(data, *pendingDownstream);
347  }
348  }
349 }
350 
351 void
352 Forwarder::onDataUnsolicited(Face& inFace, const Data& data)
353 {
354  // accept to cache?
355  fw::UnsolicitedDataDecision decision = m_unsolicitedDataPolicy->decide(inFace, data);
356  if (decision == fw::UnsolicitedDataDecision::CACHE) {
357  // CS insert
358  m_cs.insert(data, true);
359  }
360 
361  NFD_LOG_DEBUG("onDataUnsolicited face=" << inFace.getId() <<
362  " data=" << data.getName() <<
363  " decision=" << decision);
364 }
365 
366 void
367 Forwarder::onOutgoingData(const Data& data, Face& outFace)
368 {
369  if (outFace.getId() == face::INVALID_FACEID) {
370  NFD_LOG_WARN("onOutgoingData face=invalid data=" << data.getName());
371  return;
372  }
373  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() << " data=" << data.getName());
374 
375  // /localhost scope control
376  bool isViolatingLocalhost = outFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
377  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
378  if (isViolatingLocalhost) {
379  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() <<
380  " data=" << data.getName() << " violates /localhost");
381  // (drop)
382  return;
383  }
384 
385  // TODO traffic manager
386 
387  // send Data
388  outFace.sendData(data);
389  ++m_counters.nOutData;
390 }
391 
392 void
393 Forwarder::onIncomingNack(Face& inFace, const lp::Nack& nack)
394 {
395  // receive Nack
396  nack.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
397  ++m_counters.nInNacks;
398 
399  // if multi-access or ad hoc face, drop
400  if (inFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
401  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
402  " nack=" << nack.getInterest().getName() <<
403  "~" << nack.getReason() << " face-is-multi-access");
404  return;
405  }
406 
407  // PIT match
408  shared_ptr<pit::Entry> pitEntry = m_pit.find(nack.getInterest());
409  // if no PIT entry found, drop
410  if (pitEntry == nullptr) {
411  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
412  " nack=" << nack.getInterest().getName() <<
413  "~" << nack.getReason() << " no-PIT-entry");
414  return;
415  }
416 
417  // has out-record?
418  pit::OutRecordCollection::iterator outRecord = pitEntry->getOutRecord(inFace);
419  // if no out-record found, drop
420  if (outRecord == pitEntry->out_end()) {
421  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
422  " nack=" << nack.getInterest().getName() <<
423  "~" << nack.getReason() << " no-out-record");
424  return;
425  }
426 
427  // if out-record has different Nonce, drop
428  if (nack.getInterest().getNonce() != outRecord->getLastNonce()) {
429  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
430  " nack=" << nack.getInterest().getName() <<
431  "~" << nack.getReason() << " wrong-Nonce " <<
432  nack.getInterest().getNonce() << "!=" << outRecord->getLastNonce());
433  return;
434  }
435 
436  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
437  " nack=" << nack.getInterest().getName() <<
438  "~" << nack.getReason() << " OK");
439 
440  // record Nack on out-record
441  outRecord->setIncomingNack(nack);
442 
443  // set PIT expiry timer to now when all out-record receive Nack
444  if (!fw::hasPendingOutRecords(*pitEntry)) {
445  this->setExpiryTimer(pitEntry, 0_ms);
446  }
447 
448  // trigger strategy: after receive NACK
449  this->dispatchToStrategy(*pitEntry,
450  [&] (fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
451 }
452 
453 void
454 Forwarder::onOutgoingNack(const shared_ptr<pit::Entry>& pitEntry, const Face& outFace,
455  const lp::NackHeader& nack)
456 {
457  if (outFace.getId() == face::INVALID_FACEID) {
458  NFD_LOG_WARN("onOutgoingNack face=invalid" <<
459  " nack=" << pitEntry->getInterest().getName() <<
460  "~" << nack.getReason() << " no-in-record");
461  return;
462  }
463 
464  // has in-record?
465  pit::InRecordCollection::iterator inRecord = pitEntry->getInRecord(outFace);
466 
467  // if no in-record found, drop
468  if (inRecord == pitEntry->in_end()) {
469  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
470  " nack=" << pitEntry->getInterest().getName() <<
471  "~" << nack.getReason() << " no-in-record");
472  return;
473  }
474 
475  // if multi-access or ad hoc face, drop
476  if (outFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
477  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
478  " nack=" << pitEntry->getInterest().getName() <<
479  "~" << nack.getReason() << " face-is-multi-access");
480  return;
481  }
482 
483  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
484  " nack=" << pitEntry->getInterest().getName() <<
485  "~" << nack.getReason() << " OK");
486 
487  // create Nack packet with the Interest from in-record
488  lp::Nack nackPkt(inRecord->getInterest());
489  nackPkt.setHeader(nack);
490 
491  // erase in-record
492  pitEntry->deleteInRecord(outFace);
493 
494  // send Nack on face
495  const_cast<Face&>(outFace).sendNack(nackPkt);
496  ++m_counters.nOutNacks;
497 }
498 
499 void
500 Forwarder::onDroppedInterest(Face& outFace, const Interest& interest)
501 {
502  m_strategyChoice.findEffectiveStrategy(interest.getName()).onDroppedInterest(outFace, interest);
503 }
504 
505 void
506 Forwarder::setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
507 {
508  BOOST_ASSERT(duration >= 0_ms);
509 
510  scheduler::cancel(pitEntry->expiryTimer);
511 
512  pitEntry->expiryTimer = scheduler::schedule(duration,
513  bind(&Forwarder::onInterestFinalize, this, pitEntry));
514 }
515 
516 static inline void
518  const pit::OutRecord& outRecord)
519 {
520  dnl.add(pitEntry.getName(), outRecord.getLastNonce());
521 }
522 
523 void
524 Forwarder::insertDeadNonceList(pit::Entry& pitEntry, Face* upstream)
525 {
526  // need Dead Nonce List insert?
527  bool needDnl = true;
528  if (pitEntry.isSatisfied) {
529  BOOST_ASSERT(pitEntry.dataFreshnessPeriod >= 0_ms);
530  needDnl = static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
531  pitEntry.dataFreshnessPeriod < m_deadNonceList.getLifetime();
532  }
533 
534  if (!needDnl) {
535  return;
536  }
537 
538  // Dead Nonce List insert
539  if (upstream == nullptr) {
540  // insert all outgoing Nonces
541  const pit::OutRecordCollection& outRecords = pitEntry.getOutRecords();
542  std::for_each(outRecords.begin(), outRecords.end(),
543  bind(&insertNonceToDnl, ref(m_deadNonceList), cref(pitEntry), _1));
544  }
545  else {
546  // insert outgoing Nonce of a specific face
547  pit::OutRecordCollection::iterator outRecord = pitEntry.getOutRecord(*upstream);
548  if (outRecord != pitEntry.getOutRecords().end()) {
549  m_deadNonceList.add(pitEntry.getName(), outRecord->getLastNonce());
550  }
551  }
552 }
553 
554 } // namespace nfd
bool isSatisfied
indicate if PIT entry is satisfied
Definition: pit-entry.hpp:226
OutRecordCollection::iterator getOutRecord(const Face &face)
get the out-record for face
Definition: pit-entry.cpp:92
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
virtual void afterReceiveData(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data)
trigger after Data is received
Definition: strategy.cpp:170
static const Name & getStrategyName()
time::steady_clock::TimePoint getExpiry() const
gives the time point this record expires
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:45
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:164
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:517
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:182
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
virtual void afterContentStoreHit(const shared_ptr< pit::Entry > &pitEntry, const Face &inFace, const Data &data)
trigger after a Data is matched in CS
Definition: strategy.cpp:160
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
An unordered iterable of all PIT entries matching Data.
time::milliseconds dataFreshnessPeriod
Data freshness period.
Definition: pit-entry.hpp:231
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
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