blob: ec2e4a97418e48444fcee79b823480a2200e700c [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
Davide Pesavento65ee9922022-11-16 00:21:43 -050025#include "communication/sync-logic-handler.hpp"
Vince Lehman50df6b72015-03-03 12:06:40 -060026#include "conf-parameter.hpp"
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -080027#include "lsa/lsa.hpp"
28#include "lsa/name-lsa.hpp"
29#include "lsa/coordinate-lsa.hpp"
30#include "lsa/adj-lsa.hpp"
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050031#include "sequencing-manager.hpp"
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -060032#include "statistics.hpp"
Davide Pesavento65ee9922022-11-16 00:21:43 -050033#include "test-access-control.hpp"
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -060034
Davide Pesavento65ee9922022-11-16 00:21:43 -050035#include <ndn-cxx/ims/in-memory-storage-fifo.hpp>
36#include <ndn-cxx/ims/in-memory-storage-persistent.hpp>
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -060037#include <ndn-cxx/security/key-chain.hpp>
Davide Pesavento65ee9922022-11-16 00:21:43 -050038#include <ndn-cxx/util/segmenter.hpp>
39#include <ndn-cxx/util/segment-fetcher.hpp>
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -060040#include <ndn-cxx/util/signal.hpp>
41#include <ndn-cxx/util/time.hpp>
Ashlesh Gawande744e4812018-08-22 16:26:24 -050042
Ashlesh Gawande57a87172020-05-09 19:47:06 -070043#include <boost/multi_index_container.hpp>
Ashlesh Gawande57a87172020-05-09 19:47:06 -070044#include <boost/multi_index/composite_key.hpp>
Davide Pesavento65ee9922022-11-16 00:21:43 -050045#include <boost/multi_index/hashed_index.hpp>
Ashlesh Gawande939b6f82018-12-09 16:51:09 -060046
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
Davide Pesavento65ee9922022-11-16 00:21:43 -050064 ~Lsdb();
Ashlesh Gawande744e4812018-08-22 16:26:24 -050065
Ashlesh Gawande57a87172020-05-09 19:47:06 -070066 /*! \brief Returns whether the LSDB contains some LSA.
67 */
akmhoque53353462014-04-22 08:43:45 -050068 bool
Ashlesh Gawande57a87172020-05-09 19:47:06 -070069 doesLsaExist(const ndn::Name& router, Lsa::Type lsaType)
70 {
71 return m_lsdb.get<byName>().find(std::make_tuple(router, lsaType)) != m_lsdb.end();
72 }
Nick G97e34942016-07-11 14:46:27 -050073
74 /*! \brief Builds a name LSA for this router and then installs it
75 into the LSDB.
76 */
Ashlesh Gawande57a87172020-05-09 19:47:06 -070077 void
akmhoque31d1d4b2014-05-05 22:08:14 -050078 buildAndInstallOwnNameLsa();
akmhoque53353462014-04-22 08:43:45 -050079
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070080PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Nick G97e34942016-07-11 14:46:27 -050081 /*! \brief Builds a cor. LSA for this router and installs it into the LSDB. */
akmhoque53353462014-04-22 08:43:45 -050082 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -070083 buildAndInstallOwnCoordinateLsa();
Nick G97e34942016-07-11 14:46:27 -050084
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -070085public:
Nick G97e34942016-07-11 14:46:27 -050086 /*! \brief Schedules a build of this router's LSA. */
akmhoque53353462014-04-22 08:43:45 -050087 void
Vince Lehman50df6b72015-03-03 12:06:40 -060088 scheduleAdjLsaBuild();
akmhoque53353462014-04-22 08:43:45 -050089
akmhoque53353462014-04-22 08:43:45 -050090 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -070091 writeLog() const;
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050092
Ashlesh Gawande939b6f82018-12-09 16:51:09 -060093 /* \brief Process interest which can be either:
94 * 1) Discovery interest from segment fetcher:
95 * /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>
96 * 2) Interest containing segment number:
97 * /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>/<version>/<segmentNo>
98 */
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050099 void
100 processInterest(const ndn::Name& name, const ndn::Interest& interest);
101
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600102 bool
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700103 getIsBuildAdjLsaScheduled() const
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600104 {
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700105 return m_isBuildAdjLsaScheduled;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600106 }
107
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500108 SyncLogicHandler&
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700109 getSync()
110 {
Ashlesh Gawande08bce9c2019-04-05 11:08:07 -0500111 return m_sync;
112 }
113
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700114 template<typename T>
115 std::shared_ptr<T>
116 findLsa(const ndn::Name& router) const
117 {
118 return std::static_pointer_cast<T>(findLsa(router, T::type()));
119 }
120
121 struct name_hash {
122 int
123 operator()(const ndn::Name& name) const {
124 return std::hash<ndn::Name>{}(name);
125 }
126 };
127
128 struct enum_class_hash {
129 template<typename T>
130 int
131 operator()(T t) const {
132 return static_cast<int>(t);
133 }
134 };
135
136 struct byName{};
137 struct byType{};
138
139 using LsaContainer = boost::multi_index_container<
140 std::shared_ptr<Lsa>,
141 bmi::indexed_by<
142 bmi::hashed_unique<
143 bmi::tag<byName>,
144 bmi::composite_key<
145 Lsa,
146 bmi::const_mem_fun<Lsa, ndn::Name, &Lsa::getOriginRouterCopy>,
147 bmi::const_mem_fun<Lsa, Lsa::Type, &Lsa::getType>
148 >,
149 bmi::composite_key_hash<name_hash, enum_class_hash>
150 >,
151 bmi::hashed_non_unique<
152 bmi::tag<byType>,
153 bmi::const_mem_fun<Lsa, Lsa::Type, &Lsa::getType>,
154 enum_class_hash
155 >
156 >
157 >;
158
159 template<typename T>
160 std::pair<LsaContainer::index<Lsdb::byType>::type::iterator,
161 LsaContainer::index<Lsdb::byType>::type::iterator>
162 getLsdbIterator() const
163 {
164 return m_lsdb.get<byType>().equal_range(T::type());
165 }
166
167PUBLIC_WITH_TESTS_ELSE_PRIVATE:
168 std::shared_ptr<Lsa>
169 findLsa(const ndn::Name& router, Lsa::Type lsaType) const
170 {
171 auto it = m_lsdb.get<byName>().find(std::make_tuple(router, lsaType));
172 return it != m_lsdb.end() ? *it : nullptr;
173 }
174
175 void
Davide Pesavento1954a0c2022-09-30 15:56:04 -0400176 incrementDataSentStats(Lsa::Type lsaType)
177 {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700178 if (lsaType == Lsa::Type::NAME) {
179 lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_DATA);
180 }
181 else if (lsaType == Lsa::Type::ADJACENCY) {
182 lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_DATA);
183 }
184 else if (lsaType == Lsa::Type::COORDINATE) {
185 lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_DATA);
186 }
187 }
188
189 void
Davide Pesavento1954a0c2022-09-30 15:56:04 -0400190 incrementInterestRcvdStats(Lsa::Type lsaType)
191 {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700192 if (lsaType == Lsa::Type::NAME) {
193 lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_INTEREST);
194 }
195 else if (lsaType == Lsa::Type::ADJACENCY) {
196 lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_INTEREST);
197 }
198 else if (lsaType == Lsa::Type::COORDINATE) {
199 lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_INTEREST);
200 }
201 }
202
203 void
Davide Pesavento1954a0c2022-09-30 15:56:04 -0400204 incrementInterestSentStats(Lsa::Type lsaType)
205 {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700206 if (lsaType == Lsa::Type::NAME) {
207 lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_INTEREST);
208 }
209 else if (lsaType == Lsa::Type::ADJACENCY) {
210 lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_INTEREST);
211 }
212 else if (lsaType == Lsa::Type::COORDINATE) {
213 lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_INTEREST);
214 }
215 }
216
217 /*! Returns whether a seq. no. from a certain router signals a new LSA.
218 \param originRouter The name of the originating router.
219 \param lsaType The type of the LSA.
220 \param seqNo The sequence number to check.
Nick G97e34942016-07-11 14:46:27 -0500221 */
akmhoque53353462014-04-22 08:43:45 -0500222 bool
Davide Pesavento1954a0c2022-09-30 15:56:04 -0400223 isLsaNew(const ndn::Name& originRouter, const Lsa::Type& lsaType, uint64_t lsSeqNo) const
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700224 {
225 // Is the name in the LSDB and the supplied seq no is the highest so far
226 auto lsaPtr = findLsa(originRouter, lsaType);
227 return lsaPtr ? lsaPtr->getSeqNo() < lsSeqNo : true;
228 }
akmhoque53353462014-04-22 08:43:45 -0500229
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700230 void
Davide Pesaventod90338d2021-01-07 17:50:05 -0500231 installLsa(std::shared_ptr<Lsa> lsa);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700232
233 /*! \brief Remove a name LSA from the LSDB.
234 \param router The name of the router that published the LSA to remove.
235 \param lsaType The type of the LSA.
236
237 This function will remove a name LSA from the LSDB by finding an
238 LSA whose name matches key. This removal also causes the NPT to
239 remove those name prefixes if no more LSAs advertise them.
Nick G97e34942016-07-11 14:46:27 -0500240 */
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700241 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700242 removeLsa(const ndn::Name& router, Lsa::Type lsaType);
akmhoque53353462014-04-22 08:43:45 -0500243
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700244 void
245 removeLsa(const LsaContainer::index<Lsdb::byName>::type::iterator& lsaIt);
246
Nick G97e34942016-07-11 14:46:27 -0500247 /*! \brief Attempts to construct an adj. LSA.
248
249 This function will attempt to construct an adjacency LSA. An LSA
250 can only be built when the status of all of the router's neighbors
251 is known. That is, when we are not currently trying to contact any
252 neighbor.
253 */
Vince Lehman50df6b72015-03-03 12:06:40 -0600254 void
255 buildAdjLsa();
256
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700257 /*! \brief Wrapper event to build and install an adj. LSA for this router. */
258 void
259 buildAndInstallOwnAdjLsa();
akmhoque53353462014-04-22 08:43:45 -0500260
Nick G97e34942016-07-11 14:46:27 -0500261 /*! \brief Schedules a refresh/expire event in the scheduler.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700262 \param lsa The LSA.
Nick G97e34942016-07-11 14:46:27 -0500263 \param expTime How many seconds to wait before triggering the event.
264 */
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400265 ndn::scheduler::EventId
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700266 scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime);
akmhoque53353462014-04-22 08:43:45 -0500267
Nick G97e34942016-07-11 14:46:27 -0500268 /*! \brief Either allow to expire, or refresh a name LSA.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700269 \param lsa The LSA.
Nick G97e34942016-07-11 14:46:27 -0500270 */
akmhoque53353462014-04-22 08:43:45 -0500271 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700272 expireOrRefreshLsa(std::shared_ptr<Lsa> lsa);
akmhoque53353462014-04-22 08:43:45 -0500273
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700274 bool
275 processInterestForLsa(const ndn::Interest& interest, const ndn::Name& originRouter,
276 Lsa::Type lsaType, uint64_t seqNo);
akmhoque53353462014-04-22 08:43:45 -0500277
278 void
Alexander Afanasyev135288c2022-04-23 23:06:56 -0400279 expressInterest(const ndn::Name& interestName, uint32_t timeoutCount, uint64_t incomingFaceId,
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400280 ndn::time::steady_clock::time_point deadline = DEFAULT_LSA_RETRIEVAL_DEADLINE);
akmhoque53353462014-04-22 08:43:45 -0500281
Nick G97e34942016-07-11 14:46:27 -0500282 /*!
283 \brief Error callback when SegmentFetcher fails to return an LSA
284
285 In all error cases, a reattempt to fetch the LSA will be made.
286
287 Segment validation can fail either because the packet does not have a
288 valid signature (fatal) or because some of the certificates in the trust chain
289 could not be fetched (non-fatal).
290
291 Currently, the library does not provide clear indication (besides a plain-text message
292 in the error callback) of the reason for the failure nor the segment that failed
293 to be validated, thus we will continue to try to fetch the LSA until the deadline
294 is reached.
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500295 */
akmhoque31d1d4b2014-05-05 22:08:14 -0500296 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700297 onFetchLsaError(uint32_t errorCode, const std::string& msg,
298 const ndn::Name& interestName, uint32_t retransmitNo,
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400299 const ndn::time::steady_clock::time_point& deadline,
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700300 ndn::Name lsaName, uint64_t seqNo);
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500301
Nick G97e34942016-07-11 14:46:27 -0500302 /*!
303 \brief Success callback when SegmentFetcher returns a valid LSA
304
Nick Gordonb50e51b2016-07-22 16:05:57 -0500305 \param interestName The base Interest used to fetch the LSA in the format:
Nick G97e34942016-07-11 14:46:27 -0500306 /<network>/NLSR/LSA/<site>/%C1.Router/<router>/<lsa-type>/<seqNo>
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500307 */
308 void
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800309 afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName);
akmhoque31d1d4b2014-05-05 22:08:14 -0500310
Saurab Dulal427e0122019-11-28 11:58:02 -0600311 void
312 emitSegmentValidatedSignal(const ndn::Data& data)
313 {
314 afterSegmentValidatedSignal(data);
315 }
316
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400317 ndn::time::system_clock::time_point
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700318 getLsaExpirationTimePoint() const
319 {
320 return ndn::time::system_clock::now() + ndn::time::seconds(m_confParam.getRouterDeadInterval());
321 }
akmhoquec7a79b22014-05-26 08:06:19 -0500322
Jiewen Tana0497d82015-02-02 21:59:18 -0800323public:
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700324 ndn::util::Signal<Lsdb, Statistics::PacketType> lsaIncrementSignal;
325 ndn::util::Signal<Lsdb, ndn::Data> afterSegmentValidatedSignal;
326 using AfterLsdbModified = ndn::util::Signal<Lsdb, std::shared_ptr<Lsa>, LsdbUpdate,
327 std::list<ndn::Name>, std::list<ndn::Name>>;
328 AfterLsdbModified onLsdbModified;
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600329
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700330PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600331 ndn::Face& m_face;
332 ndn::Scheduler m_scheduler;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600333 ConfParameter& m_confParam;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600334
Ashlesh Gawande15052402018-12-12 20:20:00 -0600335 SyncLogicHandler m_sync;
Vince Lehman7c603292014-09-11 17:48:16 -0500336
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700337 LsaContainer m_lsdb;
akmhoque53353462014-04-22 08:43:45 -0500338
Nick Gordone98480b2017-05-24 11:23:03 -0500339 ndn::time::seconds m_lsaRefreshTime;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700340 ndn::time::seconds m_adjLsaBuildInterval;
341 const ndn::Name& m_thisRouterPrefix;
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500342
343 // Maps the name of an LSA to its highest known sequence number from sync;
344 // Used to stop NLSR from trying to fetch outdated LSAs
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700345 std::map<ndn::Name, uint64_t> m_highestSeqNo;
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500346
347 SequencingManager m_sequencingManager;
Nick Gordon9eac4d92017-08-29 17:31:29 -0500348
349 ndn::util::signal::ScopedConnection m_onNewLsaConnection;
Ashlesh Gawande744e4812018-08-22 16:26:24 -0500350
351 std::set<std::shared_ptr<ndn::util::SegmentFetcher>> m_fetchers;
Davide Pesavento65ee9922022-11-16 00:21:43 -0500352 ndn::util::Segmenter m_segmenter;
353 ndn::InMemoryStorageFifo m_segmentFifo;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600354
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700355 bool m_isBuildAdjLsaScheduled;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600356 int64_t m_adjBuildCount;
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500357 ndn::scheduler::ScopedEventId m_scheduledAdjLsaBuild;
Ashlesh Gawande15052402018-12-12 20:20:00 -0600358
Ashlesh Gawande15052402018-12-12 20:20:00 -0600359 ndn::InMemoryStoragePersistent m_lsaStorage;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700360
Davide Pesaventoc1d0e8e2022-06-15 14:26:02 -0400361 static inline const ndn::time::steady_clock::time_point DEFAULT_LSA_RETRIEVAL_DEADLINE =
362 ndn::time::steady_clock::time_point::min();
akmhoque53353462014-04-22 08:43:45 -0500363};
364
Nick Gordonfad8e252016-08-11 14:21:38 -0500365} // namespace nlsr
akmhoque53353462014-04-22 08:43:45 -0500366
dmcoomes9f936662017-03-02 10:33:09 -0600367#endif // NLSR_LSDB_HPP