lsdb.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2023, The University of Memphis,
4  * Regents of the University of California,
5  * Arizona Board of Regents.
6  *
7  * This file is part of NLSR (Named-data Link State Routing).
8  * See AUTHORS.md for complete list of NLSR authors and contributors.
9  *
10  * NLSR is free software: you can redistribute it and/or modify it under the terms
11  * of the GNU General Public License as published by the Free Software Foundation,
12  * either version 3 of the License, or (at your option) any later version.
13  *
14  * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  * PURPOSE. See the GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "lsdb.hpp"
23 
24 #include "logger.hpp"
25 #include "nlsr.hpp"
26 #include "utility/name-helper.hpp"
27 
28 #include <ndn-cxx/lp/tags.hpp>
29 
30 namespace nlsr {
31 
32 INIT_LOGGER(Lsdb);
33 
34 Lsdb::Lsdb(ndn::Face& face, ndn::KeyChain& keyChain, ConfParameter& confParam)
35  : m_face(face)
36  , m_scheduler(face.getIoService())
37  , m_confParam(confParam)
38  , m_sync(m_face, keyChain,
39  [this] (const auto& routerName, const Lsa::Type& lsaType,
40  uint64_t sequenceNumber, uint64_t incomingFaceId) {
41  return isLsaNew(routerName, lsaType, sequenceNumber);
42  }, m_confParam)
43  , m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
44  , m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
45  , m_thisRouterPrefix(m_confParam.getRouterPrefix())
46  , m_sequencingManager(m_confParam.getStateFileDir(), m_confParam.getHyperbolicState())
47  , m_onNewLsaConnection(m_sync.onNewLsa.connect(
48  [this] (const ndn::Name& updateName, uint64_t sequenceNumber,
49  const ndn::Name& originRouter, uint64_t incomingFaceId) {
50  ndn::Name lsaInterest{updateName};
51  lsaInterest.appendNumber(sequenceNumber);
52  expressInterest(lsaInterest, 0, incomingFaceId);
53  }))
54  , m_segmenter(keyChain, m_confParam.getSigningInfo())
55  , m_segmentFifo(100)
56  , m_isBuildAdjLsaScheduled(false)
57  , m_adjBuildCount(0)
58 {
59  ndn::Name name = m_confParam.getLsaPrefix();
60  NLSR_LOG_DEBUG("Setting interest filter for LsaPrefix: " << name);
61 
62  m_face.setInterestFilter(ndn::InterestFilter(name).allowLoopback(false),
63  [this] (const auto& name, const auto& interest) { processInterest(name, interest); },
64  [] (const auto& name) { NLSR_LOG_DEBUG("Successfully registered prefix: " << name); },
65  [] (const auto& name, const auto& reason) {
66  NLSR_LOG_ERROR("Failed to register prefix " << name);
67  NDN_THROW(std::runtime_error("Register prefix failed: " + reason));
68  },
69  m_confParam.getSigningInfo(), ndn::nfd::ROUTE_FLAG_CAPTURE);
70 
71  buildAndInstallOwnNameLsa();
72  // Install coordinate LSAs if using HR or dry-run HR.
73  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
74  buildAndInstallOwnCoordinateLsa();
75  }
76 }
77 
78 Lsdb::~Lsdb()
79 {
80  for (const auto& fetcher : m_fetchers) {
81  fetcher->stop();
82  }
83 }
84 
85 void
86 Lsdb::buildAndInstallOwnNameLsa()
87 {
88  NameLsa nameLsa(m_thisRouterPrefix, m_sequencingManager.getNameLsaSeq() + 1,
89  getLsaExpirationTimePoint(), m_confParam.getNamePrefixList());
90  m_sequencingManager.increaseNameLsaSeq();
91  m_sequencingManager.writeSeqNoToFile();
92  m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
93 
94  installLsa(std::make_shared<NameLsa>(nameLsa));
95 }
96 
97 void
98 Lsdb::buildAndInstallOwnCoordinateLsa()
99 {
100  CoordinateLsa corLsa(m_thisRouterPrefix, m_sequencingManager.getCorLsaSeq() + 1,
101  getLsaExpirationTimePoint(), m_confParam.getCorR(),
102  m_confParam.getCorTheta());
103  m_sequencingManager.increaseCorLsaSeq();
104  m_sequencingManager.writeSeqNoToFile();
105 
106  // Sync coordinate LSAs if using HR or HR dry run.
107  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
108  m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
109  }
110 
111  installLsa(std::make_shared<CoordinateLsa>(corLsa));
112 }
113 
114 void
115 Lsdb::scheduleAdjLsaBuild()
116 {
117  m_adjBuildCount++;
118 
119  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
120  // Don't build adjacency LSAs in hyperbolic routing
121  NLSR_LOG_DEBUG("Adjacency LSA not built while in hyperbolic routing state");
122  return;
123  }
124 
125  if (m_isBuildAdjLsaScheduled) {
126  NLSR_LOG_DEBUG("Rescheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
127  }
128  else {
129  NLSR_LOG_DEBUG("Scheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
130  m_isBuildAdjLsaScheduled = true;
131  }
132  m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [this] { buildAdjLsa(); });
133 }
134 
135 void
136 Lsdb::writeLog() const
137 {
138  static const Lsa::Type types[] = {Lsa::Type::COORDINATE, Lsa::Type::NAME, Lsa::Type::ADJACENCY};
139  for (const auto& type : types) {
140  if ((type == Lsa::Type::COORDINATE &&
141  m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) ||
142  (type == Lsa::Type::ADJACENCY &&
143  m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON)) {
144  continue;
145  }
146 
147  NLSR_LOG_DEBUG("---------------" << type << " LSDB-------------------");
148  auto lsaRange = m_lsdb.get<byType>().equal_range(type);
149  for (auto lsaIt = lsaRange.first; lsaIt != lsaRange.second; ++lsaIt) {
150  NLSR_LOG_DEBUG((*lsaIt)->toString());
151  }
152  }
153 }
154 
155 void
156 Lsdb::processInterest(const ndn::Name& name, const ndn::Interest& interest)
157 {
158  ndn::Name interestName(interest.getName());
159  NLSR_LOG_DEBUG("Interest received for LSA: " << interestName);
160 
161  if (interestName[-2].isVersion()) {
162  // Interest for particular segment
163  auto data = m_segmentFifo.find(interestName);
164  if (data) {
165  NLSR_LOG_TRACE("Replying from FIFO buffer");
166  m_face.put(*data);
167  return;
168  }
169 
170  // Remove version and segment
171  interestName = interestName.getPrefix(-2);
172  NLSR_LOG_TRACE("Interest w/o segment and version: " << interestName);
173  }
174 
175  // increment RCV_LSA_INTEREST
176  lsaIncrementSignal(Statistics::PacketType::RCV_LSA_INTEREST);
177 
178  std::string chkString("LSA");
179  int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
180 
181  // Forms the name of the router that the Interest packet came from.
182  ndn::Name originRouter = m_confParam.getNetwork();
183  originRouter.append(interestName.getSubName(lsaPosition + 1,
184  interestName.size() - lsaPosition - 3));
185 
186  // if the interest is for this router's LSA
187  if (originRouter == m_thisRouterPrefix && lsaPosition >= 0) {
188  uint64_t seqNo = interestName[-1].toNumber();
189  NLSR_LOG_DEBUG("LSA sequence number from interest: " << seqNo);
190 
191  std::string lsaType = interestName[-2].toUri();
192  Lsa::Type interestedLsType;
193  std::istringstream(lsaType) >> interestedLsType;
194  if (interestedLsType == Lsa::Type::BASE) {
195  NLSR_LOG_WARN("Received unrecognized LSA type: " << lsaType);
196  return;
197  }
198 
199  incrementInterestRcvdStats(interestedLsType);
200  if (processInterestForLsa(interest, originRouter, interestedLsType, seqNo)) {
201  lsaIncrementSignal(Statistics::PacketType::SENT_LSA_DATA);
202  }
203  }
204  // else the interest is for other router's LSA, serve signed data from LsaSegmentStorage
205  else if (auto lsaSegment = m_lsaStorage.find(interest); lsaSegment) {
206  NLSR_LOG_TRACE("Found data in lsa storage. Sending data for " << interest.getName());
207  m_face.put(*lsaSegment);
208  }
209 }
210 
211 bool
212 Lsdb::processInterestForLsa(const ndn::Interest& interest, const ndn::Name& originRouter,
213  Lsa::Type lsaType, uint64_t seqNo)
214 {
215  NLSR_LOG_DEBUG(interest << " received for " << lsaType);
216 
217  if (auto lsaPtr = findLsa(originRouter, lsaType); lsaPtr) {
218  NLSR_LOG_TRACE("Verifying SeqNo for " << lsaType << " is same as requested");
219  if (lsaPtr->getSeqNo() == seqNo) {
220  auto segments = m_segmenter.segment(lsaPtr->wireEncode(),
221  ndn::Name(interest.getName()).appendVersion(),
222  ndn::MAX_NDN_PACKET_SIZE / 2, m_lsaRefreshTime);
223  for (const auto& data : segments) {
224  m_segmentFifo.insert(*data, m_lsaRefreshTime);
225  m_scheduler.schedule(m_lsaRefreshTime,
226  [this, name = data->getName()] { m_segmentFifo.erase(name); });
227  }
228 
229  uint64_t segNum = 0;
230  if (interest.getName()[-1].isSegment()) {
231  segNum = interest.getName()[-1].toSegment();
232  }
233  if (segNum < segments.size()) {
234  m_face.put(*segments[segNum]);
235  }
236  incrementDataSentStats(lsaType);
237  return true;
238  }
239  }
240  else {
241  NLSR_LOG_TRACE(interest << " was not found in our LSDB");
242  }
243  return false;
244 }
245 
246 void
247 Lsdb::installLsa(std::shared_ptr<Lsa> lsa)
248 {
249  auto timeToExpire = m_lsaRefreshTime;
250  if (lsa->getOriginRouter() != m_thisRouterPrefix) {
251  auto duration = lsa->getExpirationTimePoint() - ndn::time::system_clock::now();
252  if (duration > ndn::time::seconds(0)) {
253  timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
254  }
255  }
256 
257  auto chkLsa = findLsa(lsa->getOriginRouter(), lsa->getType());
258  if (chkLsa == nullptr) {
259  NLSR_LOG_DEBUG("Adding " << lsa->getType() << " LSA");
260  NLSR_LOG_DEBUG(lsa->toString());
261 
262  m_lsdb.emplace(lsa);
263 
264  onLsdbModified(lsa, LsdbUpdate::INSTALLED, {}, {});
265 
266  lsa->setExpiringEventId(scheduleLsaExpiration(lsa, timeToExpire));
267  }
268  // Else this is a known name LSA, so we are updating it.
269  else if (chkLsa->getSeqNo() < lsa->getSeqNo()) {
270  NLSR_LOG_DEBUG("Updating " << lsa->getType() << " LSA:");
271  NLSR_LOG_DEBUG(chkLsa->toString());
272  chkLsa->setSeqNo(lsa->getSeqNo());
273  chkLsa->setExpirationTimePoint(lsa->getExpirationTimePoint());
274 
275  auto [updated, namesToAdd, namesToRemove] = chkLsa->update(lsa);
276  if (updated) {
277  onLsdbModified(lsa, LsdbUpdate::UPDATED, namesToAdd, namesToRemove);
278  }
279 
280  chkLsa->setExpiringEventId(scheduleLsaExpiration(chkLsa, timeToExpire));
281  NLSR_LOG_DEBUG("Updated " << lsa->getType() << " LSA:");
282  NLSR_LOG_DEBUG(chkLsa->toString());
283  }
284 }
285 
286 void
287 Lsdb::removeLsa(const LsaContainer::index<Lsdb::byName>::type::iterator& lsaIt)
288 {
289  if (lsaIt != m_lsdb.end()) {
290  auto lsaPtr = *lsaIt;
291  NLSR_LOG_DEBUG("Removing " << lsaPtr->getType() << " LSA:");
292  NLSR_LOG_DEBUG(lsaPtr->toString());
293  m_lsdb.erase(lsaIt);
294  onLsdbModified(lsaPtr, LsdbUpdate::REMOVED, {}, {});
295  }
296 }
297 
298 void
299 Lsdb::removeLsa(const ndn::Name& router, Lsa::Type lsaType)
300 {
301  removeLsa(m_lsdb.get<byName>().find(std::make_tuple(router, lsaType)));
302 }
303 
304 void
305 Lsdb::buildAdjLsa()
306 {
307  NLSR_LOG_TRACE("buildAdjLsa called");
308 
309  m_isBuildAdjLsaScheduled = false;
310 
311  if (m_confParam.getAdjacencyList().isAdjLsaBuildable(m_confParam.getInterestRetryNumber())) {
312 
313  int adjBuildCount = m_adjBuildCount;
314  // Only do the adjLsa build if there's one scheduled
315  if (adjBuildCount > 0) {
316  // It only makes sense to do the adjLsa build if we have neighbors
317  if (m_confParam.getAdjacencyList().getNumOfActiveNeighbor() > 0) {
318  NLSR_LOG_DEBUG("Building and installing own Adj LSA");
319  buildAndInstallOwnAdjLsa();
320  }
321  // We have no active neighbors, meaning no one can route through
322  // us. So delete our entry in the LSDB. This prevents this
323  // router from refreshing the LSA, eventually causing other
324  // routers to delete it, too.
325  else {
326  NLSR_LOG_DEBUG("Removing own Adj LSA; no ACTIVE neighbors");
327  removeLsa(m_thisRouterPrefix, Lsa::Type::ADJACENCY);
328  }
329  // In the case that during building the adj LSA, the FIB has to
330  // wait on an Interest response, the number of scheduled adj LSA
331  // builds could change, so we shouldn't just set it to 0.
332  m_adjBuildCount = m_adjBuildCount - adjBuildCount;
333  }
334  }
335  // We are still waiting to know the adjacency status of some
336  // neighbor, so schedule a build for later (when all that has
337  // hopefully finished)
338  else {
339  m_isBuildAdjLsaScheduled = true;
340  auto schedulingTime = ndn::time::seconds(m_confParam.getInterestRetryNumber() *
341  m_confParam.getInterestResendTime());
342  m_scheduledAdjLsaBuild = m_scheduler.schedule(schedulingTime, [this] { buildAdjLsa(); });
343  }
344 }
345 
346 void
347 Lsdb::buildAndInstallOwnAdjLsa()
348 {
349  AdjLsa adjLsa(m_thisRouterPrefix, m_sequencingManager.getAdjLsaSeq() + 1,
350  getLsaExpirationTimePoint(),
351  m_confParam.getAdjacencyList().getNumOfActiveNeighbor(),
352  m_confParam.getAdjacencyList());
353  m_sequencingManager.increaseAdjLsaSeq();
354  m_sequencingManager.writeSeqNoToFile();
355 
356  //Sync adjacency LSAs if link-state or dry-run HR is enabled.
357  if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_ON) {
358  m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
359  }
360 
361  installLsa(std::make_shared<AdjLsa>(adjLsa));
362 }
363 
364 ndn::scheduler::EventId
365 Lsdb::scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime)
366 {
367  NLSR_LOG_DEBUG("Scheduling expiration in: " << expTime + GRACE_PERIOD << " for " << lsa->getOriginRouter());
368  return m_scheduler.schedule(expTime + GRACE_PERIOD, [this, lsa] { expireOrRefreshLsa(lsa); });
369 }
370 
371 void
372 Lsdb::expireOrRefreshLsa(std::shared_ptr<Lsa> lsa)
373 {
374  NLSR_LOG_DEBUG("ExpireOrRefreshLsa called for " << lsa->getType());
375  NLSR_LOG_DEBUG("OriginRouter: " << lsa->getOriginRouter() << " Seq No: " << lsa->getSeqNo());
376 
377  auto lsaIt = m_lsdb.get<byName>().find(std::make_tuple(lsa->getOriginRouter(), lsa->getType()));
378 
379  // If this name LSA exists in the LSDB
380  if (lsaIt != m_lsdb.end()) {
381  auto lsaPtr = *lsaIt;
382  NLSR_LOG_DEBUG(lsaPtr->toString());
383  NLSR_LOG_DEBUG("LSA Exists with seq no: " << lsaPtr->getSeqNo());
384  // If its seq no is the one we are expecting.
385  if (lsaPtr->getSeqNo() == lsa->getSeqNo()) {
386  if (lsaPtr->getOriginRouter() == m_thisRouterPrefix) {
387  NLSR_LOG_DEBUG("Own " << lsaPtr->getType() << " LSA, so refreshing it");
388  NLSR_LOG_DEBUG("Current LSA:");
389  NLSR_LOG_DEBUG(lsaPtr->toString());
390  lsaPtr->setSeqNo(lsaPtr->getSeqNo() + 1);
391  m_sequencingManager.setLsaSeq(lsaPtr->getSeqNo(), lsaPtr->getType());
392  lsaPtr->setExpirationTimePoint(getLsaExpirationTimePoint());
393  NLSR_LOG_DEBUG("Updated LSA:");
394  NLSR_LOG_DEBUG(lsaPtr->toString());
395  // schedule refreshing event again
396  lsaPtr->setExpiringEventId(scheduleLsaExpiration(lsaPtr, m_lsaRefreshTime));
397  m_sequencingManager.writeSeqNoToFile();
398  m_sync.publishRoutingUpdate(lsaPtr->getType(), m_sequencingManager.getLsaSeq(lsaPtr->getType()));
399  }
400  // Since we cannot refresh other router's LSAs, our only choice is to expire.
401  else {
402  NLSR_LOG_DEBUG("Other's " << lsaPtr->getType() << " LSA, so removing from LSDB");
403  removeLsa(lsaIt);
404  }
405  }
406  }
407 }
408 
409 void
410 Lsdb::expressInterest(const ndn::Name& interestName, uint32_t timeoutCount, uint64_t incomingFaceId,
411  ndn::time::steady_clock::time_point deadline)
412 {
413  // increment SENT_LSA_INTEREST
414  lsaIncrementSignal(Statistics::PacketType::SENT_LSA_INTEREST);
415 
416  if (deadline == DEFAULT_LSA_RETRIEVAL_DEADLINE) {
417  deadline = ndn::time::steady_clock::now() + ndn::time::seconds(static_cast<int>(LSA_REFRESH_TIME_MAX));
418  }
419  // The first component of the interest is the name.
420  ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
421  // The seq no is the last
422  uint64_t seqNo = interestName[-1].toNumber();
423 
424  // If the LSA is not found in the list currently.
425  if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
426  m_highestSeqNo[lsaName] = seqNo;
427  }
428  // If the new seq no is higher, that means the LSA is valid
429  else if (seqNo > m_highestSeqNo[lsaName]) {
430  m_highestSeqNo[lsaName] = seqNo;
431  }
432  // Otherwise, its an old/invalid LSA
433  else if (seqNo < m_highestSeqNo[lsaName]) {
434  return;
435  }
436 
437  ndn::Interest interest(interestName);
438  if (incomingFaceId != 0) {
439  interest.setTag(std::make_shared<ndn::lp::NextHopFaceIdTag>(incomingFaceId));
440  }
441  ndn::util::SegmentFetcher::Options options;
442  options.interestLifetime = m_confParam.getLsaInterestLifetime();
443  options.maxTimeout = m_confParam.getLsaInterestLifetime();
444 
445  NLSR_LOG_DEBUG("Fetching Data for LSA: " << interestName << " Seq number: " << seqNo);
446  auto fetcher = ndn::util::SegmentFetcher::start(m_face, interest,
447  m_confParam.getValidator(), options);
448 
449  auto it = m_fetchers.insert(fetcher).first;
450 
451  fetcher->afterSegmentValidated.connect([this] (const ndn::Data& data) {
452  // Nlsr class subscribes to this to fetch certificates
453  afterSegmentValidatedSignal(data);
454 
455  // If we don't do this IMS throws: std::bad_weak_ptr: bad_weak_ptr
456  auto lsaSegment = std::make_shared<const ndn::Data>(data);
457  m_lsaStorage.insert(*lsaSegment);
458  // Schedule deletion of the segment
459  m_scheduler.schedule(ndn::time::seconds(LSA_REFRESH_TIME_DEFAULT),
460  [this, name = lsaSegment->getName()] { m_lsaStorage.erase(name); });
461  });
462 
463  fetcher->onComplete.connect([=] (const ndn::ConstBufferPtr& bufferPtr) {
464  m_lsaStorage.erase(ndn::Name(lsaName).appendNumber(seqNo - 1));
465  afterFetchLsa(bufferPtr, interestName);
466  m_fetchers.erase(it);
467  });
468 
469  fetcher->onError.connect([=] (uint32_t errorCode, const std::string& msg) {
470  onFetchLsaError(errorCode, msg, interestName, timeoutCount, deadline, lsaName, seqNo);
471  m_fetchers.erase(it);
472  });
473 
474  Lsa::Type lsaType;
475  std::istringstream(interestName[-2].toUri()) >> lsaType;
476  incrementInterestSentStats(lsaType);
477 }
478 
479 void
480 Lsdb::onFetchLsaError(uint32_t errorCode, const std::string& msg, const ndn::Name& interestName,
481  uint32_t retransmitNo, const ndn::time::steady_clock::time_point& deadline,
482  ndn::Name lsaName, uint64_t seqNo)
483 {
484  NLSR_LOG_DEBUG("Failed to fetch LSA: " << lsaName << ", Error code: " << errorCode
485  << ", Message: " << msg);
486 
487  if (ndn::time::steady_clock::now() < deadline) {
488  auto it = m_highestSeqNo.find(lsaName);
489  if (it != m_highestSeqNo.end() && it->second == seqNo) {
490  // If the SegmentFetcher failed due to an Interest timeout, it is safe to re-express
491  // immediately since at the least the LSA Interest lifetime has elapsed.
492  // Otherwise, it is necessary to delay the Interest re-expression to prevent
493  // the potential for constant Interest flooding.
494  ndn::time::seconds delay = m_confParam.getLsaInterestLifetime();
495 
496  if (errorCode == ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
497  delay = ndn::time::seconds(0);
498  }
499  m_scheduler.schedule(delay, std::bind(&Lsdb::expressInterest, this,
500  interestName, retransmitNo + 1, /*Multicast FaceID*/0, deadline));
501  }
502  }
503 }
504 
505 void
506 Lsdb::afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName)
507 {
508  NLSR_LOG_DEBUG("Received data for LSA interest: " << interestName);
509  lsaIncrementSignal(Statistics::PacketType::RCV_LSA_DATA);
510 
511  ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
512  uint64_t seqNo = interestName[-1].toNumber();
513 
514  if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
515  m_highestSeqNo[lsaName] = seqNo;
516  }
517  else if (seqNo > m_highestSeqNo[lsaName]) {
518  m_highestSeqNo[lsaName] = seqNo;
519  NLSR_LOG_TRACE("SeqNo for LSA(name): " << interestName << " updated");
520  }
521  else if (seqNo < m_highestSeqNo[lsaName]) {
522  return;
523  }
524 
525  std::string chkString("LSA");
526  int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
527 
528  if (lsaPosition >= 0) {
529  // Extracts the prefix of the originating router from the data.
530  ndn::Name originRouter = m_confParam.getNetwork();
531  originRouter.append(interestName.getSubName(lsaPosition + 1,
532  interestName.size() - lsaPosition - 3));
533  try {
534  Lsa::Type interestedLsType;
535  std::istringstream(interestName[-2].toUri()) >> interestedLsType;
536 
537  if (interestedLsType == Lsa::Type::BASE) {
538  NLSR_LOG_WARN("Received unrecognized LSA Type: " << interestName[-2].toUri());
539  return;
540  }
541 
542  ndn::Block block(bufferPtr);
543  if (interestedLsType == Lsa::Type::NAME) {
544  lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_DATA);
545  if (isLsaNew(originRouter, interestedLsType, seqNo)) {
546  installLsa(std::make_shared<NameLsa>(block));
547  }
548  }
549  else if (interestedLsType == Lsa::Type::ADJACENCY) {
550  lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_DATA);
551  if (isLsaNew(originRouter, interestedLsType, seqNo)) {
552  installLsa(std::make_shared<AdjLsa>(block));
553  }
554  }
555  else if (interestedLsType == Lsa::Type::COORDINATE) {
556  lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_DATA);
557  if (isLsaNew(originRouter, interestedLsType, seqNo)) {
558  installLsa(std::make_shared<CoordinateLsa>(block));
559  }
560  }
561  }
562  catch (const std::exception& e) {
563  NLSR_LOG_TRACE("LSA data decoding error :( " << e.what());
564  }
565  }
566 }
567 
568 } // namespace nlsr
A class to house all the configuration parameters for NLSR.
Data abstraction for CoordinateLsa CoordinateLsa := COORDINATE-LSA-TYPE TLV-LENGTH Lsa HyperbolicRadi...
Data abstraction for Lsa Lsa := LSA-TYPE TLV-LENGTH Name SequenceNumber ExpirationTimePoint.
Definition: lsa.hpp:42
Lsdb(ndn::Face &face, ndn::KeyChain &keyChain, ConfParameter &confParam)
Definition: lsdb.cpp:34
Data abstraction for NameLsa NameLsa := NAME-LSA-TYPE TLV-LENGTH Lsa Name+.
Definition: name-lsa.hpp:36
Copyright (c) 2014-2018, The University of Memphis, Regents of the University of California.
#define NLSR_LOG_DEBUG(x)
Definition: logger.hpp:38
#define INIT_LOGGER(name)
Definition: logger.hpp:35
#define NLSR_LOG_WARN(x)
Definition: logger.hpp:40
#define NLSR_LOG_ERROR(x)
Definition: logger.hpp:41
#define NLSR_LOG_TRACE(x)
Definition: logger.hpp:37
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:38
Copyright (c) 2014-2020, The University of Memphis, Regents of the University of California.
@ LSA_REFRESH_TIME_MAX
@ LSA_REFRESH_TIME_DEFAULT
@ HYPERBOLIC_STATE_ON
@ HYPERBOLIC_STATE_OFF
constexpr ndn::time::seconds GRACE_PERIOD
Definition: lsdb.hpp:51