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