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-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 "common/global.hpp"
32 #include "common/logger.hpp"
33 #include "table/cleanup.hpp"
34 
35 #include <ndn-cxx/lp/tags.hpp>
36 
37 #include "face/null-face.hpp"
38 
39 namespace nfd {
40 
42 
43 static Name
45 {
47 }
48 
50  : m_faceTable(faceTable)
51  , m_unsolicitedDataPolicy(make_unique<fw::DefaultUnsolicitedDataPolicy>())
52  , m_fib(m_nameTree)
53  , m_pit(m_nameTree)
54  , m_measurements(m_nameTree)
55  , m_strategyChoice(*this)
56  , m_csFace(face::makeNullFace(FaceUri("contentstore://")))
57 {
58  m_faceTable.addReserved(m_csFace, face::FACEID_CONTENT_STORE);
59 
60  m_faceTable.afterAdd.connect([this] (const Face& face) {
61  face.afterReceiveInterest.connect(
62  [this, &face] (const Interest& interest, const EndpointId& endpointId) {
63  this->startProcessInterest(FaceEndpoint(face, endpointId), interest);
64  });
65  face.afterReceiveData.connect(
66  [this, &face] (const Data& data, const EndpointId& endpointId) {
67  this->startProcessData(FaceEndpoint(face, endpointId), data);
68  });
69  face.afterReceiveNack.connect(
70  [this, &face] (const lp::Nack& nack, const EndpointId& endpointId) {
71  this->startProcessNack(FaceEndpoint(face, endpointId), nack);
72  });
73  face.onDroppedInterest.connect(
74  [this, &face] (const Interest& interest) {
75  this->onDroppedInterest(FaceEndpoint(face, 0), interest);
76  });
77  });
78 
79  m_faceTable.beforeRemove.connect([this] (const Face& face) {
80  cleanupOnFaceRemoval(m_nameTree, m_fib, m_pit, face);
81  });
82 
83  m_fib.afterNewNextHop.connect([&] (const Name& prefix, const fib::NextHop& nextHop) {
84  this->startProcessNewNextHop(prefix, nextHop);
85  });
86 
87  m_strategyChoice.setDefaultStrategy(getDefaultStrategyName());
88 }
89 
90 Forwarder::~Forwarder() = default;
91 
92 void
93 Forwarder::onIncomingInterest(const FaceEndpoint& ingress, const Interest& interest)
94 {
95  // receive Interest
96  NFD_LOG_DEBUG("onIncomingInterest in=" << ingress << " interest=" << interest.getName());
97  interest.setTag(make_shared<lp::IncomingFaceIdTag>(ingress.face.getId()));
98  ++m_counters.nInInterests;
99 
100  // /localhost scope control
101  bool isViolatingLocalhost = ingress.face.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
103  if (isViolatingLocalhost) {
104  NFD_LOG_DEBUG("onIncomingInterest in=" << ingress
105  << " interest=" << interest.getName() << " violates /localhost");
106  // (drop)
107  return;
108  }
109 
110  // detect duplicate Nonce with Dead Nonce List
111  bool hasDuplicateNonceInDnl = m_deadNonceList.has(interest.getName(), interest.getNonce());
112  if (hasDuplicateNonceInDnl) {
113  // goto Interest loop pipeline
114  this->onInterestLoop(ingress, interest);
115  return;
116  }
117 
118  // strip forwarding hint if Interest has reached producer region
119  if (!interest.getForwardingHint().empty() &&
120  m_networkRegionTable.isInProducerRegion(interest.getForwardingHint())) {
121  NFD_LOG_DEBUG("onIncomingInterest in=" << ingress
122  << " interest=" << interest.getName() << " reaching-producer-region");
123  const_cast<Interest&>(interest).setForwardingHint({});
124  }
125 
126  // PIT insert
127  shared_ptr<pit::Entry> pitEntry = m_pit.insert(interest).first;
128 
129  // detect duplicate Nonce in PIT entry
130  int dnw = fw::findDuplicateNonce(*pitEntry, interest.getNonce(), ingress.face);
131  bool hasDuplicateNonceInPit = dnw != fw::DUPLICATE_NONCE_NONE;
133  // for p2p face: duplicate Nonce from same incoming face is not loop
134  hasDuplicateNonceInPit = hasDuplicateNonceInPit && !(dnw & fw::DUPLICATE_NONCE_IN_SAME);
135  }
136  if (hasDuplicateNonceInPit) {
137  // goto Interest loop pipeline
138  this->onInterestLoop(ingress, interest);
139  this->dispatchToStrategy(*pitEntry,
140  [&] (fw::Strategy& strategy) { strategy.afterReceiveLoopedInterest(ingress, interest, *pitEntry); });
141  return;
142  }
143 
144  // is pending?
145  if (!pitEntry->hasInRecords()) {
146  m_cs.find(interest,
147  bind(&Forwarder::onContentStoreHit, this, ingress, pitEntry, _1, _2),
148  bind(&Forwarder::onContentStoreMiss, this, ingress, pitEntry, _1));
149  }
150  else {
151  this->onContentStoreMiss(ingress, pitEntry, interest);
152  }
153 }
154 
155 void
156 Forwarder::onInterestLoop(const FaceEndpoint& ingress, const Interest& interest)
157 {
158  // if multi-access or ad hoc face, drop
159  if (ingress.face.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
160  NFD_LOG_DEBUG("onInterestLoop in=" << ingress
161  << " interest=" << interest.getName() << " drop");
162  return;
163  }
164 
165  NFD_LOG_DEBUG("onInterestLoop in=" << ingress << " interest=" << interest.getName()
166  << " send-Nack-duplicate");
167 
168  // send Nack with reason=DUPLICATE
169  // note: Don't enter outgoing Nack pipeline because it needs an in-record.
170  lp::Nack nack(interest);
171  nack.setReason(lp::NackReason::DUPLICATE);
172  ingress.face.sendNack(nack, ingress.endpoint);
173 }
174 
175 void
176 Forwarder::onContentStoreMiss(const FaceEndpoint& ingress,
177  const shared_ptr<pit::Entry>& pitEntry, const Interest& interest)
178 {
179  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName());
180  ++m_counters.nCsMisses;
181  afterCsMiss(interest);
182 
183  // insert in-record
184  pitEntry->insertOrUpdateInRecord(ingress.face, interest);
185 
186  // set PIT expiry timer to the time that the last PIT in-record expires
187  auto lastExpiring = std::max_element(pitEntry->in_begin(), pitEntry->in_end(),
188  [] (const auto& a, const auto& b) {
189  return a.getExpiry() < b.getExpiry();
190  });
191  auto lastExpiryFromNow = lastExpiring->getExpiry() - time::steady_clock::now();
192  this->setExpiryTimer(pitEntry, time::duration_cast<time::milliseconds>(lastExpiryFromNow));
193 
194  // has NextHopFaceId?
195  auto nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
196  if (nextHopTag != nullptr) {
197  // chosen NextHop face exists?
198  Face* nextHopFace = m_faceTable.get(*nextHopTag);
199  if (nextHopFace != nullptr) {
200  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName()
201  << " nexthop-faceid=" << nextHopFace->getId());
202  // go to outgoing Interest pipeline
203  // scope control is unnecessary, because privileged app explicitly wants to forward
204  this->onOutgoingInterest(pitEntry, FaceEndpoint(*nextHopFace, 0), interest);
205  }
206  return;
207  }
208 
209  // dispatch to strategy: after incoming Interest
210  this->dispatchToStrategy(*pitEntry,
211  [&] (fw::Strategy& strategy) {
212  strategy.afterReceiveInterest(FaceEndpoint(ingress.face, 0), interest, pitEntry);
213  });
214 }
215 
216 void
217 Forwarder::onContentStoreHit(const FaceEndpoint& ingress, const shared_ptr<pit::Entry>& pitEntry,
218  const Interest& interest, const Data& data)
219 {
220  NFD_LOG_DEBUG("onContentStoreHit interest=" << interest.getName());
221  ++m_counters.nCsHits;
222  afterCsHit(interest, data);
223 
224  data.setTag(make_shared<lp::IncomingFaceIdTag>(face::FACEID_CONTENT_STORE));
225  // FIXME Should we lookup PIT for other Interests that also match the data?
226 
227  pitEntry->isSatisfied = true;
228  pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
229 
230  // set PIT expiry timer to now
231  this->setExpiryTimer(pitEntry, 0_ms);
232 
233  beforeSatisfyInterest(*pitEntry, *m_csFace, data);
234  this->dispatchToStrategy(*pitEntry,
235  [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, FaceEndpoint(*m_csFace, 0), data); });
236 
237  // dispatch to strategy: after Content Store hit
238  this->dispatchToStrategy(*pitEntry,
239  [&] (fw::Strategy& strategy) { strategy.afterContentStoreHit(pitEntry, ingress, data); });
240 }
241 
242 void
243 Forwarder::onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry,
244  const FaceEndpoint& egress, const Interest& interest)
245 {
246  NFD_LOG_DEBUG("onOutgoingInterest out=" << egress << " interest=" << pitEntry->getName());
247 
248  // insert out-record
249  pitEntry->insertOrUpdateOutRecord(egress.face, interest);
250 
251  // send Interest
252  egress.face.sendInterest(interest, egress.endpoint);
253  ++m_counters.nOutInterests;
254 }
255 
256 void
257 Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry)
258 {
259  NFD_LOG_DEBUG("onInterestFinalize interest=" << pitEntry->getName()
260  << (pitEntry->isSatisfied ? " satisfied" : " unsatisfied"));
261 
262  if (!pitEntry->isSatisfied) {
263  beforeExpirePendingInterest(*pitEntry);
264  }
265 
266  // Dead Nonce List insert if necessary
267  this->insertDeadNonceList(*pitEntry, nullptr);
268 
269  // Increment satisfied/unsatisfied Interests counter
270  if (pitEntry->isSatisfied) {
271  ++m_counters.nSatisfiedInterests;
272  }
273  else {
274  ++m_counters.nUnsatisfiedInterests;
275  }
276 
277  // PIT delete
278  pitEntry->expiryTimer.cancel();
279  m_pit.erase(pitEntry.get());
280 }
281 
282 void
283 Forwarder::onIncomingData(const FaceEndpoint& ingress, const Data& data)
284 {
285  // receive Data
286  NFD_LOG_DEBUG("onIncomingData in=" << ingress << " data=" << data.getName());
287  data.setTag(make_shared<lp::IncomingFaceIdTag>(ingress.face.getId()));
288  ++m_counters.nInData;
289 
290  // /localhost scope control
291  bool isViolatingLocalhost = ingress.face.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
292  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
293  if (isViolatingLocalhost) {
294  NFD_LOG_DEBUG("onIncomingData in=" << ingress << " data=" << data.getName() << " violates /localhost");
295  // (drop)
296  return;
297  }
298 
299  // PIT match
300  pit::DataMatchResult pitMatches = m_pit.findAllDataMatches(data);
301  if (pitMatches.size() == 0) {
302  // goto Data unsolicited pipeline
303  this->onDataUnsolicited(ingress, data);
304  return;
305  }
306 
307  // CS insert
308  m_cs.insert(data);
309 
310  // when only one PIT entry is matched, trigger strategy: after receive Data
311  if (pitMatches.size() == 1) {
312  auto& pitEntry = pitMatches.front();
313 
314  NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
315 
316  // set PIT expiry timer to now
317  this->setExpiryTimer(pitEntry, 0_ms);
318 
319  beforeSatisfyInterest(*pitEntry, ingress.face, data);
320  // trigger strategy: after receive Data
321  this->dispatchToStrategy(*pitEntry,
322  [&] (fw::Strategy& strategy) { strategy.afterReceiveData(pitEntry, ingress, data); });
323 
324  // mark PIT satisfied
325  pitEntry->isSatisfied = true;
326  pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
327 
328  // Dead Nonce List insert if necessary (for out-record of inFace)
329  this->insertDeadNonceList(*pitEntry, &ingress.face);
330 
331  // delete PIT entry's out-record
332  pitEntry->deleteOutRecord(ingress.face);
333  }
334  // when more than one PIT entry is matched, trigger strategy: before satisfy Interest,
335  // and send Data to all matched out faces
336  else {
337  std::set<std::pair<Face*, EndpointId>> pendingDownstreams;
338  auto now = time::steady_clock::now();
339 
340  for (const auto& pitEntry : pitMatches) {
341  NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
342 
343  // remember pending downstreams
344  for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
345  if (inRecord.getExpiry() > now) {
346  pendingDownstreams.emplace(&inRecord.getFace(), 0);
347  }
348  }
349 
350  // set PIT expiry timer to now
351  this->setExpiryTimer(pitEntry, 0_ms);
352 
353  // invoke PIT satisfy callback
354  beforeSatisfyInterest(*pitEntry, ingress.face, data);
355  this->dispatchToStrategy(*pitEntry,
356  [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, ingress, data); });
357 
358  // mark PIT satisfied
359  pitEntry->isSatisfied = true;
360  pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
361 
362  // Dead Nonce List insert if necessary (for out-record of inFace)
363  this->insertDeadNonceList(*pitEntry, &ingress.face);
364 
365  // clear PIT entry's in and out records
366  pitEntry->clearInRecords();
367  pitEntry->deleteOutRecord(ingress.face);
368  }
369 
370  // foreach pending downstream
371  for (const auto& pendingDownstream : pendingDownstreams) {
372  if (pendingDownstream.first->getId() == ingress.face.getId() &&
373  pendingDownstream.second == ingress.endpoint &&
374  pendingDownstream.first->getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
375  continue;
376  }
377  // goto outgoing Data pipeline
378  this->onOutgoingData(data, FaceEndpoint(*pendingDownstream.first, pendingDownstream.second));
379  }
380  }
381 }
382 
383 void
384 Forwarder::onDataUnsolicited(const FaceEndpoint& ingress, const Data& data)
385 {
386  // accept to cache?
387  fw::UnsolicitedDataDecision decision = m_unsolicitedDataPolicy->decide(ingress.face, data);
388  if (decision == fw::UnsolicitedDataDecision::CACHE) {
389  // CS insert
390  m_cs.insert(data, true);
391  }
392 
393  NFD_LOG_DEBUG("onDataUnsolicited in=" << ingress << " data=" << data.getName() << " decision=" << decision);
394 }
395 
396 void
397 Forwarder::onOutgoingData(const Data& data, const FaceEndpoint& egress)
398 {
399  if (egress.face.getId() == face::INVALID_FACEID) {
400  NFD_LOG_WARN("onOutgoingData out=(invalid) data=" << data.getName());
401  return;
402  }
403  NFD_LOG_DEBUG("onOutgoingData out=" << egress << " data=" << data.getName());
404 
405  // /localhost scope control
406  bool isViolatingLocalhost = egress.face.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
407  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
408  if (isViolatingLocalhost) {
409  NFD_LOG_DEBUG("onOutgoingData out=" << egress << " data=" << data.getName() << " violates /localhost");
410  // (drop)
411  return;
412  }
413 
414  // TODO traffic manager
415 
416  // send Data
417  egress.face.sendData(data, egress.endpoint);
418  ++m_counters.nOutData;
419 }
420 
421 void
422 Forwarder::onIncomingNack(const FaceEndpoint& ingress, const lp::Nack& nack)
423 {
424  // receive Nack
425  nack.setTag(make_shared<lp::IncomingFaceIdTag>(ingress.face.getId()));
426  ++m_counters.nInNacks;
427 
428  // if multi-access or ad hoc face, drop
429  if (ingress.face.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
430  NFD_LOG_DEBUG("onIncomingNack in=" << ingress
431  << " nack=" << nack.getInterest().getName() << "~" << nack.getReason()
432  << " link-type=" << ingress.face.getLinkType());
433  return;
434  }
435 
436  // PIT match
437  shared_ptr<pit::Entry> pitEntry = m_pit.find(nack.getInterest());
438  // if no PIT entry found, drop
439  if (pitEntry == nullptr) {
440  NFD_LOG_DEBUG("onIncomingNack in=" << ingress << " nack=" << nack.getInterest().getName()
441  << "~" << nack.getReason() << " no-PIT-entry");
442  return;
443  }
444 
445  // has out-record?
446  auto outRecord = pitEntry->getOutRecord(ingress.face);
447  // if no out-record found, drop
448  if (outRecord == pitEntry->out_end()) {
449  NFD_LOG_DEBUG("onIncomingNack in=" << ingress << " nack=" << nack.getInterest().getName()
450  << "~" << nack.getReason() << " no-out-record");
451  return;
452  }
453 
454  // if out-record has different Nonce, drop
455  if (nack.getInterest().getNonce() != outRecord->getLastNonce()) {
456  NFD_LOG_DEBUG("onIncomingNack in=" << ingress << " nack=" << nack.getInterest().getName()
457  << "~" << nack.getReason() << " wrong-Nonce " << nack.getInterest().getNonce()
458  << "!=" << outRecord->getLastNonce());
459  return;
460  }
461 
462  NFD_LOG_DEBUG("onIncomingNack in=" << ingress << " nack=" << nack.getInterest().getName()
463  << "~" << nack.getReason() << " OK");
464 
465  // record Nack on out-record
466  outRecord->setIncomingNack(nack);
467 
468  // set PIT expiry timer to now when all out-record receive Nack
469  if (!fw::hasPendingOutRecords(*pitEntry)) {
470  this->setExpiryTimer(pitEntry, 0_ms);
471  }
472 
473  // trigger strategy: after receive NACK
474  this->dispatchToStrategy(*pitEntry,
475  [&] (fw::Strategy& strategy) { strategy.afterReceiveNack(ingress, nack, pitEntry); });
476 }
477 
478 void
479 Forwarder::onOutgoingNack(const shared_ptr<pit::Entry>& pitEntry,
480  const FaceEndpoint& egress, const lp::NackHeader& nack)
481 {
482  if (egress.face.getId() == face::INVALID_FACEID) {
483  NFD_LOG_WARN("onOutgoingNack out=(invalid)"
484  << " nack=" << pitEntry->getInterest().getName() << "~" << nack.getReason());
485  return;
486  }
487 
488  // has in-record?
489  auto inRecord = pitEntry->getInRecord(egress.face);
490 
491  // if no in-record found, drop
492  if (inRecord == pitEntry->in_end()) {
493  NFD_LOG_DEBUG("onOutgoingNack out=" << egress
494  << " nack=" << pitEntry->getInterest().getName()
495  << "~" << nack.getReason() << " no-in-record");
496  return;
497  }
498 
499  // if multi-access or ad hoc face, drop
500  if (egress.face.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
501  NFD_LOG_DEBUG("onOutgoingNack out=" << egress
502  << " nack=" << pitEntry->getInterest().getName() << "~" << nack.getReason()
503  << " link-type=" << egress.face.getLinkType());
504  return;
505  }
506 
507  NFD_LOG_DEBUG("onOutgoingNack out=" << egress
508  << " nack=" << pitEntry->getInterest().getName()
509  << "~" << nack.getReason() << " OK");
510 
511  // create Nack packet with the Interest from in-record
512  lp::Nack nackPkt(inRecord->getInterest());
513  nackPkt.setHeader(nack);
514 
515  // erase in-record
516  pitEntry->deleteInRecord(egress.face);
517 
518  // send Nack on face
519  egress.face.sendNack(nackPkt, egress.endpoint);
520  ++m_counters.nOutNacks;
521 }
522 
523 void
524 Forwarder::onDroppedInterest(const FaceEndpoint& egress, const Interest& interest)
525 {
526  m_strategyChoice.findEffectiveStrategy(interest.getName()).onDroppedInterest(egress, interest);
527 }
528 
529 void
530 Forwarder::onNewNextHop(const Name& prefix, const fib::NextHop& nextHop)
531 {
532  const auto affectedEntries = this->getNameTree().partialEnumerate(prefix,
533  [&] (const name_tree::Entry& nte) -> std::pair<bool, bool> {
534  const fib::Entry* fibEntry = nte.getFibEntry();
535  const fw::Strategy* strategy = nullptr;
536  if (nte.getStrategyChoiceEntry() != nullptr) {
537  strategy = &nte.getStrategyChoiceEntry()->getStrategy();
538  }
539  // current nte has buffered Interests but no fibEntry (except for the root nte) and the strategy
540  // enables new nexthop behavior, we enumerate the current nte and keep visiting its children.
541  if (nte.getName().size() == 0 ||
542  (strategy != nullptr && strategy->wantNewNextHopTrigger() &&
543  fibEntry == nullptr && nte.hasPitEntries())) {
544  return {true, true};
545  }
546  // we don't need the current nte (no pitEntry or strategy doesn't support new nexthop), but
547  // if the current nte has no fibEntry, it's still possible that its children are affected by
548  // the new nexthop.
549  else if (fibEntry == nullptr) {
550  return {false, true};
551  }
552  // if the current nte has a fibEntry, we ignore the current nte and don't visit its
553  // children because they are already covered by the current nte's fibEntry.
554  else {
555  return {false, false};
556  }
557  });
558 
559  for (const auto& nte : affectedEntries) {
560  for (const auto& pitEntry : nte.getPitEntries()) {
561  this->dispatchToStrategy(*pitEntry,
562  [&] (fw::Strategy& strategy) {
563  strategy.afterNewNextHop(nextHop, pitEntry);
564  });
565  }
566  }
567 }
568 
569 void
570 Forwarder::setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
571 {
572  BOOST_ASSERT(pitEntry);
573  BOOST_ASSERT(duration >= 0_ms);
574 
575  pitEntry->expiryTimer.cancel();
576  pitEntry->expiryTimer = getScheduler().schedule(duration, [=] { onInterestFinalize(pitEntry); });
577 }
578 
579 void
580 Forwarder::insertDeadNonceList(pit::Entry& pitEntry, Face* upstream)
581 {
582  // need Dead Nonce List insert?
583  bool needDnl = true;
584  if (pitEntry.isSatisfied) {
585  BOOST_ASSERT(pitEntry.dataFreshnessPeriod >= 0_ms);
586  needDnl = static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
587  pitEntry.dataFreshnessPeriod < m_deadNonceList.getLifetime();
588  }
589 
590  if (!needDnl) {
591  return;
592  }
593 
594  // Dead Nonce List insert
595  if (upstream == nullptr) {
596  // insert all outgoing Nonces
597  const auto& outRecords = pitEntry.getOutRecords();
598  std::for_each(outRecords.begin(), outRecords.end(), [&] (const auto& outRecord) {
599  m_deadNonceList.add(pitEntry.getName(), outRecord.getLastNonce());
600  });
601  }
602  else {
603  // insert outgoing Nonce of a specific face
604  auto outRecord = pitEntry.getOutRecord(*upstream);
605  if (outRecord != pitEntry.getOutRecords().end()) {
606  m_deadNonceList.add(pitEntry.getName(), outRecord->getLastNonce());
607  }
608  }
609 }
610 
611 } // namespace nfd
ndn::Interest::getNonce
uint32_t getNonce() const
Get nonce value.
Definition: interest.cpp:400
ndn::DelegationList::empty
NDN_CXX_NODISCARD bool empty() const noexcept
Definition: delegation-list.hpp:102
global.hpp
nfd::Forwarder::beforeExpirePendingInterest
signal::Signal< Forwarder, pit::Entry > beforeExpirePendingInterest
trigger before PIT entry expires
Definition: forwarder.hpp:177
nfd::Forwarder::afterCsMiss
signal::Signal< Forwarder, Interest > afterCsMiss
Signals when the incoming interest pipeline gets a miss from the content store.
Definition: forwarder.hpp:185
nfd::Forwarder::afterCsHit
signal::Signal< Forwarder, Interest, Data > afterCsHit
Signals when the incoming interest pipeline gets a hit from the content store.
Definition: forwarder.hpp:181
nfd::fw::DUPLICATE_NONCE_IN_SAME
@ DUPLICATE_NONCE_IN_SAME
in-record of same face
Definition: algorithm.hpp:63
nfd::ForwarderCounters::nUnsatisfiedInterests
PacketCounter nUnsatisfiedInterests
Definition: forwarder-counters.hpp:45
nfd::FaceEndpoint::face
Face & face
Definition: face-endpoint.hpp:46
ndn::nfd::FACE_SCOPE_NON_LOCAL
@ FACE_SCOPE_NON_LOCAL
face is non-local
Definition: nfd-constants.hpp:36
nfd::face::Face::afterReceiveNack
signal::Signal< LinkService, lp::Nack, EndpointId > & afterReceiveNack
signals on Nack received
Definition: face.hpp:89
nfd::Forwarder::startProcessNack
void startProcessNack(const FaceEndpoint &ingress, const lp::Nack &nack)
start incoming Nack processing
Definition: forwarder.hpp:105
nfd::fw::BestRouteStrategy2::getStrategyName
static const Name & getStrategyName()
Definition: best-route-strategy2.cpp:58
ndn::lp::NackHeader
represents a Network NACK header
Definition: nack-header.hpp:58
ndn::tlv::Interest
@ Interest
Definition: tlv.hpp:65
nfd::fw::UnsolicitedDataDecision
UnsolicitedDataDecision
a decision made by UnsolicitedDataPolicy
Definition: unsolicited-data-policy.hpp:36
nfd::ForwarderCounters::nSatisfiedInterests
PacketCounter nSatisfiedInterests
Definition: forwarder-counters.hpp:44
ndn::nfd::LINK_TYPE_POINT_TO_POINT
@ LINK_TYPE_POINT_TO_POINT
link is point-to-point
Definition: nfd-constants.hpp:59
ndn::FaceUri
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:45
nfd::fw::Strategy
Strategy
Definition: strategy.cpp:38
ndn::Name::isPrefixOf
bool isPrefixOf(const Name &other) const
Check if this name is a prefix of another name.
Definition: name.cpp:299
ndn::SimpleTag
provides a tag type for simple types
Definition: tag.hpp:59
nfd::FaceTable::addReserved
void addReserved(shared_ptr< Face > face, FaceId faceId)
add a special face with a reserved FaceId
Definition: face-table.cpp:71
ndn::time::steady_clock::now
static time_point now() noexcept
Definition: time.cpp:80
ndn::nfd::LINK_TYPE_AD_HOC
@ LINK_TYPE_AD_HOC
link is ad hoc
Definition: nfd-constants.hpp:61
nfd::ForwarderCounters::nOutData
PacketCounter nOutData
Definition: forwarder-counters.hpp:41
ndn::TagHost::setTag
void setTag(shared_ptr< T > tag) const
set a tag item
Definition: tag-host.hpp:79
nfd::face::Face::afterReceiveInterest
signal::Signal< LinkService, Interest, EndpointId > & afterReceiveInterest
signals on Interest received
Definition: face.hpp:81
nfd::scope_prefix::LOCALHOST
const Name LOCALHOST("ndn:/localhost")
ndn:/localhost
Definition: scope-prefix.hpp:45
nfd::pit::Pit::insert
std::pair< shared_ptr< Entry >, bool > insert(const Interest &interest)
Inserts a PIT entry for interest.
Definition: pit.hpp:77
nfd::Forwarder::startProcessInterest
void startProcessInterest(const FaceEndpoint &ingress, const Interest &interest)
start incoming Interest processing
Definition: forwarder.hpp:85
forwarder.hpp
nfd::ForwarderCounters::nInData
PacketCounter nInData
Definition: forwarder-counters.hpp:40
nfd::fw::UnsolicitedDataDecision::CACHE
@ CACHE
the Data should be cached in the ContentStore
cleanup.hpp
nfd::fw::DUPLICATE_NONCE_NONE
@ DUPLICATE_NONCE_NONE
no duplicate Nonce is found
Definition: algorithm.hpp:62
nfd::FaceTable::afterAdd
signal::Signal< FaceTable, Face > afterAdd
Fires immediately after a face is added.
Definition: face-table.hpp:85
nfd::face::Face::onDroppedInterest
signal::Signal< LinkService, Interest > & onDroppedInterest
signals on Interest dropped by reliability system for exceeding allowed number of retx
Definition: face.hpp:93
NFD_LOG_WARN
#define NFD_LOG_WARN
Definition: logger.hpp:40
nfd::face::FACEID_CONTENT_STORE
const FaceId FACEID_CONTENT_STORE
identifies a packet comes from the ContentStore
Definition: face-common.hpp:51
ndn::Name
Represents an absolute name.
Definition: name.hpp:44
best-route-strategy2.hpp
nfd::ForwarderCounters::nOutNacks
PacketCounter nOutNacks
Definition: forwarder-counters.hpp:43
ns3::ndn::Name
Name
Definition: ndn-common.cpp:25
nfd::cs::Cs::insert
void insert(const Data &data, bool isUnsolicited=false)
inserts a Data packet
Definition: cs.cpp:51
nfd
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
nfd::Forwarder::~Forwarder
~Forwarder()
nfd::getDefaultStrategyName
static Name getDefaultStrategyName()
Definition: forwarder.cpp:44
nfd::Forwarder::getNameTree
NameTree & getNameTree()
Definition: forwarder.hpp:121
ndn::lp::Nack::getReason
NackReason getReason() const
Definition: nack.hpp:90
nfd::face::INVALID_FACEID
const FaceId INVALID_FACEID
indicates an invalid FaceId
Definition: face-common.hpp:47
nfd::face::Face
generalization of a network interface
Definition: face.hpp:53
nfd::ForwarderCounters::nCsHits
PacketCounter nCsHits
Definition: forwarder-counters.hpp:47
nfd::ForwarderCounters::nInNacks
PacketCounter nInNacks
Definition: forwarder-counters.hpp:42
nfd::FaceTable
container of all faces
Definition: face-table.hpp:39
nfd::fw::DefaultUnsolicitedDataPolicy
DropAllUnsolicitedDataPolicy DefaultUnsolicitedDataPolicy
the default UnsolicitedDataPolicy
Definition: unsolicited-data-policy.hpp:138
nfd::getScheduler
Scheduler & getScheduler()
Returns the global Scheduler instance for the calling thread.
Definition: global.cpp:70
nfd::strategy_choice::StrategyChoice::findEffectiveStrategy
fw::Strategy & findEffectiveStrategy(const Name &prefix) const
Get effective strategy for prefix.
Definition: strategy-choice.cpp:191
ndn::Interest::getForwardingHint
const DelegationList & getForwardingHint() const noexcept
Definition: interest.hpp:192
nfd::ForwarderCounters::nInInterests
PacketCounter nInInterests
Definition: forwarder-counters.hpp:38
nfd::FaceEndpoint
Represents a face-endpoint pair in the forwarder.
Definition: face-endpoint.hpp:37
ndn::Interest
Represents an Interest packet.
Definition: interest.hpp:44
nfd::fib::NextHop
Represents a nexthop record in a FIB entry.
Definition: fib-nexthop.hpp:38
nfd::face::Face::getId
FaceId getId() const
Definition: face.hpp:214
nfd::strategy_choice::StrategyChoice::setDefaultStrategy
void setDefaultStrategy(const Name &strategyName)
Set the default strategy.
Definition: strategy-choice.cpp:57
nfd::fw::Strategy::onDroppedInterest
virtual void onDroppedInterest(const FaceEndpoint &egress, const Interest &interest)
trigger after Interest dropped for exceeding allowed retransmissions
Definition: strategy.cpp:200
nfd::Forwarder::startProcessNewNextHop
void startProcessNewNextHop(const Name &prefix, const fib::NextHop &nextHop)
start new nexthop processing
Definition: forwarder.hpp:115
ndn::Data
Represents a Data packet.
Definition: data.hpp:36
nfd::FaceTable::get
Face * get(FaceId id) const
get face by FaceId
Definition: face-table.cpp:45
NFD_LOG_DEBUG
#define NFD_LOG_DEBUG
Definition: logger.hpp:38
nfd::pit::Pit::find
shared_ptr< Entry > find(const Interest &interest) const
Finds a PIT entry for interest.
Definition: pit.hpp:66
nfd::Forwarder
Main class of NFD's forwarding engine.
Definition: forwarder.hpp:52
Face
ndn Face
Definition: face-impl.hpp:41
ndn::tlv::Data
@ Data
Definition: tlv.hpp:66
nfd::fw::hasPendingOutRecords
bool hasPendingOutRecords(const pit::Entry &pitEntry)
determine whether pitEntry has any pending out-records
Definition: algorithm.cpp:108
nfd::cs::Cs::find
void find(const Interest &interest, HitCallback &&hit, MissCallback &&miss) const
finds the best matching Data packet
Definition: cs.hpp:81
nfd::Forwarder::startProcessData
void startProcessData(const FaceEndpoint &ingress, const Data &data)
start incoming Data processing
Definition: forwarder.hpp:95
nfd::Forwarder::beforeSatisfyInterest
signal::Signal< Forwarder, pit::Entry, Face, Data > beforeSatisfyInterest
trigger before PIT entry is satisfied
Definition: forwarder.hpp:172
nfd::face::Face::getScope
ndn::nfd::FaceScope getScope() const
Definition: face.hpp:250
nfd::face::makeNullFace
shared_ptr< Face > makeNullFace(const FaceUri &uri)
Definition: null-face.cpp:34
nfd::pit::Pit::findAllDataMatches
DataMatchResult findAllDataMatches(const Data &data) const
Performs a Data match.
Definition: pit.cpp:86
nfd::ForwarderCounters::nOutInterests
PacketCounter nOutInterests
Definition: forwarder-counters.hpp:39
nfd::name_tree::NameTree::partialEnumerate
Range partialEnumerate(const Name &prefix, const EntrySubTreeSelector &entrySubTreeSelector=AnyEntrySubTree()) const
Enumerate all entries under a prefix.
Definition: name-tree.cpp:232
nfd::pit::DataMatchResult
std::vector< shared_ptr< Entry > > DataMatchResult
Definition: pit.hpp:43
ndn::lp::Nack
represents a Network Nack
Definition: nack.hpp:39
algorithm.hpp
nfd::pit::Pit::erase
void erase(Entry *entry)
Deletes an entry.
Definition: pit.hpp:91
strategy.hpp
nfd::fib::Fib::afterNewNextHop
signal::Signal< Fib, Name, NextHop > afterNewNextHop
signals on Fib entry nexthop creation
Definition: fib.hpp:151
nfd::FaceTable::beforeRemove
signal::Signal< FaceTable, Face > beforeRemove
Fires immediately before a face is removed.
Definition: face-table.hpp:91
nfd::Forwarder::Forwarder
Forwarder(FaceTable &faceTable)
Definition: forwarder.cpp:49
nfd::fw::findDuplicateNonce
int findDuplicateNonce(const pit::Entry &pitEntry, uint32_t nonce, const Face &face)
determine whether pitEntry has duplicate Nonce nonce
Definition: algorithm.cpp:78
ndn::lp::NackHeader::getReason
NackReason getReason() const
Definition: nack-header.cpp:122
ndn::Interest::getName
const Name & getName() const noexcept
Definition: interest.hpp:121
nfd::ForwarderCounters::nCsMisses
PacketCounter nCsMisses
Definition: forwarder-counters.hpp:48
tags.hpp
nfd::face::Face::getLinkType
ndn::nfd::LinkType getLinkType() const
Definition: face.hpp:268
nfd::face::EndpointId
uint64_t EndpointId
Identifies a remote endpoint on the link.
Definition: face-common.hpp:65
nfd::face::Face::afterReceiveData
signal::Signal< LinkService, Data, EndpointId > & afterReceiveData
signals on Data received
Definition: face.hpp:85
nfd::DeadNonceList::has
bool has(const Name &name, uint32_t nonce) const
Determines if name+nonce exists.
Definition: dead-nonce-list.cpp:90
ndn::lp::Nack::getInterest
const Interest & getInterest() const
Definition: nack.hpp:51
NFD_LOG_INIT
#define NFD_LOG_INIT(name)
Definition: logger.hpp:31
nfd::cleanupOnFaceRemoval
void cleanupOnFaceRemoval(NameTree &nt, Fib &fib, Pit &pit, const Face &face)
cleanup tables when a face is destroyed
Definition: cleanup.cpp:31
logger.hpp
null-face.hpp
nfd::NetworkRegionTable::isInProducerRegion
bool isInProducerRegion(const DelegationList &forwardingHint) const
determines whether an Interest has reached a producer region
Definition: network-region-table.cpp:31