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