blob: a342284dbd448742aa273fb33a21a2f8752ce780 [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/*
Saurab Dulal427e0122019-11-28 11:58:02 -06003 * Copyright (c) 2014-2020, 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
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -060048#include <utility>
49#include <boost/cstdint.hpp>
akmhoque53353462014-04-22 08:43:45 -050050
Nick Gordone98480b2017-05-24 11:23:03 -050051namespace nlsr {
Alexander Afanasyev411ee4b2014-08-16 23:17:03 -070052
Ashlesh Gawande57a87172020-05-09 19:47:06 -070053namespace bmi = boost::multi_index;
54using namespace ndn::literals::time_literals;
55
56static constexpr ndn::time::seconds GRACE_PERIOD = 10_s;
57
akmhoque53353462014-04-22 08:43:45 -050058class Lsdb
59{
60public:
Saurab Dulal427e0122019-11-28 11:58:02 -060061 Lsdb(ndn::Face& face, ndn::KeyChain& keyChain, ConfParameter& confParam,
Ashlesh Gawande85998a12017-12-07 22:22:13 -060062 NamePrefixTable& namePrefixTable, RoutingTable& routingTable);
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
Nick G97e34942016-07-11 14:46:27 -050085 /*! \brief Builds a cor. LSA for this router and installs it into the LSDB. */
akmhoque53353462014-04-22 08:43:45 -050086 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -070087 buildAndInstallOwnCoordinateLsa();
Nick G97e34942016-07-11 14:46:27 -050088
89 /*! \brief Schedules a build of this router's LSA. */
akmhoque53353462014-04-22 08:43:45 -050090 void
Vince Lehman50df6b72015-03-03 12:06:40 -060091 scheduleAdjLsaBuild();
akmhoque53353462014-04-22 08:43:45 -050092
Ashlesh Gawande57a87172020-05-09 19:47:06 -070093 template<typename T>
94 void
95 writeLog() const;
akmhoque53353462014-04-22 08:43:45 -050096
97 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -070098 writeLog() const;
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -050099
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600100 /* \brief Process interest which can be either:
101 * 1) Discovery interest from segment fetcher:
102 * /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>
103 * 2) Interest containing segment number:
104 * /localhop/<network>/nlsr/LSA/<site>/<router>/<lsaType>/<seqNo>/<version>/<segmentNo>
105 */
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500106 void
107 processInterest(const ndn::Name& name, const ndn::Interest& interest);
108
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600109 bool
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700110 getIsBuildAdjLsaSheduled() const
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600111 {
112 return m_isBuildAdjLsaSheduled;
113 }
114
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500115 SyncLogicHandler&
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700116 getSync()
117 {
Ashlesh Gawande08bce9c2019-04-05 11:08:07 -0500118 return m_sync;
119 }
120
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700121 template<typename T>
122 std::shared_ptr<T>
123 findLsa(const ndn::Name& router) const
124 {
125 return std::static_pointer_cast<T>(findLsa(router, T::type()));
126 }
127
128 struct name_hash {
129 int
130 operator()(const ndn::Name& name) const {
131 return std::hash<ndn::Name>{}(name);
132 }
133 };
134
135 struct enum_class_hash {
136 template<typename T>
137 int
138 operator()(T t) const {
139 return static_cast<int>(t);
140 }
141 };
142
143 struct byName{};
144 struct byType{};
145
146 using LsaContainer = boost::multi_index_container<
147 std::shared_ptr<Lsa>,
148 bmi::indexed_by<
149 bmi::hashed_unique<
150 bmi::tag<byName>,
151 bmi::composite_key<
152 Lsa,
153 bmi::const_mem_fun<Lsa, ndn::Name, &Lsa::getOriginRouterCopy>,
154 bmi::const_mem_fun<Lsa, Lsa::Type, &Lsa::getType>
155 >,
156 bmi::composite_key_hash<name_hash, enum_class_hash>
157 >,
158 bmi::hashed_non_unique<
159 bmi::tag<byType>,
160 bmi::const_mem_fun<Lsa, Lsa::Type, &Lsa::getType>,
161 enum_class_hash
162 >
163 >
164 >;
165
166 template<typename T>
167 std::pair<LsaContainer::index<Lsdb::byType>::type::iterator,
168 LsaContainer::index<Lsdb::byType>::type::iterator>
169 getLsdbIterator() const
170 {
171 return m_lsdb.get<byType>().equal_range(T::type());
172 }
173
174PUBLIC_WITH_TESTS_ELSE_PRIVATE:
175 std::shared_ptr<Lsa>
176 findLsa(const ndn::Name& router, Lsa::Type lsaType) const
177 {
178 auto it = m_lsdb.get<byName>().find(std::make_tuple(router, lsaType));
179 return it != m_lsdb.end() ? *it : nullptr;
180 }
181
182 void
183 incrementDataSentStats(Lsa::Type lsaType) {
184 if (lsaType == Lsa::Type::NAME) {
185 lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_DATA);
186 }
187 else if (lsaType == Lsa::Type::ADJACENCY) {
188 lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_DATA);
189 }
190 else if (lsaType == Lsa::Type::COORDINATE) {
191 lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_DATA);
192 }
193 }
194
195 void
196 incrementInterestRcvdStats(Lsa::Type lsaType) {
197 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
209 incrementInterestSentStats(Lsa::Type lsaType) {
210 if (lsaType == Lsa::Type::NAME) {
211 lsaIncrementSignal(Statistics::PacketType::SENT_NAME_LSA_INTEREST);
212 }
213 else if (lsaType == Lsa::Type::ADJACENCY) {
214 lsaIncrementSignal(Statistics::PacketType::SENT_ADJ_LSA_INTEREST);
215 }
216 else if (lsaType == Lsa::Type::COORDINATE) {
217 lsaIncrementSignal(Statistics::PacketType::SENT_COORD_LSA_INTEREST);
218 }
219 }
220
221 /*! Returns whether a seq. no. from a certain router signals a new LSA.
222 \param originRouter The name of the originating router.
223 \param lsaType The type of the LSA.
224 \param seqNo The sequence number to check.
Nick G97e34942016-07-11 14:46:27 -0500225 */
akmhoque53353462014-04-22 08:43:45 -0500226 bool
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700227 isLsaNew(const ndn::Name& originRouter, const Lsa::Type& lsaType, uint64_t lsSeqNo)
228 {
229 // Is the name in the LSDB and the supplied seq no is the highest so far
230 auto lsaPtr = findLsa(originRouter, lsaType);
231 return lsaPtr ? lsaPtr->getSeqNo() < lsSeqNo : true;
232 }
akmhoque53353462014-04-22 08:43:45 -0500233
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700234 void
235 installLsa(shared_ptr<Lsa> lsa);
236
237 /*! \brief Remove a name LSA from the LSDB.
238 \param router The name of the router that published the LSA to remove.
239 \param lsaType The type of the LSA.
240
241 This function will remove a name LSA from the LSDB by finding an
242 LSA whose name matches key. This removal also causes the NPT to
243 remove those name prefixes if no more LSAs advertise them.
Nick G97e34942016-07-11 14:46:27 -0500244 */
akmhoque53353462014-04-22 08:43:45 -0500245 bool
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700246 removeLsa(const ndn::Name& router, Lsa::Type lsaType);
akmhoque53353462014-04-22 08:43:45 -0500247
Nick G97e34942016-07-11 14:46:27 -0500248 /*! \brief Attempts to construct an adj. LSA.
249
250 This function will attempt to construct an adjacency LSA. An LSA
251 can only be built when the status of all of the router's neighbors
252 is known. That is, when we are not currently trying to contact any
253 neighbor.
254 */
Vince Lehman50df6b72015-03-03 12:06:40 -0600255 void
256 buildAdjLsa();
257
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700258 /*! \brief Wrapper event to build and install an adj. LSA for this router. */
259 void
260 buildAndInstallOwnAdjLsa();
akmhoque53353462014-04-22 08:43:45 -0500261
Nick G97e34942016-07-11 14:46:27 -0500262 /*! \brief Schedules a refresh/expire event in the scheduler.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700263 \param lsa The LSA.
Nick G97e34942016-07-11 14:46:27 -0500264 \param expTime How many seconds to wait before triggering the event.
265 */
Davide Pesaventoaf7a2112019-03-19 14:55:20 -0400266 ndn::scheduler::EventId
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700267 scheduleLsaExpiration(std::shared_ptr<Lsa> lsa, ndn::time::seconds expTime)
268 {
269 return m_scheduler.schedule(expTime + GRACE_PERIOD, [this, lsa] { expireOrRefreshLsa(lsa); });
270 }
akmhoque53353462014-04-22 08:43:45 -0500271
Nick G97e34942016-07-11 14:46:27 -0500272 /*! \brief Either allow to expire, or refresh a name LSA.
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700273 \param lsa The LSA.
Nick G97e34942016-07-11 14:46:27 -0500274 */
akmhoque53353462014-04-22 08:43:45 -0500275 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700276 expireOrRefreshLsa(std::shared_ptr<Lsa> lsa);
akmhoque53353462014-04-22 08:43:45 -0500277
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700278 bool
279 processInterestForLsa(const ndn::Interest& interest, const ndn::Name& originRouter,
280 Lsa::Type lsaType, uint64_t seqNo);
akmhoque53353462014-04-22 08:43:45 -0500281
282 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700283 expressInterest(const ndn::Name& interestName, uint32_t timeoutCount,
284 ndn::time::steady_clock::TimePoint deadline = DEFAULT_LSA_RETRIEVAL_DEADLINE);
akmhoque53353462014-04-22 08:43:45 -0500285
Nick G97e34942016-07-11 14:46:27 -0500286 /*!
287 \brief Error callback when SegmentFetcher fails to return an LSA
288
289 In all error cases, a reattempt to fetch the LSA will be made.
290
291 Segment validation can fail either because the packet does not have a
292 valid signature (fatal) or because some of the certificates in the trust chain
293 could not be fetched (non-fatal).
294
295 Currently, the library does not provide clear indication (besides a plain-text message
296 in the error callback) of the reason for the failure nor the segment that failed
297 to be validated, thus we will continue to try to fetch the LSA until the deadline
298 is reached.
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500299 */
akmhoque31d1d4b2014-05-05 22:08:14 -0500300 void
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700301 onFetchLsaError(uint32_t errorCode, const std::string& msg,
302 const ndn::Name& interestName, uint32_t retransmitNo,
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500303 const ndn::time::steady_clock::TimePoint& deadline,
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700304 ndn::Name lsaName, uint64_t seqNo);
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500305
Nick G97e34942016-07-11 14:46:27 -0500306 /*!
307 \brief Success callback when SegmentFetcher returns a valid LSA
308
Nick Gordonb50e51b2016-07-22 16:05:57 -0500309 \param interestName The base Interest used to fetch the LSA in the format:
Nick G97e34942016-07-11 14:46:27 -0500310 /<network>/NLSR/LSA/<site>/%C1.Router/<router>/<lsa-type>/<seqNo>
Muktadir R Chowdhuryaa3b0852015-08-06 13:08:56 -0500311 */
312 void
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800313 afterFetchLsa(const ndn::ConstBufferPtr& bufferPtr, const ndn::Name& interestName);
akmhoque31d1d4b2014-05-05 22:08:14 -0500314
Saurab Dulal427e0122019-11-28 11:58:02 -0600315 void
316 emitSegmentValidatedSignal(const ndn::Data& data)
317 {
318 afterSegmentValidatedSignal(data);
319 }
320
Nick Gordone98480b2017-05-24 11:23:03 -0500321 ndn::time::system_clock::TimePoint
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700322 getLsaExpirationTimePoint() const
323 {
324 return ndn::time::system_clock::now() + ndn::time::seconds(m_confParam.getRouterDeadInterval());
325 }
akmhoquec7a79b22014-05-26 08:06:19 -0500326
Jiewen Tana0497d82015-02-02 21:59:18 -0800327public:
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600328 ndn::util::signal::Signal<Lsdb, Statistics::PacketType> lsaIncrementSignal;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600329 ndn::util::signal::Signal<Lsdb, const ndn::Data&> afterSegmentValidatedSignal;
Alejandro Gil Torrese0d20482016-03-06 23:56:19 -0600330
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700331PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600332 ndn::Face& m_face;
333 ndn::Scheduler m_scheduler;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600334
335 ConfParameter& m_confParam;
336 NamePrefixTable& m_namePrefixTable;
337 RoutingTable& m_routingTable;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600338
Ashlesh Gawande15052402018-12-12 20:20:00 -0600339 SyncLogicHandler m_sync;
Vince Lehman7c603292014-09-11 17:48:16 -0500340
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700341 LsaContainer m_lsdb;
akmhoque53353462014-04-22 08:43:45 -0500342
Nick Gordone98480b2017-05-24 11:23:03 -0500343 ndn::time::seconds m_lsaRefreshTime;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700344 ndn::time::seconds m_adjLsaBuildInterval;
345 const ndn::Name& m_thisRouterPrefix;
Ashlesh Gawande5bf83172014-09-19 12:38:17 -0500346
347 // Maps the name of an LSA to its highest known sequence number from sync;
348 // Used to stop NLSR from trying to fetch outdated LSAs
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700349 std::map<ndn::Name, uint64_t> m_highestSeqNo;
Ashlesh Gawande3e105a02017-05-16 17:36:56 -0500350
351 SequencingManager m_sequencingManager;
Nick Gordon9eac4d92017-08-29 17:31:29 -0500352
353 ndn::util::signal::ScopedConnection m_onNewLsaConnection;
Ashlesh Gawande744e4812018-08-22 16:26:24 -0500354
355 std::set<std::shared_ptr<ndn::util::SegmentFetcher>> m_fetchers;
Ashlesh Gawande939b6f82018-12-09 16:51:09 -0600356 psync::SegmentPublisher m_segmentPublisher;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600357
358 bool m_isBuildAdjLsaSheduled;
359 int64_t m_adjBuildCount;
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500360 ndn::scheduler::ScopedEventId m_scheduledAdjLsaBuild;
Ashlesh Gawande15052402018-12-12 20:20:00 -0600361
Ashlesh Gawande15052402018-12-12 20:20:00 -0600362 ndn::InMemoryStoragePersistent m_lsaStorage;
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700363
364 const ndn::Name::Component NAME_COMPONENT = ndn::Name::Component("lsdb");
365 static const ndn::time::steady_clock::TimePoint DEFAULT_LSA_RETRIEVAL_DEADLINE;
akmhoque53353462014-04-22 08:43:45 -0500366};
367
Nick Gordonfad8e252016-08-11 14:21:38 -0500368} // namespace nlsr
akmhoque53353462014-04-22 08:43:45 -0500369
dmcoomes9f936662017-03-02 10:33:09 -0600370#endif // NLSR_LSDB_HPP