lsdb.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2020, 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 "lsdb.hpp"
23 
24 #include "logger.hpp"
25 #include "nlsr.hpp"
26 #include "utility/name-helper.hpp"
27 
28 #include <ndn-cxx/security/signing-helpers.hpp>
29 
30 namespace nlsr {
31 
32 INIT_LOGGER(Lsdb);
33 
34 const ndn::Name::Component Lsdb::NAME_COMPONENT = ndn::Name::Component("lsdb");
35 const ndn::time::seconds Lsdb::GRACE_PERIOD = ndn::time::seconds(10);
36 const ndn::time::steady_clock::TimePoint Lsdb::DEFAULT_LSA_RETRIEVAL_DEADLINE =
37  ndn::time::steady_clock::TimePoint::min();
38 
39 Lsdb::Lsdb(ndn::Face& face, ndn::KeyChain& keyChain, ConfParameter& confParam,
40  NamePrefixTable& namePrefixTable, RoutingTable& routingTable)
41  : m_face(face)
42  , m_scheduler(face.getIoService())
43  , m_confParam(confParam)
44  , m_namePrefixTable(namePrefixTable)
45  , m_routingTable(routingTable)
46  , m_sync(m_face,
47  [this] (const ndn::Name& routerName, const Lsa::Type& lsaType,
48  const uint64_t& sequenceNumber) {
49  return isLsaNew(routerName, lsaType, sequenceNumber);
50  }, m_confParam)
51  , m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
52  , m_thisRouterPrefix(m_confParam.getRouterPrefix().toUri())
53  , m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
54  , m_sequencingManager(m_confParam.getStateFileDir(), m_confParam.getHyperbolicState())
55  , m_onNewLsaConnection(m_sync.onNewLsa->connect(
56  [this] (const ndn::Name& updateName, uint64_t sequenceNumber,
57  const ndn::Name& originRouter) {
58  ndn::Name lsaInterest{updateName};
59  lsaInterest.appendNumber(sequenceNumber);
60  expressInterest(lsaInterest, 0);
61  }))
62  , m_segmentPublisher(m_face, keyChain)
63  , m_isBuildAdjLsaSheduled(false)
64  , m_adjBuildCount(0)
65 {
66 }
67 
69 {
70  for (const auto& sp : m_fetchers) {
71  sp->stop();
72  }
73 }
74 
75 void
76 Lsdb::onFetchLsaError(uint32_t errorCode,
77  const std::string& msg,
78  const ndn::Name& interestName,
79  uint32_t retransmitNo,
80  const ndn::time::steady_clock::TimePoint& deadline,
81  ndn::Name lsaName,
82  uint64_t seqNo)
83 {
84  NLSR_LOG_DEBUG("Failed to fetch LSA: " << lsaName << ", Error code: " << errorCode
85  << ", Message: " << msg);
86 
87  if (ndn::time::steady_clock::now() < deadline) {
88  auto it = m_highestSeqNo.find(lsaName);
89  if (it != m_highestSeqNo.end() && it->second == seqNo) {
90  // If the SegmentFetcher failed due to an Interest timeout, it is safe to re-express
91  // immediately since at the least the LSA Interest lifetime has elapsed.
92  // Otherwise, it is necessary to delay the Interest re-expression to prevent
93  // the potential for constant Interest flooding.
94  ndn::time::seconds delay = m_confParam.getLsaInterestLifetime();
95 
96  if (errorCode == ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
97  delay = ndn::time::seconds(0);
98  }
99 
100  m_scheduler.schedule(delay, std::bind(&Lsdb::expressInterest, this,
101  interestName, retransmitNo + 1, deadline));
102  }
103  }
104 }
105 
106 void
107 Lsdb::afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName)
108 {
109  auto data = std::make_shared<ndn::Data>(ndn::Name(interestName));
110  try {
111  data->setContent(ndn::Block(bufferPtr));
112  }
113  catch (const std::exception& e) {
114  NDN_LOG_ERROR("LSA content not recognized: " << e.what());
115  return;
116  }
117 
118  NLSR_LOG_DEBUG("Received data for LSA(name): " << data->getName());
119 
120  ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
121  uint64_t seqNo = interestName[-1].toNumber();
122 
123  if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
124  m_highestSeqNo[lsaName] = seqNo;
125  }
126  else if (seqNo > m_highestSeqNo[lsaName]) {
127  m_highestSeqNo[lsaName] = seqNo;
128  NLSR_LOG_TRACE("SeqNo for LSA(name): " << data->getName() << " updated");
129  }
130  else if (seqNo < m_highestSeqNo[lsaName]) {
131  return;
132  }
133 
134  onContentValidated(data);
135 }
136 
142 static bool
143 nameLsaCompareByKey(const NameLsa& nlsa1, const ndn::Name& key)
144 {
145  return nlsa1.getKey() == key;
146 }
147 
148 bool
150 {
151  NameLsa nameLsa(m_confParam.getRouterPrefix(),
152  m_sequencingManager.getNameLsaSeq() + 1,
153  getLsaExpirationTimePoint(),
154  m_confParam.getNamePrefixList());
155  m_sequencingManager.increaseNameLsaSeq();
156 
157  m_sequencingManager.writeSeqNoToFile();
158  m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
159 
160  return installNameLsa(nameLsa);
161 }
162 
163 NameLsa*
164 Lsdb::findNameLsa(const ndn::Name& key)
165 {
166  auto it = std::find_if(m_nameLsdb.begin(), m_nameLsdb.end(),
167  std::bind(nameLsaCompareByKey, _1, key));
168  if (it != m_nameLsdb.end()) {
169  return &*it;
170  }
171  return nullptr;
172 }
173 
174 bool
175 Lsdb::isNameLsaNew(const ndn::Name& key, uint64_t seqNo)
176 {
177  NameLsa* nameLsaCheck = findNameLsa(key);
178  // Is the name in the LSDB
179  if (nameLsaCheck != nullptr) {
180  // And the supplied seq no is the highest so far
181  if (nameLsaCheck->getLsSeqNo() < seqNo) {
182  return true;
183  }
184  else {
185  return false;
186  }
187  }
188  return true;
189 }
190 
191 ndn::scheduler::EventId
192 Lsdb::scheduleNameLsaExpiration(const ndn::Name& key, int seqNo,
193  const ndn::time::seconds& expTime)
194 {
195  return m_scheduler.schedule(expTime + GRACE_PERIOD,
196  std::bind(&Lsdb::expireOrRefreshNameLsa, this, key, seqNo));
197 }
198 
199 bool
201 {
202  NLSR_LOG_TRACE("installNameLsa");
203  ndn::time::seconds timeToExpire = m_lsaRefreshTime;
204  NameLsa* chkNameLsa = findNameLsa(nlsa.getKey());
205  // Determines if the name LSA is new or not.
206  if (chkNameLsa == nullptr) {
207  addNameLsa(nlsa);
208  NLSR_LOG_DEBUG("New Name LSA");
209  NLSR_LOG_DEBUG("Adding Name Lsa");
210  nlsa.writeLog();
211 
212  NLSR_LOG_TRACE("nlsa.getOrigRouter(): " << nlsa.getOrigRouter());
213  NLSR_LOG_TRACE("m_confParam.getRouterPrefix(): " << m_confParam.getRouterPrefix());
214 
215  if (nlsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
216  // If this name LSA is from another router, add the advertised
217  // prefixes to the NPT.
218  m_namePrefixTable.addEntry(nlsa.getOrigRouter(), nlsa.getOrigRouter());
219 
220  for (const auto& name : nlsa.getNpl().getNames()) {
221  if (name != m_confParam.getRouterPrefix()) {
222  m_namePrefixTable.addEntry(name, nlsa.getOrigRouter());
223  }
224  }
225  auto duration = nlsa.getExpirationTimePoint() - ndn::time::system_clock::now();
226  timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
227  }
228 
229  nlsa.setExpiringEventId(scheduleNameLsaExpiration(nlsa.getKey(),
230  nlsa.getLsSeqNo(),
231  timeToExpire));
232  }
233  // Else this is a known name LSA, so we are updating it.
234  else {
235  NLSR_LOG_TRACE("Known name lsa");
236  NLSR_LOG_TRACE("chkNameLsa->getLsSeqNo(): " << chkNameLsa->getLsSeqNo());
237  NLSR_LOG_TRACE("nlsa.getLsSeqNo(): " << nlsa.getLsSeqNo());
238  if (chkNameLsa->getLsSeqNo() < nlsa.getLsSeqNo()) {
239  NLSR_LOG_DEBUG("Updated Name LSA. Updating LSDB");
240  NLSR_LOG_DEBUG("Deleting Name Lsa");
241  chkNameLsa->writeLog();
242  chkNameLsa->setLsSeqNo(nlsa.getLsSeqNo());
244  chkNameLsa->getNpl().sort();
245  nlsa.getNpl().sort();
246  // Obtain the set difference of the current and the incoming
247  // name prefix sets, and add those.
248  std::list<ndn::Name> newNames = nlsa.getNpl().getNames();
249  std::list<ndn::Name> oldNames = chkNameLsa->getNpl().getNames();
250  std::list<ndn::Name> namesToAdd;
251  std::set_difference(newNames.begin(), newNames.end(), oldNames.begin(), oldNames.end(),
252  std::inserter(namesToAdd, namesToAdd.begin()));
253  for (const auto& name : namesToAdd) {
254  chkNameLsa->addName(name);
255  if (nlsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
256  if (name != m_confParam.getRouterPrefix()) {
257  m_namePrefixTable.addEntry(name, nlsa.getOrigRouter());
258  }
259  }
260  }
261 
262  chkNameLsa->getNpl().sort();
263 
264  // Also remove any names that are no longer being advertised.
265  std::list<ndn::Name> namesToRemove;
266  std::set_difference(oldNames.begin(), oldNames.end(), newNames.begin(), newNames.end(),
267  std::inserter(namesToRemove, namesToRemove.begin()));
268  for (const auto& name : namesToRemove) {
269  NLSR_LOG_DEBUG("Removing name LSA no longer advertised: " << name);
270  chkNameLsa->removeName(name);
271  if (nlsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
272  if (name != m_confParam.getRouterPrefix()) {
273  m_namePrefixTable.removeEntry(name, nlsa.getOrigRouter());
274  }
275  }
276  }
277 
278  if (nlsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
279  auto duration = nlsa.getExpirationTimePoint() - ndn::time::system_clock::now();
280  timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
281  }
282  chkNameLsa->getExpiringEventId().cancel();
283  chkNameLsa->setExpiringEventId(scheduleNameLsaExpiration(nlsa.getKey(),
284  nlsa.getLsSeqNo(),
285  timeToExpire));
286  NLSR_LOG_DEBUG("Adding Name Lsa");
287  chkNameLsa->writeLog();
288  }
289  }
290  return true;
291 }
292 
293 bool
294 Lsdb::addNameLsa(NameLsa& nlsa)
295 {
296  auto it = std::find_if(m_nameLsdb.begin(), m_nameLsdb.end(),
297  std::bind(nameLsaCompareByKey, _1, nlsa.getKey()));
298  if (it == m_nameLsdb.end()) {
299  m_nameLsdb.push_back(nlsa);
300  return true;
301  }
302  return false;
303 }
304 
305 bool
306 Lsdb::removeNameLsa(const ndn::Name& key)
307 {
308  auto it = std::find_if(m_nameLsdb.begin(), m_nameLsdb.end(),
309  std::bind(nameLsaCompareByKey, _1, key));
310  if (it != m_nameLsdb.end()) {
311  NLSR_LOG_DEBUG("Deleting Name Lsa");
312  it->writeLog();
313  // If the requested name LSA is not ours, we also need to remove
314  // its entries from the NPT.
315  if (it->getOrigRouter() != m_confParam.getRouterPrefix()) {
316  m_namePrefixTable.removeEntry(it->getOrigRouter(), it->getOrigRouter());
317 
318  for (const auto& name : it->getNpl().getNames()) {
319  if (name != m_confParam.getRouterPrefix()) {
320  m_namePrefixTable.removeEntry(name, it->getOrigRouter());
321  }
322  }
323  }
324  m_nameLsdb.erase(it);
325  return true;
326  }
327  return false;
328 }
329 
330 bool
331 Lsdb::doesNameLsaExist(const ndn::Name& key)
332 {
333  auto it = std::find_if(m_nameLsdb.begin(), m_nameLsdb.end(),
334  std::bind(nameLsaCompareByKey, _1, key));
335  return it != m_nameLsdb.end();
336 }
337 
338 void
340 {
341  NLSR_LOG_DEBUG("---------------Name LSDB-------------------");
342  for (const auto& nlsa : m_nameLsdb) {
343  nlsa.writeLog();
344  }
345 }
346 
347 const std::list<NameLsa>&
349 {
350  return m_nameLsdb;
351 }
352 
353 // Cor LSA and LSDB related Functions start here
354 
359 static bool
360 corLsaCompareByKey(const CoordinateLsa& clsa, const ndn::Name& key)
361 {
362  return clsa.getKey() == key;
363 }
364 
365 bool
367 {
368  CoordinateLsa corLsa(m_confParam.getRouterPrefix(),
369  m_sequencingManager.getCorLsaSeq() + 1,
370  getLsaExpirationTimePoint(),
371  m_confParam.getCorR(),
372  m_confParam.getCorTheta());
373 
374  // Sync coordinate LSAs if using HR or HR dry run.
375  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
376  m_sequencingManager.increaseCorLsaSeq();
377  m_sequencingManager.writeSeqNoToFile();
378  m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
379  }
380 
381  installCoordinateLsa(corLsa);
382 
383  return true;
384 }
385 
387 Lsdb::findCoordinateLsa(const ndn::Name& key)
388 {
389  auto it = std::find_if(m_corLsdb.begin(), m_corLsdb.end(),
390  std::bind(corLsaCompareByKey, _1, key));
391  if (it != m_corLsdb.end()) {
392  return &*it;
393  }
394  return nullptr;
395 }
396 
397 bool
398 Lsdb::isCoordinateLsaNew(const ndn::Name& key, uint64_t seqNo)
399 {
400  CoordinateLsa* clsa = findCoordinateLsa(key);
401  // Is the coordinate LSA in the LSDB already
402  if (clsa != nullptr) {
403  // And the seq no is newer (higher) than the current one
404  if (clsa->getLsSeqNo() < seqNo) {
405  return true;
406  }
407  else {
408  return false;
409  }
410  }
411  return true;
412 }
413 
414  // Schedules a refresh/expire event in the scheduler.
415  // \param key The name of the router that published the LSA.
416  // \param seqNo the seq. no. associated with the LSA to check.
417  // \param expTime How long to wait before triggering the event.
418 ndn::scheduler::EventId
419 Lsdb::scheduleCoordinateLsaExpiration(const ndn::Name& key, int seqNo,
420  const ndn::time::seconds& expTime)
421 {
422  return m_scheduler.schedule(expTime + GRACE_PERIOD,
423  std::bind(&Lsdb::expireOrRefreshCoordinateLsa, this, key, seqNo));
424 }
425 
426 bool
428 {
429  ndn::time::seconds timeToExpire = m_lsaRefreshTime;
430  CoordinateLsa* chkCorLsa = findCoordinateLsa(clsa.getKey());
431  // Checking whether the LSA is new or not.
432  if (chkCorLsa == nullptr) {
433  NLSR_LOG_DEBUG("New Coordinate LSA. Adding to LSDB");
434  NLSR_LOG_DEBUG("Adding Coordinate Lsa");
435  clsa.writeLog();
436  addCoordinateLsa(clsa);
437 
438  // Register the LSA's origin router prefix
439  if (clsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
440  m_namePrefixTable.addEntry(clsa.getOrigRouter(),
441  clsa.getOrigRouter());
442  }
443  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
444  m_routingTable.scheduleRoutingTableCalculation();
445  }
446  // Set the expiration time for the new LSA.
447  if (clsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
448  ndn::time::system_clock::Duration duration = clsa.getExpirationTimePoint() -
449  ndn::time::system_clock::now();
450  timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
451  }
452  scheduleCoordinateLsaExpiration(clsa.getKey(),
453  clsa.getLsSeqNo(), timeToExpire);
454  }
455  // We are just updating this LSA.
456  else {
457  if (chkCorLsa->getLsSeqNo() < clsa.getLsSeqNo()) {
458  NLSR_LOG_DEBUG("Updated Coordinate LSA. Updating LSDB");
459  NLSR_LOG_DEBUG("Deleting Coordinate Lsa");
460  chkCorLsa->writeLog();
461  chkCorLsa->setLsSeqNo(clsa.getLsSeqNo());
463  // If the new LSA contains new routing information, update the LSDB with it.
464  if (!chkCorLsa->isEqualContent(clsa)) {
465  chkCorLsa->setCorRadius(clsa.getCorRadius());
466  chkCorLsa->setCorTheta(clsa.getCorTheta());
467  if (m_confParam.getHyperbolicState() >= HYPERBOLIC_STATE_ON) {
468  m_routingTable.scheduleRoutingTableCalculation();
469  }
470  }
471  // If this is an LSA from another router, refresh its expiration time.
472  if (clsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
473  auto duration = clsa.getExpirationTimePoint() - ndn::time::system_clock::now();
474  timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
475  }
476  chkCorLsa->getExpiringEventId().cancel();
477  chkCorLsa->setExpiringEventId(scheduleCoordinateLsaExpiration(clsa.getKey(),
478  clsa.getLsSeqNo(),
479  timeToExpire));
480  NLSR_LOG_DEBUG("Adding Coordinate Lsa");
481  chkCorLsa->writeLog();
482  }
483  }
484  return true;
485 }
486 
487 bool
488 Lsdb::addCoordinateLsa(CoordinateLsa& clsa)
489 {
490  auto it = std::find_if(m_corLsdb.begin(), m_corLsdb.end(),
491  std::bind(corLsaCompareByKey, _1, clsa.getKey()));
492  if (it == m_corLsdb.end()) {
493  m_corLsdb.push_back(clsa);
494  return true;
495  }
496  return false;
497 }
498 
499 bool
500 Lsdb::removeCoordinateLsa(const ndn::Name& key)
501 {
502  auto it = std::find_if(m_corLsdb.begin(), m_corLsdb.end(),
503  std::bind(corLsaCompareByKey, _1, key));
504 
505  if (it != m_corLsdb.end()) {
506  NLSR_LOG_DEBUG("Deleting Coordinate Lsa");
507  it->writeLog();
508 
509  if (it->getOrigRouter() != m_confParam.getRouterPrefix()) {
510  m_namePrefixTable.removeEntry(it->getOrigRouter(), it->getOrigRouter());
511  }
512 
513  m_corLsdb.erase(it);
514  return true;
515  }
516  return false;
517 }
518 
519 bool
520 Lsdb::doesCoordinateLsaExist(const ndn::Name& key)
521 {
522  auto it = std::find_if(m_corLsdb.begin(), m_corLsdb.end(),
523  std::bind(corLsaCompareByKey, _1, key));
524  return it != m_corLsdb.end();
525 }
526 
527 void
529 {
530  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) {
531  return;
532  }
533 
534  NLSR_LOG_DEBUG("---------------Cor LSDB-------------------");
535  for (const auto& corLsa : m_corLsdb) {
536  corLsa.writeLog();
537  }
538 }
539 
540 const std::list<CoordinateLsa>&
542 {
543  return m_corLsdb;
544 }
545 
546 // Adj LSA and LSDB related function starts here
547 
552 static bool
553 adjLsaCompareByKey(AdjLsa& alsa, const ndn::Name& key)
554 {
555  return alsa.getKey() == key;
556 }
557 
558 void
560 {
561  m_adjBuildCount++;
562 
563  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
564  // Don't build adjacency LSAs in hyperbolic routing
565  NLSR_LOG_DEBUG("Adjacency LSA not built. Currently in hyperbolic routing state.");
566  return;
567  }
568 
569  if (m_isBuildAdjLsaSheduled) {
570  NLSR_LOG_DEBUG("Rescheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
571  }
572  else {
573  NLSR_LOG_DEBUG("Scheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
574  m_isBuildAdjLsaSheduled = true;
575  }
576  m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [this] { buildAdjLsa(); });
577 }
578 
579 void
580 Lsdb::buildAdjLsa()
581 {
582  NLSR_LOG_TRACE("Lsdb::buildAdjLsa called");
583 
584  m_isBuildAdjLsaSheduled = false;
585 
586  if (m_confParam.getAdjacencyList().isAdjLsaBuildable(m_confParam.getInterestRetryNumber())) {
587 
588  int adjBuildCount = m_adjBuildCount;
589  // Only do the adjLsa build if there's one scheduled
590  if (adjBuildCount > 0) {
591  // It only makes sense to do the adjLsa build if we have neighbors
592  if (m_confParam.getAdjacencyList().getNumOfActiveNeighbor() > 0) {
593  NLSR_LOG_DEBUG("Building and installing own Adj LSA");
595  }
596  // We have no active neighbors, meaning no one can route through
597  // us. So delete our entry in the LSDB. This prevents this
598  // router from refreshing the LSA, eventually causing other
599  // routers to delete it, too.
600  else {
601  NLSR_LOG_DEBUG("Removing own Adj LSA; no ACTIVE neighbors");
602  // Get this router's key
603  ndn::Name key = m_confParam.getRouterPrefix();
604  key.append(std::to_string(Lsa::Type::ADJACENCY));
605 
606  removeAdjLsa(key);
607  // Recompute routing table after removal
608  m_routingTable.scheduleRoutingTableCalculation();
609  }
610  // In the case that during building the adj LSA, the FIB has to
611  // wait on an Interest response, the number of scheduled adj LSA
612  // builds could change, so we shouldn't just set it to 0.
613  m_adjBuildCount = m_adjBuildCount - adjBuildCount;
614  }
615  }
616  // We are still waiting to know the adjacency status of some
617  // neighbor, so schedule a build for later (when all that has
618  // hopefully finished)
619  else {
620  m_isBuildAdjLsaSheduled = true;
621  auto schedulingTime = ndn::time::seconds(m_confParam.getInterestRetryNumber() *
622  m_confParam.getInterestResendTime());
623  m_scheduledAdjLsaBuild = m_scheduler.schedule(schedulingTime, [this] { buildAdjLsa(); });
624  }
625 }
626 
627 bool
628 Lsdb::addAdjLsa(AdjLsa& alsa)
629 {
630  auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
631  std::bind(adjLsaCompareByKey, _1, alsa.getKey()));
632  if (it == m_adjLsdb.end()) {
633  m_adjLsdb.push_back(alsa);
634  // Add any new name prefixes to the NPT
635  // Only add NPT entries if this is an adj LSA from another router.
636  if (alsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
637  // Pass the originating router as both the name to register and
638  // where it came from.
639  m_namePrefixTable.addEntry(alsa.getOrigRouter(), alsa.getOrigRouter());
640  }
641  return true;
642  }
643  return false;
644 }
645 
646 AdjLsa*
647 Lsdb::findAdjLsa(const ndn::Name& key)
648 {
649  auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
650  std::bind(adjLsaCompareByKey, _1, key));
651  if (it != m_adjLsdb.end()) {
652  return &*it;
653  }
654  return nullptr;
655 }
656 
657 bool
658 Lsdb::isAdjLsaNew(const ndn::Name& key, uint64_t seqNo)
659 {
660  AdjLsa* adjLsaCheck = findAdjLsa(key);
661  // If it is in the LSDB
662  if (adjLsaCheck != nullptr) {
663  // And the supplied seq no is newer (higher) than the current one.
664  if (adjLsaCheck->getLsSeqNo() < seqNo) {
665  return true;
666  }
667  else {
668  return false;
669  }
670  }
671  return true;
672 }
673 
674 ndn::scheduler::EventId
675 Lsdb::scheduleAdjLsaExpiration(const ndn::Name& key, int seqNo,
676  const ndn::time::seconds& expTime)
677 {
678  return m_scheduler.schedule(expTime + GRACE_PERIOD,
679  std::bind(&Lsdb::expireOrRefreshAdjLsa, this, key, seqNo));
680 }
681 
682 bool
684 {
685  ndn::time::seconds timeToExpire = m_lsaRefreshTime;
686  AdjLsa* chkAdjLsa = findAdjLsa(alsa.getKey());
687  // If this adj. LSA is not in the LSDB already
688  if (chkAdjLsa == nullptr) {
689  NLSR_LOG_DEBUG("New Adj LSA. Adding to LSDB");
690  NLSR_LOG_DEBUG("Adding Adj Lsa");
691  alsa.writeLog();
692  addAdjLsa(alsa);
693 
694  m_routingTable.scheduleRoutingTableCalculation();
695  if (alsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
696  ndn::time::system_clock::Duration duration = alsa.getExpirationTimePoint() -
697  ndn::time::system_clock::now();
698  timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
699  }
700  scheduleAdjLsaExpiration(alsa.getKey(), alsa.getLsSeqNo(), timeToExpire);
701  }
702  else {
703  if (chkAdjLsa->getLsSeqNo() < alsa.getLsSeqNo()) {
704  NLSR_LOG_DEBUG("Updated Adj LSA. Updating LSDB");
705  NLSR_LOG_DEBUG("Deleting Adj Lsa");
706  chkAdjLsa->writeLog();
707  chkAdjLsa->setLsSeqNo(alsa.getLsSeqNo());
709  // If the new adj LSA has new content, update the contents of
710  // the LSDB entry. Additionally, since we've changed the
711  // contents of the LSDB, we have to schedule a routing
712  // calculation.
713  if (!chkAdjLsa->isEqualContent(alsa)) {
714  chkAdjLsa->getAdl().reset();
715  chkAdjLsa->getAdl().addAdjacents(alsa.getAdl());
716  m_routingTable.scheduleRoutingTableCalculation();
717  }
718  if (alsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
719  auto duration = alsa.getExpirationTimePoint() - ndn::time::system_clock::now();
720  timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
721  }
722  chkAdjLsa->getExpiringEventId().cancel();
723  chkAdjLsa->setExpiringEventId(scheduleAdjLsaExpiration(alsa.getKey(),
724  alsa.getLsSeqNo(),
725  timeToExpire));
726  NLSR_LOG_DEBUG("Adding Adj Lsa");
727  chkAdjLsa->writeLog();
728  }
729  }
730  return true;
731 }
732 
733 bool
735 {
736  AdjLsa adjLsa(m_confParam.getRouterPrefix(),
737  m_sequencingManager.getAdjLsaSeq() + 1,
738  getLsaExpirationTimePoint(),
740  m_confParam.getAdjacencyList());
741 
742  //Sync adjacency LSAs if link-state or dry-run HR is enabled.
743  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_ON) {
744  m_sequencingManager.increaseAdjLsaSeq();
745  m_sequencingManager.writeSeqNoToFile();
746  m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
747  }
748 
749  return installAdjLsa(adjLsa);
750 }
751 
752 bool
753 Lsdb::removeAdjLsa(const ndn::Name& key)
754 {
755  auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
756  std::bind(adjLsaCompareByKey, _1, key));
757  if (it != m_adjLsdb.end()) {
758  NLSR_LOG_DEBUG("Deleting Adj Lsa");
759  it->writeLog();
760  if (it->getOrigRouter() != m_confParam.getRouterPrefix()) {
761  m_namePrefixTable.removeEntry(it->getOrigRouter(), it->getOrigRouter());
762  }
763  m_adjLsdb.erase(it);
764  return true;
765  }
766  return false;
767 }
768 
769 bool
770 Lsdb::doesAdjLsaExist(const ndn::Name& key)
771 {
772  auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
773  std::bind(adjLsaCompareByKey, _1, key));
774  return it != m_adjLsdb.end();
775 }
776 
777 const std::list<AdjLsa>&
779 {
780  return m_adjLsdb;
781 }
782 
783  // This function determines whether a name LSA should be refreshed
784  // or expired. The conditions for getting refreshed are: it is still
785  // in the LSDB, it hasn't been updated by something else already (as
786  // evidenced by its seq. no.), and this is the originating router for
787  // the LSA. Is it let expire in all other cases.
788  // lsaKey is the key of the LSA's publishing router.
789  // seqNo is the seq. no. of the candidate LSA.
790 void
791 Lsdb::expireOrRefreshNameLsa(const ndn::Name& lsaKey, uint64_t seqNo)
792 {
793  NLSR_LOG_DEBUG("Lsdb::expireOrRefreshNameLsa Called");
794  NLSR_LOG_DEBUG("LSA Key : " << lsaKey << " Seq No: " << seqNo);
795  NameLsa* chkNameLsa = findNameLsa(lsaKey);
796  // If this name LSA exists in the LSDB
797  if (chkNameLsa != nullptr) {
798  NLSR_LOG_DEBUG("LSA Exists with seq no: " << chkNameLsa->getLsSeqNo());
799  // If its seq no is the one we are expecting.
800  if (chkNameLsa->getLsSeqNo() == seqNo) {
801  if (chkNameLsa->getOrigRouter() == m_thisRouterPrefix) {
802  NLSR_LOG_DEBUG("Own Name LSA, so refreshing it");
803  NLSR_LOG_DEBUG("Deleting Name Lsa");
804  chkNameLsa->writeLog();
805  chkNameLsa->setLsSeqNo(chkNameLsa->getLsSeqNo() + 1);
806  m_sequencingManager.setNameLsaSeq(chkNameLsa->getLsSeqNo());
807  chkNameLsa->setExpirationTimePoint(getLsaExpirationTimePoint());
808  NLSR_LOG_DEBUG("Adding Name Lsa");
809  chkNameLsa->writeLog();
810  // schedule refreshing event again
811  chkNameLsa->setExpiringEventId(scheduleNameLsaExpiration(chkNameLsa->getKey(),
812  chkNameLsa->getLsSeqNo(),
813  m_lsaRefreshTime));
814  m_sequencingManager.writeSeqNoToFile();
815  m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
816  }
817  // Since we cannot refresh other router's LSAs, our only choice is to expire.
818  else {
819  NLSR_LOG_DEBUG("Other's Name LSA, so removing from LSDB");
820  removeNameLsa(lsaKey);
821  }
822  }
823  }
824 }
825 
826  // This function determines whether an adj. LSA should be refreshed
827  // or expired. The conditions for getting refreshed are: it is still
828  // in the LSDB, it hasn't been updated by something else already (as
829  // evidenced by its seq. no.), and this is the originating router for
830  // the LSA. Is it let expire in all other cases.
831  // lsaKey is the key of the LSA's publishing router.
832  // seqNo is the seq. no. of the candidate LSA.
833 void
834 Lsdb::expireOrRefreshAdjLsa(const ndn::Name& lsaKey, uint64_t seqNo)
835 {
836  NLSR_LOG_DEBUG("Lsdb::expireOrRefreshAdjLsa Called");
837  NLSR_LOG_DEBUG("LSA Key: " << lsaKey << " Seq No: " << seqNo);
838  AdjLsa* chkAdjLsa = findAdjLsa(lsaKey);
839  // If this is a valid LSA
840  if (chkAdjLsa != nullptr) {
841  NLSR_LOG_DEBUG("LSA Exists with seq no: " << chkAdjLsa->getLsSeqNo());
842  // And if it hasn't been updated for some other reason
843  if (chkAdjLsa->getLsSeqNo() == seqNo) {
844  // If it is our own LSA
845  if (chkAdjLsa->getOrigRouter() == m_thisRouterPrefix) {
846  NLSR_LOG_DEBUG("Own Adj LSA, so refreshing it");
847  NLSR_LOG_DEBUG("Deleting Adj Lsa");
848  chkAdjLsa->writeLog();
849  chkAdjLsa->setLsSeqNo(chkAdjLsa->getLsSeqNo() + 1);
850  m_sequencingManager.setAdjLsaSeq(chkAdjLsa->getLsSeqNo());
851  chkAdjLsa->setExpirationTimePoint(getLsaExpirationTimePoint());
852  NLSR_LOG_DEBUG("Adding Adj Lsa");
853  chkAdjLsa->writeLog();
854  // schedule refreshing event again
855  chkAdjLsa->setExpiringEventId(scheduleAdjLsaExpiration(chkAdjLsa->getKey(),
856  chkAdjLsa->getLsSeqNo(),
857  m_lsaRefreshTime));
858  m_sequencingManager.writeSeqNoToFile();
859  m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
860  }
861  // An LSA from another router is expiring
862  else {
863  NLSR_LOG_DEBUG("Other's Adj LSA, so removing from LSDB");
864  removeAdjLsa(lsaKey);
865  }
866  // We have changed the contents of the LSDB, so we have to
867  // schedule a routing calculation
868  m_routingTable.scheduleRoutingTableCalculation();
869  }
870  }
871 }
872 
873  // This function determines whether an adj. LSA should be refreshed
874  // or expired. The conditions for getting refreshed are: it is still
875  // in the LSDB, it hasn't been updated by something else already (as
876  // evidenced by its seq. no.), and this is the originating router for
877  // the LSA. It is let expire in all other cases.
878  // lsaKey is the key of the LSA's publishing router.
879  // seqNo is the seq. no. of the candidate LSA.
880 void
881 Lsdb::expireOrRefreshCoordinateLsa(const ndn::Name& lsaKey,
882  uint64_t seqNo)
883 {
884  NLSR_LOG_DEBUG("Lsdb::expireOrRefreshCorLsa Called ");
885  NLSR_LOG_DEBUG("LSA Key : " << lsaKey << " Seq No: " << seqNo);
886  CoordinateLsa* chkCorLsa = findCoordinateLsa(lsaKey);
887  // Whether the LSA is in the LSDB or not.
888  if (chkCorLsa != nullptr) {
889  NLSR_LOG_DEBUG("LSA Exists with seq no: " << chkCorLsa->getLsSeqNo());
890  // Whether the LSA has been updated without our knowledge.
891  if (chkCorLsa->getLsSeqNo() == seqNo) {
892  if (chkCorLsa->getOrigRouter() == m_thisRouterPrefix) {
893  NLSR_LOG_DEBUG("Own Cor LSA, so refreshing it");
894  NLSR_LOG_DEBUG("Deleting Coordinate Lsa");
895  chkCorLsa->writeLog();
896  chkCorLsa->setLsSeqNo(chkCorLsa->getLsSeqNo() + 1);
897  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
898  m_sequencingManager.setCorLsaSeq(chkCorLsa->getLsSeqNo());
899  }
900 
901  chkCorLsa->setExpirationTimePoint(getLsaExpirationTimePoint());
902  NLSR_LOG_DEBUG("Adding Coordinate Lsa");
903  chkCorLsa->writeLog();
904  // schedule refreshing event again
905  chkCorLsa->setExpiringEventId(scheduleCoordinateLsaExpiration(
906  chkCorLsa->getKey(),
907  chkCorLsa->getLsSeqNo(),
908  m_lsaRefreshTime));
909  // Only sync coordinate LSAs if link-state routing is disabled
910  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
911  m_sequencingManager.writeSeqNoToFile();
912  m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
913  }
914  }
915  // We can't refresh other router's LSAs, so we remove it.
916  else {
917  NLSR_LOG_DEBUG("Other's Cor LSA, so removing from LSDB");
918  removeCoordinateLsa(lsaKey);
919  }
920  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
921  m_routingTable.scheduleRoutingTableCalculation();
922  }
923  }
924  }
925 }
926 
927 void
928 Lsdb::expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
929  ndn::time::steady_clock::TimePoint deadline)
930 {
931  // increment SENT_LSA_INTEREST
933 
934  if (deadline == DEFAULT_LSA_RETRIEVAL_DEADLINE) {
935  deadline = ndn::time::steady_clock::now() + ndn::time::seconds(static_cast<int>(LSA_REFRESH_TIME_MAX));
936  }
937  // The first component of the interest is the name.
938  ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
939  // The seq no is the last
940  uint64_t seqNo = interestName[-1].toNumber();
941 
942  // If the LSA is not found in the list currently.
943  if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
944  m_highestSeqNo[lsaName] = seqNo;
945  }
946  // If the new seq no is higher, that means the LSA is valid
947  else if (seqNo > m_highestSeqNo[lsaName]) {
948  m_highestSeqNo[lsaName] = seqNo;
949  }
950  // Otherwise, its an old/invalid LSA
951  else if (seqNo < m_highestSeqNo[lsaName]) {
952  return;
953  }
954 
955  ndn::Interest interest(interestName);
956  ndn::util::SegmentFetcher::Options options;
957  options.interestLifetime = m_confParam.getLsaInterestLifetime();
958 
959  NLSR_LOG_DEBUG("Fetching Data for LSA: " << interestName << " Seq number: " << seqNo);
960  auto fetcher = ndn::util::SegmentFetcher::start(m_face, interest,
961  m_confParam.getValidator(), options);
962 
963  auto it = m_fetchers.insert(fetcher).first;
964 
965  fetcher->afterSegmentValidated.connect([this] (const ndn::Data& data) {
966  // Nlsr class subscribes to this to fetch certificates
968 
969  // If we don't do this IMS throws: std::bad_weak_ptr: bad_weak_ptr
970  auto lsaSegment = std::make_shared<const ndn::Data>(data);
971  m_lsaStorage.insert(*lsaSegment);
972  const ndn::Name& segmentName = lsaSegment->getName();
973  // Schedule deletion of the segment
974  m_scheduler.schedule(ndn::time::seconds(LSA_REFRESH_TIME_DEFAULT),
975  [this, segmentName] { m_lsaStorage.erase(segmentName); });
976  });
977 
978  fetcher->onComplete.connect([=] (const ndn::ConstBufferPtr& bufferPtr) {
979  m_lsaStorage.erase(ndn::Name(lsaName).appendNumber(seqNo - 1));
980  afterFetchLsa(bufferPtr, interestName);
981  m_fetchers.erase(it);
982  });
983 
984  fetcher->onError.connect([=] (uint32_t errorCode, const std::string& msg) {
985  onFetchLsaError(errorCode, msg, interestName, timeoutCount, deadline, lsaName, seqNo);
986  m_fetchers.erase(it);
987  });
988 
989  // increment a specific SENT_LSA_INTEREST
990  Lsa::Type lsaType;
991  std::istringstream(interestName[-2].toUri()) >> lsaType;
992  switch (lsaType) {
995  break;
998  break;
999  case Lsa::Type::NAME:
1001  break;
1002  default:
1003  NLSR_LOG_ERROR("lsaType " << lsaType << " not recognized; failed Statistics::PacketType conversion");
1004  }
1005 }
1006 
1007 void
1008 Lsdb::processInterest(const ndn::Name& name, const ndn::Interest& interest)
1009 {
1010  ndn::Name interestName(interest.getName());
1011  NLSR_LOG_DEBUG("Interest received for LSA: " << interestName);
1012 
1013  if (interestName[-2].isVersion()) {
1014  // Interest for particular segment
1015  if (m_segmentPublisher.replyFromStore(interestName)) {
1016  NLSR_LOG_TRACE("Reply from SegmentPublisher storage");
1017  return;
1018  }
1019  // Remove version and segment
1020  interestName = interestName.getSubName(0, interestName.size() - 2);
1021  NLSR_LOG_TRACE("Interest w/o segment and version: " << interestName);
1022  }
1023 
1024  // increment RCV_LSA_INTEREST
1026 
1027  std::string chkString("LSA");
1028  int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
1029 
1030  // Forms the name of the router that the Interest packet came from.
1031  ndn::Name originRouter = m_confParam.getNetwork();
1032  originRouter.append(interestName.getSubName(lsaPosition + 1,
1033  interestName.size() - lsaPosition - 3));
1034 
1035  // if the interest is for this router's LSA
1036  if (originRouter == m_confParam.getRouterPrefix() && lsaPosition >= 0) {
1037  uint64_t seqNo = interestName[-1].toNumber();
1038  NLSR_LOG_DEBUG("LSA sequence number from interest: " << seqNo);
1039 
1040  std::string lsaType = interestName[-2].toUri();
1041  Lsa::Type interestedLsType;
1042  std::istringstream(lsaType) >> interestedLsType;
1043 
1044  if (interestedLsType == Lsa::Type::NAME) {
1045  processInterestForNameLsa(interest, originRouter.append(lsaType), seqNo);
1046  }
1047  else if (interestedLsType == Lsa::Type::ADJACENCY) {
1048  processInterestForAdjacencyLsa(interest, originRouter.append(lsaType), seqNo);
1049  }
1050  else if (interestedLsType == Lsa::Type::COORDINATE) {
1051  processInterestForCoordinateLsa(interest, originRouter.append(lsaType), seqNo);
1052  }
1053  else {
1054  NLSR_LOG_WARN("Received unrecognized LSA type: " << interestedLsType);
1055  }
1057  }
1058  else { // else the interest is for other router's lsa, serve from LsaSegmentStorage
1059  std::shared_ptr<const ndn::Data> lsaSegment = m_lsaStorage.find(interest);
1060  if (lsaSegment) {
1061  NLSR_LOG_TRACE("Found data in lsa storage. Sending the data for " << interest.getName());
1062  m_face.put(*lsaSegment);
1063  }
1064  else {
1065  NLSR_LOG_TRACE(interest << " was not found in this lsa storage.");
1066  }
1067  }
1068 }
1069 
1070  // \brief Finds and sends a requested name LSA.
1071  // \param interest The interest that seeks the name LSA.
1072  // \param lsaKey The LSA that the Interest is seeking.
1073  // \param seqNo A sequence number to ensure that we are sending the
1074  // version that was requested.
1075 void
1076 Lsdb::processInterestForNameLsa(const ndn::Interest& interest,
1077  const ndn::Name& lsaKey,
1078  uint64_t seqNo)
1079 {
1080  // increment RCV_NAME_LSA_INTEREST
1082  NLSR_LOG_DEBUG("nameLsa interest " << interest << " received");
1083  NameLsa* nameLsa = findNameLsa(lsaKey);
1084  if (nameLsa != nullptr) {
1085  NLSR_LOG_TRACE("Verifying SeqNo for NameLsa is same as requested.");
1086  if (nameLsa->getLsSeqNo() == seqNo) {
1087  std::string content = nameLsa->serialize();
1088  m_segmentPublisher.publish(interest.getName(), interest.getName(),
1089  ndn::encoding::makeStringBlock(ndn::tlv::Content, content),
1090  m_lsaRefreshTime, m_confParam.getSigningInfo());
1091 
1093  }
1094  else {
1095  NLSR_LOG_TRACE("SeqNo for nameLsa does not match");
1096  }
1097  }
1098  else {
1099  NLSR_LOG_TRACE(interest << " was not found in this lsdb");
1100  }
1101 }
1102 
1103  // \brief Finds and sends a requested adj. LSA.
1104  // \param interest The interest that seeks the adj. LSA.
1105  // \param lsaKey The LSA that the Interest is seeking.
1106  // \param seqNo A sequence number to ensure that we are sending the
1107  // version that was requested.
1108 void
1109 Lsdb::processInterestForAdjacencyLsa(const ndn::Interest& interest,
1110  const ndn::Name& lsaKey,
1111  uint64_t seqNo)
1112 {
1113  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
1114  NLSR_LOG_ERROR("Received interest for an adjacency LSA when hyperbolic routing is enabled");
1115  }
1116 
1118  NLSR_LOG_DEBUG("AdjLsa interest " << interest << " received");
1119  AdjLsa* adjLsa = findAdjLsa(lsaKey);
1120  if (adjLsa != nullptr) {
1121  NLSR_LOG_TRACE("Verifying SeqNo for AdjLsa is same as requested.");
1122  if (adjLsa->getLsSeqNo() == seqNo) {
1123  std::string content = adjLsa->serialize();
1124  m_segmentPublisher.publish(interest.getName(), interest.getName(),
1125  ndn::encoding::makeStringBlock(ndn::tlv::Content, content),
1126  m_lsaRefreshTime, m_confParam.getSigningInfo());
1127 
1129  }
1130  else {
1131  NLSR_LOG_TRACE("SeqNo for AdjLsa does not match");
1132  }
1133  }
1134  else {
1135  NLSR_LOG_TRACE(interest << " was not found in this lsdb");
1136  }
1137 }
1138 
1139  // \brief Finds and sends a requested cor. LSA.
1140  // \param interest The interest that seeks the cor. LSA.
1141  // \param lsaKey The LSA that the Interest is seeking.
1142  // \param seqNo A sequence number to ensure that we are sending the
1143  // version that was requested.
1144 void
1145 Lsdb::processInterestForCoordinateLsa(const ndn::Interest& interest,
1146  const ndn::Name& lsaKey,
1147  uint64_t seqNo)
1148 {
1149  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) {
1150  NLSR_LOG_ERROR("Received Interest for a coordinate LSA when link-state routing is enabled");
1151  }
1152 
1154  NLSR_LOG_DEBUG("CoordinateLsa interest " << interest << " received");
1155  CoordinateLsa* corLsa = findCoordinateLsa(lsaKey);
1156  if (corLsa != nullptr) {
1157  NLSR_LOG_TRACE("Verifying SeqNo for CoordinateLsa is same as requested.");
1158  if (corLsa->getLsSeqNo() == seqNo) {
1159  std::string content = corLsa->serialize();
1160  m_segmentPublisher.publish(interest.getName(), interest.getName(),
1161  ndn::encoding::makeStringBlock(ndn::tlv::Content, content),
1162  m_lsaRefreshTime, m_confParam.getSigningInfo());
1163 
1165  }
1166  else {
1167  NLSR_LOG_TRACE("SeqNo for CoordinateLsa does not match");
1168  }
1169  }
1170  else {
1171  NLSR_LOG_TRACE(interest << " was not found in this lsdb");
1172  }
1173 }
1174 
1175 void
1176 Lsdb::onContentValidated(const std::shared_ptr<const ndn::Data>& data)
1177 {
1178  const ndn::Name& dataName = data->getName();
1179  NLSR_LOG_DEBUG("Data validation successful for LSA: " << dataName);
1180 
1181  std::string chkString("LSA");
1182  int32_t lsaPosition = util::getNameComponentPosition(dataName, chkString);
1183 
1184  if (lsaPosition >= 0) {
1185 
1186  // Extracts the prefix of the originating router from the data.
1187  ndn::Name originRouter = m_confParam.getNetwork();
1188  originRouter.append(dataName.getSubName(lsaPosition + 1, dataName.size() - lsaPosition - 3));
1189 
1190  uint64_t seqNo = dataName[-1].toNumber();
1191  std::string dataContent(reinterpret_cast<const char*>(data->getContent().value()),
1192  data->getContent().value_size());
1193 
1194  Lsa::Type interestedLsType;
1195  std::istringstream(dataName[-2].toUri()) >> interestedLsType;
1196 
1197  if (interestedLsType == Lsa::Type::NAME) {
1198  processContentNameLsa(originRouter.append(std::to_string(interestedLsType)), seqNo,
1199  dataContent);
1200  }
1201  else if (interestedLsType == Lsa::Type::ADJACENCY) {
1202  processContentAdjacencyLsa(originRouter.append(std::to_string(interestedLsType)), seqNo,
1203  dataContent);
1204  }
1205  else if (interestedLsType == Lsa::Type::COORDINATE) {
1206  processContentCoordinateLsa(originRouter.append(std::to_string(interestedLsType)), seqNo,
1207  dataContent);
1208  }
1209  else {
1210  NLSR_LOG_WARN("Received unrecognized LSA Type: " << interestedLsType);
1211  }
1212 
1214  }
1215 }
1216 
1217 void
1218 Lsdb::processContentNameLsa(const ndn::Name& lsaKey,
1219  uint64_t lsSeqNo, std::string& dataContent)
1220 {
1222  if (isNameLsaNew(lsaKey, lsSeqNo)) {
1223  NameLsa nameLsa;
1224  if (nameLsa.deserialize(dataContent)) {
1225  installNameLsa(nameLsa);
1226  }
1227  else {
1228  NLSR_LOG_DEBUG("LSA data decoding error :(");
1229  }
1230  }
1231 }
1232 
1233 void
1234 Lsdb::processContentAdjacencyLsa(const ndn::Name& lsaKey,
1235  uint64_t lsSeqNo, std::string& dataContent)
1236 {
1238  if (isAdjLsaNew(lsaKey, lsSeqNo)) {
1239  AdjLsa adjLsa;
1240  if (adjLsa.deserialize(dataContent)) {
1241  installAdjLsa(adjLsa);
1242  }
1243  else {
1244  NLSR_LOG_DEBUG("LSA data decoding error :(");
1245  }
1246  }
1247 }
1248 
1249 void
1250 Lsdb::processContentCoordinateLsa(const ndn::Name& lsaKey,
1251  uint64_t lsSeqNo, std::string& dataContent)
1252 {
1254  if (isCoordinateLsaNew(lsaKey, lsSeqNo)) {
1255  CoordinateLsa corLsa;
1256  if (corLsa.deserialize(dataContent)) {
1257  installCoordinateLsa(corLsa);
1258  }
1259  else {
1260  NLSR_LOG_DEBUG("LSA data decoding error :(");
1261  }
1262  }
1263 }
1264 
1265 ndn::time::system_clock::TimePoint
1266 Lsdb::getLsaExpirationTimePoint()
1267 {
1268  ndn::time::system_clock::TimePoint expirationTimePoint = ndn::time::system_clock::now();
1269  expirationTimePoint = expirationTimePoint +
1270  ndn::time::seconds(m_confParam.getRouterDeadInterval());
1271  return expirationTimePoint;
1272 }
1273 
1274 void
1276 {
1277  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
1278  return;
1279  }
1280 
1281  NLSR_LOG_DEBUG("---------------Adj LSDB-------------------");
1282  for (const auto& adj : m_adjLsdb) {
1283  adj.writeLog();
1284  }
1285 }
1286 
1287 //-----utility function -----
1288 bool
1289 Lsdb::doesLsaExist(const ndn::Name& key, const Lsa::Type& lsType)
1290 {
1291  switch (lsType) {
1292  case Lsa::Type::ADJACENCY:
1293  return doesAdjLsaExist(key);
1294  case Lsa::Type::COORDINATE:
1295  return doesCoordinateLsaExist(key);
1296  case Lsa::Type::NAME:
1297  return doesNameLsaExist(key);
1298  default:
1299  return false;
1300  }
1301 }
1302 
1303 bool
1304 Lsdb::isLsaNew(const ndn::Name& routerName, const Lsa::Type& lsaType,
1305  const uint64_t& sequenceNumber) {
1306  ndn::Name lsaKey = routerName;
1307  lsaKey.append(std::to_string(lsaType));
1308 
1309  switch (lsaType) {
1310  case Lsa::Type::ADJACENCY:
1311  return isAdjLsaNew(lsaKey, sequenceNumber);
1312  case Lsa::Type::COORDINATE:
1313  return isCoordinateLsaNew(lsaKey, sequenceNumber);
1314  case Lsa::Type::NAME:
1315  return isNameLsaNew(lsaKey, sequenceNumber);
1316  default:
1317  return false;
1318  }
1319 }
1320 
1321 } // namespace nlsr
bool installAdjLsa(AdjLsa &alsa)
Installs an adj. LSA into the LSDB.
Definition: lsdb.cpp:683
uint32_t getLsSeqNo() const
Definition: lsa.hpp:62
#define NLSR_LOG_WARN(x)
Definition: logger.hpp:40
ndn::security::ValidatorConfig & getValidator()
A class to house all the configuration parameters for NLSR.
void setAdjLsaSeq(uint64_t alsn)
Definition: tlv-nlsr.hpp:27
void scheduleAdjLsaBuild()
Schedules a build of this router&#39;s LSA.
Definition: lsdb.cpp:559
bool removeNameLsa(const ndn::Name &key)
Remove a name LSA from the LSDB.
Definition: lsdb.cpp:306
bool deserialize(const std::string &content) noexcept override
Initializes this coordinate LSA with the data in content.
Definition: lsa.cpp:170
void writeNameLsdbLog()
Definition: lsdb.cpp:339
const ndn::time::system_clock::TimePoint & getExpirationTimePoint() const
Definition: lsa.hpp:80
static bool corLsaCompareByKey(const CoordinateLsa &clsa, const ndn::Name &key)
Compares whether an LSA object is the same as a key.
Definition: lsdb.cpp:360
uint32_t getAdjLsaBuildInterval() const
uint32_t getLsaRefreshTime() const
const std::string & getStateFileDir() const
std::string serialize() const override
Returns the data this adjacency LSA has.
Definition: lsa.cpp:222
const std::list< NameLsa > & getNameLsdb() const
Definition: lsdb.cpp:348
bool isLsaNew(const ndn::Name &routerName, const Lsa::Type &lsaType, const uint64_t &sequenceNumber)
Definition: lsdb.cpp:1304
const std::list< CoordinateLsa > & getCoordinateLsdb() const
Definition: lsdb.cpp:541
AdjacencyList & getAdl()
Definition: lsa.hpp:240
void setLsSeqNo(uint32_t lsn)
Definition: lsa.hpp:56
void writeAdjLsdbLog()
Definition: lsdb.cpp:1275
void scheduleRoutingTableCalculation()
Schedules a calculation event in the event scheduler only if one isn&#39;t already scheduled.
void writeLog() const override
Definition: lsa.cpp:269
std::list< ndn::Name > getNames() const
std::unique_ptr< OnNewLsa > onNewLsa
static bool nameLsaCompareByKey(const NameLsa &nlsa1, const ndn::Name &key)
Compares if a name LSA is the same as the one specified by key.
Definition: lsdb.cpp:143
NamePrefixList & getNpl()
Definition: lsa.hpp:166
const ndn::security::SigningInfo & getSigningInfo() const
AdjacencyList & getAdjacencyList()
#define NLSR_LOG_DEBUG(x)
Definition: logger.hpp:38
const ndn::Name & getRouterPrefix() const
Lsdb(ndn::Face &face, ndn::KeyChain &keyChain, ConfParameter &confParam, NamePrefixTable &namePrefixTable, RoutingTable &routingTable)
Definition: lsdb.cpp:39
void writeLog() const override
Definition: lsa.cpp:194
void writeCorLsdbLog()
Definition: lsdb.cpp:528
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California.
void setExpirationTimePoint(const ndn::time::system_clock::TimePoint &lt)
Definition: lsa.hpp:86
int32_t getNumOfActiveNeighbor() const
const ndn::Name getKey() const
Gets the key for this LSA.
Definition: lsa.cpp:50
double getCorRadius() const
Definition: lsa.hpp:334
const ndn::time::seconds & getLsaInterestLifetime() const
#define INIT_LOGGER(name)
Definition: logger.hpp:35
void removeEntry(const ndn::Name &name, const ndn::Name &destRouter)
Removes a destination from a name prefix table entry.
double getCorR() const
bool isCoordinateLsaNew(const ndn::Name &key, uint64_t seqNo)
Returns whether a cor. LSA from a router is new or not.
Definition: lsdb.cpp:398
uint32_t getInterestRetryNumber() const
void writeLog() const override
Definition: lsa.cpp:124
CoordinateLsa * findCoordinateLsa(const ndn::Name &key)
Finds a cor. LSA in the LSDB.
Definition: lsdb.cpp:387
ndn::util::signal::Signal< Lsdb, const ndn::Data & > afterSegmentValidatedSignal
Definition: lsdb.hpp:376
bool isNameLsaNew(const ndn::Name &key, uint64_t seqNo)
Definition: lsdb.cpp:175
bool deserialize(const std::string &content) noexcept override
Initializes this LSA object with content&#39;s data.
Definition: lsa.cpp:93
bool installCoordinateLsa(CoordinateLsa &clsa)
Installs a cor. LSA into the LSDB.
Definition: lsdb.cpp:427
NameLsa * findNameLsa(const ndn::Name &key)
Returns the name LSA with the given key.
Definition: lsdb.cpp:164
void processInterest(const ndn::Name &name, const ndn::Interest &interest)
Definition: lsdb.cpp:1008
void expressInterest(const ndn::Name &interestName, uint32_t timeoutCount, ndn::time::steady_clock::TimePoint deadline=DEFAULT_LSA_RETRIEVAL_DEADLINE)
Definition: lsdb.cpp:928
bool doesLsaExist(const ndn::Name &key, const Lsa::Type &lsType)
Definition: lsdb.cpp:1289
static int32_t getNameComponentPosition(const ndn::Name &name, const std::string &searchString)
search a name component in ndn::Name and return the position of the component
Definition: name-helper.hpp:44
std::string serialize() const override
Returns the data that this name LSA has.
Definition: lsa.cpp:81
const std::vector< double > getCorTheta() const
Definition: lsa.hpp:346
bool isAdjLsaNew(const ndn::Name &key, uint64_t seqNo)
Returns whether an LSA is new.
Definition: lsdb.cpp:658
const ndn::Name & getOrigRouter() const
Definition: lsa.hpp:68
bool removeAdjLsa(const ndn::Name &key)
Removes an adj. LSA from the LSDB.
Definition: lsdb.cpp:753
void setNameLsaSeq(uint64_t nlsn)
const ndn::Name & getNetwork() const
int32_t getHyperbolicState() const
uint64_t getNameLsaSeq() const
void setExpiringEventId(ndn::scheduler::EventId eid)
Definition: lsa.hpp:92
void setCorTheta(std::vector< double > ct)
Definition: lsa.hpp:352
#define NLSR_LOG_ERROR(x)
Definition: logger.hpp:41
~Lsdb()
Definition: lsdb.cpp:68
static const ndn::Name::Component NAME_COMPONENT
Definition: lsdb.hpp:373
void removeName(const ndn::Name &name)
Definition: lsa.hpp:184
Copyright (c) 2014-2019, The University of Memphis, Regents of the University of California, Arizona Board of Regents.
NamePrefixList & getNamePrefixList()
ndn::util::signal::Signal< Lsdb, Statistics::PacketType > lsaIncrementSignal
Definition: lsdb.hpp:375
bool installNameLsa(NameLsa &nlsa)
Installs a name LSA into the LSDB.
Definition: lsdb.cpp:200
void setCorRadius(double cr)
Definition: lsa.hpp:340
const std::list< AdjLsa > & getAdjLsdb() const
Definition: lsdb.cpp:778
static bool adjLsaCompareByKey(AdjLsa &alsa, const ndn::Name &key)
Returns whether an adj. LSA object is from some router.
Definition: lsdb.cpp:553
void setCorLsaSeq(uint64_t clsn)
bool buildAndInstallOwnNameLsa()
Builds a name LSA for this router and then installs it into the LSDB.
Definition: lsdb.cpp:149
bool isAdjLsaBuildable(const uint32_t interestRetryNo) const
Determines whether this list can be used to build an adj. LSA.
bool buildAndInstallOwnCoordinateLsa()
Builds a cor. LSA for this router and installs it into the LSDB.
Definition: lsdb.cpp:366
void addName(const ndn::Name &name)
Definition: lsa.hpp:178
bool deserialize(const std::string &content) noexcept override
Initializes this adj. LSA from the supplied content.
Definition: lsa.cpp:235
void addAdjacents(AdjacencyList &adl)
Copies the adjacencies in a list to this one.
std::string serialize() const override
Returns the data that this coordinate LSA represents.
Definition: lsa.cpp:159
ndn::scheduler::EventId getExpiringEventId() const
Definition: lsa.hpp:98
uint32_t getRouterDeadInterval() const
uint32_t getInterestResendTime() const
AdjLsa * findAdjLsa(const ndn::Name &key)
Finds an adj. LSA in the LSDB.
Definition: lsdb.cpp:647
bool buildAndInstallOwnAdjLsa()
Wrapper event to build and install an adj. LSA for this router.
Definition: lsdb.cpp:734
bool removeCoordinateLsa(const ndn::Name &key)
Removes a cor. LSA from the LSDB.
Definition: lsdb.cpp:500
#define NLSR_LOG_TRACE(x)
Definition: logger.hpp:37
bool isEqualContent(const CoordinateLsa &clsa) const
Definition: lsa.cpp:141
std::vector< double > getCorTheta() const
bool isEqualContent(const AdjLsa &alsa) const
Definition: lsa.cpp:216
void publishRoutingUpdate(const Lsa::Type &type, const uint64_t &seqNo)
Instruct ChronoSync to publish an update.
void addEntry(const ndn::Name &name, const ndn::Name &destRouter)
Adds a destination to the specified name prefix.