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