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