blob: d90d125913c535d2b3a615743f2f9e3f124ac70d [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
Junxiao Shi6593a432023-08-21 10:50:28 +000034static const ndn::Name router1Name = "/ndn/router1";
35static const ndn::Name router2Name = "/ndn/router2";
36static const ndn::Name router3Name = "/ndn/router3";
37static const ndn::FaceUri router1FaceUri("udp4://10.0.0.1:6363");
38static const ndn::FaceUri router2FaceUri("udp4://10.0.0.2:6363");
39static const ndn::FaceUri router3FaceUri("udp4://10.0.0.3:6363");
40constexpr uint32_t router1FaceId = 1;
41constexpr uint32_t router2FaceId = 2;
42constexpr uint32_t router3FaceId = 3;
43
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040044class FibFixture : public IoKeyChainFixture
Vince Lehman942eb7b2014-10-02 10:09:27 -050045{
46public:
47 FibFixture()
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040048 : adjacencies(conf.getAdjacencyList())
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070049 , fib(face, m_scheduler, adjacencies, conf, m_keyChain)
50 , interests(face.sentInterests)
Vince Lehman942eb7b2014-10-02 10:09:27 -050051 {
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070052 advanceClocks(1_s);
53
Junxiao Shi6593a432023-08-21 10:50:28 +000054 Adjacent neighbor1(router1Name, router1FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050055 adjacencies.insert(neighbor1);
56
Junxiao Shi6593a432023-08-21 10:50:28 +000057 Adjacent neighbor2(router2Name, router2FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050058 adjacencies.insert(neighbor2);
59
Junxiao Shi6593a432023-08-21 10:50:28 +000060 Adjacent neighbor3(router3Name, router3FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050061 adjacencies.insert(neighbor3);
62
63 conf.setMaxFacesPerPrefix(2);
64
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070065 fib.setEntryRefreshTime(1);
66 }
67
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040068 static void
Davide Pesavento69904fc2022-10-14 09:45:34 -040069 extractRibCommandParameters(const ndn::Interest& interest,
70 ndn::Name::Component& verb,
71 ndn::nfd::ControlParameters& params)
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040072 {
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040073 const auto& name = interest.getName();
Davide Pesavento69904fc2022-10-14 09:45:34 -040074 verb = name.at(RIB_COMMAND_PREFIX.size());
75 params.wireDecode(name.at(RIB_COMMAND_PREFIX.size() + 1).blockFromValue());
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040076 }
77
78private:
Davide Pesavento69904fc2022-10-14 09:45:34 -040079 static inline const ndn::Name RIB_COMMAND_PREFIX{"/localhost/nfd/rib"};
80
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040081 ndn::Scheduler m_scheduler{m_io};
82
83public:
Junxiao Shi43f37a02023-08-09 00:09:00 +000084 ndn::DummyClientFace face{m_io, m_keyChain, [] {
85 ndn::DummyClientFace::Options opts;
Junxiao Shi771a0de2023-08-09 00:03:21 +000086 opts.enableRegistrationReply = true;
87 opts.registrationReplyFaceId = 128;
88 return opts;
89 } ()};
Davide Pesavento8de8a8b2022-05-12 01:26:43 -040090 ConfParameter conf{face, m_keyChain};
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070091 AdjacencyList& adjacencies;
92 Fib fib;
Vince Lehman942eb7b2014-10-02 10:09:27 -050093 std::vector<ndn::Interest>& interests;
Vince Lehman942eb7b2014-10-02 10:09:27 -050094};
95
Vince Lehman942eb7b2014-10-02 10:09:27 -050096BOOST_FIXTURE_TEST_SUITE(TestFib, FibFixture)
97
98BOOST_AUTO_TEST_CASE(NextHopsAdd)
99{
100 NextHop hop1(router1FaceUri, 10);
101 NextHop hop2(router2FaceUri, 20);
102
103 NexthopList hops;
104 hops.addNextHop(hop1);
105 hops.addNextHop(hop2);
106
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700107 fib.update("/ndn/name", hops);
108 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500109
110 // Should register faces 1 and 2 for /ndn/name
111 BOOST_REQUIRE_EQUAL(interests.size(), 2);
112
113 ndn::nfd::ControlParameters extractedParameters;
114 ndn::Name::Component verb;
115 std::vector<ndn::Interest>::iterator it = interests.begin();
116
117 extractRibCommandParameters(*it, verb, extractedParameters);
118
119 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
120 extractedParameters.getFaceId() == router1FaceId &&
121 verb == ndn::Name::Component("register"));
122
123 ++it;
124 extractRibCommandParameters(*it, verb, extractedParameters);
125
126 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
127 extractedParameters.getFaceId() == router2FaceId &&
128 verb == ndn::Name::Component("register"));
129}
130
Vince Lehman942eb7b2014-10-02 10:09:27 -0500131BOOST_AUTO_TEST_CASE(NextHopsNoChange)
132{
133 NextHop hop1(router1FaceUri, 10);
134 NextHop hop2(router2FaceUri, 20);
135
136 NexthopList oldHops;
137 oldHops.addNextHop(hop1);
138 oldHops.addNextHop(hop2);
139
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700140 fib.update("/ndn/name", oldHops);
141 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500142
143 BOOST_REQUIRE_EQUAL(interests.size(), 2);
144 interests.clear();
145
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700146 fib.update("/ndn/name", oldHops);
147 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500148
149 // Should register face 1 and 2 for /ndn/name
150 BOOST_REQUIRE_EQUAL(interests.size(), 2);
151
152 ndn::nfd::ControlParameters extractedParameters;
153 ndn::Name::Component verb;
154 std::vector<ndn::Interest>::iterator it = interests.begin();
155
156 extractRibCommandParameters(*it, verb, extractedParameters);
157
158 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
159 extractedParameters.getFaceId() == router1FaceId &&
160 verb == ndn::Name::Component("register"));
161
162 ++it;
163 extractRibCommandParameters(*it, verb, extractedParameters);
164
165 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
166 extractedParameters.getFaceId() == router2FaceId &&
167 verb == ndn::Name::Component("register"));
168}
169
170BOOST_AUTO_TEST_CASE(NextHopsRemoveAll)
171{
172 NextHop hop1(router1FaceUri, 10);
173 NextHop hop2(router2FaceUri, 20);
174
175 NexthopList oldHops;
176 oldHops.addNextHop(hop1);
177 oldHops.addNextHop(hop2);
178
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700179 fib.update("/ndn/name", oldHops);
180 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500181
182 BOOST_REQUIRE_EQUAL(interests.size(), 2);
183 interests.clear();
184
185 NexthopList empty;
186
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700187 fib.update("/ndn/name", empty);
188 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500189
190 // Should unregister faces 1 and 2 for /ndn/name
191 BOOST_CHECK_EQUAL(interests.size(), 2);
192
193 ndn::nfd::ControlParameters extractedParameters;
194 ndn::Name::Component verb;
195 std::vector<ndn::Interest>::iterator it = interests.begin();
196
197 extractRibCommandParameters(*it, verb, extractedParameters);
198
199 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
200 extractedParameters.getFaceId() == router1FaceId &&
201 verb == ndn::Name::Component("unregister"));
202
203 ++it;
204 extractRibCommandParameters(*it, verb, extractedParameters);
205
206 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
207 extractedParameters.getFaceId() == router2FaceId &&
208 verb == ndn::Name::Component("unregister"));
209}
210
211BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixes)
212{
213 NextHop hop1(router1FaceUri, 10);
214 NextHop hop2(router2FaceUri, 20);
215 NextHop hop3(router3FaceUri, 30);
216
217 NexthopList hops;
218 hops.addNextHop(hop1);
219 hops.addNextHop(hop2);
220 hops.addNextHop(hop3);
221
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700222 fib.update("/ndn/name", hops);
223 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500224
225 // Should only register faces 1 and 2 for /ndn/name
226 BOOST_CHECK_EQUAL(interests.size(), 2);
227
228 ndn::nfd::ControlParameters extractedParameters;
229 ndn::Name::Component verb;
230 std::vector<ndn::Interest>::iterator it = interests.begin();
231
232 extractRibCommandParameters(*it, verb, extractedParameters);
233
234 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
235 extractedParameters.getFaceId() == router1FaceId &&
236 verb == ndn::Name::Component("register"));
237
238 ++it;
239 extractRibCommandParameters(*it, verb, extractedParameters);
240
241 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
242 extractedParameters.getFaceId() == router2FaceId &&
243 verb == ndn::Name::Component("register"));
244}
245
246BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixesAfterRecalculation)
247{
248 NextHop hop1(router1FaceUri, 10);
249 NextHop hop2(router2FaceUri, 20);
250
251 NexthopList hops;
252 hops.addNextHop(hop1);
253 hops.addNextHop(hop2);
254
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700255 fib.update("/ndn/name", hops);
256 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500257
258 // FIB
259 // Name NextHops
260 // /ndn/name (faceId=1, cost=10), (faceId=2, cost=20)
261 BOOST_REQUIRE_EQUAL(interests.size(), 2);
262 interests.clear();
263
264 // Routing table is recalculated; a new more optimal path is found
265 NextHop hop3(router3FaceUri, 5);
266 hops.addNextHop(hop3);
267
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700268 fib.update("/ndn/name", hops);
269 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500270
271 // To maintain a max 2 face requirement, face 3 should be registered and face 2 should be
272 // unregistered. Face 1 will also be re-registered.
273 //
274 // FIB
275 // Name NextHops
276 // /ndn/name (faceId=3, cost=5), (faceId=1, cost=10)
277
278 BOOST_CHECK_EQUAL(interests.size(), 3);
279
280 ndn::nfd::ControlParameters extractedParameters;
281 ndn::Name::Component verb;
282 std::vector<ndn::Interest>::iterator it = interests.begin();
283
284 extractRibCommandParameters(*it, verb, extractedParameters);
285
286 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700287 extractedParameters.getFaceId() == router1FaceId &&
Vince Lehman942eb7b2014-10-02 10:09:27 -0500288 verb == ndn::Name::Component("register"));
289
290 ++it;
291 extractRibCommandParameters(*it, verb, extractedParameters);
292
293 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700294 extractedParameters.getFaceId() == router3FaceId &&
Vince Lehman942eb7b2014-10-02 10:09:27 -0500295 verb == ndn::Name::Component("register"));
296
297 ++it;
298 extractRibCommandParameters(*it, verb, extractedParameters);
299
300 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
301 extractedParameters.getFaceId() == router2FaceId &&
302 verb == ndn::Name::Component("unregister"));
303}
304
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500305BOOST_FIXTURE_TEST_CASE(ScheduleFibEntryRefresh, FibFixture)
306{
307 ndn::Name name1("/name/1");
Ashlesh Gawande7a231c02020-06-12 20:06:44 -0700308 FibEntry fe;
309 fe.name = name1;
310 int origSeqNo = fe.seqNo;
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700311 fib.m_table.emplace(name1, std::move(fe));
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500312
Davide Pesaventod1f1df82022-03-12 16:40:37 -0500313 fib.scheduleEntryRefresh(fe, [&] (auto& entry) { BOOST_CHECK_EQUAL(origSeqNo + 1, entry.seqNo); });
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500314 this->advanceClocks(ndn::time::milliseconds(10), 1);
Davide Pesaventod1f1df82022-03-12 16:40:37 -0500315
316 // avoid "test case [...] did not check any assertions" message from Boost.Test
317 BOOST_CHECK(true);
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500318}
319
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600320BOOST_AUTO_TEST_CASE(ShouldNotRefreshNeighborRoute) // #4799
321{
322 NextHop hop1;
323 hop1.setConnectingFaceUri(router1FaceUri);
324
325 NexthopList hops;
326 hops.addNextHop(hop1);
327
328 // Simulate update for this neighbor from name prefix table
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700329 fib.update(router1Name, hops);
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600330 this->advanceClocks(ndn::time::seconds(1));
331
332 // Should not send the register interest
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700333 BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
334}
335
336BOOST_AUTO_TEST_CASE(PrefixWithdrawalFibUpdateBug) // #5179
337{
338 fib.setEntryRefreshTime(3600);
339 conf.setMaxFacesPerPrefix(3);
340
341 // Three adjacencies of Neu
342 Adjacent neighbor1("/ndn/memphis/router-memphis",
343 ndn::FaceUri("udp4://10.0.0.9:6363"), 21, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
344 adjacencies.insert(neighbor1);
345
346 Adjacent neighbor2("/ndn/michigan/router-michigan",
347 ndn::FaceUri("udp4://10.0.0.13:6363"), 14, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
348 adjacencies.insert(neighbor2);
349
350 Adjacent neighbor3("/ndn/savi/router-savi",
351 ndn::FaceUri("udp4://10.0.0.26:6363"), 15, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
352 adjacencies.insert(neighbor3);
353
354 // Wustl advertises /test
355 NexthopList nhl1;
Junxiao Shi6593a432023-08-21 10:50:28 +0000356 nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 28));
357 nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 38));
358 nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 44));
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700359 fib.update("/test", nhl1);
360
361 // Memphis advertises /test
362 NexthopList nhl2;
Junxiao Shi6593a432023-08-21 10:50:28 +0000363 nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 21));
364 nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 26));
365 nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 42));
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700366 fib.update("/test", nhl2);
367
368 advanceClocks(10_ms);
369 face.sentInterests.clear();
370 // Memphis withdraws /test
371 // NamePrefixTable calls this saying we need to install the Wu routes
372 // instead of the existing Memphis' cheaper routes
373 fib.update("/test", nhl1);
374
375 advanceClocks(10_ms);
376 int numRegister = 0;
377 // Do not expect any unregisters, just registers which will update the cost in NFD
378 for (const auto& i : face.sentInterests) {
Davide Pesavento8de8a8b2022-05-12 01:26:43 -0400379 if (i.getName().getPrefix(4) == "/localhost/nfd/rib/unregister") {
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700380 BOOST_CHECK(false);
381 }
382 else {
383 ++numRegister;
384 }
385 }
386 BOOST_CHECK_EQUAL(numRegister, 3);
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600387}
388
Vince Lehman942eb7b2014-10-02 10:09:27 -0500389BOOST_AUTO_TEST_SUITE_END()
390
Nick Gordonfad8e252016-08-11 14:21:38 -0500391} // namespace test
392} // namespace nlsr