blob: ebfe7d0ddf6be73a83f130d7a205367d37c5665e [file] [log] [blame]
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Davide Pesaventodeb54272022-03-11 18:51:05 -05003 * Copyright (c) 2014-2022, Regents of the University of California,
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +00004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050026#include "mgmt/rib-manager.hpp"
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000027
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040028#include "tests/test-common.hpp"
Davide Pesavento1d12d2f2019-03-22 12:44:14 -040029#include "tests/key-chain-fixture.hpp"
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040030#include "tests/daemon/global-io-fixture.hpp"
Junxiao Shidf1dc652019-08-30 19:03:19 +000031#include "tests/daemon/rib/fib-updates-common.hpp"
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040032
Davide Pesavento21353752020-11-20 00:43:44 -050033#include <ndn-cxx/security/transform/base64-encode.hpp>
34#include <ndn-cxx/security/transform/buffer-source.hpp>
35#include <ndn-cxx/security/transform/stream-sink.hpp>
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000036#include <ndn-cxx/util/dummy-client-face.hpp>
37
Teng Liang18c2b292019-10-18 14:31:04 -070038#include <boost/property_tree/info_parser.hpp>
39
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000040namespace nfd {
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000041namespace tests {
42
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050043using rib::Route;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000044
Teng Liang18c2b292019-10-18 14:31:04 -070045static ConfigSection
46makeSection(const std::string& config)
47{
48 std::istringstream inputStream(config);
49 ConfigSection section;
50 boost::property_tree::read_info(inputStream, section);
51 return section;
52}
53
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040054class RibManagerSlAnnounceFixture : public GlobalIoTimeFixture, public KeyChainFixture
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000055{
56public:
57 using SlAnnounceResult = RibManager::SlAnnounceResult;
58
59 RibManagerSlAnnounceFixture()
Davide Pesaventoe1bdc082018-10-11 21:20:23 -040060 : m_face(g_io, m_keyChain)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000061 , m_nfdController(m_face, m_keyChain)
62 , m_dispatcher(m_face, m_keyChain)
63 , m_fibUpdater(rib, m_nfdController)
64 , m_trustedSigner(m_keyChain.createIdentity("/trusted", ndn::RsaKeyParams()))
65 , m_untrustedSigner(m_keyChain.createIdentity("/untrusted", ndn::RsaKeyParams()))
66 {
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000067 // Face, Controller, Dispatcher are irrelevant to SlAnnounce functions but required by
68 // RibManager construction, so they are private. RibManager is a pointer to avoid code style
69 // rule 1.4 violation.
Davide Pesavento0a71dd32019-03-17 20:36:18 -040070 manager = make_unique<RibManager>(rib, m_face, m_keyChain, m_nfdController, m_dispatcher);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000071
Teng Liang18c2b292019-10-18 14:31:04 -070072 loadDefaultPaConfig();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000073 }
74
75 template<typename ...T>
76 ndn::PrefixAnnouncement
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050077 makeTrustedAnn(T&&... args)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000078 {
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050079 return signPrefixAnn(makePrefixAnn(std::forward<T>(args)...), m_keyChain, m_trustedSigner);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000080 }
81
82 template<typename ...T>
83 ndn::PrefixAnnouncement
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050084 makeUntrustedAnn(T&&... args)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000085 {
Davide Pesavento8a05c7f2019-02-28 02:26:19 -050086 return signPrefixAnn(makePrefixAnn(std::forward<T>(args)...), m_keyChain, m_untrustedSigner);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000087 }
88
89 /** \brief Invoke manager->slAnnounce and wait for result.
90 */
91 SlAnnounceResult
92 slAnnounceSync(const ndn::PrefixAnnouncement& pa, uint64_t faceId, time::milliseconds maxLifetime)
93 {
Davide Pesaventob7bfcb92022-05-22 23:55:23 -040094 std::optional<SlAnnounceResult> result;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +000095 manager->slAnnounce(pa, faceId, maxLifetime,
96 [&] (RibManager::SlAnnounceResult res) {
97 BOOST_CHECK(!result);
98 result = res;
99 });
100
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400101 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000102 BOOST_CHECK(result);
103 return result.value_or(SlAnnounceResult::ERROR);
104 }
105
106 /** \brief Invoke manager->slRenew and wait for result.
107 */
108 SlAnnounceResult
109 slRenewSync(const Name& name, uint64_t faceId, time::milliseconds maxLifetime)
110 {
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400111 std::optional<SlAnnounceResult> result;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000112 manager->slRenew(name, faceId, maxLifetime,
113 [&] (RibManager::SlAnnounceResult res) {
114 BOOST_CHECK(!result);
115 result = res;
116 });
117
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400118 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000119 BOOST_CHECK(result);
120 return result.value_or(SlAnnounceResult::ERROR);
121 }
122
123 /** \brief Invoke manager->slFindAnn and wait for result.
124 */
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400125 std::optional<ndn::PrefixAnnouncement>
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000126 slFindAnnSync(const Name& name)
127 {
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400128 std::optional<std::optional<ndn::PrefixAnnouncement>> result;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000129 manager->slFindAnn(name,
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400130 [&] (std::optional<ndn::PrefixAnnouncement> found) {
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000131 BOOST_CHECK(!result);
132 result = found;
133 });
134
Davide Pesaventoe1bdc082018-10-11 21:20:23 -0400135 g_io.poll();
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000136 BOOST_CHECK(result);
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400137 return result.value_or(std::nullopt);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000138 }
139
140 /** \brief Lookup a route with PREFIXANN origin.
141 */
142 Route*
Davide Pesavento21353752020-11-20 00:43:44 -0500143 findAnnRoute(const Name& name, uint64_t faceId) const
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000144 {
145 Route routeQuery;
146 routeQuery.faceId = faceId;
147 routeQuery.origin = ndn::nfd::ROUTE_ORIGIN_PREFIXANN;
148 return rib.find(name, routeQuery);
149 }
150
Davide Pesavento21353752020-11-20 00:43:44 -0500151 /** \brief Retrieve an identity certificate as a base64 string.
152 */
153 std::string
154 getIdentityCertificateBase64(const Name& identity) const
155 {
Davide Pesavento21353752020-11-20 00:43:44 -0500156 namespace tr = ndn::security::transform;
Davide Pesavento21353752020-11-20 00:43:44 -0500157
Davide Pesaventodeb54272022-03-11 18:51:05 -0500158 auto cert = m_keyChain.getPib().getIdentity(identity).getDefaultKey().getDefaultCertificate();
159 std::ostringstream oss;
160 tr::bufferSource(cert.wireEncode()) >> tr::base64Encode(false) >> tr::streamSink(oss);
Davide Pesavento21353752020-11-20 00:43:44 -0500161 return oss.str();
162 }
163
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000164private:
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000165 void
Teng Liang18c2b292019-10-18 14:31:04 -0700166 loadDefaultPaConfig()
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000167 {
Teng Liang18c2b292019-10-18 14:31:04 -0700168 const std::string CONFIG = R"CONFIG(
169 trust-anchor
170 {
171 type any
172 }
173 )CONFIG";
174 manager->applyPaConfig(makeSection(CONFIG), "default");
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000175 }
176
Davide Pesavento21353752020-11-20 00:43:44 -0500177protected:
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500178 rib::Rib rib;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000179 unique_ptr<RibManager> manager;
180
181private:
182 ndn::util::DummyClientFace m_face;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000183 ndn::nfd::Controller m_nfdController;
Davide Pesavento78ddcab2019-02-28 22:00:03 -0500184 Dispatcher m_dispatcher;
Junxiao Shidf1dc652019-08-30 19:03:19 +0000185 rib::tests::MockFibUpdater m_fibUpdater;
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000186
187 ndn::security::SigningInfo m_trustedSigner;
188 ndn::security::SigningInfo m_untrustedSigner;
189};
190
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500191BOOST_AUTO_TEST_SUITE(Mgmt)
192BOOST_AUTO_TEST_SUITE(TestRibManager)
193BOOST_FIXTURE_TEST_SUITE(SlAnnounce, RibManagerSlAnnounceFixture)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000194
Teng Liang18c2b292019-10-18 14:31:04 -0700195BOOST_AUTO_TEST_CASE(AnnounceWithDefaultConfig)
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000196{
Teng Liang18c2b292019-10-18 14:31:04 -0700197 auto pa = makeTrustedAnn("/fMXN7UeB", 1_h);
198 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 3275, 1_h), SlAnnounceResult::OK);
199 BOOST_CHECK(findAnnRoute("/fMXN7UeB", 3275) != nullptr);
200
201 auto pa2 = makeUntrustedAnn("/1nzAe0Y4", 1_h);
202 BOOST_CHECK_EQUAL(slAnnounceSync(pa2, 2959, 1_h), SlAnnounceResult::OK);
203 BOOST_CHECK(findAnnRoute("/1nzAe0Y4", 2959) != nullptr);
204}
205
206BOOST_AUTO_TEST_CASE(AnnounceWithEmptyConfig)
207{
208 manager->applyPaConfig(makeSection(""), "empty");
209
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000210 auto pa = makeTrustedAnn("/fMXN7UeB", 1_h);
211 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 3275, 1_h), SlAnnounceResult::VALIDATION_FAILURE);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000212 BOOST_CHECK(findAnnRoute("/fMXN7UeB", 3275) == nullptr);
Teng Liang18c2b292019-10-18 14:31:04 -0700213
214 auto pa2 = makeUntrustedAnn("/1nzAe0Y4", 1_h);
215 BOOST_CHECK_EQUAL(slAnnounceSync(pa2, 2959, 1_h), SlAnnounceResult::VALIDATION_FAILURE);
216 BOOST_CHECK(findAnnRoute("/1nzAe0Y4", 2959) == nullptr);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000217}
218
219BOOST_AUTO_TEST_CASE(AnnounceValidationError)
220{
Teng Liang18c2b292019-10-18 14:31:04 -0700221 ConfigSection section;
222 section.put("rule.id", "PA");
223 section.put("rule.for", "data");
224 section.put("rule.checker.type", "customized");
225 section.put("rule.checker.sig-type", "rsa-sha256");
226 section.put("rule.checker.key-locator.type", "name");
227 section.put("rule.checker.key-locator.name", "/trusted");
228 section.put("rule.checker.key-locator.relation", "is-prefix-of");
229 section.put("trust-anchor.type", "base64");
230 section.put("trust-anchor.base64-string", getIdentityCertificateBase64("/trusted"));
231 manager->applyPaConfig(section, "trust-schema.section");
232
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000233 auto pa = makeUntrustedAnn("/1nzAe0Y4", 1_h);
234 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2959, 1_h), SlAnnounceResult::VALIDATION_FAILURE);
235
236 BOOST_CHECK(findAnnRoute("/1nzAe0Y4", 2959) == nullptr);
237}
238
239BOOST_AUTO_TEST_CASE(AnnounceInsert_AnnLifetime)
240{
241 auto pa = makeTrustedAnn("/EHJYmJz9", 1_h);
242 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 1641, 2_h), SlAnnounceResult::OK);
243
244 Route* route = findAnnRoute("/EHJYmJz9", 1641);
245 BOOST_REQUIRE(route != nullptr);
246 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 1_h);
247 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 1_h);
248}
249
250BOOST_AUTO_TEST_CASE(AnnounceInsert_ArgLifetime)
251{
252 auto pa = makeTrustedAnn("/BU9Fec9E", 2_h);
253 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 1282, 1_h), SlAnnounceResult::OK);
254
255 Route* route = findAnnRoute("/BU9Fec9E", 1282);
256 BOOST_REQUIRE(route != nullptr);
257 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 2_h);
258 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 1_h);
259}
260
261BOOST_AUTO_TEST_CASE(AnnounceReplace)
262{
263 auto pa = makeTrustedAnn("/HsBFGvL3", 1_h);
264 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2813, 1_h), SlAnnounceResult::OK);
265
266 pa = makeTrustedAnn("/HsBFGvL3", 2_h);
267 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2813, 2_h), SlAnnounceResult::OK);
268
269 Route* route = findAnnRoute("/HsBFGvL3", 2813);
270 BOOST_REQUIRE(route != nullptr);
271 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 2_h);
272 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 2_h);
273}
274
275BOOST_AUTO_TEST_CASE(AnnounceExpired)
276{
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -0400277 auto pa = makeTrustedAnn("/awrVv6V7", 1_h, std::pair(-3_h, -1_h));
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000278 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 9087, 1_h), SlAnnounceResult::EXPIRED);
279
280 BOOST_CHECK(findAnnRoute("/awrVv6V7", 9087) == nullptr);
281}
282
283BOOST_AUTO_TEST_CASE(RenewNotFound)
284{
285 BOOST_CHECK_EQUAL(slRenewSync("IAYigN73", 1070, 1_h), SlAnnounceResult::NOT_FOUND);
286
287 BOOST_CHECK(findAnnRoute("/IAYigN73", 1070) == nullptr);
288}
289
290BOOST_AUTO_TEST_CASE(RenewProlong_ArgLifetime)
291{
292 auto pa = makeTrustedAnn("/P2IYFqtr", 4_h);
293 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 4506, 2_h), SlAnnounceResult::OK);
294 advanceClocks(1_h); // Route has 1_h remaining lifetime
295
Teng Lianga4e6ec32018-10-21 09:25:00 -0700296 BOOST_CHECK_EQUAL(slRenewSync("/P2IYFqtr/2321", 4506, 2_h), SlAnnounceResult::OK);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000297
298 Route* route = findAnnRoute("/P2IYFqtr", 4506);
299 BOOST_REQUIRE(route != nullptr);
300 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 3_h);
301 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 2_h); // set by slRenew
302}
303
304BOOST_AUTO_TEST_CASE(RenewProlong_AnnLifetime)
305{
306 auto pa = makeTrustedAnn("/be01Yiba", 4_h);
307 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 1589, 2_h), SlAnnounceResult::OK);
308 advanceClocks(1_h); // Route has 1_h remaining lifetime
309
Teng Lianga4e6ec32018-10-21 09:25:00 -0700310 BOOST_CHECK_EQUAL(slRenewSync("/be01Yiba/4324", 1589, 5_h), SlAnnounceResult::OK);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000311
312 Route* route = findAnnRoute("/be01Yiba", 1589);
313 BOOST_REQUIRE(route != nullptr);
314 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 3_h);
315 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 3_h); // capped by annExpires
316}
317
318BOOST_AUTO_TEST_CASE(RenewShorten)
319{
320 auto pa = makeTrustedAnn("/5XCHYCAd", 4_h);
321 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 3851, 4_h), SlAnnounceResult::OK);
322 advanceClocks(1_h); // Route has 3_h remaining lifetime
323
Teng Lianga4e6ec32018-10-21 09:25:00 -0700324 BOOST_CHECK_EQUAL(slRenewSync("/5XCHYCAd/98934", 3851, 1_h), SlAnnounceResult::OK);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000325
326 Route* route = findAnnRoute("/5XCHYCAd", 3851);
327 BOOST_REQUIRE(route != nullptr);
328 BOOST_CHECK_EQUAL(route->annExpires, time::steady_clock::now() + 3_h);
329 BOOST_CHECK_EQUAL(route->expires.value(), time::steady_clock::now() + 1_h); // set by slRenew
330}
331
332BOOST_AUTO_TEST_CASE(RenewShorten_Zero)
333{
334 auto pa = makeTrustedAnn("/cdQ7KPNw", 4_h);
335 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 8031, 4_h), SlAnnounceResult::OK);
336 advanceClocks(1_h); // Route has 3_h remaining lifetime
337
Teng Lianga4e6ec32018-10-21 09:25:00 -0700338 BOOST_CHECK_EQUAL(slRenewSync("/cdQ7KPNw/8023", 8031, 0_s), SlAnnounceResult::EXPIRED);
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000339
340 BOOST_CHECK(findAnnRoute("/cdQ7KPNw", 8031) == nullptr);
341}
342
343BOOST_AUTO_TEST_CASE(FindExisting)
344{
345 auto pa = makeTrustedAnn("/JHugsjjr", 1_h);
346 BOOST_CHECK_EQUAL(slAnnounceSync(pa, 2363, 1_h), SlAnnounceResult::OK);
347
348 auto found = slFindAnnSync("/JHugsjjr");
349 BOOST_REQUIRE(found);
350 BOOST_CHECK_EQUAL(found->getAnnouncedName(), "/JHugsjjr");
351 BOOST_CHECK(found->getData());
352
353 auto found2 = slFindAnnSync("/JHugsjjr/StvXhKR5");
354 BOOST_CHECK(found == found2);
355}
356
357BOOST_AUTO_TEST_CASE(FindNew)
358{
359 Route route;
360 route.faceId = 1367;
361 route.origin = ndn::nfd::ROUTE_ORIGIN_APP;
362 rib.insert("/dLY1pRhR", route);
363
364 auto pa = slFindAnnSync("/dLY1pRhR/3qNK9Ngn");
365 BOOST_REQUIRE(pa);
366 BOOST_CHECK_EQUAL(pa->getAnnouncedName(), "/dLY1pRhR");
367}
368
369BOOST_AUTO_TEST_CASE(FindNone)
370{
371 auto pa = slFindAnnSync("/2YNeYuV2");
372 BOOST_CHECK(!pa);
373}
374
Davide Pesavento8a05c7f2019-02-28 02:26:19 -0500375BOOST_AUTO_TEST_SUITE_END() // SlAnnounce
376BOOST_AUTO_TEST_SUITE_END() // TestRibManager
377BOOST_AUTO_TEST_SUITE_END() // Mgmt
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000378
379} // namespace tests
Junxiao Shi5ba7dfc2018-09-26 14:24:05 +0000380} // namespace nfd