blob: 6fbb6880a28488005b3a6b29c07faf657a49fb77 [file] [log] [blame]
Junxiao Shi8c8d2182014-01-30 22:33:00 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shifc2e13d2017-07-25 02:08:48 +00002/*
Davide Pesaventob7bfcb92022-05-22 23:55:23 -04003 * Copyright (c) 2014-2022, Regents of the University of California,
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08004 * 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.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
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/>.
Junxiao Shi82e7f582014-09-07 15:15:40 -070024 */
Junxiao Shi8c8d2182014-01-30 22:33:00 -070025
26#include "fw/forwarder.hpp"
Davide Pesavento2cae8ca2019-04-18 20:48:05 -040027#include "common/global.hpp"
Junxiao Shi8c8d2182014-01-30 22:33:00 -070028
Junxiao Shid9ee45c2014-02-27 15:38:11 -070029#include "tests/test-common.hpp"
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040030#include "tests/daemon/global-io-fixture.hpp"
Junxiao Shi06a1eab2017-09-04 13:13:02 +000031#include "tests/daemon/face/dummy-face.hpp"
32#include "choose-strategy.hpp"
33#include "dummy-strategy.hpp"
34
35#include <ndn-cxx/lp/tags.hpp>
Junxiao Shi8c8d2182014-01-30 22:33:00 -070036
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040037namespace nfd::tests {
Junxiao Shi8c8d2182014-01-30 22:33:00 -070038
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040039class ForwarderFixture : public GlobalIoTimeFixture
40{
41protected:
42 template<typename ...Args>
43 shared_ptr<DummyFace>
44 addFace(Args&&... args)
45 {
46 auto face = make_shared<DummyFace>(std::forward<Args>(args)...);
47 faceTable.add(face);
48 return face;
49 }
50
51protected:
52 FaceTable faceTable;
53 Forwarder forwarder{faceTable};
54};
55
Junxiao Shi0355e9f2015-09-02 07:24:53 -070056BOOST_AUTO_TEST_SUITE(Fw)
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040057BOOST_FIXTURE_TEST_SUITE(TestForwarder, ForwarderFixture)
Junxiao Shi8c8d2182014-01-30 22:33:00 -070058
Junxiao Shi8c8d2182014-01-30 22:33:00 -070059BOOST_AUTO_TEST_CASE(SimpleExchange)
60{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040061 auto face1 = addFace();
62 auto face2 = addFace();
Junxiao Shic041ca32014-02-25 20:01:15 -070063
Junxiao Shi8c8d2182014-01-30 22:33:00 -070064 Fib& fib = forwarder.getFib();
Ju Pand8315bf2019-07-31 06:59:07 +000065 fib::Entry* entry = fib.insert("/A").first;
66 fib.addOrUpdateNextHop(*entry, *face2, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -070067
Junxiao Shida93f1f2015-11-11 06:13:16 -070068 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 0);
69 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 0);
Junxiao Shi06a1eab2017-09-04 13:13:02 +000070 BOOST_CHECK_EQUAL(forwarder.getCounters().nCsHits, 0);
71 BOOST_CHECK_EQUAL(forwarder.getCounters().nCsMisses, 0);
Teng Liangd94b7b32022-07-10 21:29:37 +080072 face1->receiveInterest(*makeInterest("/A/B"));
Davide Pesavento14e71f02019-03-28 17:35:25 -040073 this->advanceClocks(100_ms, 1_s);
Junxiao Shicde37ad2015-12-24 01:02:05 -070074 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shia6de4292016-07-12 02:08:10 +000075 BOOST_CHECK_EQUAL(face2->sentInterests[0].getName(), "/A/B");
Junxiao Shicde37ad2015-12-24 01:02:05 -070076 BOOST_REQUIRE(face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
77 BOOST_CHECK_EQUAL(*face2->sentInterests[0].getTag<lp::IncomingFaceIdTag>(), face1->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070078 BOOST_CHECK_EQUAL(forwarder.getCounters().nInInterests, 1);
79 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutInterests, 1);
Junxiao Shi06a1eab2017-09-04 13:13:02 +000080 BOOST_CHECK_EQUAL(forwarder.getCounters().nCsHits, 0);
81 BOOST_CHECK_EQUAL(forwarder.getCounters().nCsMisses, 1);
Alex Lane6bead9b2020-05-12 19:08:20 -050082 BOOST_CHECK_EQUAL(forwarder.getCounters().nSatisfiedInterests, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -070083
Junxiao Shida93f1f2015-11-11 06:13:16 -070084 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 0);
85 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 0);
Teng Liangd94b7b32022-07-10 21:29:37 +080086 face2->receiveData(*makeData("/A/B"));
Davide Pesavento14e71f02019-03-28 17:35:25 -040087 this->advanceClocks(100_ms, 1_s);
Junxiao Shicde37ad2015-12-24 01:02:05 -070088 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shi9d727852019-05-14 13:44:22 -060089 BOOST_CHECK_EQUAL(face1->sentData[0].getName(), "/A/B");
Junxiao Shicde37ad2015-12-24 01:02:05 -070090 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
91 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face2->getId());
Junxiao Shida93f1f2015-11-11 06:13:16 -070092 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 1);
93 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 1);
Alex Lane6bead9b2020-05-12 19:08:20 -050094 BOOST_CHECK_EQUAL(forwarder.getCounters().nInNacks, 0);
95 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutNacks, 0);
96 BOOST_CHECK_EQUAL(forwarder.getCounters().nSatisfiedInterests, 1);
97 BOOST_CHECK_EQUAL(forwarder.getCounters().nUnsolicitedData, 0);
Junxiao Shi8c8d2182014-01-30 22:33:00 -070098}
99
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700100BOOST_AUTO_TEST_CASE(CsMatched)
101{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400102 auto face1 = addFace();
103 auto face2 = addFace();
104 auto face3 = addFace();
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700105
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700106 Fib& fib = forwarder.getFib();
Ju Pand8315bf2019-07-31 06:59:07 +0000107 fib::Entry* entry = fib.insert("/A").first;
108 fib.addOrUpdateNextHop(*entry, *face2, 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700109
110 Pit& pit = forwarder.getPit();
111 BOOST_CHECK_EQUAL(pit.size(), 0);
112
Junxiao Shi9d727852019-05-14 13:44:22 -0600113 auto data = makeData("/A/B");
114 data->setTag(make_shared<lp::IncomingFaceIdTag>(face3->getId()));
115 forwarder.getCs().insert(*data);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700116
Junxiao Shi06a1eab2017-09-04 13:13:02 +0000117 BOOST_CHECK_EQUAL(forwarder.getCounters().nCsHits, 0);
118 BOOST_CHECK_EQUAL(forwarder.getCounters().nCsMisses, 0);
Teng Liangd94b7b32022-07-10 21:29:37 +0800119 face1->receiveInterest(*makeInterest("/A", true));
Davide Pesavento14e71f02019-03-28 17:35:25 -0400120 this->advanceClocks(1_ms, 5_ms);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700121 // Interest matching ContentStore should not be forwarded
Junxiao Shicde37ad2015-12-24 01:02:05 -0700122 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 0);
Junxiao Shi06a1eab2017-09-04 13:13:02 +0000123 BOOST_CHECK_EQUAL(forwarder.getCounters().nCsHits, 1);
124 BOOST_CHECK_EQUAL(forwarder.getCounters().nCsMisses, 0);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700125
Junxiao Shicde37ad2015-12-24 01:02:05 -0700126 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700127 // IncomingFaceId field should be reset to represent CS
Junxiao Shi9d727852019-05-14 13:44:22 -0600128 BOOST_CHECK_EQUAL(face1->sentData[0].getName(), "/A/B");
Junxiao Shicde37ad2015-12-24 01:02:05 -0700129 BOOST_REQUIRE(face1->sentData[0].getTag<lp::IncomingFaceIdTag>() != nullptr);
130 BOOST_CHECK_EQUAL(*face1->sentData[0].getTag<lp::IncomingFaceIdTag>(), face::FACEID_CONTENT_STORE);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700131
Davide Pesavento14e71f02019-03-28 17:35:25 -0400132 this->advanceClocks(100_ms, 500_ms);
Junxiao Shiad3f1cb2014-08-18 11:12:30 -0700133 // PIT entry should not be left behind
134 BOOST_CHECK_EQUAL(pit.size(), 0);
135}
136
Eric Newberryfdc06452020-06-23 22:40:16 -0700137BOOST_AUTO_TEST_CASE(InterestWithoutNonce)
138{
139 auto face1 = addFace();
140 auto face2 = addFace();
141
142 Fib& fib = forwarder.getFib();
143 fib::Entry* entry = fib.insert("/A").first;
144 fib.addOrUpdateNextHop(*entry, *face2, 0);
145
146 auto interest = makeInterest("/A");
147 BOOST_CHECK_EQUAL(interest->hasNonce(), false);
Teng Liangd94b7b32022-07-10 21:29:37 +0800148 face1->receiveInterest(*interest);
Eric Newberryfdc06452020-06-23 22:40:16 -0700149
150 // Ensure Nonce added if incoming packet did not have Nonce
151 BOOST_REQUIRE_EQUAL(face2->getCounters().nOutInterests, 1);
152 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
153 BOOST_CHECK_EQUAL(face2->sentInterests.back().hasNonce(), true);
154}
155
Junxiao Shi891f47b2016-06-20 00:02:11 +0000156BOOST_AUTO_TEST_CASE(OutgoingInterest)
157{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400158 auto face1 = addFace();
159 auto face2 = addFace();
Junxiao Shi891f47b2016-06-20 00:02:11 +0000160
161 Pit& pit = forwarder.getPit();
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400162 auto interestA1 = makeInterest("/A", false, std::nullopt, 8378);
Eric Newberry2377ada2020-09-28 22:40:14 -0700163 auto pitA = pit.insert(*interestA1).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000164 pitA->insertOrUpdateInRecord(*face1, *interestA1);
Junxiao Shi891f47b2016-06-20 00:02:11 +0000165
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400166 auto interestA2 = makeInterest("/A", false, std::nullopt, 1698);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400167 auto outA2 = forwarder.onOutgoingInterest(*interestA2, *face2, pitA);
Eric Newberry2377ada2020-09-28 22:40:14 -0700168 BOOST_REQUIRE(outA2 != nullptr);
Junxiao Shic5f651f2016-11-17 22:58:12 +0000169 BOOST_CHECK_EQUAL(outA2->getLastNonce(), 1698);
Junxiao Shi891f47b2016-06-20 00:02:11 +0000170
Eric Newberry2377ada2020-09-28 22:40:14 -0700171 // This packet will be dropped because HopLimit=0
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400172 auto interestA3 = makeInterest("/A", false, std::nullopt, 9876);
Eric Newberry2377ada2020-09-28 22:40:14 -0700173 interestA3->setHopLimit(0);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400174 auto outA3 = forwarder.onOutgoingInterest(*interestA3, *face2, pitA);
Eric Newberry2377ada2020-09-28 22:40:14 -0700175 BOOST_CHECK(outA3 == nullptr);
176
Junxiao Shi891f47b2016-06-20 00:02:11 +0000177 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shic5f651f2016-11-17 22:58:12 +0000178 BOOST_CHECK_EQUAL(face2->sentInterests.back().getNonce(), 1698);
Junxiao Shi891f47b2016-06-20 00:02:11 +0000179}
180
Junxiao Shie342e8d2016-09-18 16:48:00 +0000181BOOST_AUTO_TEST_CASE(NextHopFaceId)
182{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400183 auto face1 = addFace();
184 auto face2 = addFace();
185 auto face3 = addFace();
Junxiao Shie342e8d2016-09-18 16:48:00 +0000186
187 Fib& fib = forwarder.getFib();
Ju Pand8315bf2019-07-31 06:59:07 +0000188 fib::Entry* entry = fib.insert("/A").first;
189 fib.addOrUpdateNextHop(*entry, *face3, 0);
Junxiao Shie342e8d2016-09-18 16:48:00 +0000190
Junxiao Shi9d727852019-05-14 13:44:22 -0600191 auto interest = makeInterest("/A/B");
Junxiao Shie342e8d2016-09-18 16:48:00 +0000192 interest->setTag(make_shared<lp::NextHopFaceIdTag>(face2->getId()));
193
Teng Liangd94b7b32022-07-10 21:29:37 +0800194 face1->receiveInterest(*interest);
Davide Pesavento14e71f02019-03-28 17:35:25 -0400195 this->advanceClocks(100_ms, 1_s);
Junxiao Shie342e8d2016-09-18 16:48:00 +0000196 BOOST_CHECK_EQUAL(face3->sentInterests.size(), 0);
197 BOOST_REQUIRE_EQUAL(face2->sentInterests.size(), 1);
198 BOOST_CHECK_EQUAL(face2->sentInterests.front().getName(), "/A/B");
199}
200
Eric Newberry9d283ad2020-04-12 23:37:17 -0700201BOOST_AUTO_TEST_CASE(HopLimit)
202{
203 auto faceIn = addFace();
204 auto faceRemote = addFace("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_NON_LOCAL);
205 auto faceLocal = addFace("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
206 Fib& fib = forwarder.getFib();
207 fib::Entry* entryRemote = fib.insert("/remote").first;
208 fib.addOrUpdateNextHop(*entryRemote, *faceRemote, 0);
209 fib::Entry* entryLocal = fib.insert("/local").first;
210 fib.addOrUpdateNextHop(*entryLocal, *faceLocal, 0);
211
212 // Incoming interest w/o HopLimit will not be dropped on send or receive paths
213 auto interestNoHopLimit = makeInterest("/remote/abcdefgh");
Teng Liangd94b7b32022-07-10 21:29:37 +0800214 faceIn->receiveInterest(*interestNoHopLimit);
Eric Newberry9d283ad2020-04-12 23:37:17 -0700215 this->advanceClocks(100_ms, 1_s);
216 BOOST_CHECK_EQUAL(faceRemote->sentInterests.size(), 1);
217 BOOST_CHECK_EQUAL(faceRemote->getCounters().nInHopLimitZero, 0);
218 BOOST_CHECK_EQUAL(faceRemote->getCounters().nOutHopLimitZero, 0);
219 BOOST_REQUIRE_EQUAL(faceRemote->sentInterests.size(), 1);
220 BOOST_CHECK(!faceRemote->sentInterests.back().getHopLimit());
221
222 // Incoming interest w/ HopLimit > 1 will not be dropped on send/receive
223 auto interestHopLimit2 = makeInterest("/remote/ijklmnop");
224 interestHopLimit2->setHopLimit(2);
Teng Liangd94b7b32022-07-10 21:29:37 +0800225 faceIn->receiveInterest(*interestHopLimit2);
Eric Newberry9d283ad2020-04-12 23:37:17 -0700226 this->advanceClocks(100_ms, 1_s);
227 BOOST_CHECK_EQUAL(faceRemote->getCounters().nOutInterests, 2);
228 BOOST_CHECK_EQUAL(faceRemote->getCounters().nInHopLimitZero, 0);
229 BOOST_CHECK_EQUAL(faceRemote->getCounters().nOutHopLimitZero, 0);
230 BOOST_REQUIRE_EQUAL(faceRemote->sentInterests.size(), 2);
231 BOOST_REQUIRE(faceRemote->sentInterests.back().getHopLimit());
232 BOOST_CHECK_EQUAL(*faceRemote->sentInterests.back().getHopLimit(), 1);
233
234 // Incoming interest w/ HopLimit == 1 will be dropped on send path if going out on remote face
235 auto interestHopLimit1Remote = makeInterest("/remote/qrstuvwx");
236 interestHopLimit1Remote->setHopLimit(1);
Teng Liangd94b7b32022-07-10 21:29:37 +0800237 faceIn->receiveInterest(*interestHopLimit1Remote);
Eric Newberry9d283ad2020-04-12 23:37:17 -0700238 this->advanceClocks(100_ms, 1_s);
239 BOOST_CHECK_EQUAL(faceRemote->getCounters().nOutInterests, 2);
240 BOOST_CHECK_EQUAL(faceRemote->getCounters().nInHopLimitZero, 0);
241 BOOST_CHECK_EQUAL(faceRemote->getCounters().nOutHopLimitZero, 1);
242 BOOST_CHECK_EQUAL(faceRemote->sentInterests.size(), 2);
243
244 // Incoming interest w/ HopLimit == 1 will not be dropped on send path if going out on local face
245 auto interestHopLimit1Local = makeInterest("/local/abcdefgh");
246 interestHopLimit1Local->setHopLimit(1);
Teng Liangd94b7b32022-07-10 21:29:37 +0800247 faceIn->receiveInterest(*interestHopLimit1Local);
Eric Newberry9d283ad2020-04-12 23:37:17 -0700248 this->advanceClocks(100_ms, 1_s);
249 BOOST_CHECK_EQUAL(faceLocal->getCounters().nOutInterests, 1);
250 BOOST_CHECK_EQUAL(faceLocal->getCounters().nInHopLimitZero, 0);
251 BOOST_CHECK_EQUAL(faceLocal->getCounters().nOutHopLimitZero, 0);
252 BOOST_REQUIRE_EQUAL(faceLocal->sentInterests.size(), 1);
253 BOOST_REQUIRE(faceLocal->sentInterests.back().getHopLimit());
254 BOOST_CHECK_EQUAL(*faceLocal->sentInterests.back().getHopLimit(), 0);
255
256 // Interest w/ HopLimit == 0 will be dropped on receive path
257 auto interestHopLimit0 = makeInterest("/remote/yzabcdef");
258 interestHopLimit0->setHopLimit(0);
Teng Liangd94b7b32022-07-10 21:29:37 +0800259 faceIn->receiveInterest(*interestHopLimit0);
Eric Newberry9d283ad2020-04-12 23:37:17 -0700260 this->advanceClocks(100_ms, 1_s);
261 BOOST_CHECK_EQUAL(faceRemote->getCounters().nOutInterests, 2);
262 BOOST_CHECK_EQUAL(faceIn->getCounters().nInHopLimitZero, 1);
263 BOOST_CHECK_EQUAL(faceRemote->getCounters().nOutHopLimitZero, 1);
264 BOOST_CHECK_EQUAL(faceRemote->sentInterests.size(), 2);
265}
266
Philipp Molla1033342021-06-14 09:34:21 +0200267BOOST_AUTO_TEST_CASE(AddDefaultHopLimit)
268{
269 auto face = addFace();
Teng Liangd94b7b32022-07-10 21:29:37 +0800270 auto faceEndpoint = FaceEndpoint(*face);
Philipp Molla1033342021-06-14 09:34:21 +0200271 Pit& pit = forwarder.getPit();
272 auto i1 = makeInterest("/A");
273 auto pitA = pit.insert(*i1).first;
274
275 // By default, no HopLimit should be added
276 auto i2 = makeInterest("/A");
277 BOOST_TEST(!i2->getHopLimit().has_value());
278 forwarder.onContentStoreMiss(*i2, faceEndpoint, pitA);
279 BOOST_TEST(!i2->getHopLimit().has_value());
280
281 // Change config value to 10
282 forwarder.m_config.defaultHopLimit = 10;
283
284 // HopLimit should be set to 10 now
285 auto i3 = makeInterest("/A");
286 BOOST_TEST(!i3->getHopLimit().has_value());
287 forwarder.onContentStoreMiss(*i3, faceEndpoint, pitA);
288 BOOST_REQUIRE(i3->getHopLimit().has_value());
289 BOOST_TEST(*i3->getHopLimit() == 10);
290
291 // An existing HopLimit should be preserved
292 auto i4 = makeInterest("/A");
293 i4->setHopLimit(50);
294 forwarder.onContentStoreMiss(*i4, faceEndpoint, pitA);
295 BOOST_REQUIRE(i4->getHopLimit().has_value());
296 BOOST_TEST(*i4->getHopLimit() == 50);
297}
298
Davide Pesavento05590472021-02-17 15:53:27 -0500299BOOST_AUTO_TEST_CASE(ScopeLocalhostIncoming)
Junxiao Shi88884492014-02-15 15:57:43 -0700300{
Davide Pesavento05590472021-02-17 15:53:27 -0500301 auto face1 = addFace("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
302 auto face2 = addFace(); // default is non-local
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400303
Davide Pesavento05590472021-02-17 15:53:27 -0500304 auto& strategy = choose<DummyStrategy>(forwarder, "/", DummyStrategy::getStrategyName());
Junxiao Shic041ca32014-02-25 20:01:15 -0700305
Junxiao Shi88884492014-02-15 15:57:43 -0700306 // local face, /localhost: OK
Davide Pesavento05590472021-02-17 15:53:27 -0500307 strategy.afterReceiveInterest_count = 0;
Junxiao Shi9d727852019-05-14 13:44:22 -0600308 auto i1 = makeInterest("/localhost/A1");
Teng Liangd94b7b32022-07-10 21:29:37 +0800309 forwarder.onIncomingInterest(*i1, FaceEndpoint(*face1));
Davide Pesavento05590472021-02-17 15:53:27 -0500310 BOOST_CHECK_EQUAL(strategy.afterReceiveInterest_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700311
Junxiao Shi88884492014-02-15 15:57:43 -0700312 // non-local face, /localhost: violate
Davide Pesavento05590472021-02-17 15:53:27 -0500313 strategy.afterReceiveInterest_count = 0;
Junxiao Shi9d727852019-05-14 13:44:22 -0600314 auto i2 = makeInterest("/localhost/A2");
Teng Liangd94b7b32022-07-10 21:29:37 +0800315 forwarder.onIncomingInterest(*i2, FaceEndpoint(*face2));
Davide Pesavento05590472021-02-17 15:53:27 -0500316 BOOST_CHECK_EQUAL(strategy.afterReceiveInterest_count, 0);
Junxiao Shic041ca32014-02-25 20:01:15 -0700317
Junxiao Shi88884492014-02-15 15:57:43 -0700318 // local face, non-/localhost: OK
Davide Pesavento05590472021-02-17 15:53:27 -0500319 strategy.afterReceiveInterest_count = 0;
Junxiao Shi9d727852019-05-14 13:44:22 -0600320 auto i3 = makeInterest("/A3");
Teng Liangd94b7b32022-07-10 21:29:37 +0800321 forwarder.onIncomingInterest(*i3, FaceEndpoint(*face1));
Davide Pesavento05590472021-02-17 15:53:27 -0500322 BOOST_CHECK_EQUAL(strategy.afterReceiveInterest_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700323
Junxiao Shi88884492014-02-15 15:57:43 -0700324 // non-local face, non-/localhost: OK
Davide Pesavento05590472021-02-17 15:53:27 -0500325 strategy.afterReceiveInterest_count = 0;
Junxiao Shi9d727852019-05-14 13:44:22 -0600326 auto i4 = makeInterest("/A4");
Teng Liangd94b7b32022-07-10 21:29:37 +0800327 forwarder.onIncomingInterest(*i4, FaceEndpoint(*face2));
Davide Pesavento05590472021-02-17 15:53:27 -0500328 BOOST_CHECK_EQUAL(strategy.afterReceiveInterest_count, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700329
Alex Lane6bead9b2020-05-12 19:08:20 -0500330 BOOST_CHECK_EQUAL(forwarder.getCounters().nUnsolicitedData, 0);
331
Junxiao Shi88884492014-02-15 15:57:43 -0700332 // local face, /localhost: OK
Junxiao Shi9d727852019-05-14 13:44:22 -0600333 auto d1 = makeData("/localhost/B1");
Teng Liangd94b7b32022-07-10 21:29:37 +0800334 forwarder.onIncomingData(*d1, FaceEndpoint(*face1));
Alex Lane6bead9b2020-05-12 19:08:20 -0500335 BOOST_CHECK_EQUAL(forwarder.getCounters().nUnsolicitedData, 1);
Junxiao Shi88884492014-02-15 15:57:43 -0700336
Davide Pesavento05590472021-02-17 15:53:27 -0500337 // non-local face, /localhost: violate
Junxiao Shi9d727852019-05-14 13:44:22 -0600338 auto d2 = makeData("/localhost/B2");
Teng Liangd94b7b32022-07-10 21:29:37 +0800339 forwarder.onIncomingData(*d2, FaceEndpoint(*face2));
Alex Lane6bead9b2020-05-12 19:08:20 -0500340 BOOST_CHECK_EQUAL(forwarder.getCounters().nUnsolicitedData, 1);
Junxiao Shic041ca32014-02-25 20:01:15 -0700341
Junxiao Shi88884492014-02-15 15:57:43 -0700342 // local face, non-/localhost: OK
Junxiao Shi9d727852019-05-14 13:44:22 -0600343 auto d3 = makeData("/B3");
Teng Liangd94b7b32022-07-10 21:29:37 +0800344 forwarder.onIncomingData(*d3, FaceEndpoint(*face1));
Alex Lane6bead9b2020-05-12 19:08:20 -0500345 BOOST_CHECK_EQUAL(forwarder.getCounters().nUnsolicitedData, 2);
Junxiao Shi88884492014-02-15 15:57:43 -0700346
347 // non-local face, non-/localhost: OK
Junxiao Shi9d727852019-05-14 13:44:22 -0600348 auto d4 = makeData("/B4");
Teng Liangd94b7b32022-07-10 21:29:37 +0800349 forwarder.onIncomingData(*d4, FaceEndpoint(*face2));
Alex Lane6bead9b2020-05-12 19:08:20 -0500350 BOOST_CHECK_EQUAL(forwarder.getCounters().nUnsolicitedData, 3);
Junxiao Shi88884492014-02-15 15:57:43 -0700351}
352
Junxiao Shi0355e9f2015-09-02 07:24:53 -0700353BOOST_AUTO_TEST_CASE(IncomingInterestStrategyDispatch)
Junxiao Shif3c07812014-03-11 21:48:49 -0700354{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400355 auto face1 = addFace();
356 auto face2 = addFace();
Junxiao Shif3c07812014-03-11 21:48:49 -0700357
Eric Newberry2377ada2020-09-28 22:40:14 -0700358 auto& strategyA = choose<DummyStrategy>(forwarder, "/", DummyStrategy::getStrategyName());
359 auto& strategyB = choose<DummyStrategy>(forwarder, "/B", DummyStrategy::getStrategyName());
Junxiao Shif3c07812014-03-11 21:48:49 -0700360
Junxiao Shi9d727852019-05-14 13:44:22 -0600361 auto interest1 = makeInterest("/A/1");
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000362 strategyA.afterReceiveInterest_count = 0;
363 strategyA.interestOutFace = face2;
Teng Liangd94b7b32022-07-10 21:29:37 +0800364 forwarder.onIncomingInterest(*interest1, FaceEndpoint(*face1));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000365 BOOST_CHECK_EQUAL(strategyA.afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700366
Junxiao Shi9d727852019-05-14 13:44:22 -0600367 auto interest2 = makeInterest("/B/2", true);
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000368 strategyB.afterReceiveInterest_count = 0;
369 strategyB.interestOutFace = face2;
Teng Liangd94b7b32022-07-10 21:29:37 +0800370 forwarder.onIncomingInterest(*interest2, FaceEndpoint(*face1));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000371 BOOST_CHECK_EQUAL(strategyB.afterReceiveInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700372
Davide Pesavento14e71f02019-03-28 17:35:25 -0400373 this->advanceClocks(1_ms, 5_ms);
Junxiao Shif3c07812014-03-11 21:48:49 -0700374
Junxiao Shi9d727852019-05-14 13:44:22 -0600375 auto data1 = makeData("/A/1");
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000376 strategyA.beforeSatisfyInterest_count = 0;
Teng Liangd94b7b32022-07-10 21:29:37 +0800377 forwarder.onIncomingData(*data1, FaceEndpoint(*face2));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000378 BOOST_CHECK_EQUAL(strategyA.beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700379
Junxiao Shi9d727852019-05-14 13:44:22 -0600380 auto data2 = makeData("/B/2/b");
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000381 strategyB.beforeSatisfyInterest_count = 0;
Teng Liangd94b7b32022-07-10 21:29:37 +0800382 forwarder.onIncomingData(*data2, FaceEndpoint(*face2));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000383 BOOST_CHECK_EQUAL(strategyB.beforeSatisfyInterest_count, 1);
Junxiao Shif3c07812014-03-11 21:48:49 -0700384
Junxiao Shi9d727852019-05-14 13:44:22 -0600385 auto interest3 = makeInterest("/A/3", false, 30_ms);
Teng Liangd94b7b32022-07-10 21:29:37 +0800386 forwarder.onIncomingInterest(*interest3, FaceEndpoint(*face1));
Junxiao Shi9d727852019-05-14 13:44:22 -0600387 auto interest4 = makeInterest("/B/4", false, 5_s);
Teng Liangd94b7b32022-07-10 21:29:37 +0800388 forwarder.onIncomingInterest(*interest4, FaceEndpoint(*face1));
Junxiao Shif3c07812014-03-11 21:48:49 -0700389}
390
Junxiao Shida006f52014-05-16 11:18:00 -0700391BOOST_AUTO_TEST_CASE(IncomingData)
392{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400393 auto face1 = addFace();
394 auto face2 = addFace();
395 auto face3 = addFace();
396 auto face4 = addFace();
Junxiao Shida006f52014-05-16 11:18:00 -0700397
398 Pit& pit = forwarder.getPit();
Junxiao Shi9d727852019-05-14 13:44:22 -0600399 auto interestD = makeInterest("/A/B/C/D");
Eric Newberry2377ada2020-09-28 22:40:14 -0700400 auto pitD = pit.insert(*interestD).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000401 pitD->insertOrUpdateInRecord(*face1, *interestD);
Junxiao Shi9d727852019-05-14 13:44:22 -0600402 auto interestA = makeInterest("/A", true);
Eric Newberry2377ada2020-09-28 22:40:14 -0700403 auto pitA = pit.insert(*interestA).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000404 pitA->insertOrUpdateInRecord(*face2, *interestA);
405 pitA->insertOrUpdateInRecord(*face3, *interestA);
Junxiao Shi9d727852019-05-14 13:44:22 -0600406 auto interestC = makeInterest("/A/B/C", true);
Eric Newberry2377ada2020-09-28 22:40:14 -0700407 auto pitC = pit.insert(*interestC).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000408 pitC->insertOrUpdateInRecord(*face3, *interestC);
409 pitC->insertOrUpdateInRecord(*face4, *interestC);
Junxiao Shida006f52014-05-16 11:18:00 -0700410
Junxiao Shi9d727852019-05-14 13:44:22 -0600411 auto dataD = makeData("/A/B/C/D");
Teng Liangd94b7b32022-07-10 21:29:37 +0800412 forwarder.onIncomingData(*dataD, FaceEndpoint(*face3));
Davide Pesavento14e71f02019-03-28 17:35:25 -0400413 this->advanceClocks(1_ms, 5_ms);
Junxiao Shida006f52014-05-16 11:18:00 -0700414
Junxiao Shicde37ad2015-12-24 01:02:05 -0700415 BOOST_CHECK_EQUAL(face1->sentData.size(), 1);
416 BOOST_CHECK_EQUAL(face2->sentData.size(), 1);
417 BOOST_CHECK_EQUAL(face3->sentData.size(), 0);
418 BOOST_CHECK_EQUAL(face4->sentData.size(), 1);
Alex Lane6bead9b2020-05-12 19:08:20 -0500419
420 BOOST_CHECK_EQUAL(forwarder.getCounters().nInData, 1);
421 BOOST_CHECK_EQUAL(forwarder.getCounters().nOutData, 3);
422 BOOST_CHECK_EQUAL(forwarder.getCounters().nUnsolicitedData, 0);
Junxiao Shida006f52014-05-16 11:18:00 -0700423}
424
Eric Newberry2377ada2020-09-28 22:40:14 -0700425BOOST_AUTO_TEST_CASE(OutgoingData)
426{
427 auto face1 = addFace("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
428 auto face2 = addFace("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_NON_LOCAL);
429 auto face3 = addFace();
430 face3->setId(face::INVALID_FACEID);
431
432 auto data = makeData("/QkzAWU6K");
433 auto localData = makeData("/localhost/YH8bqnbv");
434
435 face1->sentData.clear();
436 BOOST_CHECK(forwarder.onOutgoingData(*data, *face1));
437 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
438 BOOST_CHECK_EQUAL(face1->sentData.back().getName(), data->getName());
439
440 // scope control
441 face1->sentData.clear();
442 face2->sentData.clear();
443 BOOST_CHECK(!forwarder.onOutgoingData(*localData, *face2));
444 BOOST_CHECK_EQUAL(face2->sentData.size(), 0);
445 BOOST_CHECK(forwarder.onOutgoingData(*localData, *face1));
446 BOOST_REQUIRE_EQUAL(face1->sentData.size(), 1);
447 BOOST_CHECK_EQUAL(face1->sentData.back().getName(), localData->getName());
448
449 // face with invalid ID
450 face3->sentData.clear();
451 BOOST_CHECK(!forwarder.onOutgoingData(*data, *face3));
452 BOOST_CHECK_EQUAL(face3->sentData.size(), 0);
453}
454
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700455BOOST_AUTO_TEST_CASE(IncomingNack)
456{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400457 auto face1 = addFace();
458 auto face2 = addFace();
459 auto face3 = addFace("dummy://", "dummy://",
460 ndn::nfd::FACE_SCOPE_NON_LOCAL,
461 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
462 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700463
Eric Newberry2377ada2020-09-28 22:40:14 -0700464 auto& strategyA = choose<DummyStrategy>(forwarder, "/", DummyStrategy::getStrategyName());
465 auto& strategyB = choose<DummyStrategy>(forwarder, "/B", DummyStrategy::getStrategyName());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700466
467 Pit& pit = forwarder.getPit();
468
469 // dispatch to the correct strategy
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400470 auto interest1 = makeInterest("/A/AYJqayrzF", false, std::nullopt, 562);
Eric Newberry2377ada2020-09-28 22:40:14 -0700471 auto pit1 = pit.insert(*interest1).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000472 pit1->insertOrUpdateOutRecord(*face1, *interest1);
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400473 auto interest2 = makeInterest("/B/EVyP73ru", false, std::nullopt, 221);
Eric Newberry2377ada2020-09-28 22:40:14 -0700474 auto pit2 = pit.insert(*interest2).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000475 pit2->insertOrUpdateOutRecord(*face1, *interest2);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700476
Eric Newberry2377ada2020-09-28 22:40:14 -0700477 auto nack1 = makeNack(*interest1, lp::NackReason::CONGESTION);
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000478 strategyA.afterReceiveNack_count = 0;
479 strategyB.afterReceiveNack_count = 0;
Teng Liangd94b7b32022-07-10 21:29:37 +0800480 forwarder.onIncomingNack(nack1, FaceEndpoint(*face1));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000481 BOOST_CHECK_EQUAL(strategyA.afterReceiveNack_count, 1);
482 BOOST_CHECK_EQUAL(strategyB.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700483
Eric Newberry2377ada2020-09-28 22:40:14 -0700484 auto nack2 = makeNack(*interest2, lp::NackReason::CONGESTION);
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000485 strategyA.afterReceiveNack_count = 0;
486 strategyB.afterReceiveNack_count = 0;
Teng Liangd94b7b32022-07-10 21:29:37 +0800487 forwarder.onIncomingNack(nack2, FaceEndpoint(*face1));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000488 BOOST_CHECK_EQUAL(strategyA.afterReceiveNack_count, 0);
489 BOOST_CHECK_EQUAL(strategyB.afterReceiveNack_count, 1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700490
491 // record Nack on PIT out-record
Alex Lane6bead9b2020-05-12 19:08:20 -0500492 auto outRecord1 = pit1->getOutRecord(*face1);
Junxiao Shi4846f372016-04-05 13:39:30 -0700493 BOOST_REQUIRE(outRecord1 != pit1->out_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700494 BOOST_REQUIRE(outRecord1->getIncomingNack() != nullptr);
495 BOOST_CHECK_EQUAL(outRecord1->getIncomingNack()->getReason(), lp::NackReason::CONGESTION);
496
497 // drop if no PIT entry
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400498 auto nack3 = makeNack(*makeInterest("/yEcw5HhdM", false, std::nullopt, 243), lp::NackReason::CONGESTION);
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000499 strategyA.afterReceiveNack_count = 0;
500 strategyB.afterReceiveNack_count = 0;
Teng Liangd94b7b32022-07-10 21:29:37 +0800501 forwarder.onIncomingNack(nack3, FaceEndpoint(*face1));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000502 BOOST_CHECK_EQUAL(strategyA.afterReceiveNack_count, 0);
503 BOOST_CHECK_EQUAL(strategyB.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700504
505 // drop if no out-record
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400506 auto interest4 = makeInterest("/Etab4KpY", false, std::nullopt, 157);
Eric Newberry2377ada2020-09-28 22:40:14 -0700507 auto pit4 = pit.insert(*interest4).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000508 pit4->insertOrUpdateOutRecord(*face1, *interest4);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700509
Eric Newberry2377ada2020-09-28 22:40:14 -0700510 auto nack4a = makeNack(*interest4, lp::NackReason::CONGESTION);
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000511 strategyA.afterReceiveNack_count = 0;
512 strategyB.afterReceiveNack_count = 0;
Teng Liangd94b7b32022-07-10 21:29:37 +0800513 forwarder.onIncomingNack(nack4a, FaceEndpoint(*face2));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000514 BOOST_CHECK_EQUAL(strategyA.afterReceiveNack_count, 0);
515 BOOST_CHECK_EQUAL(strategyB.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700516
517 // drop if Nonce does not match out-record
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400518 auto nack4b = makeNack(*makeInterest("/Etab4KpY", false, std::nullopt, 294), lp::NackReason::CONGESTION);
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000519 strategyA.afterReceiveNack_count = 0;
520 strategyB.afterReceiveNack_count = 0;
Teng Liangd94b7b32022-07-10 21:29:37 +0800521 forwarder.onIncomingNack(nack4b, FaceEndpoint(*face1));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000522 BOOST_CHECK_EQUAL(strategyA.afterReceiveNack_count, 0);
523 BOOST_CHECK_EQUAL(strategyB.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700524
525 // drop if inFace is multi-access
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000526 pit4->insertOrUpdateOutRecord(*face3, *interest4);
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000527 strategyA.afterReceiveNack_count = 0;
528 strategyB.afterReceiveNack_count = 0;
Teng Liangd94b7b32022-07-10 21:29:37 +0800529 forwarder.onIncomingNack(nack4a, FaceEndpoint(*face3));
Junxiao Shi0e4a1f12016-12-24 02:39:01 +0000530 BOOST_CHECK_EQUAL(strategyA.afterReceiveNack_count, 0);
531 BOOST_CHECK_EQUAL(strategyB.afterReceiveNack_count, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700532}
533
534BOOST_AUTO_TEST_CASE(OutgoingNack)
535{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400536 auto face1 = addFace();
537 auto face2 = addFace();
538 auto face3 = addFace("dummy://", "dummy://",
539 ndn::nfd::FACE_SCOPE_NON_LOCAL,
540 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
541 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
Eric Newberry2377ada2020-09-28 22:40:14 -0700542 auto face4 = addFace();
543 face4->setId(face::INVALID_FACEID);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700544
545 Pit& pit = forwarder.getPit();
546
547 lp::NackHeader nackHeader;
548 nackHeader.setReason(lp::NackReason::CONGESTION);
549
550 // don't send Nack if there's no in-record
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400551 auto interest1 = makeInterest("/fM5IVEtC", false, std::nullopt, 719);
Eric Newberry2377ada2020-09-28 22:40:14 -0700552 auto pit1 = pit.insert(*interest1).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000553 pit1->insertOrUpdateInRecord(*face1, *interest1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700554
555 face2->sentNacks.clear();
Davide Pesavento0498ce82021-06-14 02:02:21 -0400556 BOOST_CHECK(!forwarder.onOutgoingNack(nackHeader, *face2, pit1));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700557 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
558
559 // send Nack with correct Nonce
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400560 auto interest2a = makeInterest("/Vi8tRm9MG3", false, std::nullopt, 152);
Eric Newberry2377ada2020-09-28 22:40:14 -0700561 auto pit2 = pit.insert(*interest2a).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000562 pit2->insertOrUpdateInRecord(*face1, *interest2a);
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400563 auto interest2b = makeInterest("/Vi8tRm9MG3", false, std::nullopt, 808);
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000564 pit2->insertOrUpdateInRecord(*face2, *interest2b);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700565 face1->sentNacks.clear();
Eric Newberry2377ada2020-09-28 22:40:14 -0700566 face2->sentNacks.clear();
567
Davide Pesavento0498ce82021-06-14 02:02:21 -0400568 BOOST_CHECK(forwarder.onOutgoingNack(nackHeader, *face1, pit2));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700569 BOOST_REQUIRE_EQUAL(face1->sentNacks.size(), 1);
570 BOOST_CHECK_EQUAL(face1->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
571 BOOST_CHECK_EQUAL(face1->sentNacks.back().getInterest().getNonce(), 152);
Eric Newberry2377ada2020-09-28 22:40:14 -0700572 BOOST_CHECK_EQUAL(face2->sentNacks.size(), 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700573
Eric Newberry2377ada2020-09-28 22:40:14 -0700574 // in-record is erased
Alex Lane6bead9b2020-05-12 19:08:20 -0500575 auto inRecord2a = pit2->getInRecord(*face1);
Junxiao Shi4846f372016-04-05 13:39:30 -0700576 BOOST_CHECK(inRecord2a == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700577
578 // send Nack with correct Nonce
Davide Pesavento0498ce82021-06-14 02:02:21 -0400579 BOOST_CHECK(forwarder.onOutgoingNack(nackHeader, *face2, pit2));
Eric Newberry2377ada2020-09-28 22:40:14 -0700580 BOOST_CHECK_EQUAL(face1->sentNacks.size(), 1);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700581 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
582 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::CONGESTION);
583 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().getNonce(), 808);
584
Eric Newberry2377ada2020-09-28 22:40:14 -0700585 // in-record is erased
586 auto inRecord2b = pit2->getInRecord(*face2);
Junxiao Shi4846f372016-04-05 13:39:30 -0700587 BOOST_CHECK(inRecord2b == pit2->in_end());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700588
589 // don't send Nack to multi-access face
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400590 auto interest2c = makeInterest("/Vi8tRm9MG3", false, std::nullopt, 228);
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000591 pit2->insertOrUpdateInRecord(*face3, *interest2c);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700592
593 face3->sentNacks.clear();
Davide Pesavento0498ce82021-06-14 02:02:21 -0400594 BOOST_CHECK(!forwarder.onOutgoingNack(nackHeader, *face3, pit2));
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700595 BOOST_CHECK_EQUAL(face3->sentNacks.size(), 0);
Eric Newberry2377ada2020-09-28 22:40:14 -0700596
597 // don't send Nack to face with invalid ID
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400598 auto interest1b = makeInterest("/fM5IVEtC", false, std::nullopt, 553);
Eric Newberry2377ada2020-09-28 22:40:14 -0700599 pit1->insertOrUpdateInRecord(*face4, *interest1b);
600
601 face4->sentNacks.clear();
Davide Pesavento0498ce82021-06-14 02:02:21 -0400602 BOOST_CHECK(!forwarder.onOutgoingNack(nackHeader, *face4, pit1));
Eric Newberry2377ada2020-09-28 22:40:14 -0700603 BOOST_CHECK_EQUAL(face4->sentNacks.size(), 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700604}
605
606BOOST_AUTO_TEST_CASE(InterestLoopNack)
607{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400608 auto face1 = addFace();
609 auto face2 = addFace();
610 auto face3 = addFace("dummy://", "dummy://",
611 ndn::nfd::FACE_SCOPE_NON_LOCAL,
612 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
613 ndn::nfd::LINK_TYPE_MULTI_ACCESS);
614 auto face4 = addFace();
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700615
616 Fib& fib = forwarder.getFib();
Ju Pand8315bf2019-07-31 06:59:07 +0000617 fib::Entry* entry = fib.insert("/zT4XwK0Hnx").first;
618 fib.addOrUpdateNextHop(*entry, *face4, 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700619
620 // receive Interest on face1
621 face1->sentNacks.clear();
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400622 auto interest1a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", false, std::nullopt, 732);
Teng Liangd94b7b32022-07-10 21:29:37 +0800623 face1->receiveInterest(*interest1a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700624 BOOST_CHECK(face1->sentNacks.empty());
625
Junxiao Shi2fe3af02017-03-04 17:24:19 +0000626 // receive Interest with duplicate Nonce on face1: legit retransmission
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700627 face1->sentNacks.clear();
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400628 auto interest1b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", false, std::nullopt, 732);
Teng Liangd94b7b32022-07-10 21:29:37 +0800629 face1->receiveInterest(*interest1b);
Junxiao Shi2fe3af02017-03-04 17:24:19 +0000630 BOOST_CHECK(face1->sentNacks.empty());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700631
632 // receive Interest with duplicate Nonce on face2
633 face2->sentNacks.clear();
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400634 auto interest2a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", false, std::nullopt, 732);
Teng Liangd94b7b32022-07-10 21:29:37 +0800635 face2->receiveInterest(*interest2a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700636 BOOST_REQUIRE_EQUAL(face2->sentNacks.size(), 1);
Davide Pesavento7890a9f2019-08-25 23:11:18 -0400637 BOOST_CHECK_EQUAL(face2->sentNacks.back().getInterest().wireEncode(), interest2a->wireEncode());
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700638 BOOST_CHECK_EQUAL(face2->sentNacks.back().getReason(), lp::NackReason::DUPLICATE);
639
640 // receive Interest with new Nonce on face2
641 face2->sentNacks.clear();
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400642 auto interest2b = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", false, std::nullopt, 944);
Teng Liangd94b7b32022-07-10 21:29:37 +0800643 face2->receiveInterest(*interest2b);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700644 BOOST_CHECK(face2->sentNacks.empty());
645
646 // receive Interest with duplicate Nonce on face3, don't send Nack to multi-access face
647 face3->sentNacks.clear();
Davide Pesaventob7bfcb92022-05-22 23:55:23 -0400648 auto interest3a = makeInterest("/zT4XwK0Hnx/28JBUvbEzc", false, std::nullopt, 732);
Teng Liangd94b7b32022-07-10 21:29:37 +0800649 face3->receiveInterest(*interest3a);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700650 BOOST_CHECK(face3->sentNacks.empty());
651}
652
Davide Pesaventocf7db2f2019-03-24 23:17:28 -0400653BOOST_AUTO_TEST_CASE(InterestLoopWithShortLifetime) // Bug 1953
Junxiao Shia110f262014-10-12 12:35:20 -0700654{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400655 auto face1 = addFace();
656 auto face2 = addFace();
Junxiao Shia110f262014-10-12 12:35:20 -0700657
658 // cause an Interest sent out of face2 to loop back into face1 after a delay
Junxiao Shicde37ad2015-12-24 01:02:05 -0700659 face2->afterSend.connect([face1, face2] (uint32_t pktType) {
660 if (pktType == tlv::Interest) {
661 auto interest = make_shared<Interest>(face2->sentInterests.back());
Teng Liangd94b7b32022-07-10 21:29:37 +0800662 getScheduler().schedule(170_ms, [face1, interest] { face1->receiveInterest(*interest); });
Junxiao Shicde37ad2015-12-24 01:02:05 -0700663 }
Junxiao Shic099ddb2014-12-25 20:53:20 -0700664 });
Junxiao Shia110f262014-10-12 12:35:20 -0700665
666 Fib& fib = forwarder.getFib();
Ju Pand8315bf2019-07-31 06:59:07 +0000667 fib::Entry* entry = fib.insert("/A").first;
668 fib.addOrUpdateNextHop(*entry, *face2, 0);
Junxiao Shia110f262014-10-12 12:35:20 -0700669
Junxiao Shi455581d2014-11-17 18:38:40 -0700670 // receive an Interest
Junxiao Shi9d727852019-05-14 13:44:22 -0600671 auto interest = makeInterest("/A/1", false, 50_ms, 82101183);
Teng Liangd94b7b32022-07-10 21:29:37 +0800672 face1->receiveInterest(*interest);
Junxiao Shia110f262014-10-12 12:35:20 -0700673
Junxiao Shi455581d2014-11-17 18:38:40 -0700674 // interest should be forwarded only once, as long as Nonce is in Dead Nonce List
Davide Pesavento14e71f02019-03-28 17:35:25 -0400675 BOOST_ASSERT(25_ms * 40 < forwarder.getDeadNonceList().getLifetime());
676 this->advanceClocks(25_ms, 40);
Junxiao Shicde37ad2015-12-24 01:02:05 -0700677 BOOST_CHECK_EQUAL(face2->sentInterests.size(), 1);
Junxiao Shi455581d2014-11-17 18:38:40 -0700678
679 // It's unnecessary to check that Interest with duplicate Nonce can be forwarded again
680 // after it's gone from Dead Nonce List, because the entry lifetime of Dead Nonce List
681 // is an implementation decision. NDN protocol requires Name+Nonce to be unique,
682 // without specifying when Name+Nonce could repeat. Forwarder is permitted to suppress
683 // an Interest if its Name+Nonce has appeared any point in the past.
Junxiao Shia110f262014-10-12 12:35:20 -0700684}
685
Junxiao Shid41d6072016-06-19 23:35:27 +0000686BOOST_AUTO_TEST_CASE(PitLeak) // Bug 3484
Junxiao Shi330136a2016-03-10 04:53:08 -0700687{
Davide Pesaventoa4abfb02019-10-06 16:02:56 -0400688 auto face1 = addFace();
Junxiao Shi9d727852019-05-14 13:44:22 -0600689 auto interest = makeInterest("/hcLSAsQ9A", false, 2_s, 61883075);
Junxiao Shi330136a2016-03-10 04:53:08 -0700690
Davide Pesavento0498ce82021-06-14 02:02:21 -0400691 auto& dnl = forwarder.getDeadNonceList();
Junxiao Shi330136a2016-03-10 04:53:08 -0700692 dnl.add(interest->getName(), interest->getNonce());
Davide Pesavento0498ce82021-06-14 02:02:21 -0400693 auto& pit = forwarder.getPit();
694 BOOST_CHECK_EQUAL(pit.size(), 0);
Junxiao Shi330136a2016-03-10 04:53:08 -0700695
Teng Liangd94b7b32022-07-10 21:29:37 +0800696 forwarder.onIncomingInterest(*interest, FaceEndpoint(*face1));
Davide Pesavento14e71f02019-03-28 17:35:25 -0400697 this->advanceClocks(100_ms, 20_s);
Junxiao Shi330136a2016-03-10 04:53:08 -0700698 BOOST_CHECK_EQUAL(pit.size(), 0);
699}
700
Alex Lane6bead9b2020-05-12 19:08:20 -0500701BOOST_AUTO_TEST_CASE(UnsolicitedData)
702{
703 auto face1 = addFace();
704 auto data = makeData("/A");
705
706 BOOST_CHECK_EQUAL(forwarder.getCounters().nUnsolicitedData, 0);
Teng Liangd94b7b32022-07-10 21:29:37 +0800707 forwarder.onIncomingData(*data, FaceEndpoint(*face1));
Alex Lane6bead9b2020-05-12 19:08:20 -0500708 this->advanceClocks(1_ms, 10_ms);
709 BOOST_CHECK_EQUAL(forwarder.getCounters().nUnsolicitedData, 1);
710}
711
Davide Pesaventob21bed82021-02-13 00:20:06 -0500712BOOST_AUTO_TEST_CASE(NewNextHop)
713{
714 auto face1 = addFace();
715 auto face2 = addFace();
716 auto face3 = addFace();
717 auto face4 = addFace();
718
719 auto& strategy = choose<DummyStrategy>(forwarder, "/A", DummyStrategy::getStrategyName());
720
721 Fib& fib = forwarder.getFib();
722 Pit& pit = forwarder.getPit();
723
724 // fib: "/", "/A/B", "/A/B/C/D/E"
725 fib::Entry* entry = fib.insert("/").first;
726 fib.addOrUpdateNextHop(*entry, *face1, 100);
727 entry = fib.insert("/A/B").first;
728 fib.addOrUpdateNextHop(*entry, *face2, 0);
729 entry = fib.insert("/A/B/C/D/E").first;
730 fib.addOrUpdateNextHop(*entry, *face3, 0);
731
732 // pit: "/A", "/A/B/C", "/A/B/Z"
733 auto interest1 = makeInterest("/A");
734 auto pit1 = pit.insert(*interest1).first;
735 pit1->insertOrUpdateInRecord(*face3, *interest1);
736 auto interest2 = makeInterest("/A/B/C");
737 auto pit2 = pit.insert(*interest2).first;
738 pit2->insertOrUpdateInRecord(*face3, *interest2);
739 auto interest3 = makeInterest("/A/B/Z");
740 auto pit3 = pit.insert(*interest3).first;
741 pit3->insertOrUpdateInRecord(*face3, *interest3);
742
743 // new nexthop for "/"
744 entry = fib.insert("/").first;
745 fib.addOrUpdateNextHop(*entry, *face2, 50);
746
747 // /A --> triggered
748 // /A/B/C --> not triggered
749 // /A/B/Z --> not triggered
750 BOOST_TEST_REQUIRE(strategy.afterNewNextHopCalls.size() == 1);
751 BOOST_TEST(strategy.afterNewNextHopCalls[0] == "/A");
752 strategy.afterNewNextHopCalls.clear();
753
754 // new nexthop for "/A"
755 entry = fib.insert("/A").first;
756 fib.addOrUpdateNextHop(*entry, *face4, 50);
757
758 // /A --> triggered
759 // /A/B/C --> not triggered
760 // /A/B/Z --> not triggered
761 BOOST_TEST_REQUIRE(strategy.afterNewNextHopCalls.size() == 1);
762 BOOST_TEST(strategy.afterNewNextHopCalls[0] == "/A");
763 strategy.afterNewNextHopCalls.clear();
764
765 // new nexthop for "/A/B"
766 entry = fib.insert("/A/B").first;
767 fib.addOrUpdateNextHop(*entry, *face4, 0);
768
769 // /A --> not triggered
770 // /A/B/C --> triggered
771 // /A/B/Z --> triggered
772 BOOST_TEST_REQUIRE(strategy.afterNewNextHopCalls.size() == 2);
773 BOOST_TEST(strategy.afterNewNextHopCalls[0] == "/A/B/C");
774 BOOST_TEST(strategy.afterNewNextHopCalls[1] == "/A/B/Z");
775 strategy.afterNewNextHopCalls.clear();
776
777 // new nexthop for "/A/B/C/D"
778 entry = fib.insert("/A/B/C/D").first;
779 fib.addOrUpdateNextHop(*entry, *face1, 0);
780
781 // nothing triggered
782 BOOST_TEST(strategy.afterNewNextHopCalls.size() == 0);
783
784 // create a second pit entry for /A
785 auto interest4 = makeInterest("/A");
786 interest4->setMustBeFresh(true);
787 auto pit4 = pit.insert(*interest4).first;
788 pit4->insertOrUpdateInRecord(*face3, *interest4);
789
790 // new nexthop for "/A"
791 entry = fib.insert("/A").first;
792 fib.addOrUpdateNextHop(*entry, *face1, 0);
793
794 // /A --> triggered twice
795 // /A/B/C --> not triggered
796 // /A/B/Z --> not triggered
797 BOOST_TEST_REQUIRE(strategy.afterNewNextHopCalls.size() == 2);
798 BOOST_TEST(strategy.afterNewNextHopCalls[0] == "/A");
799 BOOST_TEST(strategy.afterNewNextHopCalls[1] == "/A");
800}
801
Philipp Molla1033342021-06-14 09:34:21 +0200802BOOST_AUTO_TEST_SUITE(ProcessConfig)
803
804BOOST_AUTO_TEST_CASE(DefaultHopLimit)
805{
806 ConfigFile cf;
807 forwarder.setConfigFile(cf);
808
809 std::string config = R"CONFIG(
810 forwarder
811 {
812 default_hop_limit 10
813 }
814 )CONFIG";
815
816 // The default value is 0
817 BOOST_TEST(forwarder.m_config.defaultHopLimit == 0);
818
819 // Dry run parsing should not change the default config
820 cf.parse(config, true, "dummy-config");
821 BOOST_TEST(forwarder.m_config.defaultHopLimit == 0);
822
823 // Check if the actual parsing works
824 cf.parse(config, false, "dummy-config");
825 BOOST_TEST(forwarder.m_config.defaultHopLimit == 10);
826
827 // After removing default_hop_limit from the config file,
828 // the default value of zero should be restored
829 config = R"CONFIG(
830 forwarder
831 {
832 }
833 )CONFIG";
834
835 cf.parse(config, false, "dummy-config");
836 BOOST_TEST(forwarder.m_config.defaultHopLimit == 0);
837}
838
839BOOST_AUTO_TEST_CASE(BadDefaultHopLimit)
840{
841 ConfigFile cf;
842 forwarder.setConfigFile(cf);
843
844 // not a number
845 std::string config = R"CONFIG(
846 forwarder
847 {
848 default_hop_limit hello
849 }
850 )CONFIG";
851
852 BOOST_CHECK_THROW(cf.parse(config, true, "dummy-config"), ConfigFile::Error);
853 BOOST_CHECK_THROW(cf.parse(config, false, "dummy-config"), ConfigFile::Error);
854
855 // negative number
856 config = R"CONFIG(
857 forwarder
858 {
859 default_hop_limit -1
860 }
861 )CONFIG";
862
863 BOOST_CHECK_THROW(cf.parse(config, true, "dummy-config"), ConfigFile::Error);
864 BOOST_CHECK_THROW(cf.parse(config, false, "dummy-config"), ConfigFile::Error);
865
866 // out of range
867 config = R"CONFIG(
868 forwarder
869 {
870 default_hop_limit 256
871 }
872 )CONFIG";
873
874 BOOST_CHECK_THROW(cf.parse(config, true, "dummy-config"), ConfigFile::Error);
875 BOOST_CHECK_THROW(cf.parse(config, false, "dummy-config"), ConfigFile::Error);
876}
877
878BOOST_AUTO_TEST_SUITE_END() // ProcessConfig
879
Davide Pesaventocf7db2f2019-03-24 23:17:28 -0400880BOOST_AUTO_TEST_SUITE_END() // TestForwarder
881BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi8c8d2182014-01-30 22:33:00 -0700882
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400883} // namespace nfd::tests