blob: 5e416b354ddf0abbe0305f57a2911f87c377d4bb [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
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070035Lsdb::Lsdb(ndn::Face& face, ndn::KeyChain& keyChain, ConfParameter& confParam)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060036 : m_face(face)
37 , m_scheduler(face.getIoService())
Ashlesh Gawande85998a12017-12-07 22:22:13 -060038 , m_confParam(confParam)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060039 , m_sync(m_face,
Nick Gordon727d4832017-10-13 18:04:25 -050040 [this] (const ndn::Name& routerName, const Lsa::Type& lsaType,
Nick Gordon9eac4d92017-08-29 17:31:29 -050041 const uint64_t& sequenceNumber) {
Nick Gordon8f23b5d2017-08-31 17:53:07 -050042 return isLsaNew(routerName, lsaType, sequenceNumber);
Ashlesh Gawande85998a12017-12-07 22:22:13 -060043 }, m_confParam)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060044 , m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
Ashlesh Gawande85998a12017-12-07 22:22:13 -060045 , m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
Ashlesh Gawande57a87172020-05-09 19:47:06 -070046 , m_thisRouterPrefix(m_confParam.getRouterPrefix())
dulalsaurab82a34c22019-02-04 17:31:21 +000047 , m_sequencingManager(m_confParam.getStateFileDir(), m_confParam.getHyperbolicState())
Nick Gordon9eac4d92017-08-29 17:31:29 -050048 , m_onNewLsaConnection(m_sync.onNewLsa->connect(
Ashlesh Gawande08bce9c2019-04-05 11:08:07 -050049 [this] (const ndn::Name& updateName, uint64_t sequenceNumber,
50 const ndn::Name& originRouter) {
Nick Gordon9eac4d92017-08-29 17:31:29 -050051 ndn::Name lsaInterest{updateName};
52 lsaInterest.appendNumber(sequenceNumber);
53 expressInterest(lsaInterest, 0);
54 }))
Ashlesh Gawande85998a12017-12-07 22:22:13 -060055 , m_segmentPublisher(m_face, keyChain)
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070056 , m_isBuildAdjLsaScheduled(false)
Ashlesh Gawande85998a12017-12-07 22:22:13 -060057 , m_adjBuildCount(0)
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050058{
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070059 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 }
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050076}
77
78void
akmhoque31d1d4b2014-05-05 22:08:14 -050079Lsdb::buildAndInstallOwnNameLsa()
akmhoque53353462014-04-22 08:43:45 -050080{
Ashlesh Gawande57a87172020-05-09 19:47:06 -070081 NameLsa nameLsa(m_thisRouterPrefix, m_sequencingManager.getNameLsaSeq() + 1,
82 getLsaExpirationTimePoint(), m_confParam.getNamePrefixList());
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050083 m_sequencingManager.increaseNameLsaSeq();
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050084 m_sequencingManager.writeSeqNoToFile();
Nick Gordon727d4832017-10-13 18:04:25 -050085 m_sync.publishRoutingUpdate(Lsa::Type::NAME, m_sequencingManager.getNameLsaSeq());
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050086
Ashlesh Gawande57a87172020-05-09 19:47:06 -070087 installLsa(std::make_shared<NameLsa>(nameLsa));
akmhoque53353462014-04-22 08:43:45 -050088}
89
90void
akmhoque31d1d4b2014-05-05 22:08:14 -050091Lsdb::buildAndInstallOwnCoordinateLsa()
akmhoque53353462014-04-22 08:43:45 -050092{
Ashlesh Gawande57a87172020-05-09 19:47:06 -070093 CoordinateLsa corLsa(m_thisRouterPrefix, m_sequencingManager.getCorLsaSeq() + 1,
94 getLsaExpirationTimePoint(), m_confParam.getCorR(),
Ashlesh Gawande85998a12017-12-07 22:22:13 -060095 m_confParam.getCorTheta());
Ashlesh Gawande57a87172020-05-09 19:47:06 -070096 m_sequencingManager.increaseCorLsaSeq();
97 m_sequencingManager.writeSeqNoToFile();
Nick Gordon5c467f02016-07-13 13:40:10 -050098
99 // Sync coordinate LSAs if using HR or HR dry run.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600100 if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_OFF) {
Nick Gordon727d4832017-10-13 18:04:25 -0500101 m_sync.publishRoutingUpdate(Lsa::Type::COORDINATE, m_sequencingManager.getCorLsaSeq());
Nick Gordon5c467f02016-07-13 13:40:10 -0500102 }
103
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700104 installLsa(std::make_shared<CoordinateLsa>(corLsa));
akmhoque53353462014-04-22 08:43:45 -0500105}
106
akmhoque53353462014-04-22 08:43:45 -0500107void
Vince Lehman50df6b72015-03-03 12:06:40 -0600108Lsdb::scheduleAdjLsaBuild()
akmhoque53353462014-04-22 08:43:45 -0500109{
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600110 m_adjBuildCount++;
Vince Lehman50df6b72015-03-03 12:06:40 -0600111
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600112 if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
Nick Gordon5c467f02016-07-13 13:40:10 -0500113 // Don't build adjacency LSAs in hyperbolic routing
dmcoomes5bcb39e2017-10-31 15:07:55 -0500114 NLSR_LOG_DEBUG("Adjacency LSA not built. Currently in hyperbolic routing state.");
Nick Gordon5c467f02016-07-13 13:40:10 -0500115 return;
116 }
117
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700118 if (m_isBuildAdjLsaScheduled) {
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500119 NLSR_LOG_DEBUG("Rescheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
120 }
121 else {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500122 NLSR_LOG_DEBUG("Scheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700123 m_isBuildAdjLsaScheduled = true;
Vince Lehman50df6b72015-03-03 12:06:40 -0600124 }
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500125 m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [this] { buildAdjLsa(); });
Vince Lehman50df6b72015-03-03 12:06:40 -0600126}
127
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700128void
129Lsdb::writeLog() const
130{
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700131 static const Lsa::Type types[] = {Lsa::Type::COORDINATE, Lsa::Type::NAME, Lsa::Type::ADJACENCY};
132 for (const auto& type : types) {
133 if ((type == Lsa::Type::COORDINATE &&
134 m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) ||
135 (type == Lsa::Type::ADJACENCY &&
136 m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON)) {
137 continue;
138 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700139
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700140 NLSR_LOG_DEBUG("---------------" << type << " LSDB-------------------");
141 auto lsaRange = m_lsdb.get<byType>().equal_range(type);
142 for (auto lsaIt = lsaRange.first; lsaIt != lsaRange.second; ++lsaIt) {
143 NLSR_LOG_DEBUG((*lsaIt)->toString());
144 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700145 }
146}
147
148void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700149Lsdb::processInterest(const ndn::Name& name, const ndn::Interest& interest)
150{
151 ndn::Name interestName(interest.getName());
152 NLSR_LOG_DEBUG("Interest received for LSA: " << interestName);
153
154 if (interestName[-2].isVersion()) {
155 // Interest for particular segment
156 if (m_segmentPublisher.replyFromStore(interestName)) {
157 NLSR_LOG_TRACE("Reply from SegmentPublisher storage");
158 return;
159 }
160 // Remove version and segment
161 interestName = interestName.getSubName(0, interestName.size() - 2);
162 NLSR_LOG_TRACE("Interest w/o segment and version: " << interestName);
163 }
164
165 // increment RCV_LSA_INTEREST
166 lsaIncrementSignal(Statistics::PacketType::RCV_LSA_INTEREST);
167
168 std::string chkString("LSA");
169 int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
170
171 // Forms the name of the router that the Interest packet came from.
172 ndn::Name originRouter = m_confParam.getNetwork();
173 originRouter.append(interestName.getSubName(lsaPosition + 1,
174 interestName.size() - lsaPosition - 3));
175
176 // if the interest is for this router's LSA
177 if (originRouter == m_thisRouterPrefix && lsaPosition >= 0) {
178 uint64_t seqNo = interestName[-1].toNumber();
179 NLSR_LOG_DEBUG("LSA sequence number from interest: " << seqNo);
180
181 std::string lsaType = interestName[-2].toUri();
182 Lsa::Type interestedLsType;
183 std::istringstream(lsaType) >> interestedLsType;
184 if (interestedLsType == Lsa::Type::BASE) {
185 NLSR_LOG_WARN("Received unrecognized LSA type: " << lsaType);
186 return;
187 }
188
189 incrementInterestRcvdStats(interestedLsType);
190 if (processInterestForLsa(interest, originRouter, interestedLsType, seqNo)) {
191 lsaIncrementSignal(Statistics::PacketType::SENT_LSA_DATA);
192 }
193 }
194 // else the interest is for other router's LSA, serve signed data from LsaSegmentStorage
195 else if (auto lsaSegment = m_lsaStorage.find(interest)) {
196 NLSR_LOG_TRACE("Found data in lsa storage. Sending the data for " << interest.getName());
197 m_face.put(*lsaSegment);
198 }
199}
200
201bool
202Lsdb::processInterestForLsa(const ndn::Interest& interest, const ndn::Name& originRouter,
203 Lsa::Type lsaType, uint64_t seqNo)
204{
205 NLSR_LOG_DEBUG(interest << " received for " << lsaType);
206 if (auto lsaPtr = findLsa(originRouter, lsaType)) {
207 NLSR_LOG_TRACE("Verifying SeqNo for " << lsaType << " is same as requested.");
208 if (lsaPtr->getSeqNo() == seqNo) {
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700209 m_segmentPublisher.publish(interest.getName(), interest.getName(), lsaPtr->wireEncode(),
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700210 m_lsaRefreshTime, m_confParam.getSigningInfo());
211 incrementDataSentStats(lsaType);
212 return true;
213 }
214 }
215 else {
216 NLSR_LOG_TRACE(interest << " was not found in our LSDB");
217 }
218 return false;
219}
220
221void
Davide Pesaventod90338d2021-01-07 17:50:05 -0500222Lsdb::installLsa(std::shared_ptr<Lsa> lsa)
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700223{
224 auto timeToExpire = m_lsaRefreshTime;
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700225 if (lsa->getOriginRouter() != m_thisRouterPrefix) {
226 auto duration = lsa->getExpirationTimePoint() - ndn::time::system_clock::now();
227 if (duration > ndn::time::seconds(0)) {
228 timeToExpire = ndn::time::duration_cast<ndn::time::seconds>(duration);
229 }
230 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700231
232 auto chkLsa = findLsa(lsa->getOriginRouter(), lsa->getType());
233 if (chkLsa == nullptr) {
234 NLSR_LOG_DEBUG("Adding " << lsa->getType() << " LSA");
235 NLSR_LOG_DEBUG(lsa->toString());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700236
237 m_lsdb.emplace(lsa);
238
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700239 onLsdbModified(lsa, LsdbUpdate::INSTALLED, {}, {});
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700240
241 lsa->setExpiringEventId(scheduleLsaExpiration(lsa, timeToExpire));
242 }
243 // Else this is a known name LSA, so we are updating it.
244 else if (chkLsa->getSeqNo() < lsa->getSeqNo()) {
245 NLSR_LOG_DEBUG("Updating " << lsa->getType() << " LSA:");
246 NLSR_LOG_DEBUG(chkLsa->toString());
247 chkLsa->setSeqNo(lsa->getSeqNo());
248 chkLsa->setExpirationTimePoint(lsa->getExpirationTimePoint());
249
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700250 bool updated;
251 std::list<ndn::Name> namesToAdd, namesToRemove;
252 std::tie(updated, namesToAdd, namesToRemove) = chkLsa->update(lsa);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700253
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700254 if (updated) {
255 onLsdbModified(lsa, LsdbUpdate::UPDATED, namesToAdd, namesToRemove);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700256 }
257
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700258 chkLsa->setExpiringEventId(scheduleLsaExpiration(chkLsa, timeToExpire));
259 NLSR_LOG_DEBUG("Updated " << lsa->getType() << " LSA:");
260 NLSR_LOG_DEBUG(chkLsa->toString());
261 }
262}
263
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700264void
265Lsdb::removeLsa(const LsaContainer::index<Lsdb::byName>::type::iterator& lsaIt)
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700266{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700267 if (lsaIt != m_lsdb.end()) {
268 auto lsaPtr = *lsaIt;
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700269 NLSR_LOG_DEBUG("Removing " << lsaPtr->getType() << " LSA:");
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700270 NLSR_LOG_DEBUG(lsaPtr->toString());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700271 m_lsdb.erase(lsaIt);
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700272 onLsdbModified(lsaPtr, LsdbUpdate::REMOVED, {}, {});
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700273 }
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700274}
275
276void
277Lsdb::removeLsa(const ndn::Name& router, Lsa::Type lsaType)
278{
279 removeLsa(m_lsdb.get<byName>().find(std::make_tuple(router, lsaType)));
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700280}
281
Vince Lehman50df6b72015-03-03 12:06:40 -0600282void
283Lsdb::buildAdjLsa()
284{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700285 NLSR_LOG_TRACE("buildAdjLsa called");
Vince Lehman50df6b72015-03-03 12:06:40 -0600286
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700287 m_isBuildAdjLsaScheduled = false;
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500288
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600289 if (m_confParam.getAdjacencyList().isAdjLsaBuildable(m_confParam.getInterestRetryNumber())) {
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500290
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600291 int adjBuildCount = m_adjBuildCount;
Nick G97e34942016-07-11 14:46:27 -0500292 // Only do the adjLsa build if there's one scheduled
akmhoque157b0a42014-05-13 00:26:37 -0500293 if (adjBuildCount > 0) {
Nick G97e34942016-07-11 14:46:27 -0500294 // It only makes sense to do the adjLsa build if we have neighbors
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600295 if (m_confParam.getAdjacencyList().getNumOfActiveNeighbor() > 0) {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500296 NLSR_LOG_DEBUG("Building and installing own Adj LSA");
akmhoque31d1d4b2014-05-05 22:08:14 -0500297 buildAndInstallOwnAdjLsa();
akmhoque53353462014-04-22 08:43:45 -0500298 }
Nick G97e34942016-07-11 14:46:27 -0500299 // We have no active neighbors, meaning no one can route through
300 // us. So delete our entry in the LSDB. This prevents this
301 // router from refreshing the LSA, eventually causing other
302 // routers to delete it, too.
akmhoque157b0a42014-05-13 00:26:37 -0500303 else {
dmcoomes5bcb39e2017-10-31 15:07:55 -0500304 NLSR_LOG_DEBUG("Removing own Adj LSA; no ACTIVE neighbors");
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700305 removeLsa(m_thisRouterPrefix, Lsa::Type::ADJACENCY);
akmhoque53353462014-04-22 08:43:45 -0500306 }
Nick G97e34942016-07-11 14:46:27 -0500307 // In the case that during building the adj LSA, the FIB has to
308 // wait on an Interest response, the number of scheduled adj LSA
309 // builds could change, so we shouldn't just set it to 0.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600310 m_adjBuildCount = m_adjBuildCount - adjBuildCount;
akmhoque53353462014-04-22 08:43:45 -0500311 }
312 }
Nick G97e34942016-07-11 14:46:27 -0500313 // We are still waiting to know the adjacency status of some
314 // neighbor, so schedule a build for later (when all that has
315 // hopefully finished)
316 else {
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700317 m_isBuildAdjLsaScheduled = true;
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500318 auto schedulingTime = ndn::time::seconds(m_confParam.getInterestRetryNumber() *
319 m_confParam.getInterestResendTime());
320 m_scheduledAdjLsaBuild = m_scheduler.schedule(schedulingTime, [this] { buildAdjLsa(); });
Nick G97e34942016-07-11 14:46:27 -0500321 }
akmhoque53353462014-04-22 08:43:45 -0500322}
323
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700324void
akmhoque31d1d4b2014-05-05 22:08:14 -0500325Lsdb::buildAndInstallOwnAdjLsa()
akmhoque53353462014-04-22 08:43:45 -0500326{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700327 AdjLsa adjLsa(m_thisRouterPrefix, m_sequencingManager.getAdjLsaSeq() + 1,
akmhoquec7a79b22014-05-26 08:06:19 -0500328 getLsaExpirationTimePoint(),
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600329 m_confParam.getAdjacencyList().getNumOfActiveNeighbor(),
330 m_confParam.getAdjacencyList());
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700331 m_sequencingManager.increaseAdjLsaSeq();
332 m_sequencingManager.writeSeqNoToFile();
Vince Lehman904c2412014-09-23 19:36:11 -0500333
Nick Gordon5c467f02016-07-13 13:40:10 -0500334 //Sync adjacency LSAs if link-state or dry-run HR is enabled.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600335 if (m_confParam.getHyperbolicState() != HYPERBOLIC_STATE_ON) {
Nick Gordon727d4832017-10-13 18:04:25 -0500336 m_sync.publishRoutingUpdate(Lsa::Type::ADJACENCY, m_sequencingManager.getAdjLsaSeq());
Nick Gordon5c467f02016-07-13 13:40:10 -0500337 }
Vince Lehman904c2412014-09-23 19:36:11 -0500338
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700339 installLsa(std::make_shared<AdjLsa>(adjLsa));
akmhoque53353462014-04-22 08:43:45 -0500340}
341
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700342ndn::scheduler::EventId
343Lsdb::scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime)
344{
345 NLSR_LOG_DEBUG("Scheduling expiration in: " << expTime + GRACE_PERIOD << " for " << lsa->getOriginRouter());
346 return m_scheduler.schedule(expTime + GRACE_PERIOD, [this, lsa] { expireOrRefreshLsa(lsa); });
347}
348
akmhoque53353462014-04-22 08:43:45 -0500349void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700350Lsdb::expireOrRefreshLsa(std::shared_ptr<Lsa> lsa)
akmhoque53353462014-04-22 08:43:45 -0500351{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700352 NLSR_LOG_DEBUG("ExpireOrRefreshLsa called for " << lsa->getType());
353 NLSR_LOG_DEBUG("OriginRouter: " << lsa->getOriginRouter() << " Seq No: " << lsa->getSeqNo());
354
355 auto lsaIt = m_lsdb.get<byName>().find(std::make_tuple(lsa->getOriginRouter(), lsa->getType()));
356
Nick G97e34942016-07-11 14:46:27 -0500357 // If this name LSA exists in the LSDB
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700358 if (lsaIt != m_lsdb.end()) {
359 auto lsaPtr = *lsaIt;
360 NLSR_LOG_DEBUG(lsaPtr->toString());
361 NLSR_LOG_DEBUG("LSA Exists with seq no: " << lsaPtr->getSeqNo());
Nick G97e34942016-07-11 14:46:27 -0500362 // If its seq no is the one we are expecting.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700363 if (lsaPtr->getSeqNo() == lsa->getSeqNo()) {
364 if (lsaPtr->getOriginRouter() == m_thisRouterPrefix) {
365 NLSR_LOG_DEBUG("Own " << lsaPtr->getType() << " LSA, so refreshing it.");
366 NLSR_LOG_DEBUG("Current LSA:");
367 NLSR_LOG_DEBUG(lsaPtr->toString());
368 lsaPtr->setSeqNo(lsaPtr->getSeqNo() + 1);
369 m_sequencingManager.setLsaSeq(lsaPtr->getSeqNo(), lsaPtr->getType());
370 lsaPtr->setExpirationTimePoint(getLsaExpirationTimePoint());
371 NLSR_LOG_DEBUG("Updated LSA:");
372 NLSR_LOG_DEBUG(lsaPtr->toString());
akmhoquefdbddb12014-05-02 18:35:19 -0500373 // schedule refreshing event again
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700374 lsaPtr->setExpiringEventId(scheduleLsaExpiration(lsaPtr, m_lsaRefreshTime));
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500375 m_sequencingManager.writeSeqNoToFile();
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700376 m_sync.publishRoutingUpdate(lsaPtr->getType(), m_sequencingManager.getLsaSeq(lsaPtr->getType()));
akmhoque53353462014-04-22 08:43:45 -0500377 }
Nick G97e34942016-07-11 14:46:27 -0500378 // Since we cannot refresh other router's LSAs, our only choice is to expire.
akmhoque157b0a42014-05-13 00:26:37 -0500379 else {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700380 NLSR_LOG_DEBUG("Other's " << lsaPtr->getType() << " LSA, so removing from LSDB");
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700381 removeLsa(lsaIt);
akmhoque53353462014-04-22 08:43:45 -0500382 }
383 }
384 }
385}
386
akmhoque53353462014-04-22 08:43:45 -0500387void
Alexander Afanasyev411ee4b2014-08-16 23:17:03 -0700388Lsdb::expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
Nick Gordone98480b2017-05-24 11:23:03 -0500389 ndn::time::steady_clock::TimePoint deadline)
akmhoque31d1d4b2014-05-05 22:08:14 -0500390{
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600391 // increment SENT_LSA_INTEREST
392 lsaIncrementSignal(Statistics::PacketType::SENT_LSA_INTEREST);
393
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500394 if (deadline == DEFAULT_LSA_RETRIEVAL_DEADLINE) {
Nick Gordone98480b2017-05-24 11:23:03 -0500395 deadline = ndn::time::steady_clock::now() + ndn::time::seconds(static_cast<int>(LSA_REFRESH_TIME_MAX));
Alexander Afanasyev411ee4b2014-08-16 23:17:03 -0700396 }
Nick G97e34942016-07-11 14:46:27 -0500397 // The first component of the interest is the name.
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500398 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
Nick G97e34942016-07-11 14:46:27 -0500399 // The seq no is the last
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500400 uint64_t seqNo = interestName[-1].toNumber();
401
Nick G97e34942016-07-11 14:46:27 -0500402 // If the LSA is not found in the list currently.
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500403 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
404 m_highestSeqNo[lsaName] = seqNo;
405 }
Nick G97e34942016-07-11 14:46:27 -0500406 // If the new seq no is higher, that means the LSA is valid
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500407 else if (seqNo > m_highestSeqNo[lsaName]) {
408 m_highestSeqNo[lsaName] = seqNo;
409 }
Nick G97e34942016-07-11 14:46:27 -0500410 // Otherwise, its an old/invalid LSA
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500411 else if (seqNo < m_highestSeqNo[lsaName]) {
412 return;
413 }
414
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500415 ndn::Interest interest(interestName);
Ashlesh Gawande744e4812018-08-22 16:26:24 -0500416 ndn::util::SegmentFetcher::Options options;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600417 options.interestLifetime = m_confParam.getLsaInterestLifetime();
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500418
dmcoomes5bcb39e2017-10-31 15:07:55 -0500419 NLSR_LOG_DEBUG("Fetching Data for LSA: " << interestName << " Seq number: " << seqNo);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600420 auto fetcher = ndn::util::SegmentFetcher::start(m_face, interest,
421 m_confParam.getValidator(), options);
Ashlesh Gawande05cb7282018-08-30 14:39:41 -0500422
Ashlesh Gawande744e4812018-08-22 16:26:24 -0500423 auto it = m_fetchers.insert(fetcher).first;
424
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600425 fetcher->afterSegmentValidated.connect([this] (const ndn::Data& data) {
Ashlesh Gawande15052402018-12-12 20:20:00 -0600426 // Nlsr class subscribes to this to fetch certificates
427 afterSegmentValidatedSignal(data);
428
429 // If we don't do this IMS throws: std::bad_weak_ptr: bad_weak_ptr
430 auto lsaSegment = std::make_shared<const ndn::Data>(data);
431 m_lsaStorage.insert(*lsaSegment);
432 const ndn::Name& segmentName = lsaSegment->getName();
433 // Schedule deletion of the segment
434 m_scheduler.schedule(ndn::time::seconds(LSA_REFRESH_TIME_DEFAULT),
435 [this, segmentName] { m_lsaStorage.erase(segmentName); });
436 });
437
438 fetcher->onComplete.connect([=] (const ndn::ConstBufferPtr& bufferPtr) {
439 m_lsaStorage.erase(ndn::Name(lsaName).appendNumber(seqNo - 1));
440 afterFetchLsa(bufferPtr, interestName);
441 m_fetchers.erase(it);
442 });
443
444 fetcher->onError.connect([=] (uint32_t errorCode, const std::string& msg) {
445 onFetchLsaError(errorCode, msg, interestName, timeoutCount, deadline, lsaName, seqNo);
446 m_fetchers.erase(it);
447 });
Muktadir Chowdhuryc3ea26f2018-01-05 21:40:59 +0000448
Nick Gordon727d4832017-10-13 18:04:25 -0500449 Lsa::Type lsaType;
450 std::istringstream(interestName[-2].toUri()) >> lsaType;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700451 incrementInterestSentStats(lsaType);
452}
453
454void
455Lsdb::onFetchLsaError(uint32_t errorCode, const std::string& msg, const ndn::Name& interestName,
456 uint32_t retransmitNo, const ndn::time::steady_clock::TimePoint& deadline,
457 ndn::Name lsaName, uint64_t seqNo)
458{
459 NLSR_LOG_DEBUG("Failed to fetch LSA: " << lsaName << ", Error code: " << errorCode
460 << ", Message: " << msg);
461
462 if (ndn::time::steady_clock::now() < deadline) {
463 auto it = m_highestSeqNo.find(lsaName);
464 if (it != m_highestSeqNo.end() && it->second == seqNo) {
465 // If the SegmentFetcher failed due to an Interest timeout, it is safe to re-express
466 // immediately since at the least the LSA Interest lifetime has elapsed.
467 // Otherwise, it is necessary to delay the Interest re-expression to prevent
468 // the potential for constant Interest flooding.
469 ndn::time::seconds delay = m_confParam.getLsaInterestLifetime();
470
471 if (errorCode == ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT) {
472 delay = ndn::time::seconds(0);
473 }
474 m_scheduler.schedule(delay, std::bind(&Lsdb::expressInterest, this,
475 interestName, retransmitNo + 1, deadline));
476 }
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600477 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500478}
479
480void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700481Lsdb::afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName)
akmhoque31d1d4b2014-05-05 22:08:14 -0500482{
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700483 NLSR_LOG_DEBUG("Received data for LSA interest: " << interestName);
484 lsaIncrementSignal(Statistics::PacketType::RCV_LSA_DATA);
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600485
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700486 ndn::Name lsaName = interestName.getSubName(0, interestName.size()-1);
487 uint64_t seqNo = interestName[-1].toNumber();
488
489 if (m_highestSeqNo.find(lsaName) == m_highestSeqNo.end()) {
490 m_highestSeqNo[lsaName] = seqNo;
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600491 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700492 else if (seqNo > m_highestSeqNo[lsaName]) {
493 m_highestSeqNo[lsaName] = seqNo;
494 NLSR_LOG_TRACE("SeqNo for LSA(name): " << interestName << " updated");
495 }
496 else if (seqNo < m_highestSeqNo[lsaName]) {
497 return;
498 }
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600499
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500500 std::string chkString("LSA");
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600501 int32_t lsaPosition = util::getNameComponentPosition(interestName, chkString);
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500502
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700503 if (lsaPosition >= 0) {
504 // Extracts the prefix of the originating router from the data.
505 ndn::Name originRouter = m_confParam.getNetwork();
506 originRouter.append(interestName.getSubName(lsaPosition + 1,
507 interestName.size() - lsaPosition - 3));
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700508 try {
509 Lsa::Type interestedLsType;
510 std::istringstream(interestName[-2].toUri()) >> interestedLsType;
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500511
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700512 if (interestedLsType == Lsa::Type::BASE) {
513 NLSR_LOG_WARN("Received unrecognized LSA Type: " << interestName[-2].toUri());
514 return;
515 }
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500516
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700517 ndn::Block block(bufferPtr);
518 if (interestedLsType == Lsa::Type::NAME) {
519 lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_DATA);
520 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
521 installLsa(std::make_shared<NameLsa>(block));
522 }
523 }
524 else if (interestedLsType == Lsa::Type::ADJACENCY) {
525 lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_DATA);
526 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
527 installLsa(std::make_shared<AdjLsa>(block));
528 }
529 }
530 else if (interestedLsType == Lsa::Type::COORDINATE) {
531 lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_DATA);
532 if (isLsaNew(originRouter, interestedLsType, seqNo)) {
533 installLsa(std::make_shared<CoordinateLsa>(block));
534 }
535 }
akmhoque31d1d4b2014-05-05 22:08:14 -0500536 }
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700537 catch (const std::exception& e) {
538 NLSR_LOG_TRACE("LSA data decoding error :( " << e.what());
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600539 }
Nick Gordon8f23b5d2017-08-31 17:53:07 -0500540 }
541}
542
Alexander Afanasyev8388ec62014-08-16 18:38:57 -0700543} // namespace nlsr