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(), nlsa.getOrigRouter());
215 
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  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) {
527  return;
528  }
529 
530  NLSR_LOG_DEBUG("---------------Cor LSDB-------------------");
531  for (const auto& corLsa : m_corLsdb) {
532  corLsa.writeLog();
533  }
534 }
535 
536 const std::list<CoordinateLsa>&
538 {
539  return m_corLsdb;
540 }
541 
542 // Adj LSA and LSDB related function starts here
543 
548 static bool
549 adjLsaCompareByKey(AdjLsa& alsa, const ndn::Name& key)
550 {
551  return alsa.getKey() == key;
552 }
553 
554 void
556 {
557  m_adjBuildCount++;
558 
559  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
560  // Don't build adjacency LSAs in hyperbolic routing
561  NLSR_LOG_DEBUG("Adjacency LSA not built. Currently in hyperbolic routing state.");
562  return;
563  }
564 
565  if (m_isBuildAdjLsaSheduled) {
566  NLSR_LOG_DEBUG("Rescheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
567  }
568  else {
569  NLSR_LOG_DEBUG("Scheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
570  m_isBuildAdjLsaSheduled = true;
571  }
572  m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [this] { buildAdjLsa(); });
573 }
574 
575 void
576 Lsdb::buildAdjLsa()
577 {
578  NLSR_LOG_TRACE("Lsdb::buildAdjLsa called");
579 
580  m_isBuildAdjLsaSheduled = false;
581 
582  if (m_confParam.getAdjacencyList().isAdjLsaBuildable(m_confParam.getInterestRetryNumber())) {
583 
584  int adjBuildCount = m_adjBuildCount;
585  // Only do the adjLsa build if there's one scheduled
586  if (adjBuildCount > 0) {
587  // It only makes sense to do the adjLsa build if we have neighbors
588  if (m_confParam.getAdjacencyList().getNumOfActiveNeighbor() > 0) {
589  NLSR_LOG_DEBUG("Building and installing own Adj LSA");
591  }
592  // We have no active neighbors, meaning no one can route through
593  // us. So delete our entry in the LSDB. This prevents this
594  // router from refreshing the LSA, eventually causing other
595  // routers to delete it, too.
596  else {
597  NLSR_LOG_DEBUG("Removing own Adj LSA; no ACTIVE neighbors");
598  // Get this router's key
599  ndn::Name key = m_confParam.getRouterPrefix();
600  key.append(std::to_string(Lsa::Type::ADJACENCY));
601 
602  removeAdjLsa(key);
603  // Recompute routing table after removal
604  m_routingTable.scheduleRoutingTableCalculation();
605  }
606  // In the case that during building the adj LSA, the FIB has to
607  // wait on an Interest response, the number of scheduled adj LSA
608  // builds could change, so we shouldn't just set it to 0.
609  m_adjBuildCount = m_adjBuildCount - adjBuildCount;
610  }
611  }
612  // We are still waiting to know the adjacency status of some
613  // neighbor, so schedule a build for later (when all that has
614  // hopefully finished)
615  else {
616  m_isBuildAdjLsaSheduled = true;
617  auto schedulingTime = ndn::time::seconds(m_confParam.getInterestRetryNumber() *
618  m_confParam.getInterestResendTime());
619  m_scheduledAdjLsaBuild = m_scheduler.schedule(schedulingTime, [this] { buildAdjLsa(); });
620  }
621 }
622 
623 bool
624 Lsdb::addAdjLsa(AdjLsa& alsa)
625 {
626  auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
627  std::bind(adjLsaCompareByKey, _1, alsa.getKey()));
628  if (it == m_adjLsdb.end()) {
629  m_adjLsdb.push_back(alsa);
630  // Add any new name prefixes to the NPT
631  // Only add NPT entries if this is an adj LSA from another router.
632  if (alsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
633  // Pass the originating router as both the name to register and
634  // where it came from.
635  m_namePrefixTable.addEntry(alsa.getOrigRouter(), alsa.getOrigRouter());
636  }
637  return true;
638  }
639  return false;
640 }
641 
642 AdjLsa*
643 Lsdb::findAdjLsa(const ndn::Name& key)
644 {
645  auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
646  std::bind(adjLsaCompareByKey, _1, key));
647  if (it != m_adjLsdb.end()) {
648  return &*it;
649  }
650  return nullptr;
651 }
652 
653 bool
654 Lsdb::isAdjLsaNew(const ndn::Name& key, uint64_t seqNo)
655 {
656  AdjLsa* adjLsaCheck = findAdjLsa(key);
657  // If it is in the LSDB
658  if (adjLsaCheck != nullptr) {
659  // And the supplied seq no is newer (higher) than the current one.
660  if (adjLsaCheck->getLsSeqNo() < seqNo) {
661  return true;
662  }
663  else {
664  return false;
665  }
666  }
667  return true;
668 }
669 
670 ndn::scheduler::EventId
671 Lsdb::scheduleAdjLsaExpiration(const ndn::Name& key, int seqNo,
672  const ndn::time::seconds& expTime)
673 {
674  return m_scheduler.schedule(expTime + GRACE_PERIOD,
675  std::bind(&Lsdb::expireOrRefreshAdjLsa, this, key, seqNo));
676 }
677 
678 bool
680 {
681  ndn::time::seconds timeToExpire = m_lsaRefreshTime;
682  AdjLsa* chkAdjLsa = findAdjLsa(alsa.getKey());
683  // If this adj. LSA is not in the LSDB already
684  if (chkAdjLsa == nullptr) {
685  NLSR_LOG_DEBUG("New Adj LSA. Adding to LSDB");
686  NLSR_LOG_DEBUG("Adding Adj Lsa");
687  alsa.writeLog();
688  addAdjLsa(alsa);
689 
690  m_routingTable.scheduleRoutingTableCalculation();
691  if (alsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
692  ndn::time::system_clock::Duration duration = alsa.getExpirationTimePoint() -
693  ndn::time::system_clock::now();
694  timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
695  }
696  scheduleAdjLsaExpiration(alsa.getKey(), alsa.getLsSeqNo(), timeToExpire);
697  }
698  else {
699  if (chkAdjLsa->getLsSeqNo() < alsa.getLsSeqNo()) {
700  NLSR_LOG_DEBUG("Updated Adj LSA. Updating LSDB");
701  NLSR_LOG_DEBUG("Deleting Adj Lsa");
702  chkAdjLsa->writeLog();
703  chkAdjLsa->setLsSeqNo(alsa.getLsSeqNo());
705  // If the new adj LSA has new content, update the contents of
706  // the LSDB entry. Additionally, since we've changed the
707  // contents of the LSDB, we have to schedule a routing
708  // calculation.
709  if (!chkAdjLsa->isEqualContent(alsa)) {
710  chkAdjLsa->getAdl().reset();
711  chkAdjLsa->getAdl().addAdjacents(alsa.getAdl());
712  m_routingTable.scheduleRoutingTableCalculation();
713  }
714  if (alsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
715  auto duration = alsa.getExpirationTimePoint() - ndn::time::system_clock::now();
716  timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
717  }
718  chkAdjLsa->getExpiringEventId().cancel();
719  chkAdjLsa->setExpiringEventId(scheduleAdjLsaExpiration(alsa.getKey(),
720  alsa.getLsSeqNo(),
721  timeToExpire));
722  NLSR_LOG_DEBUG("Adding Adj Lsa");
723  chkAdjLsa->writeLog();
724  }
725  }
726  return true;
727 }
728 
729 bool
731 {
732  AdjLsa adjLsa(m_confParam.getRouterPrefix(),
733  m_sequencingManager.getAdjLsaSeq() + 1,
734  getLsaExpirationTimePoint(),
736  m_confParam.getAdjacencyList());
737 
738  //Sync adjacency LSAs if link-state or dry-run HR is enabled.
739  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_ON) {
740  m_sequencingManager.increaseAdjLsaSeq();
741  m_sequencingManager.writeSeqNoToFile();
742  m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
743  }
744 
745  return installAdjLsa(adjLsa);
746 }
747 
748 bool
749 Lsdb::removeAdjLsa(const ndn::Name& key)
750 {
751  auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
752  std::bind(adjLsaCompareByKey, _1, key));
753  if (it != m_adjLsdb.end()) {
754  NLSR_LOG_DEBUG("Deleting Adj Lsa");
755  it->writeLog();
756  if (it->getOrigRouter() != m_confParam.getRouterPrefix()) {
757  m_namePrefixTable.removeEntry(it->getOrigRouter(), it->getOrigRouter());
758  }
759  m_adjLsdb.erase(it);
760  return true;
761  }
762  return false;
763 }
764 
765 bool
766 Lsdb::doesAdjLsaExist(const ndn::Name& key)
767 {
768  auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
769  std::bind(adjLsaCompareByKey, _1, key));
770  return it != m_adjLsdb.end();
771 }
772 
773 const std::list<AdjLsa>&
775 {
776  return m_adjLsdb;
777 }
778 
779  // This function determines whether a name LSA should be refreshed
780  // or expired. The conditions for getting refreshed are: it is still
781  // in the LSDB, it hasn't been updated by something else already (as
782  // evidenced by its seq. no.), and this is the originating router for
783  // the LSA. Is it let expire in all other cases.
784  // lsaKey is the key of the LSA's publishing router.
785  // seqNo is the seq. no. of the candidate LSA.
786 void
787 Lsdb::expireOrRefreshNameLsa(const ndn::Name& lsaKey, uint64_t seqNo)
788 {
789  NLSR_LOG_DEBUG("Lsdb::expireOrRefreshNameLsa Called");
790  NLSR_LOG_DEBUG("LSA Key : " << lsaKey << " Seq No: " << seqNo);
791  NameLsa* chkNameLsa = findNameLsa(lsaKey);
792  // If this name LSA exists in the LSDB
793  if (chkNameLsa != nullptr) {
794  NLSR_LOG_DEBUG("LSA Exists with seq no: " << chkNameLsa->getLsSeqNo());
795  // If its seq no is the one we are expecting.
796  if (chkNameLsa->getLsSeqNo() == seqNo) {
797  if (chkNameLsa->getOrigRouter() == m_thisRouterPrefix) {
798  NLSR_LOG_DEBUG("Own Name LSA, so refreshing it");
799  NLSR_LOG_DEBUG("Deleting Name Lsa");
800  chkNameLsa->writeLog();
801  chkNameLsa->setLsSeqNo(chkNameLsa->getLsSeqNo() + 1);
802  m_sequencingManager.setNameLsaSeq(chkNameLsa->getLsSeqNo());
803  chkNameLsa->setExpirationTimePoint(getLsaExpirationTimePoint());
804  NLSR_LOG_DEBUG("Adding Name Lsa");
805  chkNameLsa->writeLog();
806  // schedule refreshing event again
807  chkNameLsa->setExpiringEventId(scheduleNameLsaExpiration(chkNameLsa->getKey(),
808  chkNameLsa->getLsSeqNo(),
809  m_lsaRefreshTime));
810  m_sequencingManager.writeSeqNoToFile();
811  m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
812  }
813  // Since we cannot refresh other router's LSAs, our only choice is to expire.
814  else {
815  NLSR_LOG_DEBUG("Other's Name LSA, so removing from LSDB");
816  removeNameLsa(lsaKey);
817  }
818  }
819  }
820 }
821 
822  // This function determines whether an adj. LSA should be refreshed
823  // or expired. The conditions for getting refreshed are: it is still
824  // in the LSDB, it hasn't been updated by something else already (as
825  // evidenced by its seq. no.), and this is the originating router for
826  // the LSA. Is it let expire in all other cases.
827  // lsaKey is the key of the LSA's publishing router.
828  // seqNo is the seq. no. of the candidate LSA.
829 void
830 Lsdb::expireOrRefreshAdjLsa(const ndn::Name& lsaKey, uint64_t seqNo)
831 {
832  NLSR_LOG_DEBUG("Lsdb::expireOrRefreshAdjLsa Called");
833  NLSR_LOG_DEBUG("LSA Key: " << lsaKey << " Seq No: " << seqNo);
834  AdjLsa* chkAdjLsa = findAdjLsa(lsaKey);
835  // If this is a valid LSA
836  if (chkAdjLsa != nullptr) {
837  NLSR_LOG_DEBUG("LSA Exists with seq no: " << chkAdjLsa->getLsSeqNo());
838  // And if it hasn't been updated for some other reason
839  if (chkAdjLsa->getLsSeqNo() == seqNo) {
840  // If it is our own LSA
841  if (chkAdjLsa->getOrigRouter() == m_thisRouterPrefix) {
842  NLSR_LOG_DEBUG("Own Adj LSA, so refreshing it");
843  NLSR_LOG_DEBUG("Deleting Adj Lsa");
844  chkAdjLsa->writeLog();
845  chkAdjLsa->setLsSeqNo(chkAdjLsa->getLsSeqNo() + 1);
846  m_sequencingManager.setAdjLsaSeq(chkAdjLsa->getLsSeqNo());
847  chkAdjLsa->setExpirationTimePoint(getLsaExpirationTimePoint());
848  NLSR_LOG_DEBUG("Adding Adj Lsa");
849  chkAdjLsa->writeLog();
850  // schedule refreshing event again
851  chkAdjLsa->setExpiringEventId(scheduleAdjLsaExpiration(chkAdjLsa->getKey(),
852  chkAdjLsa->getLsSeqNo(),
853  m_lsaRefreshTime));
854  m_sequencingManager.writeSeqNoToFile();
855  m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
856  }
857  // An LSA from another router is expiring
858  else {
859  NLSR_LOG_DEBUG("Other's Adj LSA, so removing from LSDB");
860  removeAdjLsa(lsaKey);
861  }
862  // We have changed the contents of the LSDB, so we have to
863  // schedule a routing calculation
864  m_routingTable.scheduleRoutingTableCalculation();
865  }
866  }
867 }
868 
869  // This function determines whether an adj. LSA should be refreshed
870  // or expired. The conditions for getting refreshed are: it is still
871  // in the LSDB, it hasn't been updated by something else already (as
872  // evidenced by its seq. no.), and this is the originating router for
873  // the LSA. It is let expire in all other cases.
874  // lsaKey is the key of the LSA's publishing router.
875  // seqNo is the seq. no. of the candidate LSA.
876 void
877 Lsdb::expireOrRefreshCoordinateLsa(const ndn::Name& lsaKey,
878  uint64_t seqNo)
879 {
880  NLSR_LOG_DEBUG("Lsdb::expireOrRefreshCorLsa Called ");
881  NLSR_LOG_DEBUG("LSA Key : " << lsaKey << " Seq No: " << seqNo);
882  CoordinateLsa* chkCorLsa = findCoordinateLsa(lsaKey);
883  // Whether the LSA is in the LSDB or not.
884  if (chkCorLsa != nullptr) {
885  NLSR_LOG_DEBUG("LSA Exists with seq no: " << chkCorLsa->getLsSeqNo());
886  // Whether the LSA has been updated without our knowledge.
887  if (chkCorLsa->getLsSeqNo() == seqNo) {
888  if (chkCorLsa->getOrigRouter() == m_thisRouterPrefix) {
889  NLSR_LOG_DEBUG("Own Cor LSA, so refreshing it");
890  NLSR_LOG_DEBUG("Deleting Coordinate Lsa");
891  chkCorLsa->writeLog();
892  chkCorLsa->setLsSeqNo(chkCorLsa->getLsSeqNo() + 1);
893  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
894  m_sequencingManager.setCorLsaSeq(chkCorLsa->getLsSeqNo());
895  }
896 
897  chkCorLsa->setExpirationTimePoint(getLsaExpirationTimePoint());
898  NLSR_LOG_DEBUG("Adding Coordinate Lsa");
899  chkCorLsa->writeLog();
900  // schedule refreshing event again
901  chkCorLsa->setExpiringEventId(scheduleCoordinateLsaExpiration(
902  chkCorLsa->getKey(),
903  chkCorLsa->getLsSeqNo(),
904  m_lsaRefreshTime));
905  // Only sync coordinate LSAs if link-state routing is disabled
906  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
907  m_sequencingManager.writeSeqNoToFile();
908  m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
909  }
910  }
911  // We can't refresh other router's LSAs, so we remove it.
912  else {
913  NLSR_LOG_DEBUG("Other's Cor LSA, so removing from LSDB");
914  removeCoordinateLsa(lsaKey);
915  }
916  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
917  m_routingTable.scheduleRoutingTableCalculation();
918  }
919  }
920  }
921 }
922 
923 void
924 Lsdb::expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
925  ndn::time::steady_clock::TimePoint deadline)
926 {
927  // increment SENT_LSA_INTEREST
929 
930  if (deadline == DEFAULT_LSA_RETRIEVAL_DEADLINE) {
931  deadline = ndn::time::steady_clock::now() + ndn::time::seconds(static_cast<int>(LSA_REFRESH_TIME_MAX));
932  }
933  // The first component of the interest is the name.
934  ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
935  // The seq no is the last
936  uint64_t seqNo = interestName[-1].toNumber();
937 
938  // If the LSA is not found in the list currently.
939  if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
940  m_highestSeqNo[lsaName] = seqNo;
941  }
942  // If the new seq no is higher, that means the LSA is valid
943  else if (seqNo > m_highestSeqNo[lsaName]) {
944  m_highestSeqNo[lsaName] = seqNo;
945  }
946  // Otherwise, its an old/invalid LSA
947  else if (seqNo < m_highestSeqNo[lsaName]) {
948  return;
949  }
950 
951  ndn::Interest interest(interestName);
952  ndn::util::SegmentFetcher::Options options;
953  options.interestLifetime = m_confParam.getLsaInterestLifetime();
954 
955  NLSR_LOG_DEBUG("Fetching Data for LSA: " << interestName << " Seq number: " << seqNo);
956  auto fetcher = ndn::util::SegmentFetcher::start(m_face, interest,
957  m_confParam.getValidator(), options);
958 
959  auto it = m_fetchers.insert(fetcher).first;
960 
961  fetcher->afterSegmentValidated.connect([this] (const ndn::Data& data) {
962  // Nlsr class subscribes to this to fetch certificates
964 
965  // If we don't do this IMS throws: std::bad_weak_ptr: bad_weak_ptr
966  auto lsaSegment = std::make_shared<const ndn::Data>(data);
967  m_lsaStorage.insert(*lsaSegment);
968  const ndn::Name& segmentName = lsaSegment->getName();
969  // Schedule deletion of the segment
970  m_scheduler.schedule(ndn::time::seconds(LSA_REFRESH_TIME_DEFAULT),
971  [this, segmentName] { m_lsaStorage.erase(segmentName); });
972  });
973 
974  fetcher->onComplete.connect([=] (const ndn::ConstBufferPtr& bufferPtr) {
975  m_lsaStorage.erase(ndn::Name(lsaName).appendNumber(seqNo - 1));
976  afterFetchLsa(bufferPtr, interestName);
977  m_fetchers.erase(it);
978  });
979 
980  fetcher->onError.connect([=] (uint32_t errorCode, const std::string& msg) {
981  onFetchLsaError(errorCode, msg, interestName, timeoutCount, deadline, lsaName, seqNo);
982  m_fetchers.erase(it);
983  });
984 
985  // increment a specific SENT_LSA_INTEREST
986  Lsa::Type lsaType;
987  std::istringstream(interestName[-2].toUri()) >> lsaType;
988  switch (lsaType) {
991  break;
994  break;
995  case Lsa::Type::NAME:
997  break;
998  default:
999  NLSR_LOG_ERROR("lsaType " << lsaType << " not recognized; failed Statistics::PacketType conversion");
1000  }
1001 }
1002 
1003 void
1004 Lsdb::processInterest(const ndn::Name& name, const ndn::Interest& interest)
1005 {
1006  ndn::Name interestName(interest.getName());
1007  NLSR_LOG_DEBUG("Interest received for LSA: " << interestName);
1008 
1009  if (interestName[-2].isVersion()) {
1010  // Interest for particular segment
1011  if (m_segmentPublisher.replyFromStore(interestName)) {
1012  NLSR_LOG_TRACE("Reply from SegmentPublisher storage");
1013  return;
1014  }
1015  // Remove version and segment
1016  interestName = interestName.getSubName(0, interestName.size() - 2);
1017  NLSR_LOG_TRACE("Interest w/o segment and version: " << interestName);
1018  }
1019 
1020  // increment RCV_LSA_INTEREST
1022 
1023  std::string chkString("LSA");
1024  int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
1025 
1026  // Forms the name of the router that the Interest packet came from.
1027  ndn::Name originRouter = m_confParam.getNetwork();
1028  originRouter.append(interestName.getSubName(lsaPosition + 1,
1029  interestName.size() - lsaPosition - 3));
1030 
1031  // if the interest is for this router's LSA
1032  if (originRouter == m_confParam.getRouterPrefix() && lsaPosition >= 0) {
1033  uint64_t seqNo = interestName[-1].toNumber();
1034  NLSR_LOG_DEBUG("LSA sequence number from interest: " << seqNo);
1035 
1036  std::string lsaType = interestName[-2].toUri();
1037  Lsa::Type interestedLsType;
1038  std::istringstream(lsaType) >> interestedLsType;
1039 
1040  if (interestedLsType == Lsa::Type::NAME) {
1041  processInterestForNameLsa(interest, originRouter.append(lsaType), seqNo);
1042  }
1043  else if (interestedLsType == Lsa::Type::ADJACENCY) {
1044  processInterestForAdjacencyLsa(interest, originRouter.append(lsaType), seqNo);
1045  }
1046  else if (interestedLsType == Lsa::Type::COORDINATE) {
1047  processInterestForCoordinateLsa(interest, originRouter.append(lsaType), seqNo);
1048  }
1049  else {
1050  NLSR_LOG_WARN("Received unrecognized LSA type: " << interestedLsType);
1051  }
1053  }
1054  else { // else the interest is for other router's lsa, serve from LsaSegmentStorage
1055  std::shared_ptr<const ndn::Data> lsaSegment = m_lsaStorage.find(interest);
1056  if (lsaSegment) {
1057  NLSR_LOG_TRACE("Found data in lsa storage. Sending the data for " << interest.getName());
1058  m_face.put(*lsaSegment);
1059  }
1060  else {
1061  NLSR_LOG_TRACE(interest << " was not found in this lsa storage.");
1062  }
1063  }
1064 }
1065 
1066  // \brief Finds and sends a requested name LSA.
1067  // \param interest The interest that seeks the name LSA.
1068  // \param lsaKey The LSA that the Interest is seeking.
1069  // \param seqNo A sequence number to ensure that we are sending the
1070  // version that was requested.
1071 void
1072 Lsdb::processInterestForNameLsa(const ndn::Interest& interest,
1073  const ndn::Name& lsaKey,
1074  uint64_t seqNo)
1075 {
1076  // increment RCV_NAME_LSA_INTEREST
1078  NLSR_LOG_DEBUG("nameLsa interest " << interest << " received");
1079  NameLsa* nameLsa = findNameLsa(lsaKey);
1080  if (nameLsa != nullptr) {
1081  NLSR_LOG_TRACE("Verifying SeqNo for NameLsa is same as requested.");
1082  if (nameLsa->getLsSeqNo() == seqNo) {
1083  std::string content = nameLsa->serialize();
1084  m_segmentPublisher.publish(interest.getName(), interest.getName(),
1085  ndn::encoding::makeStringBlock(ndn::tlv::Content, content),
1086  m_lsaRefreshTime, m_signingInfo);
1087 
1089  }
1090  else {
1091  NLSR_LOG_TRACE("SeqNo for nameLsa does not match");
1092  }
1093  }
1094  else {
1095  NLSR_LOG_TRACE(interest << " was not found in this lsdb");
1096  }
1097 }
1098 
1099  // \brief Finds and sends a requested adj. LSA.
1100  // \param interest The interest that seeks the adj. LSA.
1101  // \param lsaKey The LSA that the Interest is seeking.
1102  // \param seqNo A sequence number to ensure that we are sending the
1103  // version that was requested.
1104 void
1105 Lsdb::processInterestForAdjacencyLsa(const ndn::Interest& interest,
1106  const ndn::Name& lsaKey,
1107  uint64_t seqNo)
1108 {
1109  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
1110  NLSR_LOG_ERROR("Received interest for an adjacency LSA when hyperbolic routing is enabled");
1111  }
1112 
1114  NLSR_LOG_DEBUG("AdjLsa interest " << interest << " received");
1115  AdjLsa* adjLsa = findAdjLsa(lsaKey);
1116  if (adjLsa != nullptr) {
1117  NLSR_LOG_TRACE("Verifying SeqNo for AdjLsa is same as requested.");
1118  if (adjLsa->getLsSeqNo() == seqNo) {
1119  std::string content = adjLsa->serialize();
1120  m_segmentPublisher.publish(interest.getName(), interest.getName(),
1121  ndn::encoding::makeStringBlock(ndn::tlv::Content, content),
1122  m_lsaRefreshTime, m_signingInfo);
1123 
1125  }
1126  else {
1127  NLSR_LOG_TRACE("SeqNo for AdjLsa does not match");
1128  }
1129  }
1130  else {
1131  NLSR_LOG_TRACE(interest << " was not found in this lsdb");
1132  }
1133 }
1134 
1135  // \brief Finds and sends a requested cor. LSA.
1136  // \param interest The interest that seeks the cor. LSA.
1137  // \param lsaKey The LSA that the Interest is seeking.
1138  // \param seqNo A sequence number to ensure that we are sending the
1139  // version that was requested.
1140 void
1141 Lsdb::processInterestForCoordinateLsa(const ndn::Interest& interest,
1142  const ndn::Name& lsaKey,
1143  uint64_t seqNo)
1144 {
1145  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) {
1146  NLSR_LOG_ERROR("Received Interest for a coordinate LSA when link-state routing is enabled");
1147  }
1148 
1150  NLSR_LOG_DEBUG("CoordinateLsa interest " << interest << " received");
1151  CoordinateLsa* corLsa = findCoordinateLsa(lsaKey);
1152  if (corLsa != nullptr) {
1153  NLSR_LOG_TRACE("Verifying SeqNo for CoordinateLsa is same as requested.");
1154  if (corLsa->getLsSeqNo() == seqNo) {
1155  std::string content = corLsa->serialize();
1156  m_segmentPublisher.publish(interest.getName(), interest.getName(),
1157  ndn::encoding::makeStringBlock(ndn::tlv::Content, content),
1158  m_lsaRefreshTime, m_signingInfo);
1159 
1161  }
1162  else {
1163  NLSR_LOG_TRACE("SeqNo for CoordinateLsa does not match");
1164  }
1165  }
1166  else {
1167  NLSR_LOG_TRACE(interest << " was not found in this lsdb");
1168  }
1169 }
1170 
1171 void
1172 Lsdb::onContentValidated(const std::shared_ptr<const ndn::Data>& data)
1173 {
1174  const ndn::Name& dataName = data->getName();
1175  NLSR_LOG_DEBUG("Data validation successful for LSA: " << dataName);
1176 
1177  std::string chkString("LSA");
1178  int32_t lsaPosition = util::getNameComponentPosition(dataName, chkString);
1179 
1180  if (lsaPosition >= 0) {
1181 
1182  // Extracts the prefix of the originating router from the data.
1183  ndn::Name originRouter = m_confParam.getNetwork();
1184  originRouter.append(dataName.getSubName(lsaPosition + 1, dataName.size() - lsaPosition - 3));
1185 
1186  uint64_t seqNo = dataName[-1].toNumber();
1187  std::string dataContent(reinterpret_cast<const char*>(data->getContent().value()),
1188  data->getContent().value_size());
1189 
1190  Lsa::Type interestedLsType;
1191  std::istringstream(dataName[-2].toUri()) >> interestedLsType;
1192 
1193  if (interestedLsType == Lsa::Type::NAME) {
1194  processContentNameLsa(originRouter.append(std::to_string(interestedLsType)), seqNo,
1195  dataContent);
1196  }
1197  else if (interestedLsType == Lsa::Type::ADJACENCY) {
1198  processContentAdjacencyLsa(originRouter.append(std::to_string(interestedLsType)), seqNo,
1199  dataContent);
1200  }
1201  else if (interestedLsType == Lsa::Type::COORDINATE) {
1202  processContentCoordinateLsa(originRouter.append(std::to_string(interestedLsType)), seqNo,
1203  dataContent);
1204  }
1205  else {
1206  NLSR_LOG_WARN("Received unrecognized LSA Type: " << interestedLsType);
1207  }
1208 
1210  }
1211 }
1212 
1213 void
1214 Lsdb::processContentNameLsa(const ndn::Name& lsaKey,
1215  uint64_t lsSeqNo, std::string& dataContent)
1216 {
1218  if (isNameLsaNew(lsaKey, lsSeqNo)) {
1219  NameLsa nameLsa;
1220  if (nameLsa.deserialize(dataContent)) {
1221  installNameLsa(nameLsa);
1222  }
1223  else {
1224  NLSR_LOG_DEBUG("LSA data decoding error :(");
1225  }
1226  }
1227 }
1228 
1229 void
1230 Lsdb::processContentAdjacencyLsa(const ndn::Name& lsaKey,
1231  uint64_t lsSeqNo, std::string& dataContent)
1232 {
1234  if (isAdjLsaNew(lsaKey, lsSeqNo)) {
1235  AdjLsa adjLsa;
1236  if (adjLsa.deserialize(dataContent)) {
1237  installAdjLsa(adjLsa);
1238  }
1239  else {
1240  NLSR_LOG_DEBUG("LSA data decoding error :(");
1241  }
1242  }
1243 }
1244 
1245 void
1246 Lsdb::processContentCoordinateLsa(const ndn::Name& lsaKey,
1247  uint64_t lsSeqNo, std::string& dataContent)
1248 {
1250  if (isCoordinateLsaNew(lsaKey, lsSeqNo)) {
1251  CoordinateLsa corLsa;
1252  if (corLsa.deserialize(dataContent)) {
1253  installCoordinateLsa(corLsa);
1254  }
1255  else {
1256  NLSR_LOG_DEBUG("LSA data decoding error :(");
1257  }
1258  }
1259 }
1260 
1261 ndn::time::system_clock::TimePoint
1262 Lsdb::getLsaExpirationTimePoint()
1263 {
1264  ndn::time::system_clock::TimePoint expirationTimePoint = ndn::time::system_clock::now();
1265  expirationTimePoint = expirationTimePoint +
1266  ndn::time::seconds(m_confParam.getRouterDeadInterval());
1267  return expirationTimePoint;
1268 }
1269 
1270 void
1272 {
1273  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
1274  return;
1275  }
1276 
1277  NLSR_LOG_DEBUG("---------------Adj LSDB-------------------");
1278  for (const auto& adj : m_adjLsdb) {
1279  adj.writeLog();
1280  }
1281 }
1282 
1283 //-----utility function -----
1284 bool
1285 Lsdb::doesLsaExist(const ndn::Name& key, const Lsa::Type& lsType)
1286 {
1287  switch (lsType) {
1288  case Lsa::Type::ADJACENCY:
1289  return doesAdjLsaExist(key);
1290  case Lsa::Type::COORDINATE:
1291  return doesCoordinateLsaExist(key);
1292  case Lsa::Type::NAME:
1293  return doesNameLsaExist(key);
1294  default:
1295  return false;
1296  }
1297 }
1298 
1299 bool
1300 Lsdb::isLsaNew(const ndn::Name& routerName, const Lsa::Type& lsaType,
1301  const uint64_t& sequenceNumber) {
1302  ndn::Name lsaKey = routerName;
1303  lsaKey.append(std::to_string(lsaType));
1304 
1305  switch (lsaType) {
1306  case Lsa::Type::ADJACENCY:
1307  return isAdjLsaNew(lsaKey, sequenceNumber);
1308  case Lsa::Type::COORDINATE:
1309  return isCoordinateLsaNew(lsaKey, sequenceNumber);
1310  case Lsa::Type::NAME:
1311  return isNameLsaNew(lsaKey, sequenceNumber);
1312  default:
1313  return false;
1314  }
1315 }
1316 
1317 } // namespace nlsr
bool installAdjLsa(AdjLsa &alsa)
Installs an adj. LSA into the LSDB.
Definition: lsdb.cpp:679
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:555
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:1300
AdjacencyList & getAdl()
Definition: lsa.hpp:240
void setLsSeqNo(uint32_t lsn)
Definition: lsa.hpp:56
uint64_t getCorLsaSeq() const
void writeAdjLsdbLog()
Definition: lsdb.cpp:1271
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:537
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:1004
void expressInterest(const ndn::Name &interestName, uint32_t timeoutCount, ndn::time::steady_clock::TimePoint deadline=DEFAULT_LSA_RETRIEVAL_DEADLINE)
Definition: lsdb.cpp:924
uint32_t getLsaRefreshTime() const
bool doesLsaExist(const ndn::Name &key, const Lsa::Type &lsType)
Definition: lsdb.cpp:1285
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:654
bool removeAdjLsa(const ndn::Name &key)
Removes an adj. LSA from the LSDB.
Definition: lsdb.cpp:749
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-2019, 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:549
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:774
AdjLsa * findAdjLsa(const ndn::Name &key)
Finds an adj. LSA in the LSDB.
Definition: lsdb.cpp:643
uint32_t getRouterDeadInterval() const
bool buildAndInstallOwnAdjLsa()
Wrapper event to build and install an adj. LSA for this router.
Definition: lsdb.cpp:730
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.