nlsr.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, The University of Memphis,
4  * Regents of the University of California,
5  * Arizona Board of Regents.
6  *
7  * This file is part of NLSR (Named-data Link State Routing).
8  * See AUTHORS.md for complete list of NLSR authors and contributors.
9  *
10  * NLSR is free software: you can redistribute it and/or modify it under the terms
11  * of the GNU General Public License as published by the Free Software Foundation,
12  * either version 3 of the License, or (at your option) any later version.
13  *
14  * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  * PURPOSE. See the GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
20  **/
21 
22 #include "nlsr.hpp"
23 #include "adjacent.hpp"
24 #include "logger.hpp"
25 
26 #include <cstdlib>
27 #include <string>
28 #include <sstream>
29 #include <cstdio>
30 #include <unistd.h>
31 #include <vector>
32 
33 #include <ndn-cxx/net/face-uri.hpp>
34 #include <ndn-cxx/signature.hpp>
35 
36 namespace nlsr {
37 
38 INIT_LOGGER(Nlsr);
39 
40 const ndn::Name Nlsr::LOCALHOST_PREFIX = ndn::Name("/localhost/nlsr");
41 
42 Nlsr::Nlsr(ndn::Face& face, ndn::KeyChain& keyChain, ConfParameter& confParam)
43  : m_face(face)
44  , m_scheduler(face.getIoService())
45  , m_keyChain(keyChain)
46  , m_confParam(confParam)
47  , m_adjacencyList(confParam.getAdjacencyList())
48  , m_namePrefixList(confParam.getNamePrefixList())
49  , m_validator(m_confParam.getValidator())
50  , m_fib(m_face, m_scheduler, m_adjacencyList, m_confParam, m_keyChain)
51  , m_routingTable(m_scheduler, m_fib, m_lsdb, m_namePrefixTable, m_confParam)
52  , m_namePrefixTable(m_fib, m_routingTable, m_routingTable.afterRoutingChange)
53  , m_lsdb(m_face, m_keyChain, m_signingInfo, m_confParam, m_namePrefixTable, m_routingTable)
54  , m_helloProtocol(m_face, m_keyChain, m_signingInfo, confParam, m_routingTable, m_lsdb)
55  , m_afterSegmentValidatedConnection(m_lsdb.afterSegmentValidatedSignal.connect(
56  std::bind(&Nlsr::afterFetcherSignalEmitted, this, _1)))
57  , m_onNewLsaConnection(m_lsdb.getSync().onNewLsa->connect(
58  [this] (const ndn::Name& updateName, uint64_t sequenceNumber,
59  const ndn::Name& originRouter) {
60  registerStrategyForCerts(originRouter);
61  }))
62  , m_onPrefixRegistrationSuccess(m_fib.onPrefixRegistrationSuccess.connect(
63  [this] (const ndn::Name& name) {
64  m_helloProtocol.sendHelloInterest(name);
65  }))
66  , m_onHelloDataValidated(m_helloProtocol.onHelloDataValidated.connect(
67  [this] (const ndn::Name& neighbor) {
68  auto it = m_adjacencyList.findAdjacent(neighbor);
69  if (it != m_adjacencyList.end()) {
70  m_fib.registerPrefix(m_confParam.getSyncPrefix(), it->getFaceUri(), it->getLinkCost(),
71  ndn::time::milliseconds::max(), ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
72  }
73  }))
74  , m_dispatcher(m_face, m_keyChain)
75  , m_datasetHandler(m_dispatcher, m_lsdb, m_routingTable)
76  , m_certStore(m_confParam.getCertStore())
77  , m_controller(m_face, m_keyChain)
78  , m_faceDatasetController(m_face, m_keyChain)
79  , m_prefixUpdateProcessor(m_dispatcher,
80  m_confParam.getPrefixUpdateValidator(),
81  m_namePrefixList,
82  m_lsdb,
83  m_confParam.getConfFileNameDynamic())
84  , m_nfdRibCommandProcessor(m_dispatcher,
85  m_namePrefixList,
86  m_lsdb)
87  , m_statsCollector(m_lsdb, m_helloProtocol)
88  , m_faceMonitor(m_face)
89 {
90  NLSR_LOG_DEBUG("Initializing Nlsr");
91 
92  m_faceMonitor.onNotification.connect(std::bind(&Nlsr::onFaceEventNotification, this, _1));
93  m_faceMonitor.start();
94 
95  // Do key initialization and registrations first, then initialize faces
96  // which will create routes to neighbor
97 
98  setStrategies();
99 
100  initializeKey();
101 
102  NLSR_LOG_DEBUG("Default NLSR identity: " << m_signingInfo.getSignerName());
103 
104  // Can be moved to HelloProtocol and Lsdb ctor if initializeKey is set
105  // earlier in the Nlsr constructor so as to set m_signingInfo
106  setInfoInterestFilter();
107  setLsaInterestFilter();
108 
109  // add top-level prefixes: router and localhost prefix
110  addDispatcherTopPrefix(ndn::Name(m_confParam.getRouterPrefix()).append("nlsr"));
111  addDispatcherTopPrefix(LOCALHOST_PREFIX);
112 
113  enableIncomingFaceIdIndication();
114 
115  registerKeyPrefix();
116  registerLocalhostPrefix();
117  registerRouterPrefix();
118 
119  initializeFaces(std::bind(&Nlsr::processFaceDataset, this, _1),
120  std::bind(&Nlsr::onFaceDatasetFetchTimeout, this, _1, _2, 0));
121 
122  // Could be moved into ctor, but unit tests need to be modified
123  initialize();
124 }
125 
126 void
127 Nlsr::registerStrategyForCerts(const ndn::Name& originRouter)
128 {
129  for (const ndn::Name& router : m_strategySetOnRouters) {
130  if (router == originRouter) {
131  // Have already set strategy for this router's certs once
132  return;
133  }
134  }
135 
136  m_strategySetOnRouters.push_back(originRouter);
137 
138  ndn::Name routerKey(originRouter);
139  routerKey.append("KEY");
140  ndn::Name instanceKey(originRouter);
141  instanceKey.append("nlsr").append("KEY");
142 
143  m_fib.setStrategy(routerKey, Fib::BEST_ROUTE_V2_STRATEGY, 0);
144  m_fib.setStrategy(instanceKey, Fib::BEST_ROUTE_V2_STRATEGY, 0);
145 
146  ndn::Name siteKey;
147  for (size_t i = 0; i < originRouter.size(); ++i) {
148  if (originRouter[i].toUri() == "%C1.Router") {
149  break;
150  }
151  siteKey.append(originRouter[i]);
152  }
153  ndn::Name opPrefix(siteKey);
154  siteKey.append("KEY");
155  m_fib.setStrategy(siteKey, Fib::BEST_ROUTE_V2_STRATEGY, 0);
156 
157  opPrefix.append(std::string("%C1.Operator"));
158  m_fib.setStrategy(opPrefix, Fib::BEST_ROUTE_V2_STRATEGY, 0);
159 }
160 
161 void
162 Nlsr::registrationFailed(const ndn::Name& name)
163 {
164  NLSR_LOG_ERROR("ERROR: Failed to register prefix " << name << " in local hub's daemon");
165  BOOST_THROW_EXCEPTION(Error("Error: Prefix registration failed"));
166 }
167 
168 void
169 Nlsr::onRegistrationSuccess(const ndn::Name& name)
170 {
171  NLSR_LOG_DEBUG("Successfully registered prefix: " << name);
172 }
173 
174 void
176 {
177  ndn::Name name(m_confParam.getRouterPrefix());
178  name.append("nlsr");
179  name.append("INFO");
180 
181  NLSR_LOG_DEBUG("Setting interest filter for Hello interest: " << name);
182 
183  m_face.setInterestFilter(ndn::InterestFilter(name).allowLoopback(false),
184  std::bind(&HelloProtocol::processInterest, &m_helloProtocol, _1, _2),
185  std::bind(&Nlsr::onRegistrationSuccess, this, _1),
186  std::bind(&Nlsr::registrationFailed, this, _1),
187  m_signingInfo, ndn::nfd::ROUTE_FLAG_CAPTURE);
188 }
189 
190 void
192 {
193  ndn::Name name = m_confParam.getLsaPrefix();
194 
195  NLSR_LOG_DEBUG("Setting interest filter for LsaPrefix: " << name);
196 
197  m_face.setInterestFilter(ndn::InterestFilter(name).allowLoopback(false),
198  std::bind(&Lsdb::processInterest, &m_lsdb, _1, _2),
199  std::bind(&Nlsr::onRegistrationSuccess, this, _1),
200  std::bind(&Nlsr::registrationFailed, this, _1),
201  m_signingInfo, ndn::nfd::ROUTE_FLAG_CAPTURE);
202 }
203 
204 void
205 Nlsr::addDispatcherTopPrefix(const ndn::Name& topPrefix)
206 {
207  try {
208  // false since we want to have control over the registration process
209  m_dispatcher.addTopPrefix(topPrefix, false, m_signingInfo);
210  }
211  catch (const std::exception& e) {
212  NLSR_LOG_ERROR("Error setting top-level prefix in dispatcher: " << e.what() << "\n");
213  }
214 }
215 
216 void
218 {
219  m_fib.setStrategy(m_confParam.getLsaPrefix(), Fib::MULTICAST_STRATEGY, 0);
220  m_fib.setStrategy(m_confParam.getSyncPrefix(), Fib::MULTICAST_STRATEGY, 0);
221 }
222 
223 void
224 Nlsr::loadCertToPublish(const ndn::security::v2::Certificate& certificate)
225 {
226  NLSR_LOG_TRACE("Loading cert to publish.");
227  m_certStore.insert(certificate);
228  m_validator.loadAnchor("Authoritative-Certificate",
229  ndn::security::v2::Certificate(certificate));
230  m_prefixUpdateProcessor.getValidator().
231  loadAnchor("Authoritative-Certificate",
232  ndn::security::v2::Certificate(certificate));
233 }
234 
235 void
236 Nlsr::afterFetcherSignalEmitted(const ndn::Data& lsaSegment)
237 {
238  ndn::Name keyName = lsaSegment.getSignature().getKeyLocator().getName();
239  if (getCertificate(keyName) == nullptr) {
240  NLSR_LOG_TRACE("Publishing certificate for: " << keyName);
241  publishCertFromCache(keyName);
242  }
243  else {
244  NLSR_LOG_TRACE("Certificate is already in the store: " << keyName);
245  }
246 }
247 
248 void
249 Nlsr::publishCertFromCache(const ndn::Name& keyName)
250 {
251  const ndn::security::v2::Certificate* cert = m_validator.getUnverifiedCertCache()
252  .find(keyName);
253 
254  if (cert != nullptr) {
255  m_certStore.insert(*cert);
256  NLSR_LOG_TRACE(*cert);
257  ndn::Name certName = ndn::security::v2::extractKeyNameFromCertName(cert->getName());
258  NLSR_LOG_TRACE("Setting interest filter for: " << certName);
259  m_face.setInterestFilter(ndn::InterestFilter(certName).allowLoopback(false),
260  std::bind(&Nlsr::onKeyInterest, this, _1, _2),
261  std::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
262  std::bind(&Nlsr::registrationFailed, this, _1),
263  m_signingInfo, ndn::nfd::ROUTE_FLAG_CAPTURE);
264 
265  if (!cert->getKeyName().equals(cert->getSignature().getKeyLocator().getName())) {
266  publishCertFromCache(cert->getSignature().getKeyLocator().getName());
267  }
268  }
269  else {
270  // Happens for root cert
271  NLSR_LOG_TRACE("Cert for " << keyName << " was not found in the Validator's cache. ");
272  }
273 }
274 
275 void
277 {
278  // Logging start
279  m_adjacencyList.writeLog();
280  NLSR_LOG_DEBUG(m_namePrefixList);
281 
282  m_lsdb.buildAndInstallOwnNameLsa();
283 
284  // Install coordinate LSAs if using HR or dry-run HR.
285  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
286  m_lsdb.buildAndInstallOwnCoordinateLsa();
287  }
288 
289  // Need to set direct neighbors' costs to 0 for hyperbolic routing
290  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
291  for (auto&& neighbor : m_adjacencyList.getAdjList()) {
292  neighbor.setLinkCost(0);
293  }
294  }
295 }
296 
297 void
299 {
300  NLSR_LOG_DEBUG("Initializing Key ...");
301 
302  ndn::Name nlsrInstanceName = m_confParam.getRouterPrefix();
303  nlsrInstanceName.append("nlsr");
304 
305  try {
306  m_keyChain.deleteIdentity(m_keyChain.getPib().getIdentity(nlsrInstanceName));
307  }
308  catch (const std::exception& e) {
309  NLSR_LOG_WARN(e.what());
310  }
311 
312  ndn::security::Identity nlsrInstanceIdentity;
313  try {
314  nlsrInstanceIdentity = m_keyChain.createIdentity(nlsrInstanceName);
315  }
316  catch (const std::exception& e) {
317  NLSR_LOG_ERROR(e.what());
318  NLSR_LOG_ERROR("Unable to create identity, NLSR will run without security!");
319  NLSR_LOG_ERROR("Can be ignored if running in non-production environments.");
320  return;
321  }
322  auto nlsrInstanceKey = nlsrInstanceIdentity.getDefaultKey();
323 
324  ndn::security::v2::Certificate certificate;
325 
326  ndn::Name certificateName = nlsrInstanceKey.getName();
327  certificateName.append("NA");
328  certificateName.appendVersion();
329  certificate.setName(certificateName);
330 
331  // set metainfo
332  certificate.setContentType(ndn::tlv::ContentType_Key);
333  certificate.setFreshnessPeriod(ndn::time::days(365));
334 
335  // set content
336  certificate.setContent(nlsrInstanceKey.getPublicKey().data(), nlsrInstanceKey.getPublicKey().size());
337 
338  // set signature-info
339  ndn::SignatureInfo signatureInfo;
340  signatureInfo.setValidityPeriod(ndn::security::ValidityPeriod(ndn::time::system_clock::TimePoint(),
341  ndn::time::system_clock::now()
342  + ndn::time::days(365)));
343  try {
344  m_keyChain.sign(certificate,
345  ndn::security::SigningInfo(m_keyChain.getPib().getIdentity(m_confParam.getRouterPrefix()))
346  .setSignatureInfo(signatureInfo));
347  }
348  catch (const std::exception& e) {
349  NLSR_LOG_ERROR("Router's " << e.what() << "NLSR is running without security." <<
350  " If security is enabled NLSR will not converge.");
351  }
352 
353  m_signingInfo = ndn::security::SigningInfo(ndn::security::SigningInfo::SIGNER_TYPE_ID,
354  nlsrInstanceName);
355 
356  loadCertToPublish(certificate);
357 }
358 
359 void
360 Nlsr::registerKeyPrefix()
361 {
362  // Start listening for the interest of this router's NLSR certificate
363  ndn::Name nlsrKeyPrefix = m_confParam.getRouterPrefix();
364  nlsrKeyPrefix.append("nlsr");
365  nlsrKeyPrefix.append("KEY");
366 
367  m_face.setInterestFilter(ndn::InterestFilter(nlsrKeyPrefix).allowLoopback(false),
368  std::bind(&Nlsr::onKeyInterest, this, _1, _2),
369  std::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
370  std::bind(&Nlsr::registrationFailed, this, _1),
371  m_signingInfo, ndn::nfd::ROUTE_FLAG_CAPTURE);
372 
373  // Start listening for the interest of this router's certificate
374  ndn::Name routerKeyPrefix = m_confParam.getRouterPrefix();
375  routerKeyPrefix.append("KEY");
376 
377  m_face.setInterestFilter(ndn::InterestFilter(routerKeyPrefix).allowLoopback(false),
378  std::bind(&Nlsr::onKeyInterest, this, _1, _2),
379  std::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
380  std::bind(&Nlsr::registrationFailed, this, _1),
381  m_signingInfo, ndn::nfd::ROUTE_FLAG_CAPTURE);
382 
383  // Start listening for the interest of this router's operator's certificate
384  ndn::Name operatorKeyPrefix = m_confParam.getNetwork();
385  operatorKeyPrefix.append(m_confParam.getSiteName());
386  operatorKeyPrefix.append(std::string("%C1.Operator"));
387 
388  m_face.setInterestFilter(ndn::InterestFilter(operatorKeyPrefix).allowLoopback(false),
389  std::bind(&Nlsr::onKeyInterest, this, _1, _2),
390  std::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
391  std::bind(&Nlsr::registrationFailed, this, _1),
392  m_signingInfo, ndn::nfd::ROUTE_FLAG_CAPTURE);
393 
394  // Start listening for the interest of this router's site's certificate
395  ndn::Name siteKeyPrefix = m_confParam.getNetwork();
396  siteKeyPrefix.append(m_confParam.getSiteName());
397  siteKeyPrefix.append("KEY");
398 
399  m_face.setInterestFilter(ndn::InterestFilter(siteKeyPrefix).allowLoopback(false),
400  std::bind(&Nlsr::onKeyInterest, this, _1, _2),
401  std::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
402  std::bind(&Nlsr::registrationFailed, this, _1),
403  m_signingInfo, ndn::nfd::ROUTE_FLAG_CAPTURE);
404 }
405 
406 void
407 Nlsr::registerLocalhostPrefix()
408 {
409  m_face.registerPrefix(LOCALHOST_PREFIX,
410  std::bind(&Nlsr::onRegistrationSuccess, this, _1),
411  std::bind(&Nlsr::registrationFailed, this, _1));
412 }
413 
414 void
415 Nlsr::registerRouterPrefix()
416 {
417  m_face.registerPrefix(ndn::Name(m_confParam.getRouterPrefix()).append("nlsr"),
418  std::bind(&Nlsr::onRegistrationSuccess, this, _1),
419  std::bind(&Nlsr::registrationFailed, this, _1));
420 }
421 
422 void
423 Nlsr::onKeyInterest(const ndn::Name& name, const ndn::Interest& interest)
424 {
425  NLSR_LOG_DEBUG("Got interest for certificate. Interest: " << interest.getName());
426 
427  const ndn::Name& interestName = interest.getName();
428  const ndn::security::v2::Certificate* cert = getCertificate(interestName);
429 
430  if (cert == nullptr) {
431  NLSR_LOG_DEBUG("Certificate is not found for: " << interest);
432  return; // cert is not found
433  }
434 
435  m_face.put(*cert);
436 }
437 
438 void
439 Nlsr::onKeyPrefixRegSuccess(const ndn::Name& name)
440 {
441  NLSR_LOG_DEBUG("KEY prefix: " << name << " registration is successful.");
442 }
443 
444 void
445 Nlsr::onFaceEventNotification(const ndn::nfd::FaceEventNotification& faceEventNotification)
446 {
447  NLSR_LOG_TRACE("Nlsr::onFaceEventNotification called");
448 
449  switch (faceEventNotification.getKind()) {
450  case ndn::nfd::FACE_EVENT_DESTROYED: {
451  uint64_t faceId = faceEventNotification.getFaceId();
452 
453  auto adjacent = m_adjacencyList.findAdjacent(faceId);
454 
455  if (adjacent != m_adjacencyList.end()) {
456  NLSR_LOG_DEBUG("Face to " << adjacent->getName() << " with face id: " << faceId << " destroyed");
457 
458  adjacent->setFaceId(0);
459 
460  // Only trigger an Adjacency LSA build if this node is changing
461  // from ACTIVE to INACTIVE since this rebuild will effectively
462  // cancel the previous Adjacency LSA refresh event and schedule
463  // a new one further in the future.
464  //
465  // Continuously scheduling the refresh in the future will block
466  // the router from refreshing its Adjacency LSA. Since other
467  // routers' Name prefixes' expiration times are updated when
468  // this router refreshes its Adjacency LSA, the other routers'
469  // prefixes will expire and be removed from the RIB.
470  //
471  // This check is required to fix Bug #2733 for now. This check
472  // would be unnecessary to fix Bug #2733 when Issue #2732 is
473  // completed, but the check also helps with optimization so it
474  // can remain even when Issue #2732 is implemented.
475  if (adjacent->getStatus() == Adjacent::STATUS_ACTIVE) {
476  adjacent->setStatus(Adjacent::STATUS_INACTIVE);
477 
478  // A new adjacency LSA cannot be built until the neighbor is marked INACTIVE and
479  // has met the HELLO retry threshold
480  adjacent->setInterestTimedOutNo(m_confParam.getInterestRetryNumber());
481 
482  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
483  m_routingTable.scheduleRoutingTableCalculation();
484  }
485  else {
486  m_lsdb.scheduleAdjLsaBuild();
487  }
488  }
489  }
490  break;
491  }
492  case ndn::nfd::FACE_EVENT_CREATED: {
493  // Find the neighbor in our adjacency list
494  ndn::FaceUri faceUri;
495  try {
496  faceUri = ndn::FaceUri(faceEventNotification.getRemoteUri());
497  }
498  catch (const std::exception& e) {
499  NLSR_LOG_WARN(e.what());
500  return;
501  }
502  auto adjacent = m_adjacencyList.findAdjacent(faceUri);
503  uint64_t faceId = faceEventNotification.getFaceId();
504 
505  // If we have a neighbor by that FaceUri and it has no FaceId or
506  // the FaceId is different from ours, we have a match.
507  if (adjacent != m_adjacencyList.end() &&
508  (adjacent->getFaceId() == 0 || adjacent->getFaceId() != faceId))
509  {
510  NLSR_LOG_DEBUG("Face creation event matches neighbor: " << adjacent->getName()
511  << ". New Face ID: " << faceId << ". Registering prefixes.");
512  adjacent->setFaceId(faceId);
513 
514  registerAdjacencyPrefixes(*adjacent, ndn::time::milliseconds::max());
515 
516  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
517  m_routingTable.scheduleRoutingTableCalculation();
518  }
519  else {
520  m_lsdb.scheduleAdjLsaBuild();
521  }
522  }
523  break;
524  }
525  default:
526  break;
527  }
528 }
529 
530 void
532  const FetchDatasetTimeoutCallback& onFetchFailure)
533 {
534  NLSR_LOG_TRACE("Initializing Faces...");
535 
536  m_faceDatasetController.fetch<ndn::nfd::FaceDataset>(onFetchSuccess, onFetchFailure);
537 
538 }
539 
540 void
541 Nlsr::processFaceDataset(const std::vector<ndn::nfd::FaceStatus>& faces)
542 {
543  NLSR_LOG_DEBUG("Processing face dataset");
544 
545  // Iterate over each neighbor listed in nlsr.conf
546  for (auto&& adjacent : m_adjacencyList.getAdjList()) {
547 
548  const std::string& faceUriString = adjacent.getFaceUri().toString();
549  // Check the list of FaceStatus objects we got for a match
550  for (const auto& faceStatus : faces) {
551  // Set the adjacency FaceID if we find a URI match and it was
552  // previously unset. Change the boolean to true.
553  if (adjacent.getFaceId() == 0 && faceUriString == faceStatus.getRemoteUri()) {
554  NLSR_LOG_DEBUG("FaceUri: " << faceStatus.getRemoteUri() <<
555  " FaceId: "<< faceStatus.getFaceId());
556  adjacent.setFaceId(faceStatus.getFaceId());
557  // Register the prefixes for each neighbor
558  this->registerAdjacencyPrefixes(adjacent, ndn::time::milliseconds::max());
559  }
560  }
561  // If this adjacency has no information in this dataset, then one
562  // of two things is happening: 1. NFD is starting slowly and this
563  // Face wasn't ready yet, or 2. NFD is configured
564  // incorrectly and this Face isn't available.
565  if (adjacent.getFaceId() == 0) {
566  NLSR_LOG_WARN("The adjacency " << adjacent.getName() <<
567  " has no Face information in this dataset.");
568  }
569  }
570 
571  scheduleDatasetFetch();
572 }
573 
574 void
576  const ndn::time::milliseconds& timeout)
577 {
578  ndn::FaceUri faceUri = adj.getFaceUri();
579  double linkCost = adj.getLinkCost();
580  const ndn::Name& adjName = adj.getName();
581 
582  m_fib.registerPrefix(adjName, faceUri, linkCost,
583  timeout, ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
584 
585  m_fib.registerPrefix(m_confParam.getLsaPrefix(),
586  faceUri, linkCost, timeout,
587  ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
588 }
589 
590 void
592  const std::string& msg,
593  uint32_t nRetriesSoFar)
594 {
595  NLSR_LOG_DEBUG("onFaceDatasetFetchTimeout");
596  // If we have exceeded the maximum attempt count, do not try again.
597  if (nRetriesSoFar++ < m_confParam.getFaceDatasetFetchTries()) {
598  NLSR_LOG_DEBUG("Failed to fetch dataset: " << msg << ". Attempting retry #" << nRetriesSoFar);
599  m_faceDatasetController.fetch<ndn::nfd::FaceDataset>(std::bind(&Nlsr::processFaceDataset,
600  this, _1),
602  this, _1, _2, nRetriesSoFar));
603  }
604  else {
605  NLSR_LOG_ERROR("Failed to fetch dataset: " << msg << ". Exceeded limit of " <<
606  m_confParam.getFaceDatasetFetchTries() << ", so not trying again this time.");
607  // If we fail to fetch it, just do nothing until the next
608  // interval. Since this is a backup mechanism, we aren't as
609  // concerned with retrying.
610  scheduleDatasetFetch();
611  }
612 }
613 
614 void
615 Nlsr::scheduleDatasetFetch()
616 {
617  NLSR_LOG_DEBUG("Scheduling Dataset Fetch in " << m_confParam.getFaceDatasetFetchInterval());
618 
619  m_scheduler.schedule(m_confParam.getFaceDatasetFetchInterval(),
620  [this] {
621  this->initializeFaces(
622  [this] (const std::vector<ndn::nfd::FaceStatus>& faces) {
623  this->processFaceDataset(faces);
624  },
625  [this] (uint32_t code, const std::string& msg) {
626  this->onFaceDatasetFetchTimeout(code, msg, 0);
627  });
628  });
629 }
630 
631 void
632 Nlsr::enableIncomingFaceIdIndication()
633 {
634  NLSR_LOG_DEBUG("Enabling incoming face id indication for local face.");
635 
636  m_controller.start<ndn::nfd::FaceUpdateCommand>(
637  ndn::nfd::ControlParameters()
638  .setFlagBit(ndn::nfd::FaceFlagBit::BIT_LOCAL_FIELDS_ENABLED, true),
639  bind(&Nlsr::onFaceIdIndicationSuccess, this, _1),
640  bind(&Nlsr::onFaceIdIndicationFailure, this, _1));
641 }
642 
643 void
644 Nlsr::onFaceIdIndicationSuccess(const ndn::nfd::ControlParameters& cp)
645 {
646  NLSR_LOG_DEBUG("Successfully enabled incoming face id indication"
647  << "for face id " << cp.getFaceId());
648 }
649 
650 void
651 Nlsr::onFaceIdIndicationFailure(const ndn::nfd::ControlResponse& cr)
652 {
653  std::ostringstream os;
654  os << "Failed to enable incoming face id indication feature: " <<
655  "(code: " << cr.getCode() << ", reason: " << cr.getText() << ")";
656 
657  NLSR_LOG_DEBUG(os.str());
658 }
659 
660 } // namespace nlsr
void initializeFaces(const FetchDatasetCallback &onFetchSuccess, const FetchDatasetTimeoutCallback &onFetchFailure)
Initializes neighbors&#39; Faces using information from NFD.
Definition: nlsr.cpp:531
void onFaceDatasetFetchTimeout(uint32_t code, const std::string &reason, uint32_t nRetriesSoFar)
Definition: nlsr.cpp:591
#define NLSR_LOG_WARN(x)
Definition: logger.hpp:40
A class to house all the configuration parameters for NLSR.
Definition: tlv-nlsr.hpp:27
void initialize()
Definition: nlsr.cpp:276
std::function< void(uint32_t, const std::string &)> FetchDatasetTimeoutCallback
Definition: nlsr.hpp:71
const ndn::FaceUri & getFaceUri() const
Definition: adjacent.hpp:69
static const std::string MULTICAST_STRATEGY
Definition: fib.hpp:227
void setStrategies()
Definition: nlsr.cpp:217
double getLinkCost() const
Definition: adjacent.hpp:81
void scheduleRoutingTableCalculation()
Schedules a calculation event in the event scheduler only if one isn&#39;t already scheduled.
#define NLSR_LOG_DEBUG(x)
Definition: logger.hpp:38
const ndn::Name & getRouterPrefix() const
STL namespace.
std::function< void(const std::vector< ndn::nfd::FaceStatus > &)> FetchDatasetCallback
Definition: nlsr.hpp:70
Nlsr(ndn::Face &face, ndn::KeyChain &keyChain, ConfParameter &confParam)
Definition: nlsr.cpp:42
void setStrategy(const ndn::Name &name, const std::string &strategy, uint32_t count)
Definition: fib.cpp:293
static const std::string BEST_ROUTE_V2_STRATEGY
Definition: fib.hpp:228
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California.
void setLsaInterestFilter()
Definition: nlsr.cpp:191
void addDispatcherTopPrefix(const ndn::Name &topPrefix)
Add top level prefixes for Dispatcher.
Definition: nlsr.cpp:205
static const ndn::Name LOCALHOST_PREFIX
Definition: nlsr.hpp:263
void registerAdjacencyPrefixes(const Adjacent &adj, const ndn::time::milliseconds &timeout)
Registers NLSR-specific prefixes for a neighbor (Adjacent)
Definition: nlsr.cpp:575
#define INIT_LOGGER(name)
Definition: logger.hpp:35
const ndn::Name & getSyncPrefix() const
uint32_t getInterestRetryNumber() const
ndn::security::ValidatorConfig & getValidator()
const ndn::Name & getName() const
Definition: adjacent.hpp:57
ndn::util::Signal< HelloProtocol, const ndn::Name & > onHelloDataValidated
void insert(const ndn::security::v2::Certificate &certificate)
const ndn::Name & getLsaPrefix() const
void onRegistrationSuccess(const ndn::Name &name)
Definition: nlsr.cpp:169
void loadCertToPublish(const ndn::security::v2::Certificate &certificate)
Add a certificate NLSR claims to be authoritative for to the certificate store.
Definition: nlsr.cpp:224
void publishCertFromCache(const ndn::Name &keyName)
Retrieves the chain of certificates from Validator&#39;s cache and store them in Nlsr&#39;s own CertificateSt...
Definition: nlsr.cpp:249
void processInterest(const ndn::Name &name, const ndn::Interest &interest)
Processes a Hello Interest from a neighbor.
void setInfoInterestFilter()
Definition: nlsr.cpp:175
void afterFetcherSignalEmitted(const ndn::Data &lsaSegment)
Callback when SegmentFetcher retrieves a segment.
Definition: nlsr.cpp:236
void processInterest(const ndn::Name &name, const ndn::Interest &interest)
Definition: lsdb.cpp:1004
A neighbor reachable over a Face.
Definition: adjacent.hpp:38
void registerStrategyForCerts(const ndn::Name &originRouter)
Definition: nlsr.cpp:127
#define NLSR_LOG_ERROR(x)
Definition: logger.hpp:41
void registrationFailed(const ndn::Name &name)
Definition: nlsr.cpp:162
Copyright (c) 2014-2019, The University of Memphis, Regents of the University of California, Arizona Board of Regents.
AdjacencyList::iterator findAdjacent(const ndn::Name &adjName)
uint32_t getFaceDatasetFetchTries() const
const ndn::Name & getNetwork() const
const ndn::security::v2::Certificate * getCertificate(const ndn::Name &certificateKeyName)
Find a certificate.
Definition: nlsr.hpp:193
int32_t getHyperbolicState() const
ndn::util::Signal< Fib, const ndn::Name & > onPrefixRegistrationSuccess
Definition: fib.hpp:229
const ndn::Name & getSiteName() const
void processFaceDataset(const std::vector< ndn::nfd::FaceStatus > &faces)
Consumes a Face StatusDataset to configure NLSR neighbors.
Definition: nlsr.cpp:541
const ndn::time::seconds getFaceDatasetFetchInterval() const
std::list< Adjacent > & getAdjList()
void initializeKey()
Definition: nlsr.cpp:298
#define NLSR_LOG_TRACE(x)
Definition: logger.hpp:37
const_iterator end() const
void registerPrefix(const ndn::Name &namePrefix, const ndn::FaceUri &faceUri, uint64_t faceCost, const ndn::time::milliseconds &timeout, uint64_t flags, uint8_t times)
Inform NFD of a next-hop.
Definition: fib.cpp:201