blob: e888acf391f38a6e74bf03cfa567459b9d6dc766 [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/*
Davide Pesaventoe28d8752022-03-19 03:55:25 -04003 * Copyright (c) 2014-2022, 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
30namespace nlsr {
31namespace test {
32
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040033class MockNfdMgmtFixture : public IoKeyChainFixture
34{
35public:
36 /** \brief send one WireEncodable in reply to StatusDataset request
37 * \param prefix dataset prefix without version and segment
38 * \param payload payload block
39 * \note payload must fit in one Data
40 * \pre Interest for dataset has been expressed, sendDataset has not been invoked
41 */
42 template<typename T>
43 void
44 sendDataset(const ndn::Name& prefix, const T& payload)
45 {
46 BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T>));
47
48 this->sendDatasetReply(prefix, payload.wireEncode());
49 }
50
51 /** \brief send two WireEncodables in reply to StatusDataset request
52 * \param prefix dataset prefix without version and segment
53 * \param payload1 first vector item
54 * \param payload2 second vector item
55 * \note all payloads must fit in one Data
56 * \pre Interest for dataset has been expressed, sendDataset has not been invoked
57 */
58 template<typename T1, typename T2>
59 void
60 sendDataset(const ndn::Name& prefix, const T1& payload1, const T2& payload2)
61 {
62 BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T1>));
63 BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T2>));
64
65 ndn::encoding::EncodingBuffer buffer;
66 payload2.wireEncode(buffer);
67 payload1.wireEncode(buffer);
68
69 this->sendDatasetReply(prefix, buffer);
70 }
71
72 /** \brief send a payload in reply to StatusDataset request
73 * \param name dataset prefix without version and segment
74 * \param contentArgs passed to Data::setContent
75 */
76 template<typename ...ContentArgs>
77 void
78 sendDatasetReply(ndn::Name name, ContentArgs&&... contentArgs)
79 {
80 name.appendVersion().appendSegment(0);
81
82 // These warnings assist in debugging when nfdc does not receive StatusDataset.
83 // They usually indicate a misspelled prefix or incorrect timing in the test case.
84 if (m_face.sentInterests.empty()) {
85 BOOST_WARN_MESSAGE(false, "no Interest expressed");
86 }
87 else {
88 BOOST_WARN_MESSAGE(m_face.sentInterests.back().getName().isPrefixOf(name),
89 "last Interest " << m_face.sentInterests.back().getName() <<
90 " cannot be satisfied by this Data " << name);
91 }
92
93 auto data = std::make_shared<ndn::Data>(name);
94 data->setFreshnessPeriod(1_s);
95 data->setFinalBlock(name[-1]);
96 data->setContent(std::forward<ContentArgs>(contentArgs)...);
97 signData(*data);
98 m_face.receive(*data);
99 }
100
101public:
102 ndn::util::DummyClientFace m_face{m_io, m_keyChain, {true, true}};
103};
104
Nick Gordond5c1a372016-10-31 13:56:23 -0500105class NlsrFixture : public MockNfdMgmtFixture
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500106{
107public:
108 NlsrFixture()
Saurab Dulal427e0122019-11-28 11:58:02 -0600109 : conf(m_face, m_keyChain)
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600110 , confProcessor(conf)
111 , nlsr(m_face, m_keyChain, conf)
112 , lsdb(nlsr.m_lsdb)
113 , neighbors(conf.getAdjacencyList())
Nick Gordond5c1a372016-10-31 13:56:23 -0500114 , nSuccessCallbacks(0)
115 , nFailureCallbacks(0)
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500116 {
Davide Pesavento8de8a8b2022-05-12 01:26:43 -0400117 m_keyChain.createIdentity(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500118 }
119
120 void
121 receiveHelloData(const ndn::Name& sender, const ndn::Name& receiver)
122 {
123 ndn::Name dataName(sender);
Davide Pesaventoe28d8752022-03-19 03:55:25 -0400124 dataName.append("NLSR")
125 .append("INFO")
126 .append(ndn::tlv::GenericNameComponent, receiver.wireEncode())
127 .appendVersion();
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500128
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500129 ndn::Data data(dataName);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500130 nlsr.m_helloProtocol.onContentValidated(data);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500131 }
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500132
133public:
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600134 ConfParameter conf;
135 DummyConfFileProcessor confProcessor;
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500136 Nlsr nlsr;
137 Lsdb& lsdb;
138 AdjacencyList& neighbors;
Nick Gordond5c1a372016-10-31 13:56:23 -0500139 uint32_t nSuccessCallbacks;
140 uint32_t nFailureCallbacks;
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500141 ndn::util::signal::ScopedConnection connection;
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500142};
143
144BOOST_FIXTURE_TEST_SUITE(TestNlsr, NlsrFixture)
Vince Lehman09131122014-09-09 17:10:11 -0500145
146BOOST_AUTO_TEST_CASE(HyperbolicOn_ZeroCostNeighbors)
147{
Vince Lehman09131122014-09-09 17:10:11 -0500148 // Simulate loading configuration file
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500149 Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"), 25,
Nick Gordon727d4832017-10-13 18:04:25 -0500150 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500151 neighbors.insert(neighborA);
152
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500153 Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"), 10,
Nick Gordon727d4832017-10-13 18:04:25 -0500154 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500155 neighbors.insert(neighborB);
156
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500157 Adjacent neighborC("/ndn/neighborC", ndn::FaceUri("udp4://10.0.0.3"), 17,
Nick Gordon727d4832017-10-13 18:04:25 -0500158 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500159 neighbors.insert(neighborC);
160
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600161 conf.setHyperbolicState(HYPERBOLIC_STATE_ON);
Vince Lehman09131122014-09-09 17:10:11 -0500162
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700163 Nlsr nlsr2(m_face, m_keyChain, conf);
Vince Lehman09131122014-09-09 17:10:11 -0500164
Davide Pesaventod8d6bbc2020-11-24 21:38:44 -0500165 for (const auto& neighbor : neighbors.getAdjList()) {
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700166 BOOST_CHECK_EQUAL(neighbor.getLinkCost(), 0);
Vince Lehman09131122014-09-09 17:10:11 -0500167 }
168}
169
170BOOST_AUTO_TEST_CASE(HyperbolicOff_LinkStateCost)
171{
Vince Lehman09131122014-09-09 17:10:11 -0500172 // Simulate loading configuration file
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500173 Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"), 25,
Nick Gordon727d4832017-10-13 18:04:25 -0500174 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500175 neighbors.insert(neighborA);
176
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500177 Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"), 10,
Nick Gordon727d4832017-10-13 18:04:25 -0500178 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500179 neighbors.insert(neighborB);
180
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500181 Adjacent neighborC("/ndn/neighborC", ndn::FaceUri("udp4://10.0.0.3"), 17,
Nick Gordon727d4832017-10-13 18:04:25 -0500182 Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehman09131122014-09-09 17:10:11 -0500183 neighbors.insert(neighborC);
184
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700185 Nlsr nlsr2(m_face, m_keyChain, conf);
Vince Lehman09131122014-09-09 17:10:11 -0500186
Davide Pesaventod8d6bbc2020-11-24 21:38:44 -0500187 for (const auto& neighbor : neighbors.getAdjList()) {
188 BOOST_CHECK_NE(neighbor.getLinkCost(), 0);
Vince Lehman09131122014-09-09 17:10:11 -0500189 }
190}
191
Vince Lehman7b616582014-10-17 16:25:39 -0500192BOOST_AUTO_TEST_CASE(SetEventIntervals)
193{
Vince Lehman7b616582014-10-17 16:25:39 -0500194 // Simulate loading configuration file
Vince Lehman7b616582014-10-17 16:25:39 -0500195 conf.setAdjLsaBuildInterval(3);
Vince Lehman7b616582014-10-17 16:25:39 -0500196 conf.setRoutingCalcInterval(9);
197
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600198 Nlsr nlsr2(m_face, m_keyChain, conf);
Vince Lehman7b616582014-10-17 16:25:39 -0500199
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600200 const Lsdb& lsdb = nlsr2.m_lsdb;
201 const RoutingTable& rt = nlsr2.m_routingTable;
Vince Lehman7b616582014-10-17 16:25:39 -0500202
Ashlesh Gawande5d93aa52020-06-13 18:57:45 -0700203 BOOST_CHECK_EQUAL(lsdb.m_adjLsaBuildInterval, 3_s);
204 BOOST_CHECK_EQUAL(rt.m_routingCalcInterval, 9_s);
Vince Lehman7b616582014-10-17 16:25:39 -0500205}
206
Nick Gordond5c1a372016-10-31 13:56:23 -0500207BOOST_AUTO_TEST_CASE(FaceCreateEvent)
208{
209 // Setting constants for the unit test
210 const uint32_t faceId = 1;
211 const std::string faceUri = "udp4://10.0.0.1:6363";
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500212
213 Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(faceUri), 10,
Nick Gordon727d4832017-10-13 18:04:25 -0500214 Adjacent::STATUS_INACTIVE, 0, 0);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500215
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800216 BOOST_REQUIRE_EQUAL(conf.getAdjacencyList().insert(neighbor), true);
Nick Gordond5c1a372016-10-31 13:56:23 -0500217
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600218 this->advanceClocks(10_ms);
Nick Gordond5c1a372016-10-31 13:56:23 -0500219
220 // Build, sign, and send the Face Event
221 ndn::nfd::FaceEventNotification event;
222 event.setKind(ndn::nfd::FACE_EVENT_CREATED)
223 .setRemoteUri(faceUri)
224 .setFaceId(faceId);
Eric Newberry04bfe042021-03-26 11:06:05 -0700225 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000226 data->setFreshnessPeriod(1_s);
Nick Gordond5c1a372016-10-31 13:56:23 -0500227 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600228 m_keyChain.sign(*data);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500229 m_face.receive(*data);
Nick Gordond5c1a372016-10-31 13:56:23 -0500230
231 // Move the clocks forward so that the Face processes the event.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600232 this->advanceClocks(10_ms);
Nick Gordond5c1a372016-10-31 13:56:23 -0500233
234 // Need to explicitly provide a FaceUri object, because the
235 // conversion will attempt to create Name objects.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600236 auto iterator = conf.getAdjacencyList().findAdjacent(ndn::FaceUri(faceUri));
237 BOOST_REQUIRE(iterator != conf.getAdjacencyList().end());
Nick Gordond5c1a372016-10-31 13:56:23 -0500238 BOOST_CHECK_EQUAL(iterator->getFaceId(), faceId);
239}
240
241BOOST_AUTO_TEST_CASE(FaceCreateEventNoMatch)
242{
243 // Setting constants for the unit test
244 const uint32_t faceId = 1;
245 const std::string eventUri = "udp4://10.0.0.1:6363";
246 const std::string neighborUri = "udp4://10.0.0.2:6363";
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500247
248 Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(neighborUri), 10,
Nick Gordon727d4832017-10-13 18:04:25 -0500249 Adjacent::STATUS_INACTIVE, 0, 0);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500250
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600251 conf.getAdjacencyList().insert(neighbor);
Nick Gordond5c1a372016-10-31 13:56:23 -0500252
253 // Build, sign, and send the Face Event
254 ndn::nfd::FaceEventNotification event;
255 event.setKind(ndn::nfd::FACE_EVENT_CREATED)
256 .setRemoteUri(eventUri)
257 .setFaceId(faceId);
Eric Newberry04bfe042021-03-26 11:06:05 -0700258 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000259 data->setFreshnessPeriod(1_s);
Nick Gordond5c1a372016-10-31 13:56:23 -0500260 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600261 m_keyChain.sign(*data);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500262 m_face.receive(*data);
Nick Gordond5c1a372016-10-31 13:56:23 -0500263
264 // Move the clocks forward so that the Face processes the event.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600265 this->advanceClocks(10_ms);
Nick Gordond5c1a372016-10-31 13:56:23 -0500266
267 // The Face URIs did not match, so this neighbor should be unconfigured.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600268 auto iterator = conf.getAdjacencyList().findAdjacent(ndn::FaceUri(neighborUri));
269 BOOST_REQUIRE(iterator != conf.getAdjacencyList().end());
Nick Gordond5c1a372016-10-31 13:56:23 -0500270 BOOST_CHECK_EQUAL(iterator->getFaceId(), 0);
271}
272
273BOOST_AUTO_TEST_CASE(FaceCreateEventAlreadyConfigured)
274{
Ashlesh Gawande41878572019-09-29 00:16:02 -0500275 // So if NLSR gets the notification and registers prefixes it
276 // will change the Id to 1 and our tests will fail
277 // Need to disable registrationReply in dummy face and have own registration reply in the future
278 const uint32_t neighborFaceId = 1;
Nick Gordond5c1a372016-10-31 13:56:23 -0500279 const std::string faceUri = "udp4://10.0.0.1:6363";
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500280
281 Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(faceUri), 10,
Ashlesh Gawande41878572019-09-29 00:16:02 -0500282 Adjacent::STATUS_ACTIVE, 0, 0);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600283 conf.getAdjacencyList().insert(neighbor);
Nick Gordond5c1a372016-10-31 13:56:23 -0500284
Ashlesh Gawande41878572019-09-29 00:16:02 -0500285 // Let NLSR start the face monitor
286 this->advanceClocks(10_ms);
287
Nick Gordond5c1a372016-10-31 13:56:23 -0500288 // Build, sign, and send the Face Event
289 ndn::nfd::FaceEventNotification event;
290 event.setKind(ndn::nfd::FACE_EVENT_CREATED)
291 .setRemoteUri(faceUri)
Ashlesh Gawande41878572019-09-29 00:16:02 -0500292 .setFaceId(neighborFaceId); // Does not matter what we set here, dummy face always returns 1
Eric Newberry04bfe042021-03-26 11:06:05 -0700293 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000294 data->setFreshnessPeriod(1_s);
Nick Gordond5c1a372016-10-31 13:56:23 -0500295 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600296 m_keyChain.sign(*data);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500297 m_face.receive(*data);
Nick Gordond5c1a372016-10-31 13:56:23 -0500298
299 // Move the clocks forward so that the Face processes the event.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600300 this->advanceClocks(10_ms);
Nick Gordond5c1a372016-10-31 13:56:23 -0500301
Ashlesh Gawande41878572019-09-29 00:16:02 -0500302 // Check that the neighbor is configured with the face id of 1
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600303 auto iterator = conf.getAdjacencyList().findAdjacent(ndn::FaceUri(faceUri));
304 BOOST_REQUIRE(iterator != conf.getAdjacencyList().end());
Nick Gordond5c1a372016-10-31 13:56:23 -0500305 BOOST_CHECK_EQUAL(iterator->getFaceId(), neighborFaceId);
Ashlesh Gawande41878572019-09-29 00:16:02 -0500306
307 // Resend same event notification again
308 m_face.sentInterests.clear();
Eric Newberry04bfe042021-03-26 11:06:05 -0700309 data->setName(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(1));
Ashlesh Gawande41878572019-09-29 00:16:02 -0500310 m_keyChain.sign(*data);
311 m_face.receive(*data);
312 this->advanceClocks(10_ms);
313
314 for (const auto& interest : m_face.sentInterests) {
315 // Should not re-register prefix since this is the same event notification
316 if (ndn::Name("/localhost/nfd/rib/register").isPrefixOf(interest.getName())) {
317 BOOST_CHECK(false);
318 }
319 }
Nick Gordond5c1a372016-10-31 13:56:23 -0500320}
321
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500322BOOST_AUTO_TEST_CASE(FaceDestroyEvent)
Vince Lehman02e32992015-03-11 12:31:20 -0500323{
Vince Lehman02e32992015-03-11 12:31:20 -0500324 // Add active neighbors
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600325 AdjacencyList& neighbors = conf.getAdjacencyList();
Vince Lehman02e32992015-03-11 12:31:20 -0500326 uint64_t destroyFaceId = 128;
327
328 // Create a neighbor whose Face will be destroyed
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500329 Adjacent failNeighbor("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"),
330 10, Adjacent::STATUS_ACTIVE, 0, destroyFaceId);
Vince Lehman02e32992015-03-11 12:31:20 -0500331 neighbors.insert(failNeighbor);
332
333 // Create an additional neighbor so an adjacency LSA can be built after the face is destroyed
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500334 Adjacent otherNeighbor("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"),
335 10, Adjacent::STATUS_ACTIVE, 0, 256);
Vince Lehman02e32992015-03-11 12:31:20 -0500336 neighbors.insert(otherNeighbor);
337
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500338 // Set HelloInterest lifetime as 10 seconds so that neighbors are not marked INACTIVE
339 // upon timeout before this test ends
340 conf.setInterestResendTime(10);
Vince Lehman02e32992015-03-11 12:31:20 -0500341
342 // Simulate successful HELLO responses
Vince Lehman41b173e2015-05-07 14:13:26 -0500343 lsdb.scheduleAdjLsaBuild();
344
345 // Set up adjacency LSAs
346 // This router
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500347 Adjacent thisRouter(conf.getRouterPrefix(), ndn::FaceUri("udp4://10.0.0.3"),
348 10, Adjacent::STATUS_ACTIVE, 0, 256);
Vince Lehman41b173e2015-05-07 14:13:26 -0500349
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500350 AdjLsa ownAdjLsa(conf.getRouterPrefix(), 10,
351 ndn::time::system_clock::now(), 1, neighbors);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700352 lsdb.installLsa(std::make_shared<AdjLsa>(ownAdjLsa));
Vince Lehman41b173e2015-05-07 14:13:26 -0500353
354 // Router that will fail
355 AdjacencyList failAdjacencies;
356 failAdjacencies.insert(thisRouter);
357
Ashlesh Gawanded02c3882015-12-29 16:02:51 -0600358 AdjLsa failAdjLsa("/ndn/neighborA", 10,
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500359 ndn::time::system_clock::now() + ndn::time::seconds(3600),
360 1, failAdjacencies);
Vince Lehman41b173e2015-05-07 14:13:26 -0500361
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700362 lsdb.installLsa(std::make_shared<AdjLsa>(failAdjLsa));
Vince Lehman41b173e2015-05-07 14:13:26 -0500363
364 // Other router
365 AdjacencyList otherAdjacencies;
366 otherAdjacencies.insert(thisRouter);
367
Ashlesh Gawanded02c3882015-12-29 16:02:51 -0600368 AdjLsa otherAdjLsa("/ndn/neighborB", 10,
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500369 ndn::time::system_clock::now() + ndn::time::seconds(3600),
370 1, otherAdjacencies);
Vince Lehman41b173e2015-05-07 14:13:26 -0500371
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700372 lsdb.installLsa(std::make_shared<AdjLsa>(otherAdjLsa));
Vince Lehman02e32992015-03-11 12:31:20 -0500373
374 // Run the scheduler to build an adjacency LSA
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600375 this->advanceClocks(10_ms);
Vince Lehman02e32992015-03-11 12:31:20 -0500376
377 // Make sure an adjacency LSA was built
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700378 auto lsa = lsdb.findLsa(conf.getRouterPrefix(), Lsa::Type::ADJACENCY);
Vince Lehman02e32992015-03-11 12:31:20 -0500379 BOOST_REQUIRE(lsa != nullptr);
380
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800381 uint32_t lastAdjLsaSeqNo = lsa->getSeqNo();
Ashlesh Gawande15052402018-12-12 20:20:00 -0600382 nlsr.m_lsdb.m_sequencingManager.setAdjLsaSeq(lastAdjLsaSeqNo);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600383
384 this->advanceClocks(1500_ms, 10);
Vince Lehman02e32992015-03-11 12:31:20 -0500385
386 // Make sure the routing table was calculated
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600387 RoutingTableEntry* rtEntry = nlsr.m_routingTable.findRoutingTableEntry(failNeighbor.getName());
Vince Lehman02e32992015-03-11 12:31:20 -0500388 BOOST_REQUIRE(rtEntry != nullptr);
Nick Gordonff9a6272017-10-12 13:38:29 -0500389 BOOST_REQUIRE_EQUAL(rtEntry->getNexthopList().size(), 1);
Vince Lehman02e32992015-03-11 12:31:20 -0500390
391 // Receive FaceEventDestroyed notification
392 ndn::nfd::FaceEventNotification event;
393 event.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
394 .setFaceId(destroyFaceId);
395
Eric Newberry04bfe042021-03-26 11:06:05 -0700396 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000397 data->setFreshnessPeriod(1_s);
Vince Lehman02e32992015-03-11 12:31:20 -0500398 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600399 m_keyChain.sign(*data);
Vince Lehman02e32992015-03-11 12:31:20 -0500400
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500401 m_face.receive(*data);
Vince Lehman02e32992015-03-11 12:31:20 -0500402
403 // Run the scheduler to build an adjacency LSA
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600404 this->advanceClocks(10_ms);
Vince Lehman02e32992015-03-11 12:31:20 -0500405
406 Adjacent updatedNeighbor = neighbors.getAdjacent(failNeighbor.getName());
407
408 BOOST_CHECK_EQUAL(updatedNeighbor.getFaceId(), 0);
409 BOOST_CHECK_EQUAL(updatedNeighbor.getInterestTimedOutNo(),
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600410 conf.getInterestRetryNumber());
Vince Lehman02e32992015-03-11 12:31:20 -0500411 BOOST_CHECK_EQUAL(updatedNeighbor.getStatus(), Adjacent::STATUS_INACTIVE);
alvy46ccaae2015-06-25 14:13:39 -0500412
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700413 lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
alvy46ccaae2015-06-25 14:13:39 -0500414 BOOST_REQUIRE(lsa != nullptr);
415
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800416 BOOST_CHECK_EQUAL(lsa->getSeqNo(), lastAdjLsaSeqNo + 1);
Vince Lehman02e32992015-03-11 12:31:20 -0500417
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600418 this->advanceClocks(15_s, 10);
419
Vince Lehman02e32992015-03-11 12:31:20 -0500420 // Make sure the routing table was recalculated
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600421 rtEntry = nlsr.m_routingTable.findRoutingTableEntry(failNeighbor.getName());
Vince Lehman02e32992015-03-11 12:31:20 -0500422 BOOST_CHECK(rtEntry == nullptr);
423}
424
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500425BOOST_AUTO_TEST_CASE(BuildAdjLsaAfterHelloResponse)
426{
427 // Configure NLSR
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500428 conf.setAdjLsaBuildInterval(1);
429
430 // Add neighbors
431 // Router A
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500432 ndn::Name neighborAName("/ndn/site/%C1.Router/routerA");
433 Adjacent neighborA(neighborAName, ndn::FaceUri("udp4://10.0.0.1"),
434 0, Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500435 neighbors.insert(neighborA);
436
437 // Router B
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500438 ndn::Name neighborBName("/ndn/site/%C1.Router/routerB");
439 Adjacent neighborB(neighborBName, ndn::FaceUri("udp4://10.0.0.1"),
440 0, Adjacent::STATUS_INACTIVE, 0, 0);
441
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500442 neighbors.insert(neighborB);
443
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600444 this->advanceClocks(10_ms);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500445
446 // Receive HELLO response from Router A
447 receiveHelloData(neighborAName, conf.getRouterPrefix());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600448 this->advanceClocks(1_s, 10);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500449
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500450 // Adjacency LSA should be built even though other router is INACTIVE
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700451 auto lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500452 BOOST_REQUIRE(lsa != nullptr);
Nick Gordonff9a6272017-10-12 13:38:29 -0500453 BOOST_CHECK_EQUAL(lsa->getAdl().size(), 1);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500454
455 // Receive HELLO response from Router B
456 receiveHelloData(neighborBName, conf.getRouterPrefix());
457
458 // Both routers become INACTIVE and HELLO Interests have timed out
459 for (Adjacent& adjacency : neighbors.getAdjList()) {
460 adjacency.setStatus(Adjacent::STATUS_INACTIVE);
461 adjacency.setInterestTimedOutNo(HELLO_RETRIES_DEFAULT);
462 }
463
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600464 this->advanceClocks(1_s, 10);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500465
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500466 // Adjacency LSA should have been removed since this router's adjacencies are
467 // INACTIVE and have timed out
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700468 lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500469 BOOST_CHECK(lsa == nullptr);
470
471 // Receive HELLO response from Router A and B
472 receiveHelloData(neighborAName, conf.getRouterPrefix());
473 receiveHelloData(neighborBName, conf.getRouterPrefix());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600474 this->advanceClocks(1_s, 10);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500475
476 // Adjacency LSA should be built
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700477 lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500478 BOOST_REQUIRE(lsa != nullptr);
Nick Gordonff9a6272017-10-12 13:38:29 -0500479 BOOST_CHECK_EQUAL(lsa->getAdl().size(), 2);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500480}
481
Nick Gordond5c1a372016-10-31 13:56:23 -0500482BOOST_AUTO_TEST_CASE(FaceDatasetFetchSuccess)
483{
484 bool hasResult = false;
Nick Gordond5c1a372016-10-31 13:56:23 -0500485
486 nlsr.initializeFaces([&hasResult] (const std::vector<ndn::nfd::FaceStatus>& faces) {
487 hasResult = true;
488 BOOST_CHECK_EQUAL(faces.size(), 2);
489 BOOST_CHECK_EQUAL(faces.front().getFaceId(), 25401);
490 BOOST_CHECK_EQUAL(faces.back().getFaceId(), 25402);
491 },
492 [] (uint32_t code, const std::string& reason) {});
493
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600494 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500495
496 ndn::nfd::FaceStatus payload1;
497 payload1.setFaceId(25401);
498 ndn::nfd::FaceStatus payload2;
499 payload2.setFaceId(25402);
500 this->sendDataset("/localhost/nfd/faces/list", payload1, payload2);
501
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600502 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500503 BOOST_CHECK(hasResult);
504}
505
506BOOST_AUTO_TEST_CASE(FaceDatasetFetchFailure)
507{
Nick Gordond5c1a372016-10-31 13:56:23 -0500508 nlsr.initializeFaces([](const std::vector<ndn::nfd::FaceStatus>& faces) {},
509 [this](uint32_t code, const std::string& reason){
510 this->nFailureCallbacks++;
511 });
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600512 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500513
514 ndn::Name payload;
515 this->sendDataset("/localhost/nfd/faces/list", payload);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600516 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500517
518 BOOST_CHECK_EQUAL(nFailureCallbacks, 1);
519 BOOST_CHECK_EQUAL(nSuccessCallbacks, 0);
520}
521
522BOOST_AUTO_TEST_CASE(FaceDatasetProcess)
523{
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500524 Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://192.168.0.100:6363"),
525 25, Adjacent::STATUS_INACTIVE, 0, 0);
Nick Gordond5c1a372016-10-31 13:56:23 -0500526 neighbors.insert(neighborA);
527
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500528 Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://192.168.0.101:6363"),
529 10, Adjacent::STATUS_INACTIVE, 0, 0);
Nick Gordond5c1a372016-10-31 13:56:23 -0500530 neighbors.insert(neighborB);
531
532 ndn::nfd::FaceStatus payload1;
533 payload1.setFaceId(1)
534 .setRemoteUri("udp4://192.168.0.100:6363");
535 ndn::nfd::FaceStatus payload2;
536 payload2.setFaceId(2)
537 .setRemoteUri("udp4://192.168.0.101:6363");
538 std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload1, payload2};
539
540 nlsr.processFaceDataset(faceStatuses);
Nick Gordond5c1a372016-10-31 13:56:23 -0500541
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600542 AdjacencyList adjList = conf.getAdjacencyList();
Nick Gordond5c1a372016-10-31 13:56:23 -0500543
544 BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), payload1.getFaceId());
545 BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborB").getFaceId(), payload2.getFaceId());
546}
547
548BOOST_AUTO_TEST_CASE(UnconfiguredNeighbor)
549{
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500550 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 -0500551 neighbors.insert(neighborA);
552
553 ndn::nfd::FaceStatus payload;
554 payload.setFaceId(1)
555 .setRemoteUri("udp4://192.168.0.101:6363"); // Note dissimilar Face URI.
556 std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload};
557
558 nlsr.processFaceDataset(faceStatuses);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600559 this->advanceClocks(20_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500560
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600561 AdjacencyList adjList = conf.getAdjacencyList();
Nick Gordond5c1a372016-10-31 13:56:23 -0500562
563 BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), 0);
564}
565
566BOOST_AUTO_TEST_CASE(FaceDatasetPeriodicFetch)
567{
568 int nNameMatches = 0;
569 ndn::Name datasetPrefix("/localhost/nfd/faces/list");
570 ndn::nfd::CommandOptions options;
571 ndn::time::milliseconds defaultTimeout = options.getTimeout();
572
Ashlesh Gawande3909aa12017-07-28 16:01:35 -0500573 int fetchInterval(1);
Nick Gordond5c1a372016-10-31 13:56:23 -0500574 conf.setFaceDatasetFetchInterval(fetchInterval);
575 conf.setFaceDatasetFetchTries(0);
576
Nick Gordond5c1a372016-10-31 13:56:23 -0500577 // Elapse the default timeout time of the interest.
578 this->advanceClocks(defaultTimeout);
579
580 // Check that we have one interest for face list in the sent interests.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600581 for (const auto& interest : m_face.sentInterests) {
Nick Gordond5c1a372016-10-31 13:56:23 -0500582 if (datasetPrefix.isPrefixOf(interest.getName())) {
583 nNameMatches++;
584 }
585 }
586 BOOST_CHECK_EQUAL(nNameMatches, 1);
587
588 // Elapse the clock by the reschedule time (that we set)
Ashlesh Gawande3909aa12017-07-28 16:01:35 -0500589 this->advanceClocks(ndn::time::seconds(fetchInterval));
Nick Gordond5c1a372016-10-31 13:56:23 -0500590 // Elapse the default timeout on the interest.
591 this->advanceClocks(defaultTimeout);
Nick Gordond5c1a372016-10-31 13:56:23 -0500592
593 // Check that we now have two interests
594 nNameMatches = 0;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600595 for (const auto& interest : m_face.sentInterests) {
Nick Gordond5c1a372016-10-31 13:56:23 -0500596 if (datasetPrefix.isPrefixOf(interest.getName())) {
597 nNameMatches++;
598 }
599 }
600 BOOST_CHECK_EQUAL(nNameMatches, 2);
601}
602
Vince Lehman09131122014-09-09 17:10:11 -0500603BOOST_AUTO_TEST_SUITE_END()
604
Nick Gordonfad8e252016-08-11 14:21:38 -0500605} // namespace test
606} // namespace nlsr