blob: 932b63a80be0a534311b1b3a17d8944ac1c5a5d5 [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/*
Junxiao Shi771a0de2023-08-09 00:03:21 +00003 * Copyright (c) 2014-2023, 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
Vince Lehman942eb7b2014-10-02 10:09:27 -050031namespace nlsr {
32namespace test {
33
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040034class FibFixture : public IoKeyChainFixture
Vince Lehman942eb7b2014-10-02 10:09:27 -050035{
36public:
37 FibFixture()
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040038 : adjacencies(conf.getAdjacencyList())
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070039 , fib(face, m_scheduler, adjacencies, conf, m_keyChain)
40 , interests(face.sentInterests)
Vince Lehman942eb7b2014-10-02 10:09:27 -050041 {
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070042 advanceClocks(1_s);
43
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050044 Adjacent neighbor1(router1Name, ndn::FaceUri(router1FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050045 adjacencies.insert(neighbor1);
46
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050047 Adjacent neighbor2(router2Name, ndn::FaceUri(router2FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050048 adjacencies.insert(neighbor2);
49
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050050 Adjacent neighbor3(router3Name, ndn::FaceUri(router3FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050051 adjacencies.insert(neighbor3);
52
53 conf.setMaxFacesPerPrefix(2);
54
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070055 fib.setEntryRefreshTime(1);
56 }
57
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040058 static void
Davide Pesavento69904fc2022-10-14 09:45:34 -040059 extractRibCommandParameters(const ndn::Interest& interest,
60 ndn::Name::Component& verb,
61 ndn::nfd::ControlParameters& params)
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040062 {
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040063 const auto& name = interest.getName();
Davide Pesavento69904fc2022-10-14 09:45:34 -040064 verb = name.at(RIB_COMMAND_PREFIX.size());
65 params.wireDecode(name.at(RIB_COMMAND_PREFIX.size() + 1).blockFromValue());
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040066 }
67
68private:
Davide Pesavento69904fc2022-10-14 09:45:34 -040069 static inline const ndn::Name RIB_COMMAND_PREFIX{"/localhost/nfd/rib"};
70
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040071 ndn::Scheduler m_scheduler{m_io};
72
73public:
Junxiao Shi771a0de2023-08-09 00:03:21 +000074 ndn::util::DummyClientFace face{m_io, m_keyChain, [] {
75 ndn::util::DummyClientFace::Options opts;
76 opts.enableRegistrationReply = true;
77 opts.registrationReplyFaceId = 128;
78 return opts;
79 } ()};
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040080 ConfParameter conf{face, m_keyChain};
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070081 AdjacencyList& adjacencies;
82 Fib fib;
Vince Lehman942eb7b2014-10-02 10:09:27 -050083 std::vector<ndn::Interest>& interests;
84
85 static const ndn::Name router1Name;
86 static const ndn::Name router2Name;
87 static const ndn::Name router3Name;
88
89 static const std::string router1FaceUri;
90 static const std::string router2FaceUri;
91 static const std::string router3FaceUri;
92
93 static const uint32_t router1FaceId;
94 static const uint32_t router2FaceId;
95 static const uint32_t router3FaceId;
96};
97
98const ndn::Name FibFixture::router1Name = "/ndn/router1";
99const ndn::Name FibFixture::router2Name = "/ndn/router2";
100const ndn::Name FibFixture::router3Name = "/ndn/router3";
101
Nick Gordone9733ed2017-04-26 10:48:39 -0500102const std::string FibFixture::router1FaceUri = "udp4://10.0.0.1";
103const std::string FibFixture::router2FaceUri = "udp4://10.0.0.2";
104const std::string FibFixture::router3FaceUri = "udp4://10.0.0.3";
Vince Lehman942eb7b2014-10-02 10:09:27 -0500105
106const uint32_t FibFixture::router1FaceId = 1;
107const uint32_t FibFixture::router2FaceId = 2;
108const uint32_t FibFixture::router3FaceId = 3;
109
110BOOST_FIXTURE_TEST_SUITE(TestFib, FibFixture)
111
112BOOST_AUTO_TEST_CASE(NextHopsAdd)
113{
114 NextHop hop1(router1FaceUri, 10);
115 NextHop hop2(router2FaceUri, 20);
116
117 NexthopList hops;
118 hops.addNextHop(hop1);
119 hops.addNextHop(hop2);
120
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700121 fib.update("/ndn/name", hops);
122 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500123
124 // Should register faces 1 and 2 for /ndn/name
125 BOOST_REQUIRE_EQUAL(interests.size(), 2);
126
127 ndn::nfd::ControlParameters extractedParameters;
128 ndn::Name::Component verb;
129 std::vector<ndn::Interest>::iterator it = interests.begin();
130
131 extractRibCommandParameters(*it, verb, extractedParameters);
132
133 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
134 extractedParameters.getFaceId() == router1FaceId &&
135 verb == ndn::Name::Component("register"));
136
137 ++it;
138 extractRibCommandParameters(*it, verb, extractedParameters);
139
140 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
141 extractedParameters.getFaceId() == router2FaceId &&
142 verb == ndn::Name::Component("register"));
143}
144
Vince Lehman942eb7b2014-10-02 10:09:27 -0500145BOOST_AUTO_TEST_CASE(NextHopsNoChange)
146{
147 NextHop hop1(router1FaceUri, 10);
148 NextHop hop2(router2FaceUri, 20);
149
150 NexthopList oldHops;
151 oldHops.addNextHop(hop1);
152 oldHops.addNextHop(hop2);
153
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700154 fib.update("/ndn/name", oldHops);
155 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500156
157 BOOST_REQUIRE_EQUAL(interests.size(), 2);
158 interests.clear();
159
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700160 fib.update("/ndn/name", oldHops);
161 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500162
163 // Should register face 1 and 2 for /ndn/name
164 BOOST_REQUIRE_EQUAL(interests.size(), 2);
165
166 ndn::nfd::ControlParameters extractedParameters;
167 ndn::Name::Component verb;
168 std::vector<ndn::Interest>::iterator it = interests.begin();
169
170 extractRibCommandParameters(*it, verb, extractedParameters);
171
172 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
173 extractedParameters.getFaceId() == router1FaceId &&
174 verb == ndn::Name::Component("register"));
175
176 ++it;
177 extractRibCommandParameters(*it, verb, extractedParameters);
178
179 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
180 extractedParameters.getFaceId() == router2FaceId &&
181 verb == ndn::Name::Component("register"));
182}
183
184BOOST_AUTO_TEST_CASE(NextHopsRemoveAll)
185{
186 NextHop hop1(router1FaceUri, 10);
187 NextHop hop2(router2FaceUri, 20);
188
189 NexthopList oldHops;
190 oldHops.addNextHop(hop1);
191 oldHops.addNextHop(hop2);
192
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700193 fib.update("/ndn/name", oldHops);
194 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500195
196 BOOST_REQUIRE_EQUAL(interests.size(), 2);
197 interests.clear();
198
199 NexthopList empty;
200
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700201 fib.update("/ndn/name", empty);
202 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500203
204 // Should unregister faces 1 and 2 for /ndn/name
205 BOOST_CHECK_EQUAL(interests.size(), 2);
206
207 ndn::nfd::ControlParameters extractedParameters;
208 ndn::Name::Component verb;
209 std::vector<ndn::Interest>::iterator it = interests.begin();
210
211 extractRibCommandParameters(*it, verb, extractedParameters);
212
213 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
214 extractedParameters.getFaceId() == router1FaceId &&
215 verb == ndn::Name::Component("unregister"));
216
217 ++it;
218 extractRibCommandParameters(*it, verb, extractedParameters);
219
220 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
221 extractedParameters.getFaceId() == router2FaceId &&
222 verb == ndn::Name::Component("unregister"));
223}
224
225BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixes)
226{
227 NextHop hop1(router1FaceUri, 10);
228 NextHop hop2(router2FaceUri, 20);
229 NextHop hop3(router3FaceUri, 30);
230
231 NexthopList hops;
232 hops.addNextHop(hop1);
233 hops.addNextHop(hop2);
234 hops.addNextHop(hop3);
235
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700236 fib.update("/ndn/name", hops);
237 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500238
239 // Should only register faces 1 and 2 for /ndn/name
240 BOOST_CHECK_EQUAL(interests.size(), 2);
241
242 ndn::nfd::ControlParameters extractedParameters;
243 ndn::Name::Component verb;
244 std::vector<ndn::Interest>::iterator it = interests.begin();
245
246 extractRibCommandParameters(*it, verb, extractedParameters);
247
248 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
249 extractedParameters.getFaceId() == router1FaceId &&
250 verb == ndn::Name::Component("register"));
251
252 ++it;
253 extractRibCommandParameters(*it, verb, extractedParameters);
254
255 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
256 extractedParameters.getFaceId() == router2FaceId &&
257 verb == ndn::Name::Component("register"));
258}
259
260BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixesAfterRecalculation)
261{
262 NextHop hop1(router1FaceUri, 10);
263 NextHop hop2(router2FaceUri, 20);
264
265 NexthopList hops;
266 hops.addNextHop(hop1);
267 hops.addNextHop(hop2);
268
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700269 fib.update("/ndn/name", hops);
270 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500271
272 // FIB
273 // Name NextHops
274 // /ndn/name (faceId=1, cost=10), (faceId=2, cost=20)
275 BOOST_REQUIRE_EQUAL(interests.size(), 2);
276 interests.clear();
277
278 // Routing table is recalculated; a new more optimal path is found
279 NextHop hop3(router3FaceUri, 5);
280 hops.addNextHop(hop3);
281
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700282 fib.update("/ndn/name", hops);
283 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500284
285 // To maintain a max 2 face requirement, face 3 should be registered and face 2 should be
286 // unregistered. Face 1 will also be re-registered.
287 //
288 // FIB
289 // Name NextHops
290 // /ndn/name (faceId=3, cost=5), (faceId=1, cost=10)
291
292 BOOST_CHECK_EQUAL(interests.size(), 3);
293
294 ndn::nfd::ControlParameters extractedParameters;
295 ndn::Name::Component verb;
296 std::vector<ndn::Interest>::iterator it = interests.begin();
297
298 extractRibCommandParameters(*it, verb, extractedParameters);
299
300 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700301 extractedParameters.getFaceId() == router1FaceId &&
Vince Lehman942eb7b2014-10-02 10:09:27 -0500302 verb == ndn::Name::Component("register"));
303
304 ++it;
305 extractRibCommandParameters(*it, verb, extractedParameters);
306
307 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700308 extractedParameters.getFaceId() == router3FaceId &&
Vince Lehman942eb7b2014-10-02 10:09:27 -0500309 verb == ndn::Name::Component("register"));
310
311 ++it;
312 extractRibCommandParameters(*it, verb, extractedParameters);
313
314 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
315 extractedParameters.getFaceId() == router2FaceId &&
316 verb == ndn::Name::Component("unregister"));
317}
318
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500319BOOST_FIXTURE_TEST_CASE(ScheduleFibEntryRefresh, FibFixture)
320{
321 ndn::Name name1("/name/1");
Ashlesh Gawande7a231c02020-06-12 20:06:44 -0700322 FibEntry fe;
323 fe.name = name1;
324 int origSeqNo = fe.seqNo;
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700325 fib.m_table.emplace(name1, std::move(fe));
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500326
Davide Pesaventod1f1df82022-03-12 16:40:37 -0500327 fib.scheduleEntryRefresh(fe, [&] (auto& entry) { BOOST_CHECK_EQUAL(origSeqNo + 1, entry.seqNo); });
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500328 this->advanceClocks(ndn::time::milliseconds(10), 1);
Davide Pesaventod1f1df82022-03-12 16:40:37 -0500329
330 // avoid "test case [...] did not check any assertions" message from Boost.Test
331 BOOST_CHECK(true);
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500332}
333
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600334BOOST_AUTO_TEST_CASE(ShouldNotRefreshNeighborRoute) // #4799
335{
336 NextHop hop1;
337 hop1.setConnectingFaceUri(router1FaceUri);
338
339 NexthopList hops;
340 hops.addNextHop(hop1);
341
342 // Simulate update for this neighbor from name prefix table
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700343 fib.update(router1Name, hops);
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600344 this->advanceClocks(ndn::time::seconds(1));
345
346 // Should not send the register interest
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700347 BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
348}
349
350BOOST_AUTO_TEST_CASE(PrefixWithdrawalFibUpdateBug) // #5179
351{
352 fib.setEntryRefreshTime(3600);
353 conf.setMaxFacesPerPrefix(3);
354
355 // Three adjacencies of Neu
356 Adjacent neighbor1("/ndn/memphis/router-memphis",
357 ndn::FaceUri("udp4://10.0.0.9:6363"), 21, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
358 adjacencies.insert(neighbor1);
359
360 Adjacent neighbor2("/ndn/michigan/router-michigan",
361 ndn::FaceUri("udp4://10.0.0.13:6363"), 14, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
362 adjacencies.insert(neighbor2);
363
364 Adjacent neighbor3("/ndn/savi/router-savi",
365 ndn::FaceUri("udp4://10.0.0.26:6363"), 15, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
366 adjacencies.insert(neighbor3);
367
368 // Wustl advertises /test
369 NexthopList nhl1;
370 nhl1.addNextHop(NextHop("udp4://10.0.0.13:6363", 28));
371 nhl1.addNextHop(NextHop("udp4://10.0.0.9:6363", 38));
372 nhl1.addNextHop(NextHop("udp4://10.0.0.26:6363", 44));
373 fib.update("/test", nhl1);
374
375 // Memphis advertises /test
376 NexthopList nhl2;
377 nhl2.addNextHop(NextHop("udp4://10.0.0.9:6363", 21));
378 nhl2.addNextHop(NextHop("udp4://10.0.0.13:6363", 26));
379 nhl2.addNextHop(NextHop("udp4://10.0.0.26:6363", 42));
380 fib.update("/test", nhl2);
381
382 advanceClocks(10_ms);
383 face.sentInterests.clear();
384 // Memphis withdraws /test
385 // NamePrefixTable calls this saying we need to install the Wu routes
386 // instead of the existing Memphis' cheaper routes
387 fib.update("/test", nhl1);
388
389 advanceClocks(10_ms);
390 int numRegister = 0;
391 // Do not expect any unregisters, just registers which will update the cost in NFD
392 for (const auto& i : face.sentInterests) {
Davide Pesavento8de8a8b2022-05-12 01:26:43 -0400393 if (i.getName().getPrefix(4) == "/localhost/nfd/rib/unregister") {
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700394 BOOST_CHECK(false);
395 }
396 else {
397 ++numRegister;
398 }
399 }
400 BOOST_CHECK_EQUAL(numRegister, 3);
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600401}
402
Vince Lehman942eb7b2014-10-02 10:09:27 -0500403BOOST_AUTO_TEST_SUITE_END()
404
Nick Gordonfad8e252016-08-11 14:21:38 -0500405} // namespace test
406} // namespace nlsr