blob: ed8ce66f0ad36525bc5d23c9a3d3950f723f735d [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 Shi771a0de2023-08-09 00:03:21 +00003 * Copyright (c) 2014-2023, 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:
Junxiao Shi43f37a02023-08-09 00:09:00 +0000102 ndn::DummyClientFace m_face{m_io, m_keyChain, {true, true}};
Davide Pesavento8de8a8b2022-05-12 01:26:43 -0400103};
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;
Junxiao Shi43f37a02023-08-09 00:09:00 +0000141 ndn::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
Junxiao Shi771a0de2023-08-09 00:03:21 +0000210 const uint32_t faceId = 128;
Nick Gordond5c1a372016-10-31 13:56:23 -0500211 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
Junxiao Shi771a0de2023-08-09 00:03:21 +0000244 const uint32_t faceId = 128;
Nick Gordond5c1a372016-10-31 13:56:23 -0500245 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{
Junxiao Shi771a0de2023-08-09 00:03:21 +0000275 const uint32_t neighborFaceId = 128;
Nick Gordond5c1a372016-10-31 13:56:23 -0500276 const std::string faceUri = "udp4://10.0.0.1:6363";
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500277
278 Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(faceUri), 10,
Ashlesh Gawande41878572019-09-29 00:16:02 -0500279 Adjacent::STATUS_ACTIVE, 0, 0);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600280 conf.getAdjacencyList().insert(neighbor);
Nick Gordond5c1a372016-10-31 13:56:23 -0500281
Ashlesh Gawande41878572019-09-29 00:16:02 -0500282 // Let NLSR start the face monitor
283 this->advanceClocks(10_ms);
284
Nick Gordond5c1a372016-10-31 13:56:23 -0500285 // Build, sign, and send the Face Event
286 ndn::nfd::FaceEventNotification event;
287 event.setKind(ndn::nfd::FACE_EVENT_CREATED)
288 .setRemoteUri(faceUri)
Junxiao Shi771a0de2023-08-09 00:03:21 +0000289 .setFaceId(neighborFaceId);
Eric Newberry04bfe042021-03-26 11:06:05 -0700290 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000291 data->setFreshnessPeriod(1_s);
Nick Gordond5c1a372016-10-31 13:56:23 -0500292 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600293 m_keyChain.sign(*data);
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500294 m_face.receive(*data);
Nick Gordond5c1a372016-10-31 13:56:23 -0500295
296 // Move the clocks forward so that the Face processes the event.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600297 this->advanceClocks(10_ms);
Nick Gordond5c1a372016-10-31 13:56:23 -0500298
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600299 auto iterator = conf.getAdjacencyList().findAdjacent(ndn::FaceUri(faceUri));
300 BOOST_REQUIRE(iterator != conf.getAdjacencyList().end());
Nick Gordond5c1a372016-10-31 13:56:23 -0500301 BOOST_CHECK_EQUAL(iterator->getFaceId(), neighborFaceId);
Ashlesh Gawande41878572019-09-29 00:16:02 -0500302
303 // Resend same event notification again
304 m_face.sentInterests.clear();
Eric Newberry04bfe042021-03-26 11:06:05 -0700305 data->setName(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(1));
Ashlesh Gawande41878572019-09-29 00:16:02 -0500306 m_keyChain.sign(*data);
307 m_face.receive(*data);
308 this->advanceClocks(10_ms);
309
310 for (const auto& interest : m_face.sentInterests) {
311 // Should not re-register prefix since this is the same event notification
312 if (ndn::Name("/localhost/nfd/rib/register").isPrefixOf(interest.getName())) {
313 BOOST_CHECK(false);
314 }
315 }
Nick Gordond5c1a372016-10-31 13:56:23 -0500316}
317
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500318BOOST_AUTO_TEST_CASE(FaceDestroyEvent)
Vince Lehman02e32992015-03-11 12:31:20 -0500319{
Vince Lehman02e32992015-03-11 12:31:20 -0500320 // Add active neighbors
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600321 AdjacencyList& neighbors = conf.getAdjacencyList();
Vince Lehman02e32992015-03-11 12:31:20 -0500322 uint64_t destroyFaceId = 128;
323
324 // Create a neighbor whose Face will be destroyed
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500325 Adjacent failNeighbor("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"),
326 10, Adjacent::STATUS_ACTIVE, 0, destroyFaceId);
Vince Lehman02e32992015-03-11 12:31:20 -0500327 neighbors.insert(failNeighbor);
328
329 // Create an additional neighbor so an adjacency LSA can be built after the face is destroyed
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500330 Adjacent otherNeighbor("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"),
331 10, Adjacent::STATUS_ACTIVE, 0, 256);
Vince Lehman02e32992015-03-11 12:31:20 -0500332 neighbors.insert(otherNeighbor);
333
Ashlesh Gawande6b388fc2019-09-30 10:14:41 -0500334 // Set HelloInterest lifetime as 10 seconds so that neighbors are not marked INACTIVE
335 // upon timeout before this test ends
336 conf.setInterestResendTime(10);
Vince Lehman02e32992015-03-11 12:31:20 -0500337
338 // Simulate successful HELLO responses
Vince Lehman41b173e2015-05-07 14:13:26 -0500339 lsdb.scheduleAdjLsaBuild();
340
341 // Set up adjacency LSAs
342 // This router
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500343 Adjacent thisRouter(conf.getRouterPrefix(), ndn::FaceUri("udp4://10.0.0.3"),
344 10, Adjacent::STATUS_ACTIVE, 0, 256);
Vince Lehman41b173e2015-05-07 14:13:26 -0500345
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500346 AdjLsa ownAdjLsa(conf.getRouterPrefix(), 10,
347 ndn::time::system_clock::now(), 1, neighbors);
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700348 lsdb.installLsa(std::make_shared<AdjLsa>(ownAdjLsa));
Vince Lehman41b173e2015-05-07 14:13:26 -0500349
350 // Router that will fail
351 AdjacencyList failAdjacencies;
352 failAdjacencies.insert(thisRouter);
353
Ashlesh Gawanded02c3882015-12-29 16:02:51 -0600354 AdjLsa failAdjLsa("/ndn/neighborA", 10,
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500355 ndn::time::system_clock::now() + ndn::time::seconds(3600),
356 1, failAdjacencies);
Vince Lehman41b173e2015-05-07 14:13:26 -0500357
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700358 lsdb.installLsa(std::make_shared<AdjLsa>(failAdjLsa));
Vince Lehman41b173e2015-05-07 14:13:26 -0500359
360 // Other router
361 AdjacencyList otherAdjacencies;
362 otherAdjacencies.insert(thisRouter);
363
Ashlesh Gawanded02c3882015-12-29 16:02:51 -0600364 AdjLsa otherAdjLsa("/ndn/neighborB", 10,
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500365 ndn::time::system_clock::now() + ndn::time::seconds(3600),
366 1, otherAdjacencies);
Vince Lehman41b173e2015-05-07 14:13:26 -0500367
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700368 lsdb.installLsa(std::make_shared<AdjLsa>(otherAdjLsa));
Vince Lehman02e32992015-03-11 12:31:20 -0500369
370 // Run the scheduler to build an adjacency LSA
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600371 this->advanceClocks(10_ms);
Vince Lehman02e32992015-03-11 12:31:20 -0500372
373 // Make sure an adjacency LSA was built
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700374 auto lsa = lsdb.findLsa(conf.getRouterPrefix(), Lsa::Type::ADJACENCY);
Vince Lehman02e32992015-03-11 12:31:20 -0500375 BOOST_REQUIRE(lsa != nullptr);
376
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800377 uint32_t lastAdjLsaSeqNo = lsa->getSeqNo();
Ashlesh Gawande15052402018-12-12 20:20:00 -0600378 nlsr.m_lsdb.m_sequencingManager.setAdjLsaSeq(lastAdjLsaSeqNo);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600379
380 this->advanceClocks(1500_ms, 10);
Vince Lehman02e32992015-03-11 12:31:20 -0500381
382 // Make sure the routing table was calculated
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600383 RoutingTableEntry* rtEntry = nlsr.m_routingTable.findRoutingTableEntry(failNeighbor.getName());
Vince Lehman02e32992015-03-11 12:31:20 -0500384 BOOST_REQUIRE(rtEntry != nullptr);
Nick Gordonff9a6272017-10-12 13:38:29 -0500385 BOOST_REQUIRE_EQUAL(rtEntry->getNexthopList().size(), 1);
Vince Lehman02e32992015-03-11 12:31:20 -0500386
387 // Receive FaceEventDestroyed notification
388 ndn::nfd::FaceEventNotification event;
389 event.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
390 .setFaceId(destroyFaceId);
391
Eric Newberry04bfe042021-03-26 11:06:05 -0700392 auto data = std::make_shared<ndn::Data>(ndn::Name("/localhost/nfd/faces/events").appendSequenceNumber(0));
Junxiao Shi0b1b7d92019-05-22 15:37:18 +0000393 data->setFreshnessPeriod(1_s);
Vince Lehman02e32992015-03-11 12:31:20 -0500394 data->setContent(event.wireEncode());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600395 m_keyChain.sign(*data);
Vince Lehman02e32992015-03-11 12:31:20 -0500396
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500397 m_face.receive(*data);
Vince Lehman02e32992015-03-11 12:31:20 -0500398
399 // Run the scheduler to build an adjacency LSA
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600400 this->advanceClocks(10_ms);
Vince Lehman02e32992015-03-11 12:31:20 -0500401
402 Adjacent updatedNeighbor = neighbors.getAdjacent(failNeighbor.getName());
403
404 BOOST_CHECK_EQUAL(updatedNeighbor.getFaceId(), 0);
405 BOOST_CHECK_EQUAL(updatedNeighbor.getInterestTimedOutNo(),
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600406 conf.getInterestRetryNumber());
Vince Lehman02e32992015-03-11 12:31:20 -0500407 BOOST_CHECK_EQUAL(updatedNeighbor.getStatus(), Adjacent::STATUS_INACTIVE);
alvy46ccaae2015-06-25 14:13:39 -0500408
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700409 lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
alvy46ccaae2015-06-25 14:13:39 -0500410 BOOST_REQUIRE(lsa != nullptr);
411
Ashlesh Gawande0db4d4d2020-02-05 20:30:02 -0800412 BOOST_CHECK_EQUAL(lsa->getSeqNo(), lastAdjLsaSeqNo + 1);
Vince Lehman02e32992015-03-11 12:31:20 -0500413
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600414 this->advanceClocks(15_s, 10);
415
Vince Lehman02e32992015-03-11 12:31:20 -0500416 // Make sure the routing table was recalculated
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600417 rtEntry = nlsr.m_routingTable.findRoutingTableEntry(failNeighbor.getName());
Vince Lehman02e32992015-03-11 12:31:20 -0500418 BOOST_CHECK(rtEntry == nullptr);
419}
420
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500421BOOST_AUTO_TEST_CASE(BuildAdjLsaAfterHelloResponse)
422{
423 // Configure NLSR
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500424 conf.setAdjLsaBuildInterval(1);
425
426 // Add neighbors
427 // Router A
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500428 ndn::Name neighborAName("/ndn/site/%C1.Router/routerA");
429 Adjacent neighborA(neighborAName, ndn::FaceUri("udp4://10.0.0.1"),
430 0, Adjacent::STATUS_INACTIVE, 0, 0);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500431 neighbors.insert(neighborA);
432
433 // Router B
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500434 ndn::Name neighborBName("/ndn/site/%C1.Router/routerB");
435 Adjacent neighborB(neighborBName, ndn::FaceUri("udp4://10.0.0.1"),
436 0, Adjacent::STATUS_INACTIVE, 0, 0);
437
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500438 neighbors.insert(neighborB);
439
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600440 this->advanceClocks(10_ms);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500441
442 // Receive HELLO response from Router A
443 receiveHelloData(neighborAName, conf.getRouterPrefix());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600444 this->advanceClocks(1_s, 10);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500445
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500446 // Adjacency LSA should be built even though other router is INACTIVE
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700447 auto lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500448 BOOST_REQUIRE(lsa != nullptr);
Nick Gordonff9a6272017-10-12 13:38:29 -0500449 BOOST_CHECK_EQUAL(lsa->getAdl().size(), 1);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500450
451 // Receive HELLO response from Router B
452 receiveHelloData(neighborBName, conf.getRouterPrefix());
453
454 // Both routers become INACTIVE and HELLO Interests have timed out
455 for (Adjacent& adjacency : neighbors.getAdjList()) {
456 adjacency.setStatus(Adjacent::STATUS_INACTIVE);
457 adjacency.setInterestTimedOutNo(HELLO_RETRIES_DEFAULT);
458 }
459
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600460 this->advanceClocks(1_s, 10);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500461
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500462 // Adjacency LSA should have been removed since this router's adjacencies are
463 // INACTIVE and have timed out
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700464 lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500465 BOOST_CHECK(lsa == nullptr);
466
467 // Receive HELLO response from Router A and B
468 receiveHelloData(neighborAName, conf.getRouterPrefix());
469 receiveHelloData(neighborBName, conf.getRouterPrefix());
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600470 this->advanceClocks(1_s, 10);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500471
472 // Adjacency LSA should be built
Ashlesh Gawande57a87172020-05-09 19:47:06 -0700473 lsa = lsdb.findLsa<AdjLsa>(conf.getRouterPrefix());
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500474 BOOST_REQUIRE(lsa != nullptr);
Nick Gordonff9a6272017-10-12 13:38:29 -0500475 BOOST_CHECK_EQUAL(lsa->getAdl().size(), 2);
Vince Lehmanf7eec4f2015-05-08 19:02:31 -0500476}
477
Nick Gordond5c1a372016-10-31 13:56:23 -0500478BOOST_AUTO_TEST_CASE(FaceDatasetFetchSuccess)
479{
480 bool hasResult = false;
Nick Gordond5c1a372016-10-31 13:56:23 -0500481
482 nlsr.initializeFaces([&hasResult] (const std::vector<ndn::nfd::FaceStatus>& faces) {
483 hasResult = true;
484 BOOST_CHECK_EQUAL(faces.size(), 2);
485 BOOST_CHECK_EQUAL(faces.front().getFaceId(), 25401);
486 BOOST_CHECK_EQUAL(faces.back().getFaceId(), 25402);
487 },
488 [] (uint32_t code, const std::string& reason) {});
489
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600490 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500491
492 ndn::nfd::FaceStatus payload1;
493 payload1.setFaceId(25401);
494 ndn::nfd::FaceStatus payload2;
495 payload2.setFaceId(25402);
496 this->sendDataset("/localhost/nfd/faces/list", payload1, payload2);
497
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600498 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500499 BOOST_CHECK(hasResult);
500}
501
502BOOST_AUTO_TEST_CASE(FaceDatasetFetchFailure)
503{
Nick Gordond5c1a372016-10-31 13:56:23 -0500504 nlsr.initializeFaces([](const std::vector<ndn::nfd::FaceStatus>& faces) {},
505 [this](uint32_t code, const std::string& reason){
506 this->nFailureCallbacks++;
507 });
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600508 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500509
510 ndn::Name payload;
511 this->sendDataset("/localhost/nfd/faces/list", payload);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600512 this->advanceClocks(100_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500513
514 BOOST_CHECK_EQUAL(nFailureCallbacks, 1);
515 BOOST_CHECK_EQUAL(nSuccessCallbacks, 0);
516}
517
518BOOST_AUTO_TEST_CASE(FaceDatasetProcess)
519{
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500520 Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://192.168.0.100:6363"),
521 25, Adjacent::STATUS_INACTIVE, 0, 0);
Nick Gordond5c1a372016-10-31 13:56:23 -0500522 neighbors.insert(neighborA);
523
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500524 Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://192.168.0.101:6363"),
525 10, Adjacent::STATUS_INACTIVE, 0, 0);
Nick Gordond5c1a372016-10-31 13:56:23 -0500526 neighbors.insert(neighborB);
527
528 ndn::nfd::FaceStatus payload1;
529 payload1.setFaceId(1)
530 .setRemoteUri("udp4://192.168.0.100:6363");
531 ndn::nfd::FaceStatus payload2;
532 payload2.setFaceId(2)
533 .setRemoteUri("udp4://192.168.0.101:6363");
534 std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload1, payload2};
535
536 nlsr.processFaceDataset(faceStatuses);
Nick Gordond5c1a372016-10-31 13:56:23 -0500537
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600538 AdjacencyList adjList = conf.getAdjacencyList();
Nick Gordond5c1a372016-10-31 13:56:23 -0500539
540 BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), payload1.getFaceId());
541 BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborB").getFaceId(), payload2.getFaceId());
542}
543
544BOOST_AUTO_TEST_CASE(UnconfiguredNeighbor)
545{
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -0500546 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 -0500547 neighbors.insert(neighborA);
548
549 ndn::nfd::FaceStatus payload;
550 payload.setFaceId(1)
551 .setRemoteUri("udp4://192.168.0.101:6363"); // Note dissimilar Face URI.
552 std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload};
553
554 nlsr.processFaceDataset(faceStatuses);
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600555 this->advanceClocks(20_ms, 5);
Nick Gordond5c1a372016-10-31 13:56:23 -0500556
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600557 AdjacencyList adjList = conf.getAdjacencyList();
Nick Gordond5c1a372016-10-31 13:56:23 -0500558
559 BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), 0);
560}
561
562BOOST_AUTO_TEST_CASE(FaceDatasetPeriodicFetch)
563{
564 int nNameMatches = 0;
565 ndn::Name datasetPrefix("/localhost/nfd/faces/list");
566 ndn::nfd::CommandOptions options;
567 ndn::time::milliseconds defaultTimeout = options.getTimeout();
568
Ashlesh Gawande3909aa12017-07-28 16:01:35 -0500569 int fetchInterval(1);
Nick Gordond5c1a372016-10-31 13:56:23 -0500570 conf.setFaceDatasetFetchInterval(fetchInterval);
571 conf.setFaceDatasetFetchTries(0);
572
Nick Gordond5c1a372016-10-31 13:56:23 -0500573 // Elapse the default timeout time of the interest.
574 this->advanceClocks(defaultTimeout);
575
576 // Check that we have one interest for face list in the sent interests.
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600577 for (const auto& interest : m_face.sentInterests) {
Nick Gordond5c1a372016-10-31 13:56:23 -0500578 if (datasetPrefix.isPrefixOf(interest.getName())) {
579 nNameMatches++;
580 }
581 }
582 BOOST_CHECK_EQUAL(nNameMatches, 1);
583
584 // Elapse the clock by the reschedule time (that we set)
Ashlesh Gawande3909aa12017-07-28 16:01:35 -0500585 this->advanceClocks(ndn::time::seconds(fetchInterval));
Nick Gordond5c1a372016-10-31 13:56:23 -0500586 // Elapse the default timeout on the interest.
587 this->advanceClocks(defaultTimeout);
Nick Gordond5c1a372016-10-31 13:56:23 -0500588
589 // Check that we now have two interests
590 nNameMatches = 0;
Ashlesh Gawande85998a12017-12-07 22:22:13 -0600591 for (const auto& interest : m_face.sentInterests) {
Nick Gordond5c1a372016-10-31 13:56:23 -0500592 if (datasetPrefix.isPrefixOf(interest.getName())) {
593 nNameMatches++;
594 }
595 }
596 BOOST_CHECK_EQUAL(nNameMatches, 2);
597}
598
Vince Lehman09131122014-09-09 17:10:11 -0500599BOOST_AUTO_TEST_SUITE_END()
600
Nick Gordonfad8e252016-08-11 14:21:38 -0500601} // namespace test
602} // namespace nlsr