blob: a2f552d14ed604be6a133c2172ff0404396a2f72 [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/*
Davide Pesaventod90338d2021-01-07 17:50:05 -05003 * Copyright (c) 2014-2021, 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
akmhoque53353462014-04-22 08:43:45 -050028namespace nlsr {
29
dmcoomescf8d0ed2017-02-21 11:39:01 -060030INIT_LOGGER(Lsdb);
akmhoque674b0b12014-05-20 14:33:28 -050031
Nick Gordone98480b2017-05-24 11:23:03 -050032const ndn::time::steady_clock::TimePoint Lsdb::DEFAULT_LSA_RETRIEVAL_DEADLINE =
33 ndn::time::steady_clock::TimePoint::min();
Vince Lehman18841082014-08-19 17:15:24 -050034
Saurab Dulal427e0122019-11-28 11:58:02 -060035Lsdb::Lsdb(ndn::Face& face, ndn::KeyChain& keyChain, ConfParameter& confParam,
Ashlesh Gawande85998a12017-12-07 22:22:13 -060036 NamePrefixTable& namePrefixTable, RoutingTable& routingTable)
37 : m_face(face)
38 , m_scheduler(face.getIoService())
Ashlesh Gawande85998a12017-12-07 22:22:13 -060039 , m_confParam(confParam)
40 , m_namePrefixTable(namePrefixTable)
41 , m_routingTable(routingTable)
42 , m_sync(m_face,
Nick Gordon727d4832017-10-13 18:04:25 -050043 [this] (const ndn::Name& routerName, const Lsa::Type& lsaType,
Nick Gordon9eac4d92017-08-29 17:31:29 -050044 const uint64_t& sequenceNumber) {
Nick Gordon8f23b5d2017-08-31 17:53:07 -050045 return isLsaNew(routerName, lsaType, sequenceNumber);
Ashlesh Gawande85998a12017-12-07 22:22:13 -060046 }, m_confParam)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060047 , m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
Ashlesh Gawande85998a12017-12-07 22:22:13 -060048 , m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
Ashlesh Gawande57a87172020-05-09 19:47:06 -070049 , m_thisRouterPrefix(m_confParam.getRouterPrefix())
dulalsaurab82a34c22019-02-04 17:31:21 +000050 , m_sequencingManager(m_confParam.getStateFileDir(), m_confParam.getHyperbolicState())
Nick Gordon9eac4d92017-08-29 17:31:29 -050051 , m_onNewLsaConnection(m_sync.onNewLsa->connect(
Ashlesh Gawande08bce9c2019-04-05 11:08:07 -050052 [this] (const ndn::Name& updateName, uint64_t sequenceNumber,
53 const ndn::Name& originRouter) {
Nick Gordon9eac4d92017-08-29 17:31:29 -050054 ndn::Name lsaInterest{updateName};
55 lsaInterest.appendNumber(sequenceNumber);
56 expressInterest(lsaInterest, 0);
57 }))
Ashlesh Gawande85998a12017-12-07 22:22:13 -060058 , m_segmentPublisher(m_face, keyChain)
59 , m_isBuildAdjLsaSheduled(false)
60 , m_adjBuildCount(0)
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050061{
62}
63
64void
akmhoque31d1d4b2014-05-05 22:08:14 -050065Lsdb::buildAndInstallOwnNameLsa()
akmhoque53353462014-04-22 08:43:45 -050066{
Ashlesh Gawande57a87172020-05-09 19:47:06 -070067 NameLsa nameLsa(m_thisRouterPrefix, m_sequencingManager.getNameLsaSeq() + 1,
68 getLsaExpirationTimePoint(), m_confParam.getNamePrefixList());
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050069 m_sequencingManager.increaseNameLsaSeq();
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050070 m_sequencingManager.writeSeqNoToFile();
Nick Gordon727d4832017-10-13 18:04:25 -050071 m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050072
Ashlesh Gawande57a87172020-05-09 19:47:06 -070073 installLsa(std::make_shared<NameLsa>(nameLsa));
akmhoque53353462014-04-22 08:43:45 -050074}
75
76void
akmhoque31d1d4b2014-05-05 22:08:14 -050077Lsdb::buildAndInstallOwnCoordinateLsa()
akmhoque53353462014-04-22 08:43:45 -050078{
Ashlesh Gawande57a87172020-05-09 19:47:06 -070079 CoordinateLsa corLsa(m_thisRouterPrefix, m_sequencingManager.getCorLsaSeq() + 1,
80 getLsaExpirationTimePoint(), m_confParam.getCorR(),
Ashlesh Gawande85998a12017-12-07 22:22:13 -060081 m_confParam.getCorTheta());
Ashlesh Gawande57a87172020-05-09 19:47:06 -070082 m_sequencingManager.increaseCorLsaSeq();
83 m_sequencingManager.writeSeqNoToFile();
Nick Gordon5c467f02016-07-13 13:40:10 -050084
85 // Sync coordinate LSAs if using HR or HR dry run.
Ashlesh Gawande85998a12017-12-07 22:22:13 -060086 if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
Nick Gordon727d4832017-10-13 18:04:25 -050087 m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
Nick Gordon5c467f02016-07-13 13:40:10 -050088 }
89
Ashlesh Gawande57a87172020-05-09 19:47:06 -070090 installLsa(std::make_shared<CoordinateLsa>(corLsa));
akmhoque53353462014-04-22 08:43:45 -050091}
92
akmhoque53353462014-04-22 08:43:45 -050093void
Vince Lehman50df6b72015-03-03 12:06:40 -060094Lsdb::scheduleAdjLsaBuild()
akmhoque53353462014-04-22 08:43:45 -050095{
Ashlesh Gawande85998a12017-12-07 22:22:13 -060096 m_adjBuildCount++;
Vince Lehman50df6b72015-03-03 12:06:40 -060097
Ashlesh Gawande85998a12017-12-07 22:22:13 -060098 if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
Nick Gordon5c467f02016-07-13 13:40:10 -050099 // Don't build adjacency LSAs in hyperbolic routing
dmcoomes5bcb39e2017-10-31 15:07:55 -0500100 NLSR_LOG_DEBUG("Adjacency LSA not built. Currently in hyperbolic routing state.");
Nick Gordon5c467f02016-07-13 13:40:10 -0500101 return;
102 }
103
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500104 if (m_isBuildAdjLsaSheduled) {
105 NLSR_LOG_DEBUG("Rescheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
106 }
107 else {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500108 NLSR_LOG_DEBUG("Scheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600109 m_isBuildAdjLsaSheduled = true;
Vince Lehman50df6b72015-03-03 12:06:40 -0600110 }
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500111 m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [this] { buildAdjLsa(); });
Vince Lehman50df6b72015-03-03 12:06:40 -0600112}
113
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700114template<typename T>
115void
116Lsdb::writeLog() const
117{
118 if ((T::type() == Lsa::Type::COORDINATE &&
119 m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) ||
120 (T::type() == Lsa::Type::ADJACENCY &&
121 m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON)) {
122 return;
123 }
124
125 NLSR_LOG_DEBUG("---------------" << T::type() << " LSDB-------------------");
126 auto lsaRange = m_lsdb.get<byType>().equal_range(T::type());
127 for (auto lsaIt = lsaRange.first; lsaIt != lsaRange.second; ++lsaIt) {
128 auto lsaPtr = std::static_pointer_cast<T>(*lsaIt);
129 NLSR_LOG_DEBUG(lsaPtr->toString());
130 }
131}
132
133void
134Lsdb::writeLog() const
135{
136 writeLog<CoordinateLsa>();
137 writeLog<NameLsa>();
138 writeLog<AdjLsa>();
139}
140
141void
142Lsdb::processInterest(const ndn::Name& name, const ndn::Interest& interest)
143{
144 ndn::Name interestName(interest.getName());
145 NLSR_LOG_DEBUG("Interest received for LSA: " << interestName);
146
147 if (interestName[-2].isVersion()) {
148 // Interest for particular segment
149 if (m_segmentPublisher.replyFromStore(interestName)) {
150 NLSR_LOG_TRACE("Reply from SegmentPublisher storage");
151 return;
152 }
153 // Remove version and segment
154 interestName = interestName.getSubName(0, interestName.size() - 2);
155 NLSR_LOG_TRACE("Interest w/o segment and version: " << interestName);
156 }
157
158 // increment RCV_LSA_INTEREST
159 lsaIncrementSignal(Statistics::PacketType::RCV_LSA_INTEREST);
160
161 std::string chkString("LSA");
162 int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
163
164 // Forms the name of the router that the Interest packet came from.
165 ndn::Name originRouter = m_confParam.getNetwork();
166 originRouter.append(interestName.getSubName(lsaPosition + 1,
167 interestName.size() - lsaPosition - 3));
168
169 // if the interest is for this router's LSA
170 if (originRouter == m_thisRouterPrefix && lsaPosition >= 0) {
171 uint64_t seqNo = interestName[-1].toNumber();
172 NLSR_LOG_DEBUG("LSA sequence number from interest: " << seqNo);
173
174 std::string lsaType = interestName[-2].toUri();
175 Lsa::Type interestedLsType;
176 std::istringstream(lsaType) >> interestedLsType;
177 if (interestedLsType == Lsa::Type::BASE) {
178 NLSR_LOG_WARN("Received unrecognized LSA type: " << lsaType);
179 return;
180 }
181
182 incrementInterestRcvdStats(interestedLsType);
183 if (processInterestForLsa(interest, originRouter, interestedLsType, seqNo)) {
184 lsaIncrementSignal(Statistics::PacketType::SENT_LSA_DATA);
185 }
186 }
187 // else the interest is for other router's LSA, serve signed data from LsaSegmentStorage
188 else if (auto lsaSegment = m_lsaStorage.find(interest)) {
189 NLSR_LOG_TRACE("Found data in lsa storage. Sending the data for " << interest.getName());
190 m_face.put(*lsaSegment);
191 }
192}
193
194bool
195Lsdb::processInterestForLsa(const ndn::Interest& interest, const ndn::Name& originRouter,
196 Lsa::Type lsaType, uint64_t seqNo)
197{
198 NLSR_LOG_DEBUG(interest << " received for " << lsaType);
199 if (auto lsaPtr = findLsa(originRouter, lsaType)) {
200 NLSR_LOG_TRACE("Verifying SeqNo for " << lsaType << " is same as requested.");
201 if (lsaPtr->getSeqNo() == seqNo) {
202 m_segmentPublisher.publish(interest.getName(), interest.getName(),
203 lsaPtr->wireEncode(),
204 m_lsaRefreshTime, m_confParam.getSigningInfo());
205 incrementDataSentStats(lsaType);
206 return true;
207 }
208 }
209 else {
210 NLSR_LOG_TRACE(interest << " was not found in our LSDB");
211 }
212 return false;
213}
214
215void
Davide Pesaventod90338d2021-01-07 17:50:05 -0500216Lsdb::installLsa(std::shared_ptr<Lsa> lsa)
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700217{
218 auto timeToExpire = m_lsaRefreshTime;
219
220 auto chkLsa = findLsa(lsa->getOriginRouter(), lsa->getType());
221 if (chkLsa == nullptr) {
222 NLSR_LOG_DEBUG("Adding " << lsa->getType() << " LSA");
223 NLSR_LOG_DEBUG(lsa->toString());
224 ndn::time::seconds timeToExpire = m_lsaRefreshTime;
225
226 m_lsdb.emplace(lsa);
227
228 // Add any new name prefixes to the NPT if from another router
229 if (lsa->getOriginRouter() != m_thisRouterPrefix) {
230 // Pass the origin router as both the name to register and where it came from.
231 m_namePrefixTable.addEntry(lsa->getOriginRouter(), lsa->getOriginRouter());
232
233 if (lsa->getType() == Lsa::Type::NAME) {
234 auto nlsa = std::static_pointer_cast<NameLsa>(lsa);
235 for (const auto& name : nlsa->getNpl().getNames()) {
236 if (name != m_thisRouterPrefix) {
237 m_namePrefixTable.addEntry(name, nlsa->getOriginRouter());
238 }
239 }
240 }
241
242 auto duration = lsa->getExpirationTimePoint() - ndn::time::system_clock::now();
243 if (duration > ndn::time::seconds(0)) {
244 timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
245 }
246 }
247
248 if ((lsa->getType() == Lsa::Type::ADJACENCY && m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_ON)||
249 (lsa->getType() == Lsa::Type::COORDINATE && m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF)) {
250 m_routingTable.scheduleRoutingTableCalculation();
251 }
252
253 lsa->setExpiringEventId(scheduleLsaExpiration(lsa, timeToExpire));
254 }
255 // Else this is a known name LSA, so we are updating it.
256 else if (chkLsa->getSeqNo() < lsa->getSeqNo()) {
257 NLSR_LOG_DEBUG("Updating " << lsa->getType() << " LSA:");
258 NLSR_LOG_DEBUG(chkLsa->toString());
259 chkLsa->setSeqNo(lsa->getSeqNo());
260 chkLsa->setExpirationTimePoint(lsa->getExpirationTimePoint());
261
262 if (lsa->getType() == Lsa::Type::NAME) {
263 auto chkNameLsa = std::static_pointer_cast<NameLsa>(chkLsa);
264 auto nlsa = std::static_pointer_cast<NameLsa>(lsa);
265 chkNameLsa->getNpl().sort();
266 nlsa->getNpl().sort();
267 if (!chkNameLsa->isEqualContent(*nlsa)) {
268 // Obtain the set difference of the current and the incoming
269 // name prefix sets, and add those.
270 std::list<ndn::Name> newNames = nlsa->getNpl().getNames();
271 std::list<ndn::Name> oldNames = chkNameLsa->getNpl().getNames();
272 std::list<ndn::Name> namesToAdd;
273 std::set_difference(newNames.begin(), newNames.end(), oldNames.begin(), oldNames.end(),
274 std::inserter(namesToAdd, namesToAdd.begin()));
275 for (const auto& name : namesToAdd) {
276 chkNameLsa->addName(name);
277 if (nlsa->getOriginRouter() != m_thisRouterPrefix && name != m_thisRouterPrefix) {
278 m_namePrefixTable.addEntry(name, nlsa->getOriginRouter());
279 }
280 }
281
282 chkNameLsa->getNpl().sort();
283
284 // Also remove any names that are no longer being advertised.
285 std::list<ndn::Name> namesToRemove;
286 std::set_difference(oldNames.begin(), oldNames.end(), newNames.begin(), newNames.end(),
287 std::inserter(namesToRemove, namesToRemove.begin()));
288 for (const auto& name : namesToRemove) {
289 NLSR_LOG_DEBUG("Removing name" << name << " from Name LSA no longer advertised.");
290 chkNameLsa->removeName(name);
291 if (nlsa->getOriginRouter() != m_thisRouterPrefix && name != m_thisRouterPrefix) {
292 m_namePrefixTable.removeEntry(name, nlsa->getOriginRouter());
293 }
294 }
295 }
296 }
297 else if (lsa->getType() == Lsa::Type::ADJACENCY) {
298 auto chkAdjLsa = std::static_pointer_cast<AdjLsa>(chkLsa);
299 auto alsa = std::static_pointer_cast<AdjLsa>(lsa);
300 if (!chkAdjLsa->isEqualContent(*alsa)) {
301 chkAdjLsa->resetAdl();
302 for (const auto& adjacent : alsa->getAdl()) {
303 chkAdjLsa->addAdjacent(adjacent);
304 }
305 m_routingTable.scheduleRoutingTableCalculation();
306 }
307 }
308 else {
309 auto chkCorLsa = std::static_pointer_cast<CoordinateLsa>(chkLsa);
310 auto clsa = std::static_pointer_cast<CoordinateLsa>(lsa);
311 if (!chkCorLsa->isEqualContent(*clsa)) {
312 chkCorLsa->setCorRadius(clsa->getCorRadius());
313 chkCorLsa->setCorTheta(clsa->getCorTheta());
314 if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
315 m_routingTable.scheduleRoutingTableCalculation();
316 }
317 }
318 }
319
320 if (chkLsa->getOriginRouter() != m_thisRouterPrefix) {
321 auto duration = lsa->getExpirationTimePoint() - ndn::time::system_clock::now();
322 if (duration > ndn::time::seconds(0)) {
323 timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
324 }
325 }
326 chkLsa->getExpiringEventId().cancel();
327 chkLsa->setExpiringEventId(scheduleLsaExpiration(chkLsa, timeToExpire));
328 NLSR_LOG_DEBUG("Updated " << lsa->getType() << " LSA:");
329 NLSR_LOG_DEBUG(chkLsa->toString());
330 }
331}
332
333bool
334Lsdb::removeLsa(const ndn::Name& router, Lsa::Type lsaType)
335{
336 auto lsaIt = m_lsdb.get<byName>().find(std::make_tuple(router, lsaType));
337
338 if (lsaIt != m_lsdb.end()) {
339 auto lsaPtr = *lsaIt;
340 NLSR_LOG_DEBUG("Removing " << lsaType << " LSA:");
341 NLSR_LOG_DEBUG(lsaPtr->toString());
342 // If the requested name LSA is not ours, we also need to remove
343 // its entries from the NPT.
344 if (lsaPtr->getOriginRouter() != m_thisRouterPrefix) {
345 m_namePrefixTable.removeEntry(lsaPtr->getOriginRouter(), lsaPtr->getOriginRouter());
346
347 if (lsaType == Lsa::Type::NAME) {
348 auto nlsaPtr = std::static_pointer_cast<NameLsa>(lsaPtr);
349 for (const auto& name : nlsaPtr->getNpl().getNames()) {
350 if (name != m_thisRouterPrefix) {
351 m_namePrefixTable.removeEntry(name, nlsaPtr->getOriginRouter());
352 }
353 }
354 }
355 }
356 m_lsdb.erase(lsaIt);
357 return true;
358 }
359 return false;
360}
361
Vince Lehman50df6b72015-03-03 12:06:40 -0600362void
363Lsdb::buildAdjLsa()
364{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700365 NLSR_LOG_TRACE("buildAdjLsa called");
Vince Lehman50df6b72015-03-03 12:06:40 -0600366
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600367 m_isBuildAdjLsaSheduled = false;
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500368
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600369 if (m_confParam.getAdjacencyList().isAdjLsaBuildable(m_confParam.getInterestRetryNumber())) {
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500370
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600371 int adjBuildCount = m_adjBuildCount;
Nick G97e34942016-07-11 14:46:27 -0500372 // Only do the adjLsa build if there's one scheduled
akmhoque157b0a42014-05-13 00:26:37 -0500373 if (adjBuildCount > 0) {
Nick G97e34942016-07-11 14:46:27 -0500374 // It only makes sense to do the adjLsa build if we have neighbors
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600375 if (m_confParam.getAdjacencyList().getNumOfActiveNeighbor() > 0) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500376 NLSR_LOG_DEBUG("Building and installing own Adj LSA");
akmhoque31d1d4b2014-05-05 22:08:14 -0500377 buildAndInstallOwnAdjLsa();
akmhoque53353462014-04-22 08:43:45 -0500378 }
Nick G97e34942016-07-11 14:46:27 -0500379 // We have no active neighbors, meaning no one can route through
380 // us. So delete our entry in the LSDB. This prevents this
381 // router from refreshing the LSA, eventually causing other
382 // routers to delete it, too.
akmhoque157b0a42014-05-13 00:26:37 -0500383 else {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500384 NLSR_LOG_DEBUG("Removing own Adj LSA; no ACTIVE neighbors");
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500385
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700386 removeLsa(m_thisRouterPrefix, Lsa::Type::ADJACENCY);
Nick G97e34942016-07-11 14:46:27 -0500387 // Recompute routing table after removal
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600388 m_routingTable.scheduleRoutingTableCalculation();
akmhoque53353462014-04-22 08:43:45 -0500389 }
Nick G97e34942016-07-11 14:46:27 -0500390 // In the case that during building the adj LSA, the FIB has to
391 // wait on an Interest response, the number of scheduled adj LSA
392 // builds could change, so we shouldn't just set it to 0.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600393 m_adjBuildCount = m_adjBuildCount - adjBuildCount;
akmhoque53353462014-04-22 08:43:45 -0500394 }
395 }
Nick G97e34942016-07-11 14:46:27 -0500396 // We are still waiting to know the adjacency status of some
397 // neighbor, so schedule a build for later (when all that has
398 // hopefully finished)
399 else {
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600400 m_isBuildAdjLsaSheduled = true;
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500401 auto schedulingTime = ndn::time::seconds(m_confParam.getInterestRetryNumber() *
402 m_confParam.getInterestResendTime());
403 m_scheduledAdjLsaBuild = m_scheduler.schedule(schedulingTime, [this] { buildAdjLsa(); });
Nick G97e34942016-07-11 14:46:27 -0500404 }
akmhoque53353462014-04-22 08:43:45 -0500405}
406
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700407void
akmhoque31d1d4b2014-05-05 22:08:14 -0500408Lsdb::buildAndInstallOwnAdjLsa()
akmhoque53353462014-04-22 08:43:45 -0500409{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700410 AdjLsa adjLsa(m_thisRouterPrefix, m_sequencingManager.getAdjLsaSeq() + 1,
akmhoquec7a79b22014-05-26 08:06:19 -0500411 getLsaExpirationTimePoint(),
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600412 m_confParam.getAdjacencyList().getNumOfActiveNeighbor(),
413 m_confParam.getAdjacencyList());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700414 m_sequencingManager.increaseAdjLsaSeq();
415 m_sequencingManager.writeSeqNoToFile();
Vince Lehman904c2412014-09-23 19:36:11 -0500416
Nick Gordon5c467f02016-07-13 13:40:10 -0500417 //Sync adjacency LSAs if link-state or dry-run HR is enabled.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600418 if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_ON) {
Nick Gordon727d4832017-10-13 18:04:25 -0500419 m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
Nick Gordon5c467f02016-07-13 13:40:10 -0500420 }
Vince Lehman904c2412014-09-23 19:36:11 -0500421
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700422 installLsa(std::make_shared<AdjLsa>(adjLsa));
akmhoque53353462014-04-22 08:43:45 -0500423}
424
akmhoque53353462014-04-22 08:43:45 -0500425void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700426Lsdb::expireOrRefreshLsa(std::shared_ptr<Lsa> lsa)
akmhoque53353462014-04-22 08:43:45 -0500427{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700428 NLSR_LOG_DEBUG("ExpireOrRefreshLsa called for " << lsa->getType());
429 NLSR_LOG_DEBUG("OriginRouter: " << lsa->getOriginRouter() << " Seq No: " << lsa->getSeqNo());
430
431 auto lsaIt = m_lsdb.get<byName>().find(std::make_tuple(lsa->getOriginRouter(), lsa->getType()));
432
Nick G97e34942016-07-11 14:46:27 -0500433 // If this name LSA exists in the LSDB
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700434 if (lsaIt != m_lsdb.end()) {
435 auto lsaPtr = *lsaIt;
436 NLSR_LOG_DEBUG(lsaPtr->toString());
437 NLSR_LOG_DEBUG("LSA Exists with seq no: " << lsaPtr->getSeqNo());
Nick G97e34942016-07-11 14:46:27 -0500438 // If its seq no is the one we are expecting.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700439 if (lsaPtr->getSeqNo() == lsa->getSeqNo()) {
440 if (lsaPtr->getOriginRouter() == m_thisRouterPrefix) {
441 NLSR_LOG_DEBUG("Own " << lsaPtr->getType() << " LSA, so refreshing it.");
442 NLSR_LOG_DEBUG("Current LSA:");
443 NLSR_LOG_DEBUG(lsaPtr->toString());
444 lsaPtr->setSeqNo(lsaPtr->getSeqNo() + 1);
445 m_sequencingManager.setLsaSeq(lsaPtr->getSeqNo(), lsaPtr->getType());
446 lsaPtr->setExpirationTimePoint(getLsaExpirationTimePoint());
447 NLSR_LOG_DEBUG("Updated LSA:");
448 NLSR_LOG_DEBUG(lsaPtr->toString());
akmhoquefdbddb12014-05-02 18:35:19 -0500449 // schedule refreshing event again
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700450 lsaPtr->setExpiringEventId(scheduleLsaExpiration(lsaPtr, m_lsaRefreshTime));
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500451 m_sequencingManager.writeSeqNoToFile();
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700452 m_sync.publishRoutingUpdate(lsaPtr->getType(), m_sequencingManager.getLsaSeq(lsaPtr->getType()));
akmhoque53353462014-04-22 08:43:45 -0500453 }
Nick G97e34942016-07-11 14:46:27 -0500454 // Since we cannot refresh other router's LSAs, our only choice is to expire.
akmhoque157b0a42014-05-13 00:26:37 -0500455 else {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700456 NLSR_LOG_DEBUG("Other's " << lsaPtr->getType() << " LSA, so removing from LSDB");
457 removeLsa(lsaPtr->getOriginRouter(), lsaPtr->getType());
akmhoque53353462014-04-22 08:43:45 -0500458 }
459 }
460 }
461}
462
akmhoque53353462014-04-22 08:43:45 -0500463void
Alexander Afanasyev411ee4b2014-08-16 23:17:03 -0700464Lsdb::expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
Nick Gordone98480b2017-05-24 11:23:03 -0500465 ndn::time::steady_clock::TimePoint deadline)
akmhoque31d1d4b2014-05-05 22:08:14 -0500466{
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600467 // increment SENT_LSA_INTEREST
468 lsaIncrementSignal(Statistics::PacketType::SENT_LSA_INTEREST);
469
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500470 if (deadline == DEFAULT_LSA_RETRIEVAL_DEADLINE) {
Nick Gordone98480b2017-05-24 11:23:03 -0500471 deadline = ndn::time::steady_clock::now() + ndn::time::seconds(static_cast<int>(LSA_REFRESH_TIME_MAX));
Alexander Afanasyev411ee4b2014-08-16 23:17:03 -0700472 }
Nick G97e34942016-07-11 14:46:27 -0500473 // The first component of the interest is the name.
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500474 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
Nick G97e34942016-07-11 14:46:27 -0500475 // The seq no is the last
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500476 uint64_t seqNo = interestName[-1].toNumber();
477
Nick G97e34942016-07-11 14:46:27 -0500478 // If the LSA is not found in the list currently.
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500479 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
480 m_highestSeqNo[lsaName] = seqNo;
481 }
Nick G97e34942016-07-11 14:46:27 -0500482 // If the new seq no is higher, that means the LSA is valid
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500483 else if (seqNo > m_highestSeqNo[lsaName]) {
484 m_highestSeqNo[lsaName] = seqNo;
485 }
Nick G97e34942016-07-11 14:46:27 -0500486 // Otherwise, its an old/invalid LSA
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500487 else if (seqNo < m_highestSeqNo[lsaName]) {
488 return;
489 }
490
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500491 ndn::Interest interest(interestName);
Ashlesh Gawande744e4812018-08-22 16:26:24 -0500492 ndn::util::SegmentFetcher::Options options;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600493 options.interestLifetime = m_confParam.getLsaInterestLifetime();
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500494
dmcoomes5bcb39e2017-10-31 15:07:55 -0500495 NLSR_LOG_DEBUG("Fetching Data for LSA: " << interestName << " Seq number: " << seqNo);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600496 auto fetcher = ndn::util::SegmentFetcher::start(m_face, interest,
497 m_confParam.getValidator(), options);
Ashlesh Gawande05cb7282018-08-30 14:39:41 -0500498
Ashlesh Gawande744e4812018-08-22 16:26:24 -0500499 auto it = m_fetchers.insert(fetcher).first;
500
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600501 fetcher->afterSegmentValidated.connect([this] (const ndn::Data& data) {
Ashlesh Gawande15052402018-12-12 20:20:00 -0600502 // Nlsr class subscribes to this to fetch certificates
503 afterSegmentValidatedSignal(data);
504
505 // If we don't do this IMS throws: std::bad_weak_ptr: bad_weak_ptr
506 auto lsaSegment = std::make_shared<const ndn::Data>(data);
507 m_lsaStorage.insert(*lsaSegment);
508 const ndn::Name& segmentName = lsaSegment->getName();
509 // Schedule deletion of the segment
510 m_scheduler.schedule(ndn::time::seconds(LSA_REFRESH_TIME_DEFAULT),
511 [this, segmentName] { m_lsaStorage.erase(segmentName); });
512 });
513
514 fetcher->onComplete.connect([=] (const ndn::ConstBufferPtr& bufferPtr) {
515 m_lsaStorage.erase(ndn::Name(lsaName).appendNumber(seqNo - 1));
516 afterFetchLsa(bufferPtr, interestName);
517 m_fetchers.erase(it);
518 });
519
520 fetcher->onError.connect([=] (uint32_t errorCode, const std::string& msg) {
521 onFetchLsaError(errorCode, msg, interestName, timeoutCount, deadline, lsaName, seqNo);
522 m_fetchers.erase(it);
523 });
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +0000524
Nick Gordon727d4832017-10-13 18:04:25 -0500525 Lsa::Type lsaType;
526 std::istringstream(interestName[-2].toUri()) >> lsaType;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700527 incrementInterestSentStats(lsaType);
528}
529
530void
531Lsdb::onFetchLsaError(uint32_t errorCode, const std::string& msg, const ndn::Name& interestName,
532 uint32_t retransmitNo, const ndn::time::steady_clock::TimePoint& deadline,
533 ndn::Name lsaName, uint64_t seqNo)
534{
535 NLSR_LOG_DEBUG("Failed to fetch LSA: " << lsaName << ", Error code: " << errorCode
536 << ", Message: " << msg);
537
538 if (ndn::time::steady_clock::now() < deadline) {
539 auto it = m_highestSeqNo.find(lsaName);
540 if (it != m_highestSeqNo.end() && it->second == seqNo) {
541 // If the SegmentFetcher failed due to an Interest timeout, it is safe to re-express
542 // immediately since at the least the LSA Interest lifetime has elapsed.
543 // Otherwise, it is necessary to delay the Interest re-expression to prevent
544 // the potential for constant Interest flooding.
545 ndn::time::seconds delay = m_confParam.getLsaInterestLifetime();
546
547 if (errorCode == ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
548 delay = ndn::time::seconds(0);
549 }
550 m_scheduler.schedule(delay, std::bind(&Lsdb::expressInterest, this,
551 interestName, retransmitNo + 1, deadline));
552 }
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600553 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500554}
555
556void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700557Lsdb::afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName)
akmhoque31d1d4b2014-05-05 22:08:14 -0500558{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700559 NLSR_LOG_DEBUG("Received data for LSA interest: " << interestName);
560 lsaIncrementSignal(Statistics::PacketType::RCV_LSA_DATA);
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600561
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700562 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
563 uint64_t seqNo = interestName[-1].toNumber();
564
565 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
566 m_highestSeqNo[lsaName] = seqNo;
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600567 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700568 else if (seqNo > m_highestSeqNo[lsaName]) {
569 m_highestSeqNo[lsaName] = seqNo;
570 NLSR_LOG_TRACE("SeqNo for LSA(name): " << interestName << " updated");
571 }
572 else if (seqNo < m_highestSeqNo[lsaName]) {
573 return;
574 }
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600575
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500576 std::string chkString("LSA");
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600577 int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500578
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700579 if (lsaPosition >= 0) {
580 // Extracts the prefix of the originating router from the data.
581 ndn::Name originRouter = m_confParam.getNetwork();
582 originRouter.append(interestName.getSubName(lsaPosition + 1,
583 interestName.size() - lsaPosition - 3));
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500584
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700585 try {
586 Lsa::Type interestedLsType;
587 std::istringstream(interestName[-2].toUri()) >> interestedLsType;
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500588
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700589 if (interestedLsType == Lsa::Type::BASE) {
590 NLSR_LOG_WARN("Received unrecognized LSA Type: " << interestName[-2].toUri());
591 return;
592 }
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500593
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700594 ndn::Block block(bufferPtr);
595 if (interestedLsType == Lsa::Type::NAME) {
596 lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_DATA);
597 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
598 installLsa(std::make_shared<NameLsa>(block));
599 }
600 }
601 else if (interestedLsType == Lsa::Type::ADJACENCY) {
602 lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_DATA);
603 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
604 installLsa(std::make_shared<AdjLsa>(block));
605 }
606 }
607 else if (interestedLsType == Lsa::Type::COORDINATE) {
608 lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_DATA);
609 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
610 installLsa(std::make_shared<CoordinateLsa>(block));
611 }
612 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500613 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700614 catch (const std::exception& e) {
615 NLSR_LOG_TRACE("LSA data decoding error :( " << e.what());
616 return;
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600617 }
Nick Gordon8f23b5d2017-08-31 17:53:07 -0500618 }
619}
620
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700621} // namespace nlsr