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