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