blob: b4f97238691dde232dd7e5683073c4fc97cff103 [file] [log] [blame]
Andrea Tosatto672b9a72016-01-05 16:18:20 +01001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoe9c69852017-11-04 18:08:37 -04002/*
Davide Pesaventob3570c62022-02-19 19:19:00 -05003 * Copyright (c) 2016-2022, Regents of the University of California,
Davide Pesaventobf1c0692017-01-15 19:15:09 -05004 * Colorado State University,
5 * University Pierre & Marie Curie, Sorbonne University.
Andrea Tosatto672b9a72016-01-05 16:18:20 +01006 *
7 * This file is part of ndn-tools (Named Data Networking Essential Tools).
8 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
9 *
10 * ndn-tools is free software: you can redistribute it and/or modify it under the terms
11 * of the GNU General Public License as published by the Free Software Foundation,
12 * either version 3 of the License, or (at your option) any later version.
13 *
14 * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
22 *
23 * @author Andrea Tosatto
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080024 * @author Chavoosh Ghasemi
Andrea Tosatto672b9a72016-01-05 16:18:20 +010025 */
26
schneiderklausd8197df2019-03-16 11:31:40 -070027#include "tools/chunks/catchunks/pipeline-interests-fixed.hpp"
Andrea Tosatto672b9a72016-01-05 16:18:20 +010028#include "tools/chunks/catchunks/data-fetcher.hpp"
29
Weiwei Liue4765012016-06-01 00:10:29 -070030#include "pipeline-interests-fixture.hpp"
Andrea Tosatto672b9a72016-01-05 16:18:20 +010031
Davide Pesaventob3570c62022-02-19 19:19:00 -050032namespace ndn::chunks::tests {
Andrea Tosatto672b9a72016-01-05 16:18:20 +010033
schneiderklausd8197df2019-03-16 11:31:40 -070034class PipelineInterestFixedFixture : public PipelineInterestsFixture
Andrea Tosatto672b9a72016-01-05 16:18:20 +010035{
36public:
schneiderklausd8197df2019-03-16 11:31:40 -070037 PipelineInterestFixedFixture()
Andrea Tosatto672b9a72016-01-05 16:18:20 +010038 {
Davide Pesavento97a33b22019-10-17 22:10:47 -040039 opt.interestLifetime = 1_s;
40 opt.maxRetriesOnTimeoutOrNack = 3;
41 opt.isQuiet = true;
42 opt.maxPipelineSize = 5;
schneiderklausd8197df2019-03-16 11:31:40 -070043 createPipeline();
44 }
45
46 void
47 createPipeline()
48 {
49 auto pline = make_unique<PipelineInterestsFixed>(face, opt);
50 pipeline = pline.get();
51 setPipeline(std::move(pline));
Andrea Tosatto672b9a72016-01-05 16:18:20 +010052 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -040053
Davide Pesaventof6991e12018-01-08 20:58:50 -050054protected:
Davide Pesavento97a33b22019-10-17 22:10:47 -040055 Options opt;
schneiderklausd8197df2019-03-16 11:31:40 -070056 PipelineInterestsFixed* pipeline;
Andrea Tosatto672b9a72016-01-05 16:18:20 +010057};
58
59BOOST_AUTO_TEST_SUITE(Chunks)
schneiderklausd8197df2019-03-16 11:31:40 -070060BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsFixed, PipelineInterestFixedFixture)
Andrea Tosatto672b9a72016-01-05 16:18:20 +010061
Davide Pesaventoe9c69852017-11-04 18:08:37 -040062BOOST_AUTO_TEST_CASE(FullPipeline)
Andrea Tosatto672b9a72016-01-05 16:18:20 +010063{
64 nDataSegments = 13;
65 BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
66
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080067 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -040068 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +010069 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
70
71 for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
72 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -040073 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080074 BOOST_CHECK_EQUAL(pipeline->m_nReceived, i + 1);
Andrea Tosatto672b9a72016-01-05 16:18:20 +010075
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080076 if (i < nDataSegments - opt.maxPipelineSize) {
Andrea Tosatto672b9a72016-01-05 16:18:20 +010077 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize + i + 1);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080078 // check if the interest for the segment i is well formed
Davide Pesaventobf1c0692017-01-15 19:15:09 -050079 const auto& sentInterest = face.sentInterests[i];
Davide Pesavento84d84772019-04-07 14:40:07 -040080 BOOST_CHECK_EQUAL(sentInterest.getCanBePrefix(), false);
Andrea Tosatto672b9a72016-01-05 16:18:20 +010081 BOOST_CHECK_EQUAL(sentInterest.getMustBeFresh(), opt.mustBeFresh);
82 BOOST_CHECK_EQUAL(Name(name).isPrefixOf(sentInterest.getName()), true);
Davide Pesaventobf1c0692017-01-15 19:15:09 -050083 BOOST_CHECK_EQUAL(getSegmentFromPacket(sentInterest), i);
Andrea Tosatto672b9a72016-01-05 16:18:20 +010084 }
85 else {
86 // all the interests have been sent for all the segments
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080087 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments);
Andrea Tosatto672b9a72016-01-05 16:18:20 +010088 }
89 }
90
91 BOOST_CHECK_EQUAL(hasFailed, false);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080092
Davide Pesavento66777622020-10-09 18:46:03 -040093 advanceClocks(ndn::DEFAULT_INTEREST_LIFETIME, opt.maxRetriesOnTimeoutOrNack + 1);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080094 BOOST_CHECK_EQUAL(hasFailed, true);
Andrea Tosatto672b9a72016-01-05 16:18:20 +010095}
96
Davide Pesaventoe9c69852017-11-04 18:08:37 -040097BOOST_AUTO_TEST_CASE(TimeoutAllSegments)
Andrea Tosatto672b9a72016-01-05 16:18:20 +010098{
99 nDataSegments = 13;
100 BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
101
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800102 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400103 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100104 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
105
106 for (int i = 0; i < opt.maxRetriesOnTimeoutOrNack; ++i) {
Davide Pesavento66777622020-10-09 18:46:03 -0400107 advanceClocks(opt.interestLifetime);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100108 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize * (i + 2));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800109 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 0);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100110
111 // A single retry for every pipeline element
112 for (size_t j = 0; j < opt.maxPipelineSize; ++j) {
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500113 const auto& interest = face.sentInterests[(opt.maxPipelineSize * (i + 1)) + j];
114 BOOST_CHECK_EQUAL(static_cast<size_t>(getSegmentFromPacket(interest)), j);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100115 }
116 }
117
Davide Pesavento66777622020-10-09 18:46:03 -0400118 advanceClocks(opt.interestLifetime);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100119 BOOST_CHECK_EQUAL(hasFailed, true);
120}
121
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400122BOOST_AUTO_TEST_CASE(TimeoutAfterFinalBlockIdReceived)
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100123{
124 // the FinalBlockId is sent with the first segment, after the first segment failure the pipeline
125 // should fail
126
127 nDataSegments = 18;
128 BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
129
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800130 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400131 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100132 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
133
134 // send a single segment for each pipeline element but not the first element
Davide Pesavento66777622020-10-09 18:46:03 -0400135 advanceClocks(opt.interestLifetime);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100136 for (uint64_t i = 1; i < opt.maxPipelineSize; ++i) {
137 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400138 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100139 }
140
141 // send a single data packet for each pipeline element
Davide Pesavento66777622020-10-09 18:46:03 -0400142 advanceClocks(opt.interestLifetime, opt.maxRetriesOnTimeoutOrNack - 1);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800143 for (uint64_t i = 0; i < opt.maxPipelineSize; ++i) {
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100144 face.receive(*makeDataWithSegment(opt.maxPipelineSize + i));
Davide Pesavento66777622020-10-09 18:46:03 -0400145 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100146 }
Davide Pesavento66777622020-10-09 18:46:03 -0400147 advanceClocks(opt.interestLifetime);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100148
149 size_t interestAfterFailure = face.sentInterests.size();
150
151 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
152 BOOST_CHECK_EQUAL(hasFailed, true);
153
154 // these new segments should not generate new interests
Davide Pesavento66777622020-10-09 18:46:03 -0400155 advanceClocks(opt.interestLifetime);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800156 for (uint64_t i = 0; i < opt.maxPipelineSize; ++i) {
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100157 face.receive(*makeDataWithSegment(opt.maxPipelineSize * 2 + i - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400158 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100159 }
160
161 // no more interests after a failure
Davide Pesavento66777622020-10-09 18:46:03 -0400162 advanceClocks(opt.interestLifetime, opt.maxRetriesOnTimeoutOrNack);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100163 BOOST_CHECK_EQUAL(interestAfterFailure, face.sentInterests.size());
164 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
165}
166
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400167BOOST_AUTO_TEST_CASE(TimeoutBeforeFinalBlockIdReceived)
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100168{
169 // the FinalBlockId is sent only with the last segment, all segments are sent except for the
170 // second one (segment #1); all segments are received correctly until the FinalBlockId is received
171
172 nDataSegments = 22;
173 BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
174
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800175 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400176 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100177 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
178
Davide Pesavento66777622020-10-09 18:46:03 -0400179 advanceClocks(opt.interestLifetime);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100180 for (uint64_t i = 2; i < opt.maxPipelineSize; ++i) {
181 face.receive(*makeDataWithSegment(i, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400182 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100183
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500184 const auto& lastInterest = face.sentInterests.back();
185 BOOST_CHECK_EQUAL(getSegmentFromPacket(lastInterest), opt.maxPipelineSize + i - 2);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100186 }
187 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize * 3 - 2);
188
189 // nack for the first pipeline element (segment #0)
190 auto nack = make_shared<lp::Nack>(face.sentInterests[opt.maxPipelineSize]);
191 nack->setReason(lp::NackReason::DUPLICATE);
192 face.receive(*nack);
193
194 // all the pipeline elements are two retries near the timeout error, but not the
195 // second (segment #1) that is only one retry near the timeout
Davide Pesavento66777622020-10-09 18:46:03 -0400196 advanceClocks(opt.interestLifetime, opt.maxRetriesOnTimeoutOrNack - 1);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100197 BOOST_CHECK_EQUAL(hasFailed, false);
198
199 // data for the first pipeline element (segment #0)
200 face.receive(*makeDataWithSegment(0, false));
201 BOOST_CHECK_EQUAL(hasFailed, false);
202
203 // data for all the pipeline element, but not the second (segment #1)
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800204 for (uint64_t i = opt.maxPipelineSize; i < nDataSegments; ++i) {
205 if (i == nDataSegments - 1) {
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100206 face.receive(*makeDataWithSegment(i, true));
207 }
208 else {
209 face.receive(*makeDataWithSegment(i, false));
210 }
Davide Pesavento66777622020-10-09 18:46:03 -0400211 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100212 }
213 // timeout for the second pipeline element (segment #1), this should trigger an error
Davide Pesavento66777622020-10-09 18:46:03 -0400214 advanceClocks(opt.interestLifetime);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100215
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400216 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100217 BOOST_CHECK_EQUAL(hasFailed, true);
218}
219
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400220BOOST_AUTO_TEST_CASE(SegmentReceivedAfterTimeout)
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100221{
222 // the FinalBlockId is never sent, all the pipeline elements with a segment number greater than
223 // segment #0 will fail, after this failure also segment #0 fail and this should trigger an error
224
225 nDataSegments = 22;
226 BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
227
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800228 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400229 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100230 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
231
Davide Pesavento66777622020-10-09 18:46:03 -0400232 advanceClocks(opt.interestLifetime);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100233
234 // nack for the first pipeline element (segment #0)
235 auto nack = make_shared<lp::Nack>(face.sentInterests[opt.maxPipelineSize]);
236 nack->setReason(lp::NackReason::DUPLICATE);
237 face.receive(*nack);
238 BOOST_CHECK_EQUAL(hasFailed, false);
239
240 // timeout for all the pipeline elements, but not the first (segment #0)
Davide Pesavento66777622020-10-09 18:46:03 -0400241 advanceClocks(opt.interestLifetime, opt.maxRetriesOnTimeoutOrNack);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100242 BOOST_CHECK_EQUAL(hasFailed, false);
243
244 // data for the first pipeline element (segment #0), this should trigger an error because the
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800245 // other pipeline elements failed
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100246 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400247 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100248
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800249 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100250 BOOST_CHECK_EQUAL(hasFailed, true);
251}
252
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400253BOOST_AUTO_TEST_CASE(CongestionAllSegments)
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100254{
255 nDataSegments = 13;
256 BOOST_ASSERT(nDataSegments > opt.maxPipelineSize);
257
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800258 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400259 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100260 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize);
261
262 // send nack for all the pipeline elements first interest
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800263 for (size_t i = 0; i < opt.maxPipelineSize; i++) {
264 auto nack = make_shared<lp::Nack>(face.sentInterests[i]);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100265 nack->setReason(lp::NackReason::CONGESTION);
266 face.receive(*nack);
Davide Pesavento66777622020-10-09 18:46:03 -0400267 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100268 }
269
270 // send nack for all the pipeline elements interests after the first
271 for (int i = 1; i <= opt.maxRetriesOnTimeoutOrNack; ++i) {
272 time::milliseconds backoffTime(static_cast<uint64_t>(std::pow(2, i)));
273 if (backoffTime > DataFetcher::MAX_CONGESTION_BACKOFF_TIME)
274 backoffTime = DataFetcher::MAX_CONGESTION_BACKOFF_TIME;
275
Davide Pesavento66777622020-10-09 18:46:03 -0400276 advanceClocks(backoffTime);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100277 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), opt.maxPipelineSize * (i +1));
278
279 // A single retry for every pipeline element
280 for (size_t j = 0; j < opt.maxPipelineSize; ++j) {
Davide Pesaventobf1c0692017-01-15 19:15:09 -0500281 const auto& interest = face.sentInterests[(opt.maxPipelineSize * i) + j];
282 BOOST_CHECK_LT(static_cast<size_t>(getSegmentFromPacket(interest)), opt.maxPipelineSize);
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100283 }
284
285 for (size_t j = 0; j < opt.maxPipelineSize; j++) {
286 auto nack = make_shared<lp::Nack>(face.sentInterests[(opt.maxPipelineSize * i) + j]);
287 nack->setReason(lp::NackReason::CONGESTION);
288 face.receive(*nack);
Davide Pesavento66777622020-10-09 18:46:03 -0400289 advanceClocks(time::nanoseconds(1));
Andrea Tosatto672b9a72016-01-05 16:18:20 +0100290 }
291 }
292
293 BOOST_CHECK_EQUAL(hasFailed, true);
294}
295
296BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterests
297BOOST_AUTO_TEST_SUITE_END() // Chunks
298
Davide Pesaventob3570c62022-02-19 19:19:00 -0500299} // namespace ndn::chunks::tests