blob: 0578edd945255c93ba2f72a04d1eee322919d672 [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/*
Alexander Afanasyev135288c2022-04-23 23:06:56 -04003 * Copyright (c) 2014-2022, 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 Gawande57a87172020-05-09 19:47:06 -070020 */
Ashlesh Gawande5bf83172014-09-19 12:38:17 -050021
akmhoque53353462014-04-22 08:43:45 -050022#ifndef NLSR_LSDB_HPP
23#define NLSR_LSDB_HPP
24
Vince Lehman50df6b72015-03-03 12:06:40 -060025#include "conf-parameter.hpp"
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -080026#include "lsa/lsa.hpp"
27#include "lsa/name-lsa.hpp"
28#include "lsa/coordinate-lsa.hpp"
29#include "lsa/adj-lsa.hpp"
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050030#include "sequencing-manager.hpp"
Ashlesh Gawande5bf83172014-09-19 12:38:17 -050031#include "test-access-control.hpp"
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050032#include "communication/sync-logic-handler.hpp"
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -060033#include "statistics.hpp"
34
35#include <ndn-cxx/security/key-chain.hpp>
36#include <ndn-cxx/util/signal.hpp>
37#include <ndn-cxx/util/time.hpp>
Ashlesh Gawande744e4812018-08-22 16:26:24 -050038#include <ndn-cxx/util/segment-fetcher.hpp>
Ashlesh Gawande15052402018-12-12 20:20:00 -060039#include <ndn-cxx/ims/in-memory-storage-persistent.hpp>
Ashlesh Gawande744e4812018-08-22 16:26:24 -050040
Ashlesh Gawande57a87172020-05-09 19:47:06 -070041#include <boost/multi_index_container.hpp>
42#include <boost/multi_index/hashed_index.hpp>
43#include <boost/multi_index/composite_key.hpp>
44
Ashlesh Gawande939b6f82018-12-09 16:51:09 -060045#include <PSync/segment-publisher.hpp>
46
Nick Gordone98480b2017-05-24 11:23:03 -050047namespace nlsr {
Alexander Afanasyev411ee4b2014-08-16 23:17:03 -070048
Ashlesh Gawande57a87172020-05-09 19:47:06 -070049namespace bmi = boost::multi_index;
Ashlesh Gawande57a87172020-05-09 19:47:06 -070050
51static constexpr ndn::time::seconds GRACE_PERIOD = 10_s;
52
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070053enum class LsdbUpdate {
54 INSTALLED,
55 UPDATED,
56 REMOVED
57};
58
akmhoque53353462014-04-22 08:43:45 -050059class Lsdb
60{
61public:
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070062 Lsdb(ndn::Face& face, ndn::KeyChain& keyChain, ConfParameter& confParam);
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050063
Ashlesh Gawande57a87172020-05-09 19:47:06 -070064 ~Lsdb()
65 {
66 for (const auto& sp : m_fetchers) {
67 sp->stop();
68 }
69 }
Ashlesh Gawande744e4812018-08-22 16:26:24 -050070
Ashlesh Gawande57a87172020-05-09 19:47:06 -070071 /*! \brief Returns whether the LSDB contains some LSA.
72 */
akmhoque53353462014-04-22 08:43:45 -050073 bool
Ashlesh Gawande57a87172020-05-09 19:47:06 -070074 doesLsaExist(const ndn::Name& router, Lsa::Type lsaType)
75 {
76 return m_lsdb.get<byName>().find(std::make_tuple(router, lsaType)) != m_lsdb.end();
77 }
Nick G97e34942016-07-11 14:46:27 -050078
79 /*! \brief Builds a name LSA for this router and then installs it
80 into the LSDB.
81 */
Ashlesh Gawande57a87172020-05-09 19:47:06 -070082 void
akmhoque31d1d4b2014-05-05 22:08:14 -050083 buildAndInstallOwnNameLsa();
akmhoque53353462014-04-22 08:43:45 -050084
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070085PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Nick G97e34942016-07-11 14:46:27 -050086 /*! \brief Builds a cor. LSA for this router and installs it into the LSDB. */
akmhoque53353462014-04-22 08:43:45 -050087 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -070088 buildAndInstallOwnCoordinateLsa();
Nick G97e34942016-07-11 14:46:27 -050089
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070090public:
Nick G97e34942016-07-11 14:46:27 -050091 /*! \brief Schedules a build of this router's LSA. */
akmhoque53353462014-04-22 08:43:45 -050092 void
Vince Lehman50df6b72015-03-03 12:06:40 -060093 scheduleAdjLsaBuild();
akmhoque53353462014-04-22 08:43:45 -050094
akmhoque53353462014-04-22 08:43:45 -050095 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -070096 writeLog() const;
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050097
Ashlesh Gawande939b6f82018-12-09 16:51:09 -060098 /* \brief Process interest which can be either:
99 * 1) Discovery interest from segment fetcher:
100 * /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>
101 * 2) Interest containing segment number:
102 * /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>/<version>/<segmentNo>
103 */
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500104 void
105 processInterest(const ndn::Name& name, const ndn::Interest& interest);
106
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600107 bool
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700108 getIsBuildAdjLsaScheduled() const
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600109 {
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700110 return m_isBuildAdjLsaScheduled;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600111 }
112
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500113 SyncLogicHandler&
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700114 getSync()
115 {
Ashlesh Gawande08bce9c2019-04-05 11:08:07 -0500116 return m_sync;
117 }
118
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700119 template<typename T>
120 std::shared_ptr<T>
121 findLsa(const ndn::Name& router) const
122 {
123 return std::static_pointer_cast<T>(findLsa(router, T::type()));
124 }
125
126 struct name_hash {
127 int
128 operator()(const ndn::Name& name) const {
129 return std::hash<ndn::Name>{}(name);
130 }
131 };
132
133 struct enum_class_hash {
134 template<typename T>
135 int
136 operator()(T t) const {
137 return static_cast<int>(t);
138 }
139 };
140
141 struct byName{};
142 struct byType{};
143
144 using LsaContainer = boost::multi_index_container<
145 std::shared_ptr<Lsa>,
146 bmi::indexed_by<
147 bmi::hashed_unique<
148 bmi::tag<byName>,
149 bmi::composite_key<
150 Lsa,
151 bmi::const_mem_fun<Lsa, ndn::Name, &Lsa::getOriginRouterCopy>,
152 bmi::const_mem_fun<Lsa, Lsa::Type, &Lsa::getType>
153 >,
154 bmi::composite_key_hash<name_hash, enum_class_hash>
155 >,
156 bmi::hashed_non_unique<
157 bmi::tag<byType>,
158 bmi::const_mem_fun<Lsa, Lsa::Type, &Lsa::getType>,
159 enum_class_hash
160 >
161 >
162 >;
163
164 template<typename T>
165 std::pair<LsaContainer::index<Lsdb::byType>::type::iterator,
166 LsaContainer::index<Lsdb::byType>::type::iterator>
167 getLsdbIterator() const
168 {
169 return m_lsdb.get<byType>().equal_range(T::type());
170 }
171
172PUBLIC_WITH_TESTS_ELSE_PRIVATE:
173 std::shared_ptr<Lsa>
174 findLsa(const ndn::Name& router, Lsa::Type lsaType) const
175 {
176 auto it = m_lsdb.get<byName>().find(std::make_tuple(router, lsaType));
177 return it != m_lsdb.end() ? *it : nullptr;
178 }
179
180 void
Davide Pesavento1954a0c2022-09-30 15:56:04 -0400181 incrementDataSentStats(Lsa::Type lsaType)
182 {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700183 if (lsaType == Lsa::Type::NAME) {
184 lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_DATA);
185 }
186 else if (lsaType == Lsa::Type::ADJACENCY) {
187 lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_DATA);
188 }
189 else if (lsaType == Lsa::Type::COORDINATE) {
190 lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_DATA);
191 }
192 }
193
194 void
Davide Pesavento1954a0c2022-09-30 15:56:04 -0400195 incrementInterestRcvdStats(Lsa::Type lsaType)
196 {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700197 if (lsaType == Lsa::Type::NAME) {
198 lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_INTEREST);
199 }
200 else if (lsaType == Lsa::Type::ADJACENCY) {
201 lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_INTEREST);
202 }
203 else if (lsaType == Lsa::Type::COORDINATE) {
204 lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_INTEREST);
205 }
206 }
207
208 void
Davide Pesavento1954a0c2022-09-30 15:56:04 -0400209 incrementInterestSentStats(Lsa::Type lsaType)
210 {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700211 if (lsaType == Lsa::Type::NAME) {
212 lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_INTEREST);
213 }
214 else if (lsaType == Lsa::Type::ADJACENCY) {
215 lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_INTEREST);
216 }
217 else if (lsaType == Lsa::Type::COORDINATE) {
218 lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_INTEREST);
219 }
220 }
221
222 /*! Returns whether a seq. no. from a certain router signals a new LSA.
223 \param originRouter The name of the originating router.
224 \param lsaType The type of the LSA.
225 \param seqNo The sequence number to check.
Nick G97e34942016-07-11 14:46:27 -0500226 */
akmhoque53353462014-04-22 08:43:45 -0500227 bool
Davide Pesavento1954a0c2022-09-30 15:56:04 -0400228 isLsaNew(const ndn::Name& originRouter, const Lsa::Type& lsaType, uint64_t lsSeqNo) const
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700229 {
230 // Is the name in the LSDB and the supplied seq no is the highest so far
231 auto lsaPtr = findLsa(originRouter, lsaType);
232 return lsaPtr ? lsaPtr->getSeqNo() < lsSeqNo : true;
233 }
akmhoque53353462014-04-22 08:43:45 -0500234
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700235 void
Davide Pesaventod90338d2021-01-07 17:50:05 -0500236 installLsa(std::shared_ptr<Lsa> lsa);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700237
238 /*! \brief Remove a name LSA from the LSDB.
239 \param router The name of the router that published the LSA to remove.
240 \param lsaType The type of the LSA.
241
242 This function will remove a name LSA from the LSDB by finding an
243 LSA whose name matches key. This removal also causes the NPT to
244 remove those name prefixes if no more LSAs advertise them.
Nick G97e34942016-07-11 14:46:27 -0500245 */
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700246 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700247 removeLsa(const ndn::Name& router, Lsa::Type lsaType);
akmhoque53353462014-04-22 08:43:45 -0500248
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700249 void
250 removeLsa(const LsaContainer::index<Lsdb::byName>::type::iterator& lsaIt);
251
Nick G97e34942016-07-11 14:46:27 -0500252 /*! \brief Attempts to construct an adj. LSA.
253
254 This function will attempt to construct an adjacency LSA. An LSA
255 can only be built when the status of all of the router's neighbors
256 is known. That is, when we are not currently trying to contact any
257 neighbor.
258 */
Vince Lehman50df6b72015-03-03 12:06:40 -0600259 void
260 buildAdjLsa();
261
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700262 /*! \brief Wrapper event to build and install an adj. LSA for this router. */
263 void
264 buildAndInstallOwnAdjLsa();
akmhoque53353462014-04-22 08:43:45 -0500265
Nick G97e34942016-07-11 14:46:27 -0500266 /*! \brief Schedules a refresh/expire event in the scheduler.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700267 \param lsa The LSA.
Nick G97e34942016-07-11 14:46:27 -0500268 \param expTime How many seconds to wait before triggering the event.
269 */
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400270 ndn::scheduler::EventId
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700271 scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime);
akmhoque53353462014-04-22 08:43:45 -0500272
Nick G97e34942016-07-11 14:46:27 -0500273 /*! \brief Either allow to expire, or refresh a name LSA.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700274 \param lsa The LSA.
Nick G97e34942016-07-11 14:46:27 -0500275 */
akmhoque53353462014-04-22 08:43:45 -0500276 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700277 expireOrRefreshLsa(std::shared_ptr<Lsa> lsa);
akmhoque53353462014-04-22 08:43:45 -0500278
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700279 bool
280 processInterestForLsa(const ndn::Interest& interest, const ndn::Name& originRouter,
281 Lsa::Type lsaType, uint64_t seqNo);
akmhoque53353462014-04-22 08:43:45 -0500282
283 void
Alexander Afanasyev135288c2022-04-23 23:06:56 -0400284 expressInterest(const ndn::Name& interestName, uint32_t timeoutCount, uint64_t incomingFaceId,
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400285 ndn::time::steady_clock::time_point deadline = DEFAULT_LSA_RETRIEVAL_DEADLINE);
akmhoque53353462014-04-22 08:43:45 -0500286
Nick G97e34942016-07-11 14:46:27 -0500287 /*!
288 \brief Error callback when SegmentFetcher fails to return an LSA
289
290 In all error cases, a reattempt to fetch the LSA will be made.
291
292 Segment validation can fail either because the packet does not have a
293 valid signature (fatal) or because some of the certificates in the trust chain
294 could not be fetched (non-fatal).
295
296 Currently, the library does not provide clear indication (besides a plain-text message
297 in the error callback) of the reason for the failure nor the segment that failed
298 to be validated, thus we will continue to try to fetch the LSA until the deadline
299 is reached.
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500300 */
akmhoque31d1d4b2014-05-05 22:08:14 -0500301 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700302 onFetchLsaError(uint32_t errorCode, const std::string& msg,
303 const ndn::Name& interestName, uint32_t retransmitNo,
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400304 const ndn::time::steady_clock::time_point& deadline,
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700305 ndn::Name lsaName, uint64_t seqNo);
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500306
Nick G97e34942016-07-11 14:46:27 -0500307 /*!
308 \brief Success callback when SegmentFetcher returns a valid LSA
309
Nick Gordonb50e51b2016-07-22 16:05:57 -0500310 \param interestName The base Interest used to fetch the LSA in the format:
Nick G97e34942016-07-11 14:46:27 -0500311 /<network>/NLSR/LSA/<site>/%C1.Router/<router>/<lsa-type>/<seqNo>
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500312 */
313 void
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800314 afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName);
akmhoque31d1d4b2014-05-05 22:08:14 -0500315
Saurab Dulal427e0122019-11-28 11:58:02 -0600316 void
317 emitSegmentValidatedSignal(const ndn::Data& data)
318 {
319 afterSegmentValidatedSignal(data);
320 }
321
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400322 ndn::time::system_clock::time_point
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700323 getLsaExpirationTimePoint() const
324 {
325 return ndn::time::system_clock::now() + ndn::time::seconds(m_confParam.getRouterDeadInterval());
326 }
akmhoquec7a79b22014-05-26 08:06:19 -0500327
Jiewen Tana0497d82015-02-02 21:59:18 -0800328public:
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700329 ndn::util::Signal<Lsdb, Statistics::PacketType> lsaIncrementSignal;
330 ndn::util::Signal<Lsdb, ndn::Data> afterSegmentValidatedSignal;
331 using AfterLsdbModified = ndn::util::Signal<Lsdb, std::shared_ptr<Lsa>, LsdbUpdate,
332 std::list<ndn::Name>, std::list<ndn::Name>>;
333 AfterLsdbModified onLsdbModified;
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600334
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700335PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600336 ndn::Face& m_face;
337 ndn::Scheduler m_scheduler;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600338
339 ConfParameter& m_confParam;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600340
Ashlesh Gawande15052402018-12-12 20:20:00 -0600341 SyncLogicHandler m_sync;
Vince Lehman7c603292014-09-11 17:48:16 -0500342
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700343 LsaContainer m_lsdb;
akmhoque53353462014-04-22 08:43:45 -0500344
Nick Gordone98480b2017-05-24 11:23:03 -0500345 ndn::time::seconds m_lsaRefreshTime;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700346 ndn::time::seconds m_adjLsaBuildInterval;
347 const ndn::Name& m_thisRouterPrefix;
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500348
349 // Maps the name of an LSA to its highest known sequence number from sync;
350 // Used to stop NLSR from trying to fetch outdated LSAs
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700351 std::map<ndn::Name, uint64_t> m_highestSeqNo;
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500352
353 SequencingManager m_sequencingManager;
Nick Gordon9eac4d92017-08-29 17:31:29 -0500354
355 ndn::util::signal::ScopedConnection m_onNewLsaConnection;
Ashlesh Gawande744e4812018-08-22 16:26:24 -0500356
357 std::set<std::shared_ptr<ndn::util::SegmentFetcher>> m_fetchers;
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600358 psync::SegmentPublisher m_segmentPublisher;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600359
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700360 bool m_isBuildAdjLsaScheduled;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600361 int64_t m_adjBuildCount;
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500362 ndn::scheduler::ScopedEventId m_scheduledAdjLsaBuild;
Ashlesh Gawande15052402018-12-12 20:20:00 -0600363
Ashlesh Gawande15052402018-12-12 20:20:00 -0600364 ndn::InMemoryStoragePersistent m_lsaStorage;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700365
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400366 static inline const ndn::time::steady_clock::time_point DEFAULT_LSA_RETRIEVAL_DEADLINE =
367 ndn::time::steady_clock::time_point::min();
akmhoque53353462014-04-22 08:43:45 -0500368};
369
Nick Gordonfad8e252016-08-11 14:21:38 -0500370} // namespace nlsr
akmhoque53353462014-04-22 08:43:45 -0500371
dmcoomes9f936662017-03-02 10:33:09 -0600372#endif // NLSR_LSDB_HPP