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-2018, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "forwarder.hpp"
27 #include "algorithm.hpp"
28 #include "best-route-strategy2.hpp"
29 #include "strategy.hpp"
30 #include "core/logger.hpp"
31 #include "table/cleanup.hpp"
32 #include <ndn-cxx/lp/tags.hpp>
33 
34 #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  // is pending?
136  if (!pitEntry->hasInRecords()) {
137  if (m_csFromNdnSim == nullptr) {
138  m_cs.find(interest,
139  bind(&Forwarder::onContentStoreHit, this, ref(inFace), pitEntry, _1, _2),
140  bind(&Forwarder::onContentStoreMiss, this, ref(inFace), pitEntry, _1));
141  }
142  else {
143  shared_ptr<Data> match = m_csFromNdnSim->Lookup(interest.shared_from_this());
144  if (match != nullptr) {
145  this->onContentStoreHit(inFace, pitEntry, interest, *match);
146  }
147  else {
148  this->onContentStoreMiss(inFace, pitEntry, interest);
149  }
150  }
151  }
152  else {
153  this->onContentStoreMiss(inFace, pitEntry, interest);
154  }
155 }
156 
157 void
158 Forwarder::onInterestLoop(Face& inFace, const Interest& interest)
159 {
160  // if multi-access or ad hoc face, drop
161  if (inFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
162  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
163  " interest=" << interest.getName() <<
164  " drop");
165  return;
166  }
167 
168  NFD_LOG_DEBUG("onInterestLoop face=" << inFace.getId() <<
169  " interest=" << interest.getName() <<
170  " send-Nack-duplicate");
171 
172  // send Nack with reason=DUPLICATE
173  // note: Don't enter outgoing Nack pipeline because it needs an in-record.
174  lp::Nack nack(interest);
175  nack.setReason(lp::NackReason::DUPLICATE);
176  inFace.sendNack(nack);
177 }
178 
179 static inline bool
181 {
182  return a.getExpiry() < b.getExpiry();
183 }
184 
185 void
186 Forwarder::onContentStoreMiss(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
187  const Interest& interest)
188 {
189  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName());
190  ++m_counters.nCsMisses;
191 
192  // insert in-record
193  pitEntry->insertOrUpdateInRecord(const_cast<Face&>(inFace), interest);
194 
195  // set PIT expiry timer to the time that the last PIT in-record expires
196  auto lastExpiring = std::max_element(pitEntry->in_begin(), pitEntry->in_end(), &compare_InRecord_expiry);
197  auto lastExpiryFromNow = lastExpiring->getExpiry() - time::steady_clock::now();
198  this->setExpiryTimer(pitEntry, time::duration_cast<time::milliseconds>(lastExpiryFromNow));
199 
200  // has NextHopFaceId?
201  shared_ptr<lp::NextHopFaceIdTag> nextHopTag = interest.getTag<lp::NextHopFaceIdTag>();
202  if (nextHopTag != nullptr) {
203  // chosen NextHop face exists?
204  Face* nextHopFace = m_faceTable.get(*nextHopTag);
205  if (nextHopFace != nullptr) {
206  NFD_LOG_DEBUG("onContentStoreMiss interest=" << interest.getName() << " nexthop-faceid=" << nextHopFace->getId());
207  // go to outgoing Interest pipeline
208  // scope control is unnecessary, because privileged app explicitly wants to forward
209  this->onOutgoingInterest(pitEntry, *nextHopFace, interest);
210  }
211  return;
212  }
213 
214  // dispatch to strategy: after incoming Interest
215  this->dispatchToStrategy(*pitEntry,
216  [&] (fw::Strategy& strategy) { strategy.afterReceiveInterest(inFace, interest, pitEntry); });
217 }
218 
219 void
220 Forwarder::onContentStoreHit(const Face& inFace, const shared_ptr<pit::Entry>& pitEntry,
221  const Interest& interest, const Data& data)
222 {
223  NFD_LOG_DEBUG("onContentStoreHit interest=" << interest.getName());
224  ++m_counters.nCsHits;
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  pitEntry->isSatisfied = true;
230  pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
231 
232  // set PIT expiry timer to now
233  this->setExpiryTimer(pitEntry, 0_ms);
234 
235  beforeSatisfyInterest(*pitEntry, *m_csFace, data);
236  this->dispatchToStrategy(*pitEntry,
237  [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, *m_csFace, data); });
238 
239  // dispatch to strategy: after Content Store hit
240  this->dispatchToStrategy(*pitEntry,
241  [&] (fw::Strategy& strategy) { strategy.afterContentStoreHit(pitEntry, inFace, data); });
242 }
243 
244 void
245 Forwarder::onOutgoingInterest(const shared_ptr<pit::Entry>& pitEntry, Face& outFace, const Interest& interest)
246 {
247  NFD_LOG_DEBUG("onOutgoingInterest face=" << outFace.getId() <<
248  " interest=" << pitEntry->getName());
249 
250  // insert out-record
251  pitEntry->insertOrUpdateOutRecord(outFace, interest);
252 
253  // send Interest
254  outFace.sendInterest(interest);
255  ++m_counters.nOutInterests;
256 }
257 
258 void
259 Forwarder::onInterestFinalize(const shared_ptr<pit::Entry>& pitEntry)
260 {
261  NFD_LOG_DEBUG("onInterestFinalize interest=" << pitEntry->getName() <<
262  (pitEntry->isSatisfied ? " satisfied" : " unsatisfied"));
263 
264  if (!pitEntry->isSatisfied) {
265  beforeExpirePendingInterest(*pitEntry);
266  }
267 
268  // Dead Nonce List insert if necessary
269  this->insertDeadNonceList(*pitEntry, 0);
270 
271  // PIT delete
272  scheduler::cancel(pitEntry->expiryTimer);
273  m_pit.erase(pitEntry.get());
274 }
275 
276 void
277 Forwarder::onIncomingData(Face& inFace, const Data& data)
278 {
279  // receive Data
280  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() << " data=" << data.getName());
281  data.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
282  ++m_counters.nInData;
283 
284  // /localhost scope control
285  bool isViolatingLocalhost = inFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
286  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
287  if (isViolatingLocalhost) {
288  NFD_LOG_DEBUG("onIncomingData face=" << inFace.getId() <<
289  " data=" << data.getName() << " violates /localhost");
290  // (drop)
291  return;
292  }
293 
294  // PIT match
295  pit::DataMatchResult pitMatches = m_pit.findAllDataMatches(data);
296  if (pitMatches.size() == 0) {
297  // goto Data unsolicited pipeline
298  this->onDataUnsolicited(inFace, data);
299  return;
300  }
301 
302  shared_ptr<Data> dataCopyWithoutTag = make_shared<Data>(data);
303  dataCopyWithoutTag->removeTag<lp::HopCountTag>();
304 
305  // CS insert
306  if (m_csFromNdnSim == nullptr)
307  m_cs.insert(*dataCopyWithoutTag);
308  else
309  m_csFromNdnSim->Add(dataCopyWithoutTag);
310 
311  // when only one PIT entry is matched, trigger strategy: after receive Data
312  if (pitMatches.size() == 1) {
313  auto& pitEntry = pitMatches.front();
314 
315  NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
316 
317  // set PIT expiry timer to now
318  this->setExpiryTimer(pitEntry, 0_ms);
319 
320  beforeSatisfyInterest(*pitEntry, inFace, data);
321  // trigger strategy: after receive Data
322  this->dispatchToStrategy(*pitEntry,
323  [&] (fw::Strategy& strategy) { strategy.afterReceiveData(pitEntry, inFace, data); });
324 
325  // mark PIT satisfied
326  pitEntry->isSatisfied = true;
327  pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
328 
329  // Dead Nonce List insert if necessary (for out-record of inFace)
330  this->insertDeadNonceList(*pitEntry, &inFace);
331 
332  // delete PIT entry's out-record
333  pitEntry->deleteOutRecord(inFace);
334  }
335  // when more than one PIT entry is matched, trigger strategy: before satisfy Interest,
336  // and send Data to all matched out faces
337  else {
338  std::set<Face*> pendingDownstreams;
339  auto now = time::steady_clock::now();
340 
341  for (const shared_ptr<pit::Entry>& pitEntry : pitMatches) {
342  NFD_LOG_DEBUG("onIncomingData matching=" << pitEntry->getName());
343 
344  // remember pending downstreams
345  for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
346  if (inRecord.getExpiry() > now) {
347  pendingDownstreams.insert(&inRecord.getFace());
348  }
349  }
350 
351  // set PIT expiry timer to now
352  this->setExpiryTimer(pitEntry, 0_ms);
353 
354  // invoke PIT satisfy callback
355  beforeSatisfyInterest(*pitEntry, inFace, data);
356  this->dispatchToStrategy(*pitEntry,
357  [&] (fw::Strategy& strategy) { strategy.beforeSatisfyInterest(pitEntry, inFace, data); });
358 
359  // mark PIT satisfied
360  pitEntry->isSatisfied = true;
361  pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
362 
363  // Dead Nonce List insert if necessary (for out-record of inFace)
364  this->insertDeadNonceList(*pitEntry, &inFace);
365 
366  // clear PIT entry's in and out records
367  pitEntry->clearInRecords();
368  pitEntry->deleteOutRecord(inFace);
369  }
370 
371  // foreach pending downstream
372  for (Face* pendingDownstream : pendingDownstreams) {
373  if (pendingDownstream->getId() == inFace.getId() &&
374  pendingDownstream->getLinkType() != ndn::nfd::LINK_TYPE_AD_HOC) {
375  continue;
376  }
377  // goto outgoing Data pipeline
378  this->onOutgoingData(data, *pendingDownstream);
379  }
380  }
381 }
382 
383 void
384 Forwarder::onDataUnsolicited(Face& inFace, const Data& data)
385 {
386  // accept to cache?
387  fw::UnsolicitedDataDecision decision = m_unsolicitedDataPolicy->decide(inFace, data);
388  if (decision == fw::UnsolicitedDataDecision::CACHE) {
389  // CS insert
390  if (m_csFromNdnSim == nullptr)
391  m_cs.insert(data, true);
392  else
393  m_csFromNdnSim->Add(data.shared_from_this());
394  }
395 
396  NFD_LOG_DEBUG("onDataUnsolicited face=" << inFace.getId() <<
397  " data=" << data.getName() <<
398  " decision=" << decision);
399 }
400 
401 void
402 Forwarder::onOutgoingData(const Data& data, Face& outFace)
403 {
404  if (outFace.getId() == face::INVALID_FACEID) {
405  NFD_LOG_WARN("onOutgoingData face=invalid data=" << data.getName());
406  return;
407  }
408  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() << " data=" << data.getName());
409 
410  // /localhost scope control
411  bool isViolatingLocalhost = outFace.getScope() == ndn::nfd::FACE_SCOPE_NON_LOCAL &&
412  scope_prefix::LOCALHOST.isPrefixOf(data.getName());
413  if (isViolatingLocalhost) {
414  NFD_LOG_DEBUG("onOutgoingData face=" << outFace.getId() <<
415  " data=" << data.getName() << " violates /localhost");
416  // (drop)
417  return;
418  }
419 
420  // TODO traffic manager
421 
422  // send Data
423  outFace.sendData(data);
424  ++m_counters.nOutData;
425 }
426 
427 void
428 Forwarder::onIncomingNack(Face& inFace, const lp::Nack& nack)
429 {
430  // receive Nack
431  nack.setTag(make_shared<lp::IncomingFaceIdTag>(inFace.getId()));
432  ++m_counters.nInNacks;
433 
434  // if multi-access or ad hoc face, drop
435  if (inFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
436  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
437  " nack=" << nack.getInterest().getName() <<
438  "~" << nack.getReason() << " face-is-multi-access");
439  return;
440  }
441 
442  // PIT match
443  shared_ptr<pit::Entry> pitEntry = m_pit.find(nack.getInterest());
444  // if no PIT entry found, drop
445  if (pitEntry == nullptr) {
446  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
447  " nack=" << nack.getInterest().getName() <<
448  "~" << nack.getReason() << " no-PIT-entry");
449  return;
450  }
451 
452  // has out-record?
453  pit::OutRecordCollection::iterator outRecord = pitEntry->getOutRecord(inFace);
454  // if no out-record found, drop
455  if (outRecord == pitEntry->out_end()) {
456  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
457  " nack=" << nack.getInterest().getName() <<
458  "~" << nack.getReason() << " no-out-record");
459  return;
460  }
461 
462  // if out-record has different Nonce, drop
463  if (nack.getInterest().getNonce() != outRecord->getLastNonce()) {
464  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
465  " nack=" << nack.getInterest().getName() <<
466  "~" << nack.getReason() << " wrong-Nonce " <<
467  nack.getInterest().getNonce() << "!=" << outRecord->getLastNonce());
468  return;
469  }
470 
471  NFD_LOG_DEBUG("onIncomingNack face=" << inFace.getId() <<
472  " nack=" << nack.getInterest().getName() <<
473  "~" << nack.getReason() << " OK");
474 
475  // record Nack on out-record
476  outRecord->setIncomingNack(nack);
477 
478  // set PIT expiry timer to now when all out-record receive Nack
479  if (!fw::hasPendingOutRecords(*pitEntry)) {
480  this->setExpiryTimer(pitEntry, 0_ms);
481  }
482 
483  // trigger strategy: after receive NACK
484  this->dispatchToStrategy(*pitEntry,
485  [&] (fw::Strategy& strategy) { strategy.afterReceiveNack(inFace, nack, pitEntry); });
486 }
487 
488 void
489 Forwarder::onOutgoingNack(const shared_ptr<pit::Entry>& pitEntry, const Face& outFace,
490  const lp::NackHeader& nack)
491 {
492  if (outFace.getId() == face::INVALID_FACEID) {
493  NFD_LOG_WARN("onOutgoingNack face=invalid" <<
494  " nack=" << pitEntry->getInterest().getName() <<
495  "~" << nack.getReason() << " no-in-record");
496  return;
497  }
498 
499  // has in-record?
500  pit::InRecordCollection::iterator inRecord = pitEntry->getInRecord(outFace);
501 
502  // if no in-record found, drop
503  if (inRecord == pitEntry->in_end()) {
504  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
505  " nack=" << pitEntry->getInterest().getName() <<
506  "~" << nack.getReason() << " no-in-record");
507  return;
508  }
509 
510  // if multi-access or ad hoc face, drop
511  if (outFace.getLinkType() != ndn::nfd::LINK_TYPE_POINT_TO_POINT) {
512  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
513  " nack=" << pitEntry->getInterest().getName() <<
514  "~" << nack.getReason() << " face-is-multi-access");
515  return;
516  }
517 
518  NFD_LOG_DEBUG("onOutgoingNack face=" << outFace.getId() <<
519  " nack=" << pitEntry->getInterest().getName() <<
520  "~" << nack.getReason() << " OK");
521 
522  // create Nack packet with the Interest from in-record
523  lp::Nack nackPkt(inRecord->getInterest());
524  nackPkt.setHeader(nack);
525 
526  // erase in-record
527  pitEntry->deleteInRecord(outFace);
528 
529  // send Nack on face
530  const_cast<Face&>(outFace).sendNack(nackPkt);
531  ++m_counters.nOutNacks;
532 }
533 
534 void
535 Forwarder::onDroppedInterest(Face& outFace, const Interest& interest)
536 {
537  m_strategyChoice.findEffectiveStrategy(interest.getName()).onDroppedInterest(outFace, interest);
538 }
539 
540 void
541 Forwarder::setExpiryTimer(const shared_ptr<pit::Entry>& pitEntry, time::milliseconds duration)
542 {
543  BOOST_ASSERT(duration >= 0_ms);
544 
545  scheduler::cancel(pitEntry->expiryTimer);
546 
547  pitEntry->expiryTimer = scheduler::schedule(duration,
548  bind(&Forwarder::onInterestFinalize, this, pitEntry));
549 }
550 
551 static inline void
553  const pit::OutRecord& outRecord)
554 {
555  dnl.add(pitEntry.getName(), outRecord.getLastNonce());
556 }
557 
558 void
559 Forwarder::insertDeadNonceList(pit::Entry& pitEntry, Face* upstream)
560 {
561  // need Dead Nonce List insert?
562  bool needDnl = true;
563  if (pitEntry.isSatisfied) {
564  BOOST_ASSERT(pitEntry.dataFreshnessPeriod >= 0_ms);
565  needDnl = static_cast<bool>(pitEntry.getInterest().getMustBeFresh()) &&
566  pitEntry.dataFreshnessPeriod < m_deadNonceList.getLifetime();
567  }
568 
569  if (!needDnl) {
570  return;
571  }
572 
573  // Dead Nonce List insert
574  if (upstream == nullptr) {
575  // insert all outgoing Nonces
576  const pit::OutRecordCollection& outRecords = pitEntry.getOutRecords();
577  std::for_each(outRecords.begin(), outRecords.end(),
578  bind(&insertNonceToDnl, ref(m_deadNonceList), cref(pitEntry), _1));
579  }
580  else {
581  // insert outgoing Nonce of a specific face
582  pit::OutRecordCollection::iterator outRecord = pitEntry.getOutRecord(*upstream);
583  if (outRecord != pitEntry.getOutRecords().end()) {
584  m_deadNonceList.add(pitEntry.getName(), outRecord->getLastNonce());
585  }
586  }
587 }
588 
589 } // 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
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
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:54
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:255
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:180
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: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
std::vector< shared_ptr< Entry > > DataMatchResult
Definition: pit.hpp:43
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:42
FaceTable & getFaceTable()
Definition: forwarder.hpp:70
static void insertNonceToDnl(DeadNonceList &dnl, const pit::Entry &pitEntry, const pit::OutRecord &outRecord)
Definition: forwarder.cpp:552
void insert(const Data &data, bool isUnsolicited=false)
inserts a Data packet
Definition: cs.cpp:56
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:445
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:77
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:116
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:48
void addReserved(shared_ptr< Face > face, FaceId faceId)
add a special face with a reserved FaceId
Definition: face-table.cpp:71
contains information about an Interest toward an outgoing face
the Data should be cached in the ContentStore
const DelegationList & getForwardingHint() const
Definition: interest.hpp:205
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: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
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:137