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