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