blob: 82c60ac4df389527f0d3bbbac8d7f0cdcab2b93a [file] [log] [blame]
Vince Lehman09131122014-09-09 17:10:11 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi0b1b7d92019-05-22 15:37:18 +00002/*
Junxiao Shib8752932024-01-07 15:18:46 +00003 * Copyright (c) 2014-2024, The University of Memphis,
Vince Lehmanc2acdcb2015-04-29 11:14:35 -05004 * Regents of the University of California,
5 * Arizona Board of Regents.
Vince Lehman09131122014-09-09 17:10:11 -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/>.
Junxiao Shi0b1b7d92019-05-22 15:37:18 +000020 */
Vince Lehman09131122014-09-09 17:10:11 -050021
Ashlesh Gawande3909aa12017-07-28 16:01:35 -050022#include "nlsr.hpp"
Nick Gordonc0c6bcf2017-08-15 18:11:21 -050023#include "logger.hpp"
Vince Lehman09131122014-09-09 17:10:11 -050024
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040025#include "tests/io-key-chain-fixture.hpp"
26#include "tests/test-common.hpp"
27
Junxiao Shi3e5120c2016-09-10 16:58:34 +000028#include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
Vince Lehman09131122014-09-09 17:10:11 -050029
Davide Pesavento288141a2024-02-13 17:30:35 -050030namespace nlsr::tests {
Vince Lehman09131122014-09-09 17:10:11 -050031
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040032class MockNfdMgmtFixture : public IoKeyChainFixture
33{
34public:
35 /** \brief send one WireEncodable in reply to StatusDataset request
36 * \param prefix dataset prefix without version and segment
37 * \param payload payload block
38 * \note payload must fit in one Data
39 * \pre Interest for dataset has been expressed, sendDataset has not been invoked
40 */
41 template<typename T>
42 void
43 sendDataset(const ndn::Name& prefix, const T& payload)
44 {
45 BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T>));
46
47 this->sendDatasetReply(prefix, payload.wireEncode());
48 }
49
50 /** \brief send two WireEncodables in reply to StatusDataset request
51 * \param prefix dataset prefix without version and segment
52 * \param payload1 first vector item
53 * \param payload2 second vector item
54 * \note all payloads must fit in one Data
55 * \pre Interest for dataset has been expressed, sendDataset has not been invoked
56 */
57 template<typename T1, typename T2>
58 void
59 sendDataset(const ndn::Name& prefix, const T1& payload1, const T2& payload2)
60 {
61 BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T1>));
62 BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T2>));
63
64 ndn::encoding::EncodingBuffer buffer;
65 payload2.wireEncode(buffer);
66 payload1.wireEncode(buffer);
67
68 this->sendDatasetReply(prefix, buffer);
69 }
70
71 /** \brief send a payload in reply to StatusDataset request
72 * \param name dataset prefix without version and segment
73 * \param contentArgs passed to Data::setContent
74 */
75 template<typename ...ContentArgs>
76 void
77 sendDatasetReply(ndn::Name name, ContentArgs&&... contentArgs)
78 {
79 name.appendVersion().appendSegment(0);
80
81 // These warnings assist in debugging when nfdc does not receive StatusDataset.
82 // They usually indicate a misspelled prefix or incorrect timing in the test case.
83 if (m_face.sentInterests.empty()) {
84 BOOST_WARN_MESSAGE(false, "no Interest expressed");
85 }
86 else {
87 BOOST_WARN_MESSAGE(m_face.sentInterests.back().getName().isPrefixOf(name),
88 "last Interest " << m_face.sentInterests.back().getName() <<
89 " cannot be satisfied by this Data " << name);
90 }
91
92 auto data = std::make_shared<ndn::Data>(name);
93 data->setFreshnessPeriod(1_s);
94 data->setFinalBlock(name[-1]);
95 data->setContent(std::forward<ContentArgs>(contentArgs)...);
96 signData(*data);
97 m_face.receive(*data);
98 }
99
100public:
Junxiao Shi43f37a02023-08-09 00:09:00 +0000101 ndn::DummyClientFace m_face{m_io, m_keyChain, {true, true}};
Davide Pesavento8de8a8b2022-05-12 01:26:43 -0400102};
103
Nick Gordond5c1a372016-10-31 13:56:23 -0500104class NlsrFixture : public MockNfdMgmtFixture
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500105{
106public:
107 NlsrFixture()
Saurab Dulal427e0122019-11-28 11:58:02 -0600108 : conf(m_face, m_keyChain)
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600109 , confProcessor(conf)
110 , nlsr(m_face, m_keyChain, conf)
111 , lsdb(nlsr.m_lsdb)
112 , neighbors(conf.getAdjacencyList())
Nick Gordond5c1a372016-10-31 13:56:23 -0500113 , nSuccessCallbacks(0)
114 , nFailureCallbacks(0)
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500115 {
Davide Pesavento8de8a8b2022-05-12 01:26:43 -0400116 m_keyChain.createIdentity(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500117 }
118
119 void
120 receiveHelloData(const ndn::Name& sender, const ndn::Name& receiver)
121 {
122 ndn::Name dataName(sender);
Davide Pesaventoe28d8752022-03-19 03:55:25 -0400123 dataName.append("NLSR")
124 .append("INFO")
125 .append(ndn::tlv::GenericNameComponent, receiver.wireEncode())
126 .appendVersion();
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500127
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500128 ndn::Data data(dataName);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500129 nlsr.m_helloProtocol.onContentValidated(data);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500130 }
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500131
132public:
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600133 ConfParameter conf;
134 DummyConfFileProcessor confProcessor;
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500135 Nlsr nlsr;
136 Lsdb& lsdb;
137 AdjacencyList& neighbors;
Nick Gordond5c1a372016-10-31 13:56:23 -0500138 uint32_t nSuccessCallbacks;
139 uint32_t nFailureCallbacks;
Junxiao Shi43f37a02023-08-09 00:09:00 +0000140 ndn::signal::ScopedConnection connection;
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500141};
142
143BOOST_FIXTURE_TEST_SUITE(TestNlsr, NlsrFixture)
Vince Lehman09131122014-09-09 17:10:11 -0500144
145BOOST_AUTO_TEST_CASE(HyperbolicOn_ZeroCostNeighbors)
146{
Vince Lehman09131122014-09-09 17:10:11 -0500147 // Simulate loading configuration file
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500148 Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"), 25,
Nick Gordon727d4832017-10-13 18:04:25 -0500149 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500150 neighbors.insert(neighborA);
151
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500152 Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"), 10,
Nick Gordon727d4832017-10-13 18:04:25 -0500153 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500154 neighbors.insert(neighborB);
155
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500156 Adjacent neighborC("/ndn/neighborC", ndn::FaceUri("udp4://10.0.0.3"), 17,
Nick Gordon727d4832017-10-13 18:04:25 -0500157 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500158 neighbors.insert(neighborC);
159
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600160 conf.setHyperbolicState(HYPERBOLIC_STATE_ON);
Vince Lehman09131122014-09-09 17:10:11 -0500161
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700162 Nlsr nlsr2(m_face, m_keyChain, conf);
Vince Lehman09131122014-09-09 17:10:11 -0500163
Davide Pesaventod8d6bbc2020-11-24 21:38:44 -0500164 for (const auto& neighbor : neighbors.getAdjList()) {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700165 BOOST_CHECK_EQUAL(neighbor.getLinkCost(), 0);
Vince Lehman09131122014-09-09 17:10:11 -0500166 }
167}
168
169BOOST_AUTO_TEST_CASE(HyperbolicOff_LinkStateCost)
170{
Vince Lehman09131122014-09-09 17:10:11 -0500171 // Simulate loading configuration file
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500172 Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"), 25,
Nick Gordon727d4832017-10-13 18:04:25 -0500173 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500174 neighbors.insert(neighborA);
175
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500176 Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"), 10,
Nick Gordon727d4832017-10-13 18:04:25 -0500177 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500178 neighbors.insert(neighborB);
179
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500180 Adjacent neighborC("/ndn/neighborC", ndn::FaceUri("udp4://10.0.0.3"), 17,
Nick Gordon727d4832017-10-13 18:04:25 -0500181 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500182 neighbors.insert(neighborC);
183
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700184 Nlsr nlsr2(m_face, m_keyChain, conf);
Vince Lehman09131122014-09-09 17:10:11 -0500185
Davide Pesaventod8d6bbc2020-11-24 21:38:44 -0500186 for (const auto& neighbor : neighbors.getAdjList()) {
187 BOOST_CHECK_NE(neighbor.getLinkCost(), 0);
Vince Lehman09131122014-09-09 17:10:11 -0500188 }
189}
190
Vince Lehman7b616582014-10-17 16:25:39 -0500191BOOST_AUTO_TEST_CASE(SetEventIntervals)
192{
Vince Lehman7b616582014-10-17 16:25:39 -0500193 // Simulate loading configuration file
Vince Lehman7b616582014-10-17 16:25:39 -0500194 conf.setAdjLsaBuildInterval(3);
Vince Lehman7b616582014-10-17 16:25:39 -0500195 conf.setRoutingCalcInterval(9);
196
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600197 Nlsr nlsr2(m_face, m_keyChain, conf);
Vince Lehman7b616582014-10-17 16:25:39 -0500198
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600199 const Lsdb& lsdb = nlsr2.m_lsdb;
200 const RoutingTable& rt = nlsr2.m_routingTable;
Vince Lehman7b616582014-10-17 16:25:39 -0500201
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700202 BOOST_CHECK_EQUAL(lsdb.m_adjLsaBuildInterval, 3_s);
203 BOOST_CHECK_EQUAL(rt.m_routingCalcInterval, 9_s);
Vince Lehman7b616582014-10-17 16:25:39 -0500204}
205
Nick Gordond5c1a372016-10-31 13:56:23 -0500206BOOST_AUTO_TEST_CASE(FaceCreateEvent)
207{
208 // Setting constants for the unit test
Junxiao Shi771a0de2023-08-09 00:03:21 +0000209 const uint32_t faceId = 128;
Nick Gordond5c1a372016-10-31 13:56:23 -0500210 const std::string faceUri = "udp4://10.0.0.1:6363";
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500211
212 Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(faceUri), 10,
Nick Gordon727d4832017-10-13 18:04:25 -0500213 Adjacent::STATUS_INACTIVE, 0, 0);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500214
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800215 BOOST_REQUIRE_EQUAL(conf.getAdjacencyList().insert(neighbor), true);
Nick Gordond5c1a372016-10-31 13:56:23 -0500216
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600217 this->advanceClocks(10_ms);
Nick Gordond5c1a372016-10-31 13:56:23 -0500218
219 // Build, sign, and send the Face Event
220 ndn::nfd::FaceEventNotification event;
221 event.setKind(ndn::nfd::FACE_EVENT_CREATED)
222 .setRemoteUri(faceUri)
223 .setFaceId(faceId);
Eric Newberry04bfe042021-03-26 11:06:05 -0700224 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000225 data->setFreshnessPeriod(1_s);
Nick Gordond5c1a372016-10-31 13:56:23 -0500226 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600227 m_keyChain.sign(*data);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500228 m_face.receive(*data);
Nick Gordond5c1a372016-10-31 13:56:23 -0500229
230 // Move the clocks forward so that the Face processes the event.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600231 this->advanceClocks(10_ms);
Nick Gordond5c1a372016-10-31 13:56:23 -0500232
233 // Need to explicitly provide a FaceUri object, because the
234 // conversion will attempt to create Name objects.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600235 auto iterator = conf.getAdjacencyList().findAdjacent(ndn::FaceUri(faceUri));
236 BOOST_REQUIRE(iterator != conf.getAdjacencyList().end());
Nick Gordond5c1a372016-10-31 13:56:23 -0500237 BOOST_CHECK_EQUAL(iterator->getFaceId(), faceId);
238}
239
240BOOST_AUTO_TEST_CASE(FaceCreateEventNoMatch)
241{
242 // Setting constants for the unit test
Junxiao Shi771a0de2023-08-09 00:03:21 +0000243 const uint32_t faceId = 128;
Nick Gordond5c1a372016-10-31 13:56:23 -0500244 const std::string eventUri = "udp4://10.0.0.1:6363";
245 const std::string neighborUri = "udp4://10.0.0.2:6363";
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500246
247 Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(neighborUri), 10,
Nick Gordon727d4832017-10-13 18:04:25 -0500248 Adjacent::STATUS_INACTIVE, 0, 0);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500249
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600250 conf.getAdjacencyList().insert(neighbor);
Nick Gordond5c1a372016-10-31 13:56:23 -0500251
252 // Build, sign, and send the Face Event
253 ndn::nfd::FaceEventNotification event;
254 event.setKind(ndn::nfd::FACE_EVENT_CREATED)
255 .setRemoteUri(eventUri)
256 .setFaceId(faceId);
Eric Newberry04bfe042021-03-26 11:06:05 -0700257 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000258 data->setFreshnessPeriod(1_s);
Nick Gordond5c1a372016-10-31 13:56:23 -0500259 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600260 m_keyChain.sign(*data);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500261 m_face.receive(*data);
Nick Gordond5c1a372016-10-31 13:56:23 -0500262
263 // Move the clocks forward so that the Face processes the event.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600264 this->advanceClocks(10_ms);
Nick Gordond5c1a372016-10-31 13:56:23 -0500265
266 // The Face URIs did not match, so this neighbor should be unconfigured.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600267 auto iterator = conf.getAdjacencyList().findAdjacent(ndn::FaceUri(neighborUri));
268 BOOST_REQUIRE(iterator != conf.getAdjacencyList().end());
Nick Gordond5c1a372016-10-31 13:56:23 -0500269 BOOST_CHECK_EQUAL(iterator->getFaceId(), 0);
270}
271
272BOOST_AUTO_TEST_CASE(FaceCreateEventAlreadyConfigured)
273{
Junxiao Shi771a0de2023-08-09 00:03:21 +0000274 const uint32_t neighborFaceId = 128;
Nick Gordond5c1a372016-10-31 13:56:23 -0500275 const std::string faceUri = "udp4://10.0.0.1:6363";
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500276
277 Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(faceUri), 10,
Ashlesh Gawande41878572019-09-29 00:16:02 -0500278 Adjacent::STATUS_ACTIVE, 0, 0);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600279 conf.getAdjacencyList().insert(neighbor);
Nick Gordond5c1a372016-10-31 13:56:23 -0500280
Ashlesh Gawande41878572019-09-29 00:16:02 -0500281 // Let NLSR start the face monitor
282 this->advanceClocks(10_ms);
283
Nick Gordond5c1a372016-10-31 13:56:23 -0500284 // Build, sign, and send the Face Event
285 ndn::nfd::FaceEventNotification event;
286 event.setKind(ndn::nfd::FACE_EVENT_CREATED)
287 .setRemoteUri(faceUri)
Junxiao Shi771a0de2023-08-09 00:03:21 +0000288 .setFaceId(neighborFaceId);
Eric Newberry04bfe042021-03-26 11:06:05 -0700289 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000290 data->setFreshnessPeriod(1_s);
Nick Gordond5c1a372016-10-31 13:56:23 -0500291 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600292 m_keyChain.sign(*data);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500293 m_face.receive(*data);
Nick Gordond5c1a372016-10-31 13:56:23 -0500294
295 // Move the clocks forward so that the Face processes the event.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600296 this->advanceClocks(10_ms);
Nick Gordond5c1a372016-10-31 13:56:23 -0500297
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600298 auto iterator = conf.getAdjacencyList().findAdjacent(ndn::FaceUri(faceUri));
299 BOOST_REQUIRE(iterator != conf.getAdjacencyList().end());
Nick Gordond5c1a372016-10-31 13:56:23 -0500300 BOOST_CHECK_EQUAL(iterator->getFaceId(), neighborFaceId);
Ashlesh Gawande41878572019-09-29 00:16:02 -0500301
302 // Resend same event notification again
303 m_face.sentInterests.clear();
Eric Newberry04bfe042021-03-26 11:06:05 -0700304 data->setName(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(1));
Ashlesh Gawande41878572019-09-29 00:16:02 -0500305 m_keyChain.sign(*data);
306 m_face.receive(*data);
307 this->advanceClocks(10_ms);
308
309 for (const auto& interest : m_face.sentInterests) {
310 // Should not re-register prefix since this is the same event notification
311 if (ndn::Name("/localhost/nfd/rib/register").isPrefixOf(interest.getName())) {
312 BOOST_CHECK(false);
313 }
314 }
Nick Gordond5c1a372016-10-31 13:56:23 -0500315}
316
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500317BOOST_AUTO_TEST_CASE(FaceDestroyEvent)
Vince Lehman02e32992015-03-11 12:31:20 -0500318{
Vince Lehman02e32992015-03-11 12:31:20 -0500319 // Add active neighbors
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600320 AdjacencyList& neighbors = conf.getAdjacencyList();
Vince Lehman02e32992015-03-11 12:31:20 -0500321 uint64_t destroyFaceId = 128;
322
323 // Create a neighbor whose Face will be destroyed
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500324 Adjacent failNeighbor("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"),
325 10, Adjacent::STATUS_ACTIVE, 0, destroyFaceId);
Vince Lehman02e32992015-03-11 12:31:20 -0500326 neighbors.insert(failNeighbor);
327
328 // Create an additional neighbor so an adjacency LSA can be built after the face is destroyed
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500329 Adjacent otherNeighbor("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"),
330 10, Adjacent::STATUS_ACTIVE, 0, 256);
Vince Lehman02e32992015-03-11 12:31:20 -0500331 neighbors.insert(otherNeighbor);
332
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500333 // Set HelloInterest lifetime as 10 seconds so that neighbors are not marked INACTIVE
334 // upon timeout before this test ends
335 conf.setInterestResendTime(10);
Vince Lehman02e32992015-03-11 12:31:20 -0500336
337 // Simulate successful HELLO responses
Vince Lehman41b173e2015-05-07 14:13:26 -0500338 lsdb.scheduleAdjLsaBuild();
339
340 // Set up adjacency LSAs
341 // This router
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500342 Adjacent thisRouter(conf.getRouterPrefix(), ndn::FaceUri("udp4://10.0.0.3"),
343 10, Adjacent::STATUS_ACTIVE, 0, 256);
Vince Lehman41b173e2015-05-07 14:13:26 -0500344
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500345 AdjLsa ownAdjLsa(conf.getRouterPrefix(), 10,
Junxiao Shib8752932024-01-07 15:18:46 +0000346 ndn::time::system_clock::now(), neighbors);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700347 lsdb.installLsa(std::make_shared<AdjLsa>(ownAdjLsa));
Vince Lehman41b173e2015-05-07 14:13:26 -0500348
349 // Router that will fail
350 AdjacencyList failAdjacencies;
351 failAdjacencies.insert(thisRouter);
352
Ashlesh Gawanded02c3882015-12-29 16:02:51 -0600353 AdjLsa failAdjLsa("/ndn/neighborA", 10,
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500354 ndn::time::system_clock::now() + ndn::time::seconds(3600),
Junxiao Shib8752932024-01-07 15:18:46 +0000355 failAdjacencies);
Vince Lehman41b173e2015-05-07 14:13:26 -0500356
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700357 lsdb.installLsa(std::make_shared<AdjLsa>(failAdjLsa));
Vince Lehman41b173e2015-05-07 14:13:26 -0500358
359 // Other router
360 AdjacencyList otherAdjacencies;
361 otherAdjacencies.insert(thisRouter);
362
Ashlesh Gawanded02c3882015-12-29 16:02:51 -0600363 AdjLsa otherAdjLsa("/ndn/neighborB", 10,
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500364 ndn::time::system_clock::now() + ndn::time::seconds(3600),
Junxiao Shib8752932024-01-07 15:18:46 +0000365 otherAdjacencies);
Vince Lehman41b173e2015-05-07 14:13:26 -0500366
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700367 lsdb.installLsa(std::make_shared<AdjLsa>(otherAdjLsa));
Vince Lehman02e32992015-03-11 12:31:20 -0500368
369 // Run the scheduler to build an adjacency LSA
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600370 this->advanceClocks(10_ms);
Vince Lehman02e32992015-03-11 12:31:20 -0500371
372 // Make sure an adjacency LSA was built
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700373 auto lsa = lsdb.findLsa(conf.getRouterPrefix(), Lsa::Type::ADJACENCY);
Vince Lehman02e32992015-03-11 12:31:20 -0500374 BOOST_REQUIRE(lsa != nullptr);
375
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800376 uint32_t lastAdjLsaSeqNo = lsa->getSeqNo();
Ashlesh Gawande15052402018-12-12 20:20:00 -0600377 nlsr.m_lsdb.m_sequencingManager.setAdjLsaSeq(lastAdjLsaSeqNo);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600378
379 this->advanceClocks(1500_ms, 10);
Vince Lehman02e32992015-03-11 12:31:20 -0500380
381 // Make sure the routing table was calculated
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600382 RoutingTableEntry* rtEntry = nlsr.m_routingTable.findRoutingTableEntry(failNeighbor.getName());
Vince Lehman02e32992015-03-11 12:31:20 -0500383 BOOST_REQUIRE(rtEntry != nullptr);
Nick Gordonff9a6272017-10-12 13:38:29 -0500384 BOOST_REQUIRE_EQUAL(rtEntry->getNexthopList().size(), 1);
Vince Lehman02e32992015-03-11 12:31:20 -0500385
386 // Receive FaceEventDestroyed notification
387 ndn::nfd::FaceEventNotification event;
388 event.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
389 .setFaceId(destroyFaceId);
390
Eric Newberry04bfe042021-03-26 11:06:05 -0700391 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000392 data->setFreshnessPeriod(1_s);
Vince Lehman02e32992015-03-11 12:31:20 -0500393 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600394 m_keyChain.sign(*data);
Vince Lehman02e32992015-03-11 12:31:20 -0500395
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500396 m_face.receive(*data);
Vince Lehman02e32992015-03-11 12:31:20 -0500397
398 // Run the scheduler to build an adjacency LSA
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600399 this->advanceClocks(10_ms);
Vince Lehman02e32992015-03-11 12:31:20 -0500400
401 Adjacent updatedNeighbor = neighbors.getAdjacent(failNeighbor.getName());
402
403 BOOST_CHECK_EQUAL(updatedNeighbor.getFaceId(), 0);
404 BOOST_CHECK_EQUAL(updatedNeighbor.getInterestTimedOutNo(),
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600405 conf.getInterestRetryNumber());
Vince Lehman02e32992015-03-11 12:31:20 -0500406 BOOST_CHECK_EQUAL(updatedNeighbor.getStatus(), Adjacent::STATUS_INACTIVE);
alvy46ccaae2015-06-25 14:13:39 -0500407
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700408 lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
alvy46ccaae2015-06-25 14:13:39 -0500409 BOOST_REQUIRE(lsa != nullptr);
410
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800411 BOOST_CHECK_EQUAL(lsa->getSeqNo(), lastAdjLsaSeqNo + 1);
Vince Lehman02e32992015-03-11 12:31:20 -0500412
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600413 this->advanceClocks(15_s, 10);
414
Vince Lehman02e32992015-03-11 12:31:20 -0500415 // Make sure the routing table was recalculated
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600416 rtEntry = nlsr.m_routingTable.findRoutingTableEntry(failNeighbor.getName());
Vince Lehman02e32992015-03-11 12:31:20 -0500417 BOOST_CHECK(rtEntry == nullptr);
418}
419
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500420BOOST_AUTO_TEST_CASE(BuildAdjLsaAfterHelloResponse)
421{
422 // Configure NLSR
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500423 conf.setAdjLsaBuildInterval(1);
424
425 // Add neighbors
426 // Router A
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500427 ndn::Name neighborAName("/ndn/site/%C1.Router/routerA");
428 Adjacent neighborA(neighborAName, ndn::FaceUri("udp4://10.0.0.1"),
429 0, Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500430 neighbors.insert(neighborA);
431
432 // Router B
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500433 ndn::Name neighborBName("/ndn/site/%C1.Router/routerB");
434 Adjacent neighborB(neighborBName, ndn::FaceUri("udp4://10.0.0.1"),
435 0, Adjacent::STATUS_INACTIVE, 0, 0);
436
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500437 neighbors.insert(neighborB);
438
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600439 this->advanceClocks(10_ms);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500440
441 // Receive HELLO response from Router A
442 receiveHelloData(neighborAName, conf.getRouterPrefix());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600443 this->advanceClocks(1_s, 10);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500444
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500445 // Adjacency LSA should be built even though other router is INACTIVE
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700446 auto lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500447 BOOST_REQUIRE(lsa != nullptr);
Nick Gordonff9a6272017-10-12 13:38:29 -0500448 BOOST_CHECK_EQUAL(lsa->getAdl().size(), 1);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500449
450 // Receive HELLO response from Router B
451 receiveHelloData(neighborBName, conf.getRouterPrefix());
452
453 // Both routers become INACTIVE and HELLO Interests have timed out
454 for (Adjacent& adjacency : neighbors.getAdjList()) {
455 adjacency.setStatus(Adjacent::STATUS_INACTIVE);
456 adjacency.setInterestTimedOutNo(HELLO_RETRIES_DEFAULT);
457 }
458
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600459 this->advanceClocks(1_s, 10);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500460
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500461 // Adjacency LSA should have been removed since this router's adjacencies are
462 // INACTIVE and have timed out
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700463 lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500464 BOOST_CHECK(lsa == nullptr);
465
466 // Receive HELLO response from Router A and B
467 receiveHelloData(neighborAName, conf.getRouterPrefix());
468 receiveHelloData(neighborBName, conf.getRouterPrefix());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600469 this->advanceClocks(1_s, 10);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500470
471 // Adjacency LSA should be built
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700472 lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500473 BOOST_REQUIRE(lsa != nullptr);
Nick Gordonff9a6272017-10-12 13:38:29 -0500474 BOOST_CHECK_EQUAL(lsa->getAdl().size(), 2);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500475}
476
Nick Gordond5c1a372016-10-31 13:56:23 -0500477BOOST_AUTO_TEST_CASE(FaceDatasetFetchSuccess)
478{
479 bool hasResult = false;
Nick Gordond5c1a372016-10-31 13:56:23 -0500480
481 nlsr.initializeFaces([&hasResult] (const std::vector<ndn::nfd::FaceStatus>& faces) {
482 hasResult = true;
483 BOOST_CHECK_EQUAL(faces.size(), 2);
484 BOOST_CHECK_EQUAL(faces.front().getFaceId(), 25401);
485 BOOST_CHECK_EQUAL(faces.back().getFaceId(), 25402);
486 },
487 [] (uint32_t code, const std::string& reason) {});
488
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600489 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500490
491 ndn::nfd::FaceStatus payload1;
492 payload1.setFaceId(25401);
493 ndn::nfd::FaceStatus payload2;
494 payload2.setFaceId(25402);
495 this->sendDataset("/localhost/nfd/faces/list", payload1, payload2);
496
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600497 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500498 BOOST_CHECK(hasResult);
499}
500
501BOOST_AUTO_TEST_CASE(FaceDatasetFetchFailure)
502{
Nick Gordond5c1a372016-10-31 13:56:23 -0500503 nlsr.initializeFaces([](const std::vector<ndn::nfd::FaceStatus>& faces) {},
504 [this](uint32_t code, const std::string& reason){
505 this->nFailureCallbacks++;
506 });
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600507 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500508
509 ndn::Name payload;
510 this->sendDataset("/localhost/nfd/faces/list", payload);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600511 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500512
513 BOOST_CHECK_EQUAL(nFailureCallbacks, 1);
514 BOOST_CHECK_EQUAL(nSuccessCallbacks, 0);
515}
516
517BOOST_AUTO_TEST_CASE(FaceDatasetProcess)
518{
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500519 Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://192.168.0.100:6363"),
520 25, Adjacent::STATUS_INACTIVE, 0, 0);
Nick Gordond5c1a372016-10-31 13:56:23 -0500521 neighbors.insert(neighborA);
522
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500523 Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://192.168.0.101:6363"),
524 10, Adjacent::STATUS_INACTIVE, 0, 0);
Nick Gordond5c1a372016-10-31 13:56:23 -0500525 neighbors.insert(neighborB);
526
527 ndn::nfd::FaceStatus payload1;
528 payload1.setFaceId(1)
529 .setRemoteUri("udp4://192.168.0.100:6363");
530 ndn::nfd::FaceStatus payload2;
531 payload2.setFaceId(2)
532 .setRemoteUri("udp4://192.168.0.101:6363");
533 std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload1, payload2};
534
535 nlsr.processFaceDataset(faceStatuses);
Nick Gordond5c1a372016-10-31 13:56:23 -0500536
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600537 AdjacencyList adjList = conf.getAdjacencyList();
Nick Gordond5c1a372016-10-31 13:56:23 -0500538
539 BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), payload1.getFaceId());
540 BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborB").getFaceId(), payload2.getFaceId());
541}
542
543BOOST_AUTO_TEST_CASE(UnconfiguredNeighbor)
544{
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500545 Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://192.168.0.100:6363"), 25, Adjacent::STATUS_INACTIVE, 0, 0);
Nick Gordond5c1a372016-10-31 13:56:23 -0500546 neighbors.insert(neighborA);
547
548 ndn::nfd::FaceStatus payload;
549 payload.setFaceId(1)
550 .setRemoteUri("udp4://192.168.0.101:6363"); // Note dissimilar Face URI.
551 std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload};
552
553 nlsr.processFaceDataset(faceStatuses);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600554 this->advanceClocks(20_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500555
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600556 AdjacencyList adjList = conf.getAdjacencyList();
Nick Gordond5c1a372016-10-31 13:56:23 -0500557
558 BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), 0);
559}
560
561BOOST_AUTO_TEST_CASE(FaceDatasetPeriodicFetch)
562{
563 int nNameMatches = 0;
564 ndn::Name datasetPrefix("/localhost/nfd/faces/list");
565 ndn::nfd::CommandOptions options;
566 ndn::time::milliseconds defaultTimeout = options.getTimeout();
567
Ashlesh Gawande3909aa12017-07-28 16:01:35 -0500568 int fetchInterval(1);
Nick Gordond5c1a372016-10-31 13:56:23 -0500569 conf.setFaceDatasetFetchInterval(fetchInterval);
570 conf.setFaceDatasetFetchTries(0);
571
Nick Gordond5c1a372016-10-31 13:56:23 -0500572 // Elapse the default timeout time of the interest.
573 this->advanceClocks(defaultTimeout);
574
575 // Check that we have one interest for face list in the sent interests.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600576 for (const auto& interest : m_face.sentInterests) {
Nick Gordond5c1a372016-10-31 13:56:23 -0500577 if (datasetPrefix.isPrefixOf(interest.getName())) {
578 nNameMatches++;
579 }
580 }
581 BOOST_CHECK_EQUAL(nNameMatches, 1);
582
583 // Elapse the clock by the reschedule time (that we set)
Ashlesh Gawande3909aa12017-07-28 16:01:35 -0500584 this->advanceClocks(ndn::time::seconds(fetchInterval));
Nick Gordond5c1a372016-10-31 13:56:23 -0500585 // Elapse the default timeout on the interest.
586 this->advanceClocks(defaultTimeout);
Nick Gordond5c1a372016-10-31 13:56:23 -0500587
588 // Check that we now have two interests
589 nNameMatches = 0;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600590 for (const auto& interest : m_face.sentInterests) {
Nick Gordond5c1a372016-10-31 13:56:23 -0500591 if (datasetPrefix.isPrefixOf(interest.getName())) {
592 nNameMatches++;
593 }
594 }
595 BOOST_CHECK_EQUAL(nNameMatches, 2);
596}
597
Vince Lehman09131122014-09-09 17:10:11 -0500598BOOST_AUTO_TEST_SUITE_END()
599
Davide Pesavento288141a2024-02-13 17:30:35 -0500600} // namespace nlsr::tests