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