blob: 915c7b6ed4becffe877305d625c78157dec9dd40 [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
181 incrementDataSentStats(Lsa::Type lsaType) {
182 if (lsaType == Lsa::Type::NAME) {
183 lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_DATA);
184 }
185 else if (lsaType == Lsa::Type::ADJACENCY) {
186 lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_DATA);
187 }
188 else if (lsaType == Lsa::Type::COORDINATE) {
189 lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_DATA);
190 }
191 }
192
193 void
194 incrementInterestRcvdStats(Lsa::Type lsaType) {
195 if (lsaType == Lsa::Type::NAME) {
196 lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_INTEREST);
197 }
198 else if (lsaType == Lsa::Type::ADJACENCY) {
199 lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_INTEREST);
200 }
201 else if (lsaType == Lsa::Type::COORDINATE) {
202 lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_INTEREST);
203 }
204 }
205
206 void
207 incrementInterestSentStats(Lsa::Type lsaType) {
208 if (lsaType == Lsa::Type::NAME) {
209 lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_INTEREST);
210 }
211 else if (lsaType == Lsa::Type::ADJACENCY) {
212 lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_INTEREST);
213 }
214 else if (lsaType == Lsa::Type::COORDINATE) {
215 lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_INTEREST);
216 }
217 }
218
219 /*! Returns whether a seq. no. from a certain router signals a new LSA.
220 \param originRouter The name of the originating router.
221 \param lsaType The type of the LSA.
222 \param seqNo The sequence number to check.
Nick G97e34942016-07-11 14:46:27 -0500223 */
akmhoque53353462014-04-22 08:43:45 -0500224 bool
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700225 isLsaNew(const ndn::Name& originRouter, const Lsa::Type& lsaType, uint64_t lsSeqNo)
226 {
227 // Is the name in the LSDB and the supplied seq no is the highest so far
228 auto lsaPtr = findLsa(originRouter, lsaType);
229 return lsaPtr ? lsaPtr->getSeqNo() < lsSeqNo : true;
230 }
akmhoque53353462014-04-22 08:43:45 -0500231
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700232 void
Davide Pesaventod90338d2021-01-07 17:50:05 -0500233 installLsa(std::shared_ptr<Lsa> lsa);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700234
235 /*! \brief Remove a name LSA from the LSDB.
236 \param router The name of the router that published the LSA to remove.
237 \param lsaType The type of the LSA.
238
239 This function will remove a name LSA from the LSDB by finding an
240 LSA whose name matches key. This removal also causes the NPT to
241 remove those name prefixes if no more LSAs advertise them.
Nick G97e34942016-07-11 14:46:27 -0500242 */
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700243 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700244 removeLsa(const ndn::Name& router, Lsa::Type lsaType);
akmhoque53353462014-04-22 08:43:45 -0500245
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700246 void
247 removeLsa(const LsaContainer::index<Lsdb::byName>::type::iterator& lsaIt);
248
Nick G97e34942016-07-11 14:46:27 -0500249 /*! \brief Attempts to construct an adj. LSA.
250
251 This function will attempt to construct an adjacency LSA. An LSA
252 can only be built when the status of all of the router's neighbors
253 is known. That is, when we are not currently trying to contact any
254 neighbor.
255 */
Vince Lehman50df6b72015-03-03 12:06:40 -0600256 void
257 buildAdjLsa();
258
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700259 /*! \brief Wrapper event to build and install an adj. LSA for this router. */
260 void
261 buildAndInstallOwnAdjLsa();
akmhoque53353462014-04-22 08:43:45 -0500262
Nick G97e34942016-07-11 14:46:27 -0500263 /*! \brief Schedules a refresh/expire event in the scheduler.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700264 \param lsa The LSA.
Nick G97e34942016-07-11 14:46:27 -0500265 \param expTime How many seconds to wait before triggering the event.
266 */
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400267 ndn::scheduler::EventId
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700268 scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime);
akmhoque53353462014-04-22 08:43:45 -0500269
Nick G97e34942016-07-11 14:46:27 -0500270 /*! \brief Either allow to expire, or refresh a name LSA.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700271 \param lsa The LSA.
Nick G97e34942016-07-11 14:46:27 -0500272 */
akmhoque53353462014-04-22 08:43:45 -0500273 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700274 expireOrRefreshLsa(std::shared_ptr<Lsa> lsa);
akmhoque53353462014-04-22 08:43:45 -0500275
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700276 bool
277 processInterestForLsa(const ndn::Interest& interest, const ndn::Name& originRouter,
278 Lsa::Type lsaType, uint64_t seqNo);
akmhoque53353462014-04-22 08:43:45 -0500279
280 void
Alexander Afanasyev135288c2022-04-23 23:06:56 -0400281 expressInterest(const ndn::Name& interestName, uint32_t timeoutCount, uint64_t incomingFaceId,
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400282 ndn::time::steady_clock::time_point deadline = DEFAULT_LSA_RETRIEVAL_DEADLINE);
akmhoque53353462014-04-22 08:43:45 -0500283
Nick G97e34942016-07-11 14:46:27 -0500284 /*!
285 \brief Error callback when SegmentFetcher fails to return an LSA
286
287 In all error cases, a reattempt to fetch the LSA will be made.
288
289 Segment validation can fail either because the packet does not have a
290 valid signature (fatal) or because some of the certificates in the trust chain
291 could not be fetched (non-fatal).
292
293 Currently, the library does not provide clear indication (besides a plain-text message
294 in the error callback) of the reason for the failure nor the segment that failed
295 to be validated, thus we will continue to try to fetch the LSA until the deadline
296 is reached.
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500297 */
akmhoque31d1d4b2014-05-05 22:08:14 -0500298 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700299 onFetchLsaError(uint32_t errorCode, const std::string& msg,
300 const ndn::Name& interestName, uint32_t retransmitNo,
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400301 const ndn::time::steady_clock::time_point& deadline,
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700302 ndn::Name lsaName, uint64_t seqNo);
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500303
Nick G97e34942016-07-11 14:46:27 -0500304 /*!
305 \brief Success callback when SegmentFetcher returns a valid LSA
306
Nick Gordonb50e51b2016-07-22 16:05:57 -0500307 \param interestName The base Interest used to fetch the LSA in the format:
Nick G97e34942016-07-11 14:46:27 -0500308 /<network>/NLSR/LSA/<site>/%C1.Router/<router>/<lsa-type>/<seqNo>
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500309 */
310 void
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800311 afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName);
akmhoque31d1d4b2014-05-05 22:08:14 -0500312
Saurab Dulal427e0122019-11-28 11:58:02 -0600313 void
314 emitSegmentValidatedSignal(const ndn::Data& data)
315 {
316 afterSegmentValidatedSignal(data);
317 }
318
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400319 ndn::time::system_clock::time_point
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700320 getLsaExpirationTimePoint() const
321 {
322 return ndn::time::system_clock::now() + ndn::time::seconds(m_confParam.getRouterDeadInterval());
323 }
akmhoquec7a79b22014-05-26 08:06:19 -0500324
Jiewen Tana0497d82015-02-02 21:59:18 -0800325public:
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700326 ndn::util::Signal<Lsdb, Statistics::PacketType> lsaIncrementSignal;
327 ndn::util::Signal<Lsdb, ndn::Data> afterSegmentValidatedSignal;
328 using AfterLsdbModified = ndn::util::Signal<Lsdb, std::shared_ptr<Lsa>, LsdbUpdate,
329 std::list<ndn::Name>, std::list<ndn::Name>>;
330 AfterLsdbModified onLsdbModified;
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600331
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700332PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600333 ndn::Face& m_face;
334 ndn::Scheduler m_scheduler;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600335
336 ConfParameter& m_confParam;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600337
Ashlesh Gawande15052402018-12-12 20:20:00 -0600338 SyncLogicHandler m_sync;
Vince Lehman7c603292014-09-11 17:48:16 -0500339
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700340 LsaContainer m_lsdb;
akmhoque53353462014-04-22 08:43:45 -0500341
Nick Gordone98480b2017-05-24 11:23:03 -0500342 ndn::time::seconds m_lsaRefreshTime;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700343 ndn::time::seconds m_adjLsaBuildInterval;
344 const ndn::Name& m_thisRouterPrefix;
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500345
346 // Maps the name of an LSA to its highest known sequence number from sync;
347 // Used to stop NLSR from trying to fetch outdated LSAs
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700348 std::map<ndn::Name, uint64_t> m_highestSeqNo;
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500349
350 SequencingManager m_sequencingManager;
Nick Gordon9eac4d92017-08-29 17:31:29 -0500351
352 ndn::util::signal::ScopedConnection m_onNewLsaConnection;
Ashlesh Gawande744e4812018-08-22 16:26:24 -0500353
354 std::set<std::shared_ptr<ndn::util::SegmentFetcher>> m_fetchers;
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600355 psync::SegmentPublisher m_segmentPublisher;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600356
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700357 bool m_isBuildAdjLsaScheduled;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600358 int64_t m_adjBuildCount;
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500359 ndn::scheduler::ScopedEventId m_scheduledAdjLsaBuild;
Ashlesh Gawande15052402018-12-12 20:20:00 -0600360
Ashlesh Gawande15052402018-12-12 20:20:00 -0600361 ndn::InMemoryStoragePersistent m_lsaStorage;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700362
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400363 static inline const ndn::time::steady_clock::time_point DEFAULT_LSA_RETRIEVAL_DEADLINE =
364 ndn::time::steady_clock::time_point::min();
akmhoque53353462014-04-22 08:43:45 -0500365};
366
Nick Gordonfad8e252016-08-11 14:21:38 -0500367} // namespace nlsr
akmhoque53353462014-04-22 08:43:45 -0500368
dmcoomes9f936662017-03-02 10:33:09 -0600369#endif // NLSR_LSDB_HPP