blob: d9b435463690fd9982298e841e3f0f666b8faae2 [file] [log] [blame]
Vince Lehman942eb7b2014-10-02 10:09:27 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Ashlesh Gawande7a231c02020-06-12 20:06:44 -07002/*
Davide Pesavento288141a2024-02-13 17:30:35 -05003 * Copyright (c) 2014-2024, The University of Memphis,
Nick Gordonf8b5bcd2016-08-11 15:06:50 -05004 * Regents of the University of California
Vince Lehman942eb7b2014-10-02 10:09:27 -05005 *
6 * This file is part of NLSR (Named-data Link State Routing).
7 * See AUTHORS.md for complete list of NLSR authors and contributors.
8 *
9 * NLSR is free software: you can redistribute it and/or modify it under the terms
10 * of the GNU General Public License as published by the Free Software Foundation,
11 * either version 3 of the License, or (at your option) any later version.
12 *
13 * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Ashlesh Gawande7a231c02020-06-12 20:06:44 -070019 */
Vince Lehman942eb7b2014-10-02 10:09:27 -050020
Nick Gordon5867b522017-09-06 17:41:37 -050021#include "route/fib.hpp"
Vince Lehman942eb7b2014-10-02 10:09:27 -050022#include "adjacency-list.hpp"
23#include "conf-parameter.hpp"
24
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040025#include "tests/boost-test.hpp"
26#include "tests/io-key-chain-fixture.hpp"
Davide Pesaventod1f1df82022-03-12 16:40:37 -050027
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040028#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
Muktadir R Chowdhuryc69da0a2015-12-18 13:24:38 -060029#include <ndn-cxx/util/dummy-client-face.hpp>
30
Davide Pesavento288141a2024-02-13 17:30:35 -050031namespace nlsr::tests {
Vince Lehman942eb7b2014-10-02 10:09:27 -050032
Junxiao Shi6593a432023-08-21 10:50:28 +000033static const ndn::Name router1Name = "/ndn/router1";
34static const ndn::Name router2Name = "/ndn/router2";
35static const ndn::Name router3Name = "/ndn/router3";
36static const ndn::FaceUri router1FaceUri("udp4://10.0.0.1:6363");
37static const ndn::FaceUri router2FaceUri("udp4://10.0.0.2:6363");
38static const ndn::FaceUri router3FaceUri("udp4://10.0.0.3:6363");
39constexpr uint32_t router1FaceId = 1;
40constexpr uint32_t router2FaceId = 2;
41constexpr uint32_t router3FaceId = 3;
42
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040043class FibFixture : public IoKeyChainFixture
Vince Lehman942eb7b2014-10-02 10:09:27 -050044{
45public:
46 FibFixture()
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040047 : adjacencies(conf.getAdjacencyList())
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070048 , fib(face, m_scheduler, adjacencies, conf, m_keyChain)
49 , interests(face.sentInterests)
Vince Lehman942eb7b2014-10-02 10:09:27 -050050 {
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070051 advanceClocks(1_s);
52
Junxiao Shi6593a432023-08-21 10:50:28 +000053 Adjacent neighbor1(router1Name, router1FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050054 adjacencies.insert(neighbor1);
55
Junxiao Shi6593a432023-08-21 10:50:28 +000056 Adjacent neighbor2(router2Name, router2FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050057 adjacencies.insert(neighbor2);
58
Junxiao Shi6593a432023-08-21 10:50:28 +000059 Adjacent neighbor3(router3Name, router3FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050060 adjacencies.insert(neighbor3);
61
62 conf.setMaxFacesPerPrefix(2);
63
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070064 fib.setEntryRefreshTime(1);
65 }
66
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040067 static void
Davide Pesavento69904fc2022-10-14 09:45:34 -040068 extractRibCommandParameters(const ndn::Interest& interest,
69 ndn::Name::Component& verb,
70 ndn::nfd::ControlParameters& params)
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040071 {
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040072 const auto& name = interest.getName();
Davide Pesavento69904fc2022-10-14 09:45:34 -040073 verb = name.at(RIB_COMMAND_PREFIX.size());
74 params.wireDecode(name.at(RIB_COMMAND_PREFIX.size() + 1).blockFromValue());
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040075 }
76
77private:
Davide Pesavento69904fc2022-10-14 09:45:34 -040078 static inline const ndn::Name RIB_COMMAND_PREFIX{"/localhost/nfd/rib"};
79
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040080 ndn::Scheduler m_scheduler{m_io};
81
82public:
Junxiao Shi43f37a02023-08-09 00:09:00 +000083 ndn::DummyClientFace face{m_io, m_keyChain, [] {
84 ndn::DummyClientFace::Options opts;
Junxiao Shi771a0de2023-08-09 00:03:21 +000085 opts.enableRegistrationReply = true;
86 opts.registrationReplyFaceId = 128;
87 return opts;
88 } ()};
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040089 ConfParameter conf{face, m_keyChain};
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070090 AdjacencyList& adjacencies;
91 Fib fib;
Vince Lehman942eb7b2014-10-02 10:09:27 -050092 std::vector<ndn::Interest>& interests;
Vince Lehman942eb7b2014-10-02 10:09:27 -050093};
94
Vince Lehman942eb7b2014-10-02 10:09:27 -050095BOOST_FIXTURE_TEST_SUITE(TestFib, FibFixture)
96
97BOOST_AUTO_TEST_CASE(NextHopsAdd)
98{
99 NextHop hop1(router1FaceUri, 10);
100 NextHop hop2(router2FaceUri, 20);
101
102 NexthopList hops;
103 hops.addNextHop(hop1);
104 hops.addNextHop(hop2);
105
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700106 fib.update("/ndn/name", hops);
107 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500108
109 // Should register faces 1 and 2 for /ndn/name
110 BOOST_REQUIRE_EQUAL(interests.size(), 2);
111
112 ndn::nfd::ControlParameters extractedParameters;
113 ndn::Name::Component verb;
Davide Pesavento288141a2024-02-13 17:30:35 -0500114 auto it = interests.begin();
Vince Lehman942eb7b2014-10-02 10:09:27 -0500115
116 extractRibCommandParameters(*it, verb, extractedParameters);
117
118 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
119 extractedParameters.getFaceId() == router1FaceId &&
120 verb == ndn::Name::Component("register"));
121
122 ++it;
123 extractRibCommandParameters(*it, verb, extractedParameters);
124
125 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
126 extractedParameters.getFaceId() == router2FaceId &&
127 verb == ndn::Name::Component("register"));
128}
129
Vince Lehman942eb7b2014-10-02 10:09:27 -0500130BOOST_AUTO_TEST_CASE(NextHopsNoChange)
131{
132 NextHop hop1(router1FaceUri, 10);
133 NextHop hop2(router2FaceUri, 20);
134
135 NexthopList oldHops;
136 oldHops.addNextHop(hop1);
137 oldHops.addNextHop(hop2);
138
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700139 fib.update("/ndn/name", oldHops);
140 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500141
142 BOOST_REQUIRE_EQUAL(interests.size(), 2);
143 interests.clear();
144
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700145 fib.update("/ndn/name", oldHops);
146 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500147
148 // Should register face 1 and 2 for /ndn/name
149 BOOST_REQUIRE_EQUAL(interests.size(), 2);
150
151 ndn::nfd::ControlParameters extractedParameters;
152 ndn::Name::Component verb;
Davide Pesavento288141a2024-02-13 17:30:35 -0500153 auto it = interests.begin();
Vince Lehman942eb7b2014-10-02 10:09:27 -0500154
155 extractRibCommandParameters(*it, verb, extractedParameters);
156
157 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
158 extractedParameters.getFaceId() == router1FaceId &&
159 verb == ndn::Name::Component("register"));
160
161 ++it;
162 extractRibCommandParameters(*it, verb, extractedParameters);
163
164 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
165 extractedParameters.getFaceId() == router2FaceId &&
166 verb == ndn::Name::Component("register"));
167}
168
169BOOST_AUTO_TEST_CASE(NextHopsRemoveAll)
170{
171 NextHop hop1(router1FaceUri, 10);
172 NextHop hop2(router2FaceUri, 20);
173
174 NexthopList oldHops;
175 oldHops.addNextHop(hop1);
176 oldHops.addNextHop(hop2);
177
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700178 fib.update("/ndn/name", oldHops);
179 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500180
181 BOOST_REQUIRE_EQUAL(interests.size(), 2);
182 interests.clear();
183
184 NexthopList empty;
185
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700186 fib.update("/ndn/name", empty);
187 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500188
189 // Should unregister faces 1 and 2 for /ndn/name
190 BOOST_CHECK_EQUAL(interests.size(), 2);
191
192 ndn::nfd::ControlParameters extractedParameters;
193 ndn::Name::Component verb;
Davide Pesavento288141a2024-02-13 17:30:35 -0500194 auto it = interests.begin();
Vince Lehman942eb7b2014-10-02 10:09:27 -0500195
196 extractRibCommandParameters(*it, verb, extractedParameters);
197
198 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
199 extractedParameters.getFaceId() == router1FaceId &&
200 verb == ndn::Name::Component("unregister"));
201
202 ++it;
203 extractRibCommandParameters(*it, verb, extractedParameters);
204
205 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
206 extractedParameters.getFaceId() == router2FaceId &&
207 verb == ndn::Name::Component("unregister"));
208}
209
210BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixes)
211{
212 NextHop hop1(router1FaceUri, 10);
213 NextHop hop2(router2FaceUri, 20);
214 NextHop hop3(router3FaceUri, 30);
215
216 NexthopList hops;
217 hops.addNextHop(hop1);
218 hops.addNextHop(hop2);
219 hops.addNextHop(hop3);
220
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700221 fib.update("/ndn/name", hops);
222 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500223
224 // Should only register faces 1 and 2 for /ndn/name
225 BOOST_CHECK_EQUAL(interests.size(), 2);
226
227 ndn::nfd::ControlParameters extractedParameters;
228 ndn::Name::Component verb;
Davide Pesavento288141a2024-02-13 17:30:35 -0500229 auto it = interests.begin();
Vince Lehman942eb7b2014-10-02 10:09:27 -0500230
231 extractRibCommandParameters(*it, verb, extractedParameters);
232
233 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
234 extractedParameters.getFaceId() == router1FaceId &&
235 verb == ndn::Name::Component("register"));
236
237 ++it;
238 extractRibCommandParameters(*it, verb, extractedParameters);
239
240 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
241 extractedParameters.getFaceId() == router2FaceId &&
242 verb == ndn::Name::Component("register"));
243}
244
245BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixesAfterRecalculation)
246{
247 NextHop hop1(router1FaceUri, 10);
248 NextHop hop2(router2FaceUri, 20);
249
250 NexthopList hops;
251 hops.addNextHop(hop1);
252 hops.addNextHop(hop2);
253
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700254 fib.update("/ndn/name", hops);
255 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500256
257 // FIB
258 // Name NextHops
259 // /ndn/name (faceId=1, cost=10), (faceId=2, cost=20)
260 BOOST_REQUIRE_EQUAL(interests.size(), 2);
261 interests.clear();
262
263 // Routing table is recalculated; a new more optimal path is found
264 NextHop hop3(router3FaceUri, 5);
265 hops.addNextHop(hop3);
266
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700267 fib.update("/ndn/name", hops);
268 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500269
270 // To maintain a max 2 face requirement, face 3 should be registered and face 2 should be
271 // unregistered. Face 1 will also be re-registered.
272 //
273 // FIB
274 // Name NextHops
275 // /ndn/name (faceId=3, cost=5), (faceId=1, cost=10)
276
277 BOOST_CHECK_EQUAL(interests.size(), 3);
278
279 ndn::nfd::ControlParameters extractedParameters;
280 ndn::Name::Component verb;
Davide Pesavento288141a2024-02-13 17:30:35 -0500281 auto it = interests.begin();
Vince Lehman942eb7b2014-10-02 10:09:27 -0500282
283 extractRibCommandParameters(*it, verb, extractedParameters);
284
285 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700286 extractedParameters.getFaceId() == router1FaceId &&
Vince Lehman942eb7b2014-10-02 10:09:27 -0500287 verb == ndn::Name::Component("register"));
288
289 ++it;
290 extractRibCommandParameters(*it, verb, extractedParameters);
291
292 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700293 extractedParameters.getFaceId() == router3FaceId &&
Vince Lehman942eb7b2014-10-02 10:09:27 -0500294 verb == ndn::Name::Component("register"));
295
296 ++it;
297 extractRibCommandParameters(*it, verb, extractedParameters);
298
299 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
300 extractedParameters.getFaceId() == router2FaceId &&
301 verb == ndn::Name::Component("unregister"));
302}
303
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500304BOOST_FIXTURE_TEST_CASE(ScheduleFibEntryRefresh, FibFixture)
305{
306 ndn::Name name1("/name/1");
Ashlesh Gawande7a231c02020-06-12 20:06:44 -0700307 FibEntry fe;
308 fe.name = name1;
309 int origSeqNo = fe.seqNo;
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700310 fib.m_table.emplace(name1, std::move(fe));
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500311
Davide Pesaventod1f1df82022-03-12 16:40:37 -0500312 fib.scheduleEntryRefresh(fe, [&] (auto& entry) { BOOST_CHECK_EQUAL(origSeqNo + 1, entry.seqNo); });
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500313 this->advanceClocks(ndn::time::milliseconds(10), 1);
Davide Pesaventod1f1df82022-03-12 16:40:37 -0500314
315 // avoid "test case [...] did not check any assertions" message from Boost.Test
316 BOOST_CHECK(true);
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500317}
318
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600319BOOST_AUTO_TEST_CASE(ShouldNotRefreshNeighborRoute) // #4799
320{
321 NextHop hop1;
322 hop1.setConnectingFaceUri(router1FaceUri);
323
324 NexthopList hops;
325 hops.addNextHop(hop1);
326
327 // Simulate update for this neighbor from name prefix table
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700328 fib.update(router1Name, hops);
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600329 this->advanceClocks(ndn::time::seconds(1));
330
331 // Should not send the register interest
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700332 BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
333}
334
335BOOST_AUTO_TEST_CASE(PrefixWithdrawalFibUpdateBug) // #5179
336{
337 fib.setEntryRefreshTime(3600);
338 conf.setMaxFacesPerPrefix(3);
339
340 // Three adjacencies of Neu
341 Adjacent neighbor1("/ndn/memphis/router-memphis",
342 ndn::FaceUri("udp4://10.0.0.9:6363"), 21, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
343 adjacencies.insert(neighbor1);
344
345 Adjacent neighbor2("/ndn/michigan/router-michigan",
346 ndn::FaceUri("udp4://10.0.0.13:6363"), 14, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
347 adjacencies.insert(neighbor2);
348
349 Adjacent neighbor3("/ndn/savi/router-savi",
350 ndn::FaceUri("udp4://10.0.0.26:6363"), 15, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
351 adjacencies.insert(neighbor3);
352
353 // Wustl advertises /test
354 NexthopList nhl1;
Junxiao Shi6593a432023-08-21 10:50:28 +0000355 nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 28));
356 nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 38));
357 nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 44));
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700358 fib.update("/test", nhl1);
359
360 // Memphis advertises /test
361 NexthopList nhl2;
Junxiao Shi6593a432023-08-21 10:50:28 +0000362 nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 21));
363 nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 26));
364 nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 42));
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700365 fib.update("/test", nhl2);
366
367 advanceClocks(10_ms);
368 face.sentInterests.clear();
369 // Memphis withdraws /test
370 // NamePrefixTable calls this saying we need to install the Wu routes
371 // instead of the existing Memphis' cheaper routes
372 fib.update("/test", nhl1);
373
374 advanceClocks(10_ms);
375 int numRegister = 0;
376 // Do not expect any unregisters, just registers which will update the cost in NFD
377 for (const auto& i : face.sentInterests) {
Davide Pesavento8de8a8b2022-05-12 01:26:43 -0400378 if (i.getName().getPrefix(4) == "/localhost/nfd/rib/unregister") {
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700379 BOOST_CHECK(false);
380 }
381 else {
382 ++numRegister;
383 }
384 }
385 BOOST_CHECK_EQUAL(numRegister, 3);
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600386}
387
Vince Lehman942eb7b2014-10-02 10:09:27 -0500388BOOST_AUTO_TEST_SUITE_END()
389
Davide Pesavento288141a2024-02-13 17:30:35 -0500390} // namespace nlsr::tests