blob: 6a3610577b49b16f3d7b380dbafb778a1da13aee [file] [log] [blame]
Weiwei Liu245d7912016-07-28 00:04:25 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoe9c69852017-11-04 18:08:37 -04002/*
Davide Pesavento5748e822024-01-26 18:40:22 -05003 * Copyright (c) 2016-2024, Regents of the University of California,
Davide Pesavento958896e2017-01-19 00:52:04 -05004 * Colorado State University,
5 * University Pierre & Marie Curie, Sorbonne University.
Weiwei Liu245d7912016-07-28 00:04:25 -07006 *
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 Weiwei Liu
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000024 * @author Chavoosh Ghasemi
schneiderklausd8197df2019-03-16 11:31:40 -070025 * @author Klaus Schneider
Weiwei Liu245d7912016-07-28 00:04:25 -070026 */
27
Klaus Schneider9e5122b2019-03-19 17:03:25 -070028#include "tools/chunks/catchunks/pipeline-interests-cubic.hpp"
Weiwei Liu245d7912016-07-28 00:04:25 -070029
30#include "pipeline-interests-fixture.hpp"
31
Davide Pesaventob3570c62022-02-19 19:19:00 -050032namespace ndn::chunks::tests {
Weiwei Liu245d7912016-07-28 00:04:25 -070033
34using namespace ndn::tests;
35
Klaus Schneider9e5122b2019-03-19 17:03:25 -070036class PipelineInterestCubicFixture : public PipelineInterestsFixture
Weiwei Liu245d7912016-07-28 00:04:25 -070037{
Davide Pesaventob3570c62022-02-19 19:19:00 -050038protected:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070039 PipelineInterestCubicFixture()
Weiwei Liu245d7912016-07-28 00:04:25 -070040 {
Davide Pesavento97a33b22019-10-17 22:10:47 -040041 opt.isQuiet = true;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000042 createPipeline();
43 }
44
45 void
46 createPipeline()
47 {
Davide Pesavento5748e822024-01-26 18:40:22 -050048 auto pline = std::make_unique<PipelineInterestsCubic>(face, rttEstimator, opt);
schneiderklausd8197df2019-03-16 11:31:40 -070049 pipeline = pline.get();
Weiwei Liu245d7912016-07-28 00:04:25 -070050 setPipeline(std::move(pline));
51 }
52
53private:
Davide Pesavento5748e822024-01-26 18:40:22 -050054 static std::shared_ptr<RttEstimatorWithStats::Options>
Weiwei Liu245d7912016-07-28 00:04:25 -070055 makeRttEstimatorOptions()
56 {
Davide Pesavento5748e822024-01-26 18:40:22 -050057 auto rttOptions = std::make_shared<RttEstimatorWithStats::Options>();
Davide Pesavento5e3773d2019-08-22 15:35:08 -040058 rttOptions->alpha = 0.125;
59 rttOptions->beta = 0.25;
60 rttOptions->k = 8;
61 rttOptions->initialRto = 1_s;
62 rttOptions->minRto = 200_ms;
63 rttOptions->maxRto = 4_s;
64 rttOptions->rtoBackoffMultiplier = 2;
Weiwei Liu245d7912016-07-28 00:04:25 -070065 return rttOptions;
66 }
67
68protected:
Davide Pesavento97a33b22019-10-17 22:10:47 -040069 Options opt;
Davide Pesaventob3570c62022-02-19 19:19:00 -050070 RttEstimatorWithStats rttEstimator{makeRttEstimatorOptions()};
Klaus Schneider9e5122b2019-03-19 17:03:25 -070071 PipelineInterestsCubic* pipeline;
Davide Pesaventoba560662019-06-26 22:45:44 -040072 static constexpr double MARGIN = 0.001;
Weiwei Liu245d7912016-07-28 00:04:25 -070073};
74
75BOOST_AUTO_TEST_SUITE(Chunks)
Klaus Schneider9e5122b2019-03-19 17:03:25 -070076BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsCubic, PipelineInterestCubicFixture)
Weiwei Liu245d7912016-07-28 00:04:25 -070077
78BOOST_AUTO_TEST_CASE(SlowStart)
79{
80 nDataSegments = 4;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -070081 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -070082
schneiderklausd8197df2019-03-16 11:31:40 -070083 double preCwnd = pipeline->m_cwnd;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080084 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -040085 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -070086 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -070087
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080088 for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -070089 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -040090 advanceClocks(time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -070091 BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, 1, MARGIN);
92 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -070093 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -040094
95 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
Weiwei Liu245d7912016-07-28 00:04:25 -070096}
97
Weiwei Liu245d7912016-07-28 00:04:25 -070098
99BOOST_AUTO_TEST_CASE(Timeout)
100{
101 nDataSegments = 8;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700102 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700103
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800104 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400105 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700106 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700107
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800108 // receive segment 0, 1, and 2
109 for (uint64_t i = 0; i < 3; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700110 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400111 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700112 }
113
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400114 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700115 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 5, MARGIN);
116 BOOST_CHECK_EQUAL(face.sentInterests.size(), 8); // request for segment #7 has been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700117
Davide Pesavento66777622020-10-09 18:46:03 -0400118 advanceClocks(time::milliseconds(100));
Weiwei Liu245d7912016-07-28 00:04:25 -0700119
120 // receive segment 4
121 face.receive(*makeDataWithSegment(4));
Davide Pesavento66777622020-10-09 18:46:03 -0400122 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700123
124 // receive segment 5
125 face.receive(*makeDataWithSegment(5));
Davide Pesavento66777622020-10-09 18:46:03 -0400126 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700127
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400128 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700129 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800130 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700131
schneiderklausd8197df2019-03-16 11:31:40 -0700132 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
133 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 0);
134 BOOST_CHECK_EQUAL(pipeline->m_nMarkDecr, 0);
135 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 0);
136 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
137 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 0);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700138
139 // timeout segment 3 & 6
Davide Pesavento66777622020-10-09 18:46:03 -0400140 advanceClocks(time::milliseconds(150));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700141 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 3);
142 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 3);
schneiderklausd8197df2019-03-16 11:31:40 -0700143 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
144 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700145
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400146 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700147 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // window size drop to 0.7x of previous size
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700148 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700149
150 // receive segment 6, retransmit 3
151 face.receive(*makeDataWithSegment(6));
Davide Pesavento66777622020-10-09 18:46:03 -0400152 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700153
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400154 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700155 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // congestion avoidance
schneiderklausd8197df2019-03-16 11:31:40 -0700156 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
157 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700158
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700159 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 3);
160 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 3);
schneiderklausd8197df2019-03-16 11:31:40 -0700161 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts,
162 pipeline->m_nRetransmitted + pipeline->m_nSkippedRetx);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700163
Weiwei Liu245d7912016-07-28 00:04:25 -0700164}
165
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000166BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
167{
168 nDataSegments = 7;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700169 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000170
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800171 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400172 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700173 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000174
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800175 // receive segments 0 to 4
176 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000177 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400178 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000179 }
180
181 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700182 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000183
184 // receive segment 5 with congestion mark
185 face.receive(*makeDataWithSegmentAndCongMark(5));
Davide Pesavento66777622020-10-09 18:46:03 -0400186 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000187
188 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700189 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // window size drops to 0.7x of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800190 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000191
192 // receive the last segment with congestion mark
193 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400194 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000195
196 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700197 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // conservative window adaption (window size should not decrease)
schneiderklausd8197df2019-03-16 11:31:40 -0700198 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000199
200 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700201 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
202 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000203
204 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700205 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000206}
207
208BOOST_AUTO_TEST_CASE(CongestionMarksWithoutCwa)
209{
210 opt.disableCwa = true;
211 createPipeline();
212
213 nDataSegments = 7;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700214 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000215
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800216 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400217 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700218 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000219
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800220 // receive segments 0 to 4
221 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000222 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400223 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000224 }
225
226 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700227 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000228
229 // receive segment 5 with congestion mark
230 face.receive(*makeDataWithSegmentAndCongMark(5));
Davide Pesavento66777622020-10-09 18:46:03 -0400231 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000232
233 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700234 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // window size drops to 0.7x of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800235 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000236
237 // receive the last segment with congestion mark
238 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400239 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000240
241 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700242 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 3.43, MARGIN); // window size should decrease, as cwa is disabled
schneiderklausd8197df2019-03-16 11:31:40 -0700243 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000244
245 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700246 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
247 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000248
249 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700250 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000251}
252
253BOOST_AUTO_TEST_CASE(IgnoreCongestionMarks)
254{
255 opt.ignoreCongMarks = true;
256 createPipeline();
257
258 nDataSegments = 7;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700259 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000260
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800261 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400262 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700263 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000264
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800265 // receive segments 0 to 5
266 for (uint64_t i = 0; i < 6; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000267 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400268 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000269 }
270
271 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700272 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 8.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800273 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000274
275 // receive the last segment with congestion mark
276 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400277 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000278
279 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700280 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 9.0, MARGIN); // window size increases
schneiderklausd8197df2019-03-16 11:31:40 -0700281 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000282
283 // make sure no interest is retransmitted for marked data packet
schneiderklausd8197df2019-03-16 11:31:40 -0700284 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000285
286 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700287 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 1);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000288}
289
Weiwei Liu245d7912016-07-28 00:04:25 -0700290BOOST_AUTO_TEST_CASE(Nack)
291{
292 nDataSegments = 5;
schneiderklausd8197df2019-03-16 11:31:40 -0700293 pipeline->m_cwnd = 10.0;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800294 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400295 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800296
297 face.receive(*makeDataWithSegment(0));
Davide Pesavento66777622020-10-09 18:46:03 -0400298 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700299
300 face.receive(*makeDataWithSegment(1));
Davide Pesavento66777622020-10-09 18:46:03 -0400301 advanceClocks(time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400302
303 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800304 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
Weiwei Liu245d7912016-07-28 00:04:25 -0700305
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800306 // receive a nack with NackReason::DUPLICATE for segment 1
Weiwei Liu245d7912016-07-28 00:04:25 -0700307 auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
308 face.receive(nack1);
Davide Pesavento66777622020-10-09 18:46:03 -0400309 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700310
311 // nack1 is ignored
312 BOOST_CHECK_EQUAL(hasFailed, false);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400313 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700314 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700315
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800316 // receive a nack with NackReason::CONGESTION for segment 2
Weiwei Liu245d7912016-07-28 00:04:25 -0700317 auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
318 face.receive(nack2);
Davide Pesavento66777622020-10-09 18:46:03 -0400319 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700320
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800321 // segment 2 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700322 BOOST_CHECK_EQUAL(pipeline->m_retxCount[2], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700323
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800324 // receive a nack with NackReason::NONE for segment 3
Weiwei Liu245d7912016-07-28 00:04:25 -0700325 auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
326 face.receive(nack3);
Davide Pesavento66777622020-10-09 18:46:03 -0400327 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700328
329 // Other types of Nack will trigger a failure
330 BOOST_CHECK_EQUAL(hasFailed, true);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400331 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700332}
333
334BOOST_AUTO_TEST_CASE(FinalBlockIdNotSetAtBeginning)
335{
336 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700337 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800338 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400339 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700340
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800341 // receive segment 0 without FinalBlockId
342 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400343 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700344
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800345 // interests for segment 0 - 5 have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700346 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800347 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
schneiderklausd8197df2019-03-16 11:31:40 -0700348 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, false);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800349 // pending interests: segment 1, 2, 3, 4, 5
Weiwei Liu245d7912016-07-28 00:04:25 -0700350 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
351
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800352 // receive segment 1 with FinalBlockId
353 face.receive(*makeDataWithSegment(1));
Davide Pesavento66777622020-10-09 18:46:03 -0400354 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800355 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700356 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
Weiwei Liu245d7912016-07-28 00:04:25 -0700357
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800358 // pending interests for segment 1, 4, 5 haven been removed
359 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700360}
361
362BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
363{
364 // failed to retrieve segNo while the FinalBlockId has not yet been
365 // set, and later received a FinalBlockId >= segNo, i.e. segNo is
366 // part of the content.
367
368 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700369 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800370 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400371 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800372
373 // receive segment 0 without FinalBlockId
374 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400375 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700376
377 // receive segment 1 without FinalBlockId
378 face.receive(*makeDataWithSegment(1, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400379 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800380
381 // interests for segment 0 - 7 have been sent
382 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700383
384 // receive nack with NackReason::NONE for segment 3
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800385 auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700386 face.receive(nack);
Davide Pesavento66777622020-10-09 18:46:03 -0400387 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700388
389 // error not triggered
390 // pending interests for segment > 3 haven been removed
391 BOOST_CHECK_EQUAL(hasFailed, false);
392 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
393
394 // receive segment 2 with FinalBlockId
395 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400396 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700397
398 // error triggered since segment 3 is part of the content
399 BOOST_CHECK_EQUAL(hasFailed, true);
400}
401
402BOOST_AUTO_TEST_CASE(SpuriousFailureBeforeFinalBlockIdReceived)
403{
404 // failed to retrieve segNo while the FinalBlockId has not yet been
405 // set, and later received a FinalBlockId < segNo, i.e. segNo is
406 // not part of the content, and it was actually a spurious failure
407
408 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700409 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800410 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400411 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800412
413 // receive segment 0 without FinalBlockId
414 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400415 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700416
417 // receive segment 1 without FinalBlockId
418 face.receive(*makeDataWithSegment(1, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400419 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800420
421 // interests for segment 0 - 7 have been sent
422 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700423
424 // receive nack with NackReason::NONE for segment 4
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800425 auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700426 face.receive(nack);
Davide Pesavento66777622020-10-09 18:46:03 -0400427 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700428
429 // error not triggered
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800430 // pending interests for segment > 3 have been removed
Weiwei Liu245d7912016-07-28 00:04:25 -0700431 BOOST_CHECK_EQUAL(hasFailed, false);
432 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
433
434 // receive segment 2 with FinalBlockId
435 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400436 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700437
438 // timeout segment 3
Davide Pesavento66777622020-10-09 18:46:03 -0400439 advanceClocks(time::seconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700440
441 // segment 3 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700442 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700443
444 // receive segment 3
445 face.receive(*makeDataWithSegment(3));
Davide Pesavento66777622020-10-09 18:46:03 -0400446 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700447
448 BOOST_CHECK_EQUAL(hasFailed, false);
449}
450
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500451BOOST_AUTO_TEST_CASE(SegmentInfoMaintenance)
452{
453 // test that m_segmentInfo is properly maintained when
454 // a segment is received after two consecutive timeouts
455
456 nDataSegments = 3;
457
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800458 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400459 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800460
461 // receive segment 0
462 face.receive(*makeDataWithSegment(0));
Davide Pesavento66777622020-10-09 18:46:03 -0400463 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500464
465 // receive segment 1
466 face.receive(*makeDataWithSegment(1));
Davide Pesavento66777622020-10-09 18:46:03 -0400467 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500468
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800469 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500470
471 // check if segment 2's state is FirstTimeSent
schneiderklausd8197df2019-03-16 11:31:40 -0700472 auto it = pipeline->m_segmentInfo.find(2);
473 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500474 BOOST_CHECK(it->second.state == SegmentState::FirstTimeSent);
475
476 // timeout segment 2 twice
Davide Pesavento66777622020-10-09 18:46:03 -0400477 advanceClocks(time::milliseconds(400), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500478
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800479 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500480
481 // check if segment 2's state is Retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700482 it = pipeline->m_segmentInfo.find(2);
483 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500484 BOOST_CHECK(it->second.state == SegmentState::Retransmitted);
485
486 // check if segment 2 was retransmitted twice
schneiderklausd8197df2019-03-16 11:31:40 -0700487 BOOST_CHECK_EQUAL(pipeline->m_retxCount.at(2), 2);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500488
489 // receive segment 2 the first time
490 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400491 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500492
493 // check if segment 2 was erased from m_segmentInfo
schneiderklausd8197df2019-03-16 11:31:40 -0700494 it = pipeline->m_segmentInfo.find(2);
495 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500496
497 auto prevRtt = rttEstimator.getAvgRtt();
498 auto prevRto = rttEstimator.getEstimatedRto();
499
500 // receive segment 2 the second time
501 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400502 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500503
504 // nothing changed
schneiderklausd8197df2019-03-16 11:31:40 -0700505 it = pipeline->m_segmentInfo.find(2);
506 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800507 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500508 BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
509 BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
510}
511
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400512BOOST_AUTO_TEST_CASE(PrintSummaryWithNoRttMeasurements)
513{
514 // test the console ouptut when no RTT measurement is available,
515 // to make sure a proper message will be printed out
516
517 std::stringstream ss;
518
519 // change the underlying buffer and save the old buffer
520 auto oldBuf = std::cerr.rdbuf(ss.rdbuf());
521
schneiderklausd8197df2019-03-16 11:31:40 -0700522 pipeline->printSummary();
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400523 std::string line;
524
525 bool found = false;
526 while (std::getline(ss, line)) {
527 if (line == "RTT stats unavailable") {
528 found = true;
529 break;
530 }
531 }
532 BOOST_CHECK(found);
533 std::cerr.rdbuf(oldBuf); // reset
534}
535
Ryan Wickman034f30f2018-06-06 11:11:11 -0500536BOOST_AUTO_TEST_CASE(StopsWhenFileSizeLessThanChunkSize)
537{
538 // test to see if the program doesn't hang,
539 // when transfer is complete, for files less than the chunk size
540 // (i.e. when only one segment is sent/received)
541
542 createPipeline();
543 nDataSegments = 1;
544
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800545 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400546 advanceClocks(time::nanoseconds(1));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500547
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800548 face.receive(*makeDataWithSegment(0));
Davide Pesavento66777622020-10-09 18:46:03 -0400549 advanceClocks(time::nanoseconds(1));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500550
schneiderklausd8197df2019-03-16 11:31:40 -0700551 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
552 BOOST_CHECK_EQUAL(pipeline->m_segmentInfo.size(), 0);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500553 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
554}
555
556
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700557BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsCubic
Weiwei Liu245d7912016-07-28 00:04:25 -0700558BOOST_AUTO_TEST_SUITE_END() // Chunks
559
Davide Pesaventob3570c62022-02-19 19:19:00 -0500560} // namespace ndn::chunks::tests