blob: 9a5f147818c79e31a491865568758ee22c82ae91 [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 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"
Ashlesh Gawande85998a12017-12-07 22:22:13 -060034#include "route/name-prefix-table.hpp"
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -060035
36#include <ndn-cxx/security/key-chain.hpp>
37#include <ndn-cxx/util/signal.hpp>
38#include <ndn-cxx/util/time.hpp>
Ashlesh Gawande744e4812018-08-22 16:26:24 -050039#include <ndn-cxx/util/segment-fetcher.hpp>
Ashlesh Gawande15052402018-12-12 20:20:00 -060040#include <ndn-cxx/ims/in-memory-storage-persistent.hpp>
Ashlesh Gawande744e4812018-08-22 16:26:24 -050041
Ashlesh Gawande57a87172020-05-09 19:47:06 -070042#include <boost/multi_index_container.hpp>
43#include <boost/multi_index/hashed_index.hpp>
44#include <boost/multi_index/composite_key.hpp>
45
Ashlesh Gawande939b6f82018-12-09 16:51:09 -060046#include <PSync/segment-publisher.hpp>
47
Nick Gordone98480b2017-05-24 11:23:03 -050048namespace nlsr {
Alexander Afanasyev411ee4b2014-08-16 23:17:03 -070049
Ashlesh Gawande57a87172020-05-09 19:47:06 -070050namespace bmi = boost::multi_index;
Ashlesh Gawande57a87172020-05-09 19:47:06 -070051
52static constexpr ndn::time::seconds GRACE_PERIOD = 10_s;
53
akmhoque53353462014-04-22 08:43:45 -050054class Lsdb
55{
56public:
Saurab Dulal427e0122019-11-28 11:58:02 -060057 Lsdb(ndn::Face& face, ndn::KeyChain& keyChain, ConfParameter& confParam,
Ashlesh Gawande85998a12017-12-07 22:22:13 -060058 NamePrefixTable& namePrefixTable, RoutingTable& routingTable);
Ashlesh Gawande3e105a02017-05-16 17:36:56 -050059
Ashlesh Gawande57a87172020-05-09 19:47:06 -070060 ~Lsdb()
61 {
62 for (const auto& sp : m_fetchers) {
63 sp->stop();
64 }
65 }
Ashlesh Gawande744e4812018-08-22 16:26:24 -050066
Ashlesh Gawande57a87172020-05-09 19:47:06 -070067 /*! \brief Returns whether the LSDB contains some LSA.
68 */
akmhoque53353462014-04-22 08:43:45 -050069 bool
Ashlesh Gawande57a87172020-05-09 19:47:06 -070070 doesLsaExist(const ndn::Name& router, Lsa::Type lsaType)
71 {
72 return m_lsdb.get<byName>().find(std::make_tuple(router, lsaType)) != m_lsdb.end();
73 }
Nick G97e34942016-07-11 14:46:27 -050074
75 /*! \brief Builds a name LSA for this router and then installs it
76 into the LSDB.
77 */
Ashlesh Gawande57a87172020-05-09 19:47:06 -070078 void
akmhoque31d1d4b2014-05-05 22:08:14 -050079 buildAndInstallOwnNameLsa();
akmhoque53353462014-04-22 08:43:45 -050080
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
85 /*! \brief Schedules a build of this router's LSA. */
akmhoque53353462014-04-22 08:43:45 -050086 void
Vince Lehman50df6b72015-03-03 12:06:40 -060087 scheduleAdjLsaBuild();
akmhoque53353462014-04-22 08:43:45 -050088
Ashlesh Gawande57a87172020-05-09 19:47:06 -070089 template<typename T>
90 void
91 writeLog() const;
akmhoque53353462014-04-22 08:43:45 -050092
93 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -070094 writeLog() const;
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050095
Ashlesh Gawande939b6f82018-12-09 16:51:09 -060096 /* \brief Process interest which can be either:
97 * 1) Discovery interest from segment fetcher:
98 * /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>
99 * 2) Interest containing segment number:
100 * /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>/<version>/<segmentNo>
101 */
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500102 void
103 processInterest(const ndn::Name& name, const ndn::Interest& interest);
104
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600105 bool
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700106 getIsBuildAdjLsaSheduled() const
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600107 {
108 return m_isBuildAdjLsaSheduled;
109 }
110
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500111 SyncLogicHandler&
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700112 getSync()
113 {
Ashlesh Gawande08bce9c2019-04-05 11:08:07 -0500114 return m_sync;
115 }
116
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700117 template<typename T>
118 std::shared_ptr<T>
119 findLsa(const ndn::Name& router) const
120 {
121 return std::static_pointer_cast<T>(findLsa(router, T::type()));
122 }
123
124 struct name_hash {
125 int
126 operator()(const ndn::Name& name) const {
127 return std::hash<ndn::Name>{}(name);
128 }
129 };
130
131 struct enum_class_hash {
132 template<typename T>
133 int
134 operator()(T t) const {
135 return static_cast<int>(t);
136 }
137 };
138
139 struct byName{};
140 struct byType{};
141
142 using LsaContainer = boost::multi_index_container<
143 std::shared_ptr<Lsa>,
144 bmi::indexed_by<
145 bmi::hashed_unique<
146 bmi::tag<byName>,
147 bmi::composite_key<
148 Lsa,
149 bmi::const_mem_fun<Lsa, ndn::Name, &Lsa::getOriginRouterCopy>,
150 bmi::const_mem_fun<Lsa, Lsa::Type, &Lsa::getType>
151 >,
152 bmi::composite_key_hash<name_hash, enum_class_hash>
153 >,
154 bmi::hashed_non_unique<
155 bmi::tag<byType>,
156 bmi::const_mem_fun<Lsa, Lsa::Type, &Lsa::getType>,
157 enum_class_hash
158 >
159 >
160 >;
161
162 template<typename T>
163 std::pair<LsaContainer::index<Lsdb::byType>::type::iterator,
164 LsaContainer::index<Lsdb::byType>::type::iterator>
165 getLsdbIterator() const
166 {
167 return m_lsdb.get<byType>().equal_range(T::type());
168 }
169
170PUBLIC_WITH_TESTS_ELSE_PRIVATE:
171 std::shared_ptr<Lsa>
172 findLsa(const ndn::Name& router, Lsa::Type lsaType) const
173 {
174 auto it = m_lsdb.get<byName>().find(std::make_tuple(router, lsaType));
175 return it != m_lsdb.end() ? *it : nullptr;
176 }
177
178 void
179 incrementDataSentStats(Lsa::Type lsaType) {
180 if (lsaType == Lsa::Type::NAME) {
181 lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_DATA);
182 }
183 else if (lsaType == Lsa::Type::ADJACENCY) {
184 lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_DATA);
185 }
186 else if (lsaType == Lsa::Type::COORDINATE) {
187 lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_DATA);
188 }
189 }
190
191 void
192 incrementInterestRcvdStats(Lsa::Type lsaType) {
193 if (lsaType == Lsa::Type::NAME) {
194 lsaIncrementSignal(Statistics::PacketType::RCV_NAME_LSA_INTEREST);
195 }
196 else if (lsaType == Lsa::Type::ADJACENCY) {
197 lsaIncrementSignal(Statistics::PacketType::RCV_ADJ_LSA_INTEREST);
198 }
199 else if (lsaType == Lsa::Type::COORDINATE) {
200 lsaIncrementSignal(Statistics::PacketType::RCV_COORD_LSA_INTEREST);
201 }
202 }
203
204 void
205 incrementInterestSentStats(Lsa::Type lsaType) {
206 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
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700223 isLsaNew(const ndn::Name& originRouter, const Lsa::Type& lsaType, uint64_t lsSeqNo)
224 {
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 */
akmhoque53353462014-04-22 08:43:45 -0500241 bool
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700242 removeLsa(const ndn::Name& router, Lsa::Type lsaType);
akmhoque53353462014-04-22 08:43:45 -0500243
Nick G97e34942016-07-11 14:46:27 -0500244 /*! \brief Attempts to construct an adj. LSA.
245
246 This function will attempt to construct an adjacency LSA. An LSA
247 can only be built when the status of all of the router's neighbors
248 is known. That is, when we are not currently trying to contact any
249 neighbor.
250 */
Vince Lehman50df6b72015-03-03 12:06:40 -0600251 void
252 buildAdjLsa();
253
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700254 /*! \brief Wrapper event to build and install an adj. LSA for this router. */
255 void
256 buildAndInstallOwnAdjLsa();
akmhoque53353462014-04-22 08:43:45 -0500257
Nick G97e34942016-07-11 14:46:27 -0500258 /*! \brief Schedules a refresh/expire event in the scheduler.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700259 \param lsa The LSA.
Nick G97e34942016-07-11 14:46:27 -0500260 \param expTime How many seconds to wait before triggering the event.
261 */
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400262 ndn::scheduler::EventId
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700263 scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime)
264 {
265 return m_scheduler.schedule(expTime + GRACE_PERIOD, [this, lsa] { expireOrRefreshLsa(lsa); });
266 }
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
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700279 expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
280 ndn::time::steady_clock::TimePoint 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,
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500299 const ndn::time::steady_clock::TimePoint& 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
Nick Gordone98480b2017-05-24 11:23:03 -0500317 ndn::time::system_clock::TimePoint
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:
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600324 ndn::util::signal::Signal<Lsdb, Statistics::PacketType> lsaIncrementSignal;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600325 ndn::util::signal::Signal<Lsdb, const ndn::Data&> afterSegmentValidatedSignal;
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600326
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700327PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600328 ndn::Face& m_face;
329 ndn::Scheduler m_scheduler;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600330
331 ConfParameter& m_confParam;
332 NamePrefixTable& m_namePrefixTable;
333 RoutingTable& m_routingTable;
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;
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600352 psync::SegmentPublisher m_segmentPublisher;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600353
354 bool m_isBuildAdjLsaSheduled;
355 int64_t m_adjBuildCount;
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500356 ndn::scheduler::ScopedEventId m_scheduledAdjLsaBuild;
Ashlesh Gawande15052402018-12-12 20:20:00 -0600357
Ashlesh Gawande15052402018-12-12 20:20:00 -0600358 ndn::InMemoryStoragePersistent m_lsaStorage;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700359
360 const ndn::Name::Component NAME_COMPONENT = ndn::Name::Component("lsdb");
361 static const ndn::time::steady_clock::TimePoint DEFAULT_LSA_RETRIEVAL_DEADLINE;
akmhoque53353462014-04-22 08:43:45 -0500362};
363
Nick Gordonfad8e252016-08-11 14:21:38 -0500364} // namespace nlsr
akmhoque53353462014-04-22 08:43:45 -0500365
dmcoomes9f936662017-03-02 10:33:09 -0600366#endif // NLSR_LSDB_HPP