blob: 844de226f966f56d08056c1571e419c4fe54435f [file] [log] [blame]
akmhoque3d06e792014-05-27 16:23:20 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoaf7a2112019-03-19 14:55:20 -04002/*
Junxiao Shib8752932024-01-07 15:18:46 +00003 * Copyright (c) 2014-2024, The University of Memphis,
Vince Lehmanc2e51f62015-01-20 15:03:11 -06004 * Regents of the University of California,
5 * Arizona Board of Regents.
akmhoque3d06e792014-05-27 16:23:20 -05006 *
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/>.
Ashlesh Gawande0421bc62020-05-08 20:42:19 -070020 */
Vince Lehmanc2e51f62015-01-20 15:03:11 -060021
akmhoque53353462014-04-22 08:43:45 -050022#include "lsdb.hpp"
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050023
akmhoque674b0b12014-05-20 14:33:28 -050024#include "logger.hpp"
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050025#include "nlsr.hpp"
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050026#include "utility/name-helper.hpp"
27
Alexander Afanasyev135288c2022-04-23 23:06:56 -040028#include <ndn-cxx/lp/tags.hpp>
29
akmhoque53353462014-04-22 08:43:45 -050030namespace nlsr {
31
dmcoomescf8d0ed2017-02-21 11:39:01 -060032INIT_LOGGER(Lsdb);
akmhoque674b0b12014-05-20 14:33:28 -050033
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070034Lsdb::Lsdb(ndn::Face& face, ndn::KeyChain& keyChain, ConfParameter& confParam)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060035 : m_face(face)
Davide Pesaventofd1e9402023-11-13 15:40:41 -050036 , m_scheduler(face.getIoContext())
Ashlesh Gawande85998a12017-12-07 22:22:13 -060037 , m_confParam(confParam)
Davide Pesavento1954a0c2022-09-30 15:56:04 -040038 , m_sync(m_face, keyChain,
Junxiao Shif4674672024-01-06 02:27:36 +000039 [this] (const auto& routerName, Lsa::Type lsaType, uint64_t seqNo, uint64_t) {
40 return isLsaNew(routerName, lsaType, seqNo);
41 },
42 SyncLogicOptions{
43 confParam.getSyncProtocol(),
44 confParam.getSyncPrefix(),
45 confParam.getSyncUserPrefix(),
46 confParam.getSyncInterestLifetime(),
47 confParam.getRouterPrefix(),
48 confParam.getHyperbolicState()
49 })
Ashlesh Gawande85998a12017-12-07 22:22:13 -060050 , m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
Ashlesh Gawande85998a12017-12-07 22:22:13 -060051 , m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
Ashlesh Gawande57a87172020-05-09 19:47:06 -070052 , m_thisRouterPrefix(m_confParam.getRouterPrefix())
dulalsaurab82a34c22019-02-04 17:31:21 +000053 , m_sequencingManager(m_confParam.getStateFileDir(), m_confParam.getHyperbolicState())
Davide Pesavento1954a0c2022-09-30 15:56:04 -040054 , m_onNewLsaConnection(m_sync.onNewLsa.connect(
Ashlesh Gawande08bce9c2019-04-05 11:08:07 -050055 [this] (const ndn::Name& updateName, uint64_t sequenceNumber,
Alexander Afanasyev135288c2022-04-23 23:06:56 -040056 const ndn::Name& originRouter, uint64_t incomingFaceId) {
Nick Gordon9eac4d92017-08-29 17:31:29 -050057 ndn::Name lsaInterest{updateName};
58 lsaInterest.appendNumber(sequenceNumber);
Alexander Afanasyev135288c2022-04-23 23:06:56 -040059 expressInterest(lsaInterest, 0, incomingFaceId);
Nick Gordon9eac4d92017-08-29 17:31:29 -050060 }))
Davide Pesavento65ee9922022-11-16 00:21:43 -050061 , m_segmenter(keyChain, m_confParam.getSigningInfo())
62 , m_segmentFifo(100)
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070063 , m_isBuildAdjLsaScheduled(false)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060064 , m_adjBuildCount(0)
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050065{
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070066 ndn::Name name = m_confParam.getLsaPrefix();
67 NLSR_LOG_DEBUG("Setting interest filter for LsaPrefix: " << name);
68
69 m_face.setInterestFilter(ndn::InterestFilter(name).allowLoopback(false),
70 [this] (const auto& name, const auto& interest) { processInterest(name, interest); },
71 [] (const auto& name) { NLSR_LOG_DEBUG("Successfully registered prefix: " << name); },
72 [] (const auto& name, const auto& reason) {
73 NLSR_LOG_ERROR("Failed to register prefix " << name);
74 NDN_THROW(std::runtime_error("Register prefix failed: " + reason));
75 },
76 m_confParam.getSigningInfo(), ndn::nfd::ROUTE_FLAG_CAPTURE);
77
78 buildAndInstallOwnNameLsa();
79 // Install coordinate LSAs if using HR or dry-run HR.
80 if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
81 buildAndInstallOwnCoordinateLsa();
82 }
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050083}
84
Davide Pesavento65ee9922022-11-16 00:21:43 -050085Lsdb::~Lsdb()
86{
87 for (const auto& fetcher : m_fetchers) {
88 fetcher->stop();
89 }
90}
91
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050092void
akmhoque31d1d4b2014-05-05 22:08:14 -050093Lsdb::buildAndInstallOwnNameLsa()
akmhoque53353462014-04-22 08:43:45 -050094{
Ashlesh Gawande57a87172020-05-09 19:47:06 -070095 NameLsa nameLsa(m_thisRouterPrefix, m_sequencingManager.getNameLsaSeq() + 1,
96 getLsaExpirationTimePoint(), m_confParam.getNamePrefixList());
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050097 m_sequencingManager.increaseNameLsaSeq();
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050098 m_sequencingManager.writeSeqNoToFile();
Nick Gordon727d4832017-10-13 18:04:25 -050099 m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500100
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700101 installLsa(std::make_shared<NameLsa>(nameLsa));
akmhoque53353462014-04-22 08:43:45 -0500102}
103
104void
akmhoque31d1d4b2014-05-05 22:08:14 -0500105Lsdb::buildAndInstallOwnCoordinateLsa()
akmhoque53353462014-04-22 08:43:45 -0500106{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700107 CoordinateLsa corLsa(m_thisRouterPrefix, m_sequencingManager.getCorLsaSeq() + 1,
108 getLsaExpirationTimePoint(), m_confParam.getCorR(),
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600109 m_confParam.getCorTheta());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700110 m_sequencingManager.increaseCorLsaSeq();
111 m_sequencingManager.writeSeqNoToFile();
Nick Gordon5c467f02016-07-13 13:40:10 -0500112
113 // Sync coordinate LSAs if using HR or HR dry run.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600114 if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
Nick Gordon727d4832017-10-13 18:04:25 -0500115 m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
Nick Gordon5c467f02016-07-13 13:40:10 -0500116 }
117
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700118 installLsa(std::make_shared<CoordinateLsa>(corLsa));
akmhoque53353462014-04-22 08:43:45 -0500119}
120
akmhoque53353462014-04-22 08:43:45 -0500121void
Vince Lehman50df6b72015-03-03 12:06:40 -0600122Lsdb::scheduleAdjLsaBuild()
akmhoque53353462014-04-22 08:43:45 -0500123{
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600124 m_adjBuildCount++;
Vince Lehman50df6b72015-03-03 12:06:40 -0600125
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600126 if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
Nick Gordon5c467f02016-07-13 13:40:10 -0500127 // Don't build adjacency LSAs in hyperbolic routing
Davide Pesavento65ee9922022-11-16 00:21:43 -0500128 NLSR_LOG_DEBUG("Adjacency LSA not built while in hyperbolic routing state");
Nick Gordon5c467f02016-07-13 13:40:10 -0500129 return;
130 }
131
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700132 if (m_isBuildAdjLsaScheduled) {
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500133 NLSR_LOG_DEBUG("Rescheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
134 }
135 else {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500136 NLSR_LOG_DEBUG("Scheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700137 m_isBuildAdjLsaScheduled = true;
Vince Lehman50df6b72015-03-03 12:06:40 -0600138 }
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500139 m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [this] { buildAdjLsa(); });
Vince Lehman50df6b72015-03-03 12:06:40 -0600140}
141
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700142void
143Lsdb::writeLog() const
144{
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700145 static const Lsa::Type types[] = {Lsa::Type::COORDINATE, Lsa::Type::NAME, Lsa::Type::ADJACENCY};
146 for (const auto& type : types) {
147 if ((type == Lsa::Type::COORDINATE &&
148 m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) ||
149 (type == Lsa::Type::ADJACENCY &&
150 m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON)) {
151 continue;
152 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700153
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700154 NLSR_LOG_DEBUG("---------------" << type << " LSDB-------------------");
155 auto lsaRange = m_lsdb.get<byType>().equal_range(type);
156 for (auto lsaIt = lsaRange.first; lsaIt != lsaRange.second; ++lsaIt) {
157 NLSR_LOG_DEBUG((*lsaIt)->toString());
158 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700159 }
160}
161
162void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700163Lsdb::processInterest(const ndn::Name& name, const ndn::Interest& interest)
164{
165 ndn::Name interestName(interest.getName());
166 NLSR_LOG_DEBUG("Interest received for LSA: " << interestName);
167
168 if (interestName[-2].isVersion()) {
169 // Interest for particular segment
Davide Pesavento65ee9922022-11-16 00:21:43 -0500170 auto data = m_segmentFifo.find(interestName);
171 if (data) {
172 NLSR_LOG_TRACE("Replying from FIFO buffer");
173 m_face.put(*data);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700174 return;
175 }
Davide Pesavento65ee9922022-11-16 00:21:43 -0500176
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700177 // Remove version and segment
Davide Pesavento65ee9922022-11-16 00:21:43 -0500178 interestName = interestName.getPrefix(-2);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700179 NLSR_LOG_TRACE("Interest w/o segment and version: " << interestName);
180 }
181
182 // increment RCV_LSA_INTEREST
183 lsaIncrementSignal(Statistics::PacketType::RCV_LSA_INTEREST);
184
185 std::string chkString("LSA");
186 int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
187
188 // Forms the name of the router that the Interest packet came from.
189 ndn::Name originRouter = m_confParam.getNetwork();
190 originRouter.append(interestName.getSubName(lsaPosition + 1,
191 interestName.size() - lsaPosition - 3));
192
193 // if the interest is for this router's LSA
194 if (originRouter == m_thisRouterPrefix && lsaPosition >= 0) {
195 uint64_t seqNo = interestName[-1].toNumber();
196 NLSR_LOG_DEBUG("LSA sequence number from interest: " << seqNo);
197
198 std::string lsaType = interestName[-2].toUri();
199 Lsa::Type interestedLsType;
200 std::istringstream(lsaType) >> interestedLsType;
201 if (interestedLsType == Lsa::Type::BASE) {
202 NLSR_LOG_WARN("Received unrecognized LSA type: " << lsaType);
203 return;
204 }
205
206 incrementInterestRcvdStats(interestedLsType);
207 if (processInterestForLsa(interest, originRouter, interestedLsType, seqNo)) {
208 lsaIncrementSignal(Statistics::PacketType::SENT_LSA_DATA);
209 }
210 }
211 // else the interest is for other router's LSA, serve signed data from LsaSegmentStorage
Davide Pesavento65ee9922022-11-16 00:21:43 -0500212 else if (auto lsaSegment = m_lsaStorage.find(interest); lsaSegment) {
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500213 NLSR_LOG_TRACE("Found data in LSA storage. Sending data for " << interest.getName());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700214 m_face.put(*lsaSegment);
215 }
216}
217
218bool
219Lsdb::processInterestForLsa(const ndn::Interest& interest, const ndn::Name& originRouter,
220 Lsa::Type lsaType, uint64_t seqNo)
221{
222 NLSR_LOG_DEBUG(interest << " received for " << lsaType);
Davide Pesavento65ee9922022-11-16 00:21:43 -0500223
224 if (auto lsaPtr = findLsa(originRouter, lsaType); lsaPtr) {
225 NLSR_LOG_TRACE("Verifying SeqNo for " << lsaType << " is same as requested");
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700226 if (lsaPtr->getSeqNo() == seqNo) {
Davide Pesavento65ee9922022-11-16 00:21:43 -0500227 auto segments = m_segmenter.segment(lsaPtr->wireEncode(),
228 ndn::Name(interest.getName()).appendVersion(),
229 ndn::MAX_NDN_PACKET_SIZE / 2, m_lsaRefreshTime);
230 for (const auto& data : segments) {
231 m_segmentFifo.insert(*data, m_lsaRefreshTime);
232 m_scheduler.schedule(m_lsaRefreshTime,
233 [this, name = data->getName()] { m_segmentFifo.erase(name); });
234 }
235
236 uint64_t segNum = 0;
237 if (interest.getName()[-1].isSegment()) {
238 segNum = interest.getName()[-1].toSegment();
239 }
240 if (segNum < segments.size()) {
241 m_face.put(*segments[segNum]);
242 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700243 incrementDataSentStats(lsaType);
244 return true;
245 }
246 }
247 else {
Davide Pesavento65ee9922022-11-16 00:21:43 -0500248 NLSR_LOG_TRACE(interest << " was not found in our LSDB");
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700249 }
250 return false;
251}
252
253void
Davide Pesaventod90338d2021-01-07 17:50:05 -0500254Lsdb::installLsa(std::shared_ptr<Lsa> lsa)
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700255{
256 auto timeToExpire = m_lsaRefreshTime;
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700257 if (lsa->getOriginRouter() != m_thisRouterPrefix) {
258 auto duration = lsa->getExpirationTimePoint() - ndn::time::system_clock::now();
259 if (duration > ndn::time::seconds(0)) {
260 timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
261 }
262 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700263
264 auto chkLsa = findLsa(lsa->getOriginRouter(), lsa->getType());
265 if (chkLsa == nullptr) {
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500266 NLSR_LOG_DEBUG("Adding LSA:\n" << lsa->toString());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700267
268 m_lsdb.emplace(lsa);
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700269 onLsdbModified(lsa, LsdbUpdate::INSTALLED, {}, {});
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700270
271 lsa->setExpiringEventId(scheduleLsaExpiration(lsa, timeToExpire));
272 }
273 // Else this is a known name LSA, so we are updating it.
274 else if (chkLsa->getSeqNo() < lsa->getSeqNo()) {
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500275 NLSR_LOG_DEBUG("Updating LSA:\n" << chkLsa->toString());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700276 chkLsa->setSeqNo(lsa->getSeqNo());
277 chkLsa->setExpirationTimePoint(lsa->getExpirationTimePoint());
278
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400279 auto [updated, namesToAdd, namesToRemove] = chkLsa->update(lsa);
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700280 if (updated) {
281 onLsdbModified(lsa, LsdbUpdate::UPDATED, namesToAdd, namesToRemove);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700282 }
283
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700284 chkLsa->setExpiringEventId(scheduleLsaExpiration(chkLsa, timeToExpire));
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500285 NLSR_LOG_DEBUG("Updated LSA:\n" << chkLsa->toString());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700286 }
287}
288
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700289void
290Lsdb::removeLsa(const LsaContainer::index<Lsdb::byName>::type::iterator& lsaIt)
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700291{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700292 if (lsaIt != m_lsdb.end()) {
293 auto lsaPtr = *lsaIt;
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500294 NLSR_LOG_DEBUG("Removing LSA:\n" << lsaPtr->toString());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700295 m_lsdb.erase(lsaIt);
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700296 onLsdbModified(lsaPtr, LsdbUpdate::REMOVED, {}, {});
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700297 }
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700298}
299
300void
301Lsdb::removeLsa(const ndn::Name& router, Lsa::Type lsaType)
302{
303 removeLsa(m_lsdb.get<byName>().find(std::make_tuple(router, lsaType)));
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700304}
305
Vince Lehman50df6b72015-03-03 12:06:40 -0600306void
307Lsdb::buildAdjLsa()
308{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700309 NLSR_LOG_TRACE("buildAdjLsa called");
Vince Lehman50df6b72015-03-03 12:06:40 -0600310
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700311 m_isBuildAdjLsaScheduled = false;
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500312
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600313 if (m_confParam.getAdjacencyList().isAdjLsaBuildable(m_confParam.getInterestRetryNumber())) {
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500314
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600315 int adjBuildCount = m_adjBuildCount;
Nick G97e34942016-07-11 14:46:27 -0500316 // Only do the adjLsa build if there's one scheduled
akmhoque157b0a42014-05-13 00:26:37 -0500317 if (adjBuildCount > 0) {
Nick G97e34942016-07-11 14:46:27 -0500318 // It only makes sense to do the adjLsa build if we have neighbors
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600319 if (m_confParam.getAdjacencyList().getNumOfActiveNeighbor() > 0) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500320 NLSR_LOG_DEBUG("Building and installing own Adj LSA");
akmhoque31d1d4b2014-05-05 22:08:14 -0500321 buildAndInstallOwnAdjLsa();
akmhoque53353462014-04-22 08:43:45 -0500322 }
Nick G97e34942016-07-11 14:46:27 -0500323 // We have no active neighbors, meaning no one can route through
324 // us. So delete our entry in the LSDB. This prevents this
325 // router from refreshing the LSA, eventually causing other
326 // routers to delete it, too.
akmhoque157b0a42014-05-13 00:26:37 -0500327 else {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500328 NLSR_LOG_DEBUG("Removing own Adj LSA; no ACTIVE neighbors");
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700329 removeLsa(m_thisRouterPrefix, Lsa::Type::ADJACENCY);
akmhoque53353462014-04-22 08:43:45 -0500330 }
Nick G97e34942016-07-11 14:46:27 -0500331 // In the case that during building the adj LSA, the FIB has to
332 // wait on an Interest response, the number of scheduled adj LSA
333 // builds could change, so we shouldn't just set it to 0.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600334 m_adjBuildCount = m_adjBuildCount - adjBuildCount;
akmhoque53353462014-04-22 08:43:45 -0500335 }
336 }
Nick G97e34942016-07-11 14:46:27 -0500337 // We are still waiting to know the adjacency status of some
338 // neighbor, so schedule a build for later (when all that has
339 // hopefully finished)
340 else {
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700341 m_isBuildAdjLsaScheduled = true;
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500342 auto schedulingTime = ndn::time::seconds(m_confParam.getInterestRetryNumber() *
343 m_confParam.getInterestResendTime());
344 m_scheduledAdjLsaBuild = m_scheduler.schedule(schedulingTime, [this] { buildAdjLsa(); });
Nick G97e34942016-07-11 14:46:27 -0500345 }
akmhoque53353462014-04-22 08:43:45 -0500346}
347
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700348void
akmhoque31d1d4b2014-05-05 22:08:14 -0500349Lsdb::buildAndInstallOwnAdjLsa()
akmhoque53353462014-04-22 08:43:45 -0500350{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700351 AdjLsa adjLsa(m_thisRouterPrefix, m_sequencingManager.getAdjLsaSeq() + 1,
akmhoquec7a79b22014-05-26 08:06:19 -0500352 getLsaExpirationTimePoint(),
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600353 m_confParam.getAdjacencyList());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700354 m_sequencingManager.increaseAdjLsaSeq();
355 m_sequencingManager.writeSeqNoToFile();
Vince Lehman904c2412014-09-23 19:36:11 -0500356
Nick Gordon5c467f02016-07-13 13:40:10 -0500357 //Sync adjacency LSAs if link-state or dry-run HR is enabled.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600358 if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_ON) {
Nick Gordon727d4832017-10-13 18:04:25 -0500359 m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
Nick Gordon5c467f02016-07-13 13:40:10 -0500360 }
Vince Lehman904c2412014-09-23 19:36:11 -0500361
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700362 installLsa(std::make_shared<AdjLsa>(adjLsa));
akmhoque53353462014-04-22 08:43:45 -0500363}
364
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700365ndn::scheduler::EventId
366Lsdb::scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime)
367{
368 NLSR_LOG_DEBUG("Scheduling expiration in: " << expTime + GRACE_PERIOD << " for " << lsa->getOriginRouter());
369 return m_scheduler.schedule(expTime + GRACE_PERIOD, [this, lsa] { expireOrRefreshLsa(lsa); });
370}
371
akmhoque53353462014-04-22 08:43:45 -0500372void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700373Lsdb::expireOrRefreshLsa(std::shared_ptr<Lsa> lsa)
akmhoque53353462014-04-22 08:43:45 -0500374{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700375 NLSR_LOG_DEBUG("ExpireOrRefreshLsa called for " << lsa->getType());
376 NLSR_LOG_DEBUG("OriginRouter: " << lsa->getOriginRouter() << " Seq No: " << lsa->getSeqNo());
377
378 auto lsaIt = m_lsdb.get<byName>().find(std::make_tuple(lsa->getOriginRouter(), lsa->getType()));
379
Nick G97e34942016-07-11 14:46:27 -0500380 // If this name LSA exists in the LSDB
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700381 if (lsaIt != m_lsdb.end()) {
382 auto lsaPtr = *lsaIt;
383 NLSR_LOG_DEBUG(lsaPtr->toString());
384 NLSR_LOG_DEBUG("LSA Exists with seq no: " << lsaPtr->getSeqNo());
Nick G97e34942016-07-11 14:46:27 -0500385 // If its seq no is the one we are expecting.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700386 if (lsaPtr->getSeqNo() == lsa->getSeqNo()) {
387 if (lsaPtr->getOriginRouter() == m_thisRouterPrefix) {
Davide Pesavento65ee9922022-11-16 00:21:43 -0500388 NLSR_LOG_DEBUG("Own " << lsaPtr->getType() << " LSA, so refreshing it");
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500389 NLSR_LOG_DEBUG("Current LSA:\n" << lsaPtr->toString());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700390 lsaPtr->setSeqNo(lsaPtr->getSeqNo() + 1);
391 m_sequencingManager.setLsaSeq(lsaPtr->getSeqNo(), lsaPtr->getType());
392 lsaPtr->setExpirationTimePoint(getLsaExpirationTimePoint());
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500393 NLSR_LOG_DEBUG("Updated LSA:\n" << lsaPtr->toString());
akmhoquefdbddb12014-05-02 18:35:19 -0500394 // schedule refreshing event again
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700395 lsaPtr->setExpiringEventId(scheduleLsaExpiration(lsaPtr, m_lsaRefreshTime));
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500396 m_sequencingManager.writeSeqNoToFile();
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700397 m_sync.publishRoutingUpdate(lsaPtr->getType(), m_sequencingManager.getLsaSeq(lsaPtr->getType()));
akmhoque53353462014-04-22 08:43:45 -0500398 }
Nick G97e34942016-07-11 14:46:27 -0500399 // Since we cannot refresh other router's LSAs, our only choice is to expire.
akmhoque157b0a42014-05-13 00:26:37 -0500400 else {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700401 NLSR_LOG_DEBUG("Other's " << lsaPtr->getType() << " LSA, so removing from LSDB");
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700402 removeLsa(lsaIt);
akmhoque53353462014-04-22 08:43:45 -0500403 }
404 }
405 }
406}
407
akmhoque53353462014-04-22 08:43:45 -0500408void
Alexander Afanasyev135288c2022-04-23 23:06:56 -0400409Lsdb::expressInterest(const ndn::Name& interestName, uint32_t timeoutCount, uint64_t incomingFaceId,
Davide Pesavento658fd852023-05-10 22:15:03 -0400410 ndn::time::steady_clock::time_point deadline)
akmhoque31d1d4b2014-05-05 22:08:14 -0500411{
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600412 // increment SENT_LSA_INTEREST
413 lsaIncrementSignal(Statistics::PacketType::SENT_LSA_INTEREST);
414
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500415 if (deadline == DEFAULT_LSA_RETRIEVAL_DEADLINE) {
Nick Gordone98480b2017-05-24 11:23:03 -0500416 deadline = ndn::time::steady_clock::now() + ndn::time::seconds(static_cast<int>(LSA_REFRESH_TIME_MAX));
Alexander Afanasyev411ee4b2014-08-16 23:17:03 -0700417 }
Nick G97e34942016-07-11 14:46:27 -0500418 // The first component of the interest is the name.
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500419 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
Nick G97e34942016-07-11 14:46:27 -0500420 // The seq no is the last
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500421 uint64_t seqNo = interestName[-1].toNumber();
422
Nick G97e34942016-07-11 14:46:27 -0500423 // If the LSA is not found in the list currently.
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500424 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
425 m_highestSeqNo[lsaName] = seqNo;
426 }
Nick G97e34942016-07-11 14:46:27 -0500427 // If the new seq no is higher, that means the LSA is valid
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500428 else if (seqNo > m_highestSeqNo[lsaName]) {
429 m_highestSeqNo[lsaName] = seqNo;
430 }
Nick G97e34942016-07-11 14:46:27 -0500431 // Otherwise, its an old/invalid LSA
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500432 else if (seqNo < m_highestSeqNo[lsaName]) {
433 return;
434 }
435
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500436 ndn::Interest interest(interestName);
Alexander Afanasyev135288c2022-04-23 23:06:56 -0400437 if (incomingFaceId != 0) {
438 interest.setTag(std::make_shared<ndn::lp::NextHopFaceIdTag>(incomingFaceId));
439 }
Junxiao Shi43f37a02023-08-09 00:09:00 +0000440 ndn::SegmentFetcher::Options options;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600441 options.interestLifetime = m_confParam.getLsaInterestLifetime();
awlane0c87b122022-06-17 15:53:10 -0500442 options.maxTimeout = m_confParam.getLsaInterestLifetime();
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500443
dmcoomes5bcb39e2017-10-31 15:07:55 -0500444 NLSR_LOG_DEBUG("Fetching Data for LSA: " << interestName << " Seq number: " << seqNo);
Junxiao Shi43f37a02023-08-09 00:09:00 +0000445 auto fetcher = ndn::SegmentFetcher::start(m_face, interest, m_confParam.getValidator(), options);
Ashlesh Gawande05cb7282018-08-30 14:39:41 -0500446
Ashlesh Gawande744e4812018-08-22 16:26:24 -0500447 auto it = m_fetchers.insert(fetcher).first;
448
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600449 fetcher->afterSegmentValidated.connect([this] (const ndn::Data& data) {
Ashlesh Gawande15052402018-12-12 20:20:00 -0600450 // Nlsr class subscribes to this to fetch certificates
451 afterSegmentValidatedSignal(data);
452
453 // If we don't do this IMS throws: std::bad_weak_ptr: bad_weak_ptr
454 auto lsaSegment = std::make_shared<const ndn::Data>(data);
455 m_lsaStorage.insert(*lsaSegment);
Ashlesh Gawande15052402018-12-12 20:20:00 -0600456 // Schedule deletion of the segment
457 m_scheduler.schedule(ndn::time::seconds(LSA_REFRESH_TIME_DEFAULT),
Davide Pesavento65ee9922022-11-16 00:21:43 -0500458 [this, name = lsaSegment->getName()] { m_lsaStorage.erase(name); });
Ashlesh Gawande15052402018-12-12 20:20:00 -0600459 });
460
461 fetcher->onComplete.connect([=] (const ndn::ConstBufferPtr& bufferPtr) {
462 m_lsaStorage.erase(ndn::Name(lsaName).appendNumber(seqNo - 1));
463 afterFetchLsa(bufferPtr, interestName);
464 m_fetchers.erase(it);
465 });
466
467 fetcher->onError.connect([=] (uint32_t errorCode, const std::string& msg) {
468 onFetchLsaError(errorCode, msg, interestName, timeoutCount, deadline, lsaName, seqNo);
469 m_fetchers.erase(it);
470 });
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +0000471
Nick Gordon727d4832017-10-13 18:04:25 -0500472 Lsa::Type lsaType;
473 std::istringstream(interestName[-2].toUri()) >> lsaType;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700474 incrementInterestSentStats(lsaType);
475}
476
477void
478Lsdb::onFetchLsaError(uint32_t errorCode, const std::string& msg, const ndn::Name& interestName,
Davide Pesavento658fd852023-05-10 22:15:03 -0400479 uint32_t retransmitNo, const ndn::time::steady_clock::time_point& deadline,
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700480 ndn::Name lsaName, uint64_t seqNo)
481{
482 NLSR_LOG_DEBUG("Failed to fetch LSA: " << lsaName << ", Error code: " << errorCode
483 << ", Message: " << msg);
484
485 if (ndn::time::steady_clock::now() < deadline) {
486 auto it = m_highestSeqNo.find(lsaName);
487 if (it != m_highestSeqNo.end() && it->second == seqNo) {
488 // If the SegmentFetcher failed due to an Interest timeout, it is safe to re-express
489 // immediately since at the least the LSA Interest lifetime has elapsed.
490 // Otherwise, it is necessary to delay the Interest re-expression to prevent
491 // the potential for constant Interest flooding.
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500492 auto delay = m_confParam.getLsaInterestLifetime();
Junxiao Shi43f37a02023-08-09 00:09:00 +0000493 if (errorCode == ndn::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500494 delay = 0_s;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700495 }
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500496 m_scheduler.schedule(delay, std::bind(&Lsdb::expressInterest, this, interestName,
497 retransmitNo + 1, /*Multicast FaceID*/0, deadline));
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700498 }
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600499 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500500}
501
502void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700503Lsdb::afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName)
akmhoque31d1d4b2014-05-05 22:08:14 -0500504{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700505 NLSR_LOG_DEBUG("Received data for LSA interest: " << interestName);
506 lsaIncrementSignal(Statistics::PacketType::RCV_LSA_DATA);
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600507
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700508 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
509 uint64_t seqNo = interestName[-1].toNumber();
510
511 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
512 m_highestSeqNo[lsaName] = seqNo;
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600513 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700514 else if (seqNo > m_highestSeqNo[lsaName]) {
515 m_highestSeqNo[lsaName] = seqNo;
Davide Pesavento65ee9922022-11-16 00:21:43 -0500516 NLSR_LOG_TRACE("SeqNo for LSA(name): " << interestName << " updated");
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700517 }
518 else if (seqNo < m_highestSeqNo[lsaName]) {
519 return;
520 }
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600521
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500522 std::string chkString("LSA");
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600523 int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500524
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700525 if (lsaPosition >= 0) {
526 // Extracts the prefix of the originating router from the data.
527 ndn::Name originRouter = m_confParam.getNetwork();
528 originRouter.append(interestName.getSubName(lsaPosition + 1,
529 interestName.size() - lsaPosition - 3));
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700530 try {
531 Lsa::Type interestedLsType;
532 std::istringstream(interestName[-2].toUri()) >> interestedLsType;
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500533
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700534 if (interestedLsType == Lsa::Type::BASE) {
535 NLSR_LOG_WARN("Received unrecognized LSA Type: " << interestName[-2].toUri());
536 return;
537 }
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500538
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700539 ndn::Block block(bufferPtr);
540 if (interestedLsType == Lsa::Type::NAME) {
541 lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_DATA);
542 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
543 installLsa(std::make_shared<NameLsa>(block));
544 }
545 }
546 else if (interestedLsType == Lsa::Type::ADJACENCY) {
547 lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_DATA);
548 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
549 installLsa(std::make_shared<AdjLsa>(block));
550 }
551 }
552 else if (interestedLsType == Lsa::Type::COORDINATE) {
553 lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_DATA);
554 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
555 installLsa(std::make_shared<CoordinateLsa>(block));
556 }
557 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500558 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700559 catch (const std::exception& e) {
Davide Pesaventofd1e9402023-11-13 15:40:41 -0500560 NLSR_LOG_TRACE("LSA data decoding error: " << e.what());
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600561 }
Nick Gordon8f23b5d2017-08-31 17:53:07 -0500562 }
563}
564
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700565} // namespace nlsr