blob: 3961b051b9d10382bf38038c974dcd1ce2e05620 [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/*
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -07003 * Copyright (c) 2014-2021, 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"
Ashlesh Gawande85998a12017-12-07 22:22:13 -060022#include "../test-common.hpp"
23#include "../control-commands.hpp"
Vince Lehman942eb7b2014-10-02 10:09:27 -050024#include "adjacency-list.hpp"
25#include "conf-parameter.hpp"
26
Muktadir R Chowdhuryc69da0a2015-12-18 13:24:38 -060027#include <ndn-cxx/util/dummy-client-face.hpp>
28
Vince Lehman942eb7b2014-10-02 10:09:27 -050029namespace nlsr {
30namespace test {
31
Muktadir Chowdhury3be64662015-05-01 14:50:53 -050032class FibFixture : public UnitTestTimeFixture
Vince Lehman942eb7b2014-10-02 10:09:27 -050033{
34public:
35 FibFixture()
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070036 : face(m_ioService, m_keyChain)
37 , conf(face, m_keyChain)
38 , adjacencies(conf.getAdjacencyList())
39 , 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 enableRegistrationReplyWithFaceId();
43 advanceClocks(1_s);
44
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050045 Adjacent neighbor1(router1Name, ndn::FaceUri(router1FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050046 adjacencies.insert(neighbor1);
47
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050048 Adjacent neighbor2(router2Name, ndn::FaceUri(router2FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050049 adjacencies.insert(neighbor2);
50
Muktadir Chowdhuryf04f9892017-08-20 20:42:56 -050051 Adjacent neighbor3(router3Name, ndn::FaceUri(router3FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
Vince Lehman942eb7b2014-10-02 10:09:27 -050052 adjacencies.insert(neighbor3);
53
54 conf.setMaxFacesPerPrefix(2);
55
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070056 fib.setEntryRefreshTime(1);
57 }
58
59 void
60 enableRegistrationReplyWithFaceId() {
61 face.onSendInterest.connect([this] (const ndn::Interest& interest) {
62 static const ndn::Name localhostRegistration("/localhost/nfd/rib");
63 if (!localhostRegistration.isPrefixOf(interest.getName()))
64 return;
65
66 ndn::nfd::ControlParameters params(interest.getName().get(-5).blockFromValue());
67 if (!params.hasFaceId()) {
68 params.setFaceId(1);
69 }
70 params.setOrigin(ndn::nfd::ROUTE_ORIGIN_APP);
71 if (interest.getName().get(3) == ndn::name::Component("register")) {
72 params.setCost(0);
73 }
74
75 ndn::nfd::ControlResponse resp;
76 resp.setCode(200);
77 resp.setBody(params.wireEncode());
78
79 ndn::Data data(interest.getName());
80 data.setContent(resp.wireEncode());
81
82 m_keyChain.sign(data, ndn::security::SigningInfo(ndn::security::SigningInfo::SIGNER_TYPE_SHA256));
83
84 face.getIoService().post([this, data] { face.receive(data); });
85 });
Vince Lehman942eb7b2014-10-02 10:09:27 -050086 }
87
88public:
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070089 ndn::util::DummyClientFace face;
Vince Lehman942eb7b2014-10-02 10:09:27 -050090
Vince Lehman942eb7b2014-10-02 10:09:27 -050091 ConfParameter conf;
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -070092 AdjacencyList& adjacencies;
93 Fib fib;
Vince Lehman942eb7b2014-10-02 10:09:27 -050094 std::vector<ndn::Interest>& interests;
95
96 static const ndn::Name router1Name;
97 static const ndn::Name router2Name;
98 static const ndn::Name router3Name;
99
100 static const std::string router1FaceUri;
101 static const std::string router2FaceUri;
102 static const std::string router3FaceUri;
103
104 static const uint32_t router1FaceId;
105 static const uint32_t router2FaceId;
106 static const uint32_t router3FaceId;
107};
108
109const ndn::Name FibFixture::router1Name = "/ndn/router1";
110const ndn::Name FibFixture::router2Name = "/ndn/router2";
111const ndn::Name FibFixture::router3Name = "/ndn/router3";
112
Nick Gordone9733ed2017-04-26 10:48:39 -0500113const std::string FibFixture::router1FaceUri = "udp4://10.0.0.1";
114const std::string FibFixture::router2FaceUri = "udp4://10.0.0.2";
115const std::string FibFixture::router3FaceUri = "udp4://10.0.0.3";
Vince Lehman942eb7b2014-10-02 10:09:27 -0500116
117const uint32_t FibFixture::router1FaceId = 1;
118const uint32_t FibFixture::router2FaceId = 2;
119const uint32_t FibFixture::router3FaceId = 3;
120
121BOOST_FIXTURE_TEST_SUITE(TestFib, FibFixture)
122
123BOOST_AUTO_TEST_CASE(NextHopsAdd)
124{
125 NextHop hop1(router1FaceUri, 10);
126 NextHop hop2(router2FaceUri, 20);
127
128 NexthopList hops;
129 hops.addNextHop(hop1);
130 hops.addNextHop(hop2);
131
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700132 fib.update("/ndn/name", hops);
133 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500134
135 // Should register faces 1 and 2 for /ndn/name
136 BOOST_REQUIRE_EQUAL(interests.size(), 2);
137
138 ndn::nfd::ControlParameters extractedParameters;
139 ndn::Name::Component verb;
140 std::vector<ndn::Interest>::iterator it = interests.begin();
141
142 extractRibCommandParameters(*it, verb, extractedParameters);
143
144 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
145 extractedParameters.getFaceId() == router1FaceId &&
146 verb == ndn::Name::Component("register"));
147
148 ++it;
149 extractRibCommandParameters(*it, verb, extractedParameters);
150
151 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
152 extractedParameters.getFaceId() == router2FaceId &&
153 verb == ndn::Name::Component("register"));
154}
155
Vince Lehman942eb7b2014-10-02 10:09:27 -0500156BOOST_AUTO_TEST_CASE(NextHopsNoChange)
157{
158 NextHop hop1(router1FaceUri, 10);
159 NextHop hop2(router2FaceUri, 20);
160
161 NexthopList oldHops;
162 oldHops.addNextHop(hop1);
163 oldHops.addNextHop(hop2);
164
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700165 fib.update("/ndn/name", oldHops);
166 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500167
168 BOOST_REQUIRE_EQUAL(interests.size(), 2);
169 interests.clear();
170
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700171 fib.update("/ndn/name", oldHops);
172 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500173
174 // Should register face 1 and 2 for /ndn/name
175 BOOST_REQUIRE_EQUAL(interests.size(), 2);
176
177 ndn::nfd::ControlParameters extractedParameters;
178 ndn::Name::Component verb;
179 std::vector<ndn::Interest>::iterator it = interests.begin();
180
181 extractRibCommandParameters(*it, verb, extractedParameters);
182
183 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
184 extractedParameters.getFaceId() == router1FaceId &&
185 verb == ndn::Name::Component("register"));
186
187 ++it;
188 extractRibCommandParameters(*it, verb, extractedParameters);
189
190 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
191 extractedParameters.getFaceId() == router2FaceId &&
192 verb == ndn::Name::Component("register"));
193}
194
195BOOST_AUTO_TEST_CASE(NextHopsRemoveAll)
196{
197 NextHop hop1(router1FaceUri, 10);
198 NextHop hop2(router2FaceUri, 20);
199
200 NexthopList oldHops;
201 oldHops.addNextHop(hop1);
202 oldHops.addNextHop(hop2);
203
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700204 fib.update("/ndn/name", oldHops);
205 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500206
207 BOOST_REQUIRE_EQUAL(interests.size(), 2);
208 interests.clear();
209
210 NexthopList empty;
211
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700212 fib.update("/ndn/name", empty);
213 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500214
215 // Should unregister faces 1 and 2 for /ndn/name
216 BOOST_CHECK_EQUAL(interests.size(), 2);
217
218 ndn::nfd::ControlParameters extractedParameters;
219 ndn::Name::Component verb;
220 std::vector<ndn::Interest>::iterator it = interests.begin();
221
222 extractRibCommandParameters(*it, verb, extractedParameters);
223
224 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
225 extractedParameters.getFaceId() == router1FaceId &&
226 verb == ndn::Name::Component("unregister"));
227
228 ++it;
229 extractRibCommandParameters(*it, verb, extractedParameters);
230
231 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
232 extractedParameters.getFaceId() == router2FaceId &&
233 verb == ndn::Name::Component("unregister"));
234}
235
236BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixes)
237{
238 NextHop hop1(router1FaceUri, 10);
239 NextHop hop2(router2FaceUri, 20);
240 NextHop hop3(router3FaceUri, 30);
241
242 NexthopList hops;
243 hops.addNextHop(hop1);
244 hops.addNextHop(hop2);
245 hops.addNextHop(hop3);
246
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700247 fib.update("/ndn/name", hops);
248 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500249
250 // Should only register faces 1 and 2 for /ndn/name
251 BOOST_CHECK_EQUAL(interests.size(), 2);
252
253 ndn::nfd::ControlParameters extractedParameters;
254 ndn::Name::Component verb;
255 std::vector<ndn::Interest>::iterator it = interests.begin();
256
257 extractRibCommandParameters(*it, verb, extractedParameters);
258
259 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
260 extractedParameters.getFaceId() == router1FaceId &&
261 verb == ndn::Name::Component("register"));
262
263 ++it;
264 extractRibCommandParameters(*it, verb, extractedParameters);
265
266 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
267 extractedParameters.getFaceId() == router2FaceId &&
268 verb == ndn::Name::Component("register"));
269}
270
271BOOST_AUTO_TEST_CASE(NextHopsMaxPrefixesAfterRecalculation)
272{
273 NextHop hop1(router1FaceUri, 10);
274 NextHop hop2(router2FaceUri, 20);
275
276 NexthopList hops;
277 hops.addNextHop(hop1);
278 hops.addNextHop(hop2);
279
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700280 fib.update("/ndn/name", hops);
281 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500282
283 // FIB
284 // Name NextHops
285 // /ndn/name (faceId=1, cost=10), (faceId=2, cost=20)
286 BOOST_REQUIRE_EQUAL(interests.size(), 2);
287 interests.clear();
288
289 // Routing table is recalculated; a new more optimal path is found
290 NextHop hop3(router3FaceUri, 5);
291 hops.addNextHop(hop3);
292
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700293 fib.update("/ndn/name", hops);
294 face.processEvents(ndn::time::milliseconds(-1));
Vince Lehman942eb7b2014-10-02 10:09:27 -0500295
296 // To maintain a max 2 face requirement, face 3 should be registered and face 2 should be
297 // unregistered. Face 1 will also be re-registered.
298 //
299 // FIB
300 // Name NextHops
301 // /ndn/name (faceId=3, cost=5), (faceId=1, cost=10)
302
303 BOOST_CHECK_EQUAL(interests.size(), 3);
304
305 ndn::nfd::ControlParameters extractedParameters;
306 ndn::Name::Component verb;
307 std::vector<ndn::Interest>::iterator it = interests.begin();
308
309 extractRibCommandParameters(*it, verb, extractedParameters);
310
311 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700312 extractedParameters.getFaceId() == router1FaceId &&
Vince Lehman942eb7b2014-10-02 10:09:27 -0500313 verb == ndn::Name::Component("register"));
314
315 ++it;
316 extractRibCommandParameters(*it, verb, extractedParameters);
317
318 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700319 extractedParameters.getFaceId() == router3FaceId &&
Vince Lehman942eb7b2014-10-02 10:09:27 -0500320 verb == ndn::Name::Component("register"));
321
322 ++it;
323 extractRibCommandParameters(*it, verb, extractedParameters);
324
325 BOOST_CHECK(extractedParameters.getName() == "/ndn/name" &&
326 extractedParameters.getFaceId() == router2FaceId &&
327 verb == ndn::Name::Component("unregister"));
328}
329
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500330BOOST_FIXTURE_TEST_CASE(ScheduleFibEntryRefresh, FibFixture)
331{
332 ndn::Name name1("/name/1");
Ashlesh Gawande7a231c02020-06-12 20:06:44 -0700333 FibEntry fe;
334 fe.name = name1;
335 int origSeqNo = fe.seqNo;
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700336 fib.m_table.emplace(name1, std::move(fe));
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500337
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700338 fib.scheduleEntryRefresh(fe,
Ashlesh Gawandee6ba9152018-03-30 01:15:00 -0500339 [&] (FibEntry& entry) {
Ashlesh Gawande7a231c02020-06-12 20:06:44 -0700340 BOOST_CHECK_EQUAL(origSeqNo + 1, entry.seqNo);
Muktadir Chowdhury3be64662015-05-01 14:50:53 -0500341 });
342 this->advanceClocks(ndn::time::milliseconds(10), 1);
343}
344
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600345BOOST_AUTO_TEST_CASE(ShouldNotRefreshNeighborRoute) // #4799
346{
347 NextHop hop1;
348 hop1.setConnectingFaceUri(router1FaceUri);
349
350 NexthopList hops;
351 hops.addNextHop(hop1);
352
353 // Simulate update for this neighbor from name prefix table
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700354 fib.update(router1Name, hops);
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600355 this->advanceClocks(ndn::time::seconds(1));
356
357 // Should not send the register interest
Ashlesh Gawande6f0f35d2021-08-21 23:52:14 -0700358 BOOST_CHECK_EQUAL(face.sentInterests.size(), 0);
359}
360
361BOOST_AUTO_TEST_CASE(PrefixWithdrawalFibUpdateBug) // #5179
362{
363 fib.setEntryRefreshTime(3600);
364 conf.setMaxFacesPerPrefix(3);
365
366 // Three adjacencies of Neu
367 Adjacent neighbor1("/ndn/memphis/router-memphis",
368 ndn::FaceUri("udp4://10.0.0.9:6363"), 21, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
369 adjacencies.insert(neighbor1);
370
371 Adjacent neighbor2("/ndn/michigan/router-michigan",
372 ndn::FaceUri("udp4://10.0.0.13:6363"), 14, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
373 adjacencies.insert(neighbor2);
374
375 Adjacent neighbor3("/ndn/savi/router-savi",
376 ndn::FaceUri("udp4://10.0.0.26:6363"), 15, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
377 adjacencies.insert(neighbor3);
378
379 // Wustl advertises /test
380 NexthopList nhl1;
381 nhl1.addNextHop(NextHop("udp4://10.0.0.13:6363", 28));
382 nhl1.addNextHop(NextHop("udp4://10.0.0.9:6363", 38));
383 nhl1.addNextHop(NextHop("udp4://10.0.0.26:6363", 44));
384 fib.update("/test", nhl1);
385
386 // Memphis advertises /test
387 NexthopList nhl2;
388 nhl2.addNextHop(NextHop("udp4://10.0.0.9:6363", 21));
389 nhl2.addNextHop(NextHop("udp4://10.0.0.13:6363", 26));
390 nhl2.addNextHop(NextHop("udp4://10.0.0.26:6363", 42));
391 fib.update("/test", nhl2);
392
393 advanceClocks(10_ms);
394 face.sentInterests.clear();
395 // Memphis withdraws /test
396 // NamePrefixTable calls this saying we need to install the Wu routes
397 // instead of the existing Memphis' cheaper routes
398 fib.update("/test", nhl1);
399
400 advanceClocks(10_ms);
401 int numRegister = 0;
402 // Do not expect any unregisters, just registers which will update the cost in NFD
403 for (const auto& i : face.sentInterests) {
404 if (i.getName().getPrefix(4) == "/localhost/nfd/rib/unregister/") {
405 BOOST_CHECK(false);
406 }
407 else {
408 ++numRegister;
409 }
410 }
411 BOOST_CHECK_EQUAL(numRegister, 3);
Ashlesh Gawandee5002b32018-12-20 21:07:31 -0600412}
413
Vince Lehman942eb7b2014-10-02 10:09:27 -0500414BOOST_AUTO_TEST_SUITE_END()
415
Nick Gordonfad8e252016-08-11 14:21:38 -0500416} // namespace test
417} // namespace nlsr