blob: c1f3b601fb8c8c3fc6241d734806c31a7faadaaf [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 Pesavento0b6e1db2025-04-19 19:23:11 -04003 * Copyright (c) 2016-2025, 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
Davide Pesavento0b6e1db2025-04-19 19:23:11 -040028#include "tools/get/pipeline-interests-cubic.hpp"
Weiwei Liu245d7912016-07-28 00:04:25 -070029
30#include "pipeline-interests-fixture.hpp"
31
Davide Pesavento0b6e1db2025-04-19 19:23:11 -040032namespace ndn::tests {
Weiwei Liu245d7912016-07-28 00:04:25 -070033
Klaus Schneider9e5122b2019-03-19 17:03:25 -070034class PipelineInterestCubicFixture : public PipelineInterestsFixture
Weiwei Liu245d7912016-07-28 00:04:25 -070035{
Davide Pesaventob3570c62022-02-19 19:19:00 -050036protected:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070037 PipelineInterestCubicFixture()
Weiwei Liu245d7912016-07-28 00:04:25 -070038 {
Davide Pesavento97a33b22019-10-17 22:10:47 -040039 opt.isQuiet = true;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000040 createPipeline();
41 }
42
43 void
44 createPipeline()
45 {
Davide Pesavento5748e822024-01-26 18:40:22 -050046 auto pline = std::make_unique<PipelineInterestsCubic>(face, rttEstimator, opt);
schneiderklausd8197df2019-03-16 11:31:40 -070047 pipeline = pline.get();
Weiwei Liu245d7912016-07-28 00:04:25 -070048 setPipeline(std::move(pline));
49 }
50
51private:
Davide Pesavento5748e822024-01-26 18:40:22 -050052 static std::shared_ptr<RttEstimatorWithStats::Options>
Weiwei Liu245d7912016-07-28 00:04:25 -070053 makeRttEstimatorOptions()
54 {
Davide Pesavento5748e822024-01-26 18:40:22 -050055 auto rttOptions = std::make_shared<RttEstimatorWithStats::Options>();
Davide Pesavento5e3773d2019-08-22 15:35:08 -040056 rttOptions->alpha = 0.125;
57 rttOptions->beta = 0.25;
58 rttOptions->k = 8;
59 rttOptions->initialRto = 1_s;
60 rttOptions->minRto = 200_ms;
61 rttOptions->maxRto = 4_s;
62 rttOptions->rtoBackoffMultiplier = 2;
Weiwei Liu245d7912016-07-28 00:04:25 -070063 return rttOptions;
64 }
65
66protected:
Davide Pesavento97a33b22019-10-17 22:10:47 -040067 Options opt;
Davide Pesaventob3570c62022-02-19 19:19:00 -050068 RttEstimatorWithStats rttEstimator{makeRttEstimatorOptions()};
Klaus Schneider9e5122b2019-03-19 17:03:25 -070069 PipelineInterestsCubic* pipeline;
Davide Pesaventoba560662019-06-26 22:45:44 -040070 static constexpr double MARGIN = 0.001;
Weiwei Liu245d7912016-07-28 00:04:25 -070071};
72
Davide Pesavento0b6e1db2025-04-19 19:23:11 -040073BOOST_AUTO_TEST_SUITE(Get)
Klaus Schneider9e5122b2019-03-19 17:03:25 -070074BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsCubic, PipelineInterestCubicFixture)
Weiwei Liu245d7912016-07-28 00:04:25 -070075
76BOOST_AUTO_TEST_CASE(SlowStart)
77{
78 nDataSegments = 4;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -070079 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -070080
schneiderklausd8197df2019-03-16 11:31:40 -070081 double preCwnd = pipeline->m_cwnd;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080082 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -040083 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -070084 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -070085
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080086 for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -070087 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -040088 advanceClocks(time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -070089 BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, 1, MARGIN);
90 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -070091 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -040092
93 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
Weiwei Liu245d7912016-07-28 00:04:25 -070094}
95
Weiwei Liu245d7912016-07-28 00:04:25 -070096
97BOOST_AUTO_TEST_CASE(Timeout)
98{
99 nDataSegments = 8;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700100 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700101
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800102 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400103 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700104 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700105
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800106 // receive segment 0, 1, and 2
107 for (uint64_t i = 0; i < 3; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700108 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400109 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700110 }
111
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400112 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700113 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 5, MARGIN);
114 BOOST_CHECK_EQUAL(face.sentInterests.size(), 8); // request for segment #7 has been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700115
Davide Pesavento66777622020-10-09 18:46:03 -0400116 advanceClocks(time::milliseconds(100));
Weiwei Liu245d7912016-07-28 00:04:25 -0700117
118 // receive segment 4
119 face.receive(*makeDataWithSegment(4));
Davide Pesavento66777622020-10-09 18:46:03 -0400120 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700121
122 // receive segment 5
123 face.receive(*makeDataWithSegment(5));
Davide Pesavento66777622020-10-09 18:46:03 -0400124 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700125
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400126 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700127 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800128 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700129
schneiderklausd8197df2019-03-16 11:31:40 -0700130 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
131 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 0);
132 BOOST_CHECK_EQUAL(pipeline->m_nMarkDecr, 0);
133 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 0);
134 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
135 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 0);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700136
137 // timeout segment 3 & 6
Davide Pesavento66777622020-10-09 18:46:03 -0400138 advanceClocks(time::milliseconds(150));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700139 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 3);
140 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 3);
schneiderklausd8197df2019-03-16 11:31:40 -0700141 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
142 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700143
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400144 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700145 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 -0700146 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700147
148 // receive segment 6, retransmit 3
149 face.receive(*makeDataWithSegment(6));
Davide Pesavento66777622020-10-09 18:46:03 -0400150 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700151
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400152 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700153 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // congestion avoidance
schneiderklausd8197df2019-03-16 11:31:40 -0700154 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
155 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700156
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700157 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 3);
158 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 3);
schneiderklausd8197df2019-03-16 11:31:40 -0700159 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts,
160 pipeline->m_nRetransmitted + pipeline->m_nSkippedRetx);
Weiwei Liu245d7912016-07-28 00:04:25 -0700161}
162
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000163BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
164{
165 nDataSegments = 7;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700166 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000167
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800168 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400169 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700170 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000171
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800172 // receive segments 0 to 4
173 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000174 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400175 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000176 }
177
178 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700179 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000180
181 // receive segment 5 with congestion mark
182 face.receive(*makeDataWithSegmentAndCongMark(5));
Davide Pesavento66777622020-10-09 18:46:03 -0400183 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000184
185 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700186 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 -0800187 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000188
189 // receive the last segment with congestion mark
190 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400191 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000192
193 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700194 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.9, MARGIN); // conservative window adaption (window size should not decrease)
schneiderklausd8197df2019-03-16 11:31:40 -0700195 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000196
197 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700198 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
199 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000200
201 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700202 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000203}
204
205BOOST_AUTO_TEST_CASE(CongestionMarksWithoutCwa)
206{
207 opt.disableCwa = true;
208 createPipeline();
209
210 nDataSegments = 7;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700211 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000212
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800213 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400214 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700215 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000216
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800217 // receive segments 0 to 4
218 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000219 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400220 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000221 }
222
223 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700224 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000225
226 // receive segment 5 with congestion mark
227 face.receive(*makeDataWithSegmentAndCongMark(5));
Davide Pesavento66777622020-10-09 18:46:03 -0400228 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000229
230 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700231 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 -0800232 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000233
234 // receive the last segment with congestion mark
235 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400236 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000237
238 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700239 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 3.43, MARGIN); // window size should decrease, as cwa is disabled
schneiderklausd8197df2019-03-16 11:31:40 -0700240 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000241
242 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700243 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
244 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000245
246 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700247 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000248}
249
250BOOST_AUTO_TEST_CASE(IgnoreCongestionMarks)
251{
252 opt.ignoreCongMarks = true;
253 createPipeline();
254
255 nDataSegments = 7;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700256 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000257
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800258 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400259 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700260 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000261
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800262 // receive segments 0 to 5
263 for (uint64_t i = 0; i < 6; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000264 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400265 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000266 }
267
268 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700269 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 8.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800270 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000271
272 // receive the last segment with congestion mark
273 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400274 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000275
276 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700277 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 9.0, MARGIN); // window size increases
schneiderklausd8197df2019-03-16 11:31:40 -0700278 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000279
280 // make sure no interest is retransmitted for marked data packet
schneiderklausd8197df2019-03-16 11:31:40 -0700281 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000282
283 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700284 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 1);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000285}
286
Weiwei Liu245d7912016-07-28 00:04:25 -0700287BOOST_AUTO_TEST_CASE(Nack)
288{
289 nDataSegments = 5;
schneiderklausd8197df2019-03-16 11:31:40 -0700290 pipeline->m_cwnd = 10.0;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800291 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400292 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800293
294 face.receive(*makeDataWithSegment(0));
Davide Pesavento66777622020-10-09 18:46:03 -0400295 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700296
297 face.receive(*makeDataWithSegment(1));
Davide Pesavento66777622020-10-09 18:46:03 -0400298 advanceClocks(time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400299
300 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800301 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
Weiwei Liu245d7912016-07-28 00:04:25 -0700302
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800303 // receive a nack with NackReason::DUPLICATE for segment 1
Weiwei Liu245d7912016-07-28 00:04:25 -0700304 auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
305 face.receive(nack1);
Davide Pesavento66777622020-10-09 18:46:03 -0400306 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700307
308 // nack1 is ignored
309 BOOST_CHECK_EQUAL(hasFailed, false);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400310 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700311 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700312
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800313 // receive a nack with NackReason::CONGESTION for segment 2
Weiwei Liu245d7912016-07-28 00:04:25 -0700314 auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
315 face.receive(nack2);
Davide Pesavento66777622020-10-09 18:46:03 -0400316 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700317
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800318 // segment 2 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700319 BOOST_CHECK_EQUAL(pipeline->m_retxCount[2], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700320
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800321 // receive a nack with NackReason::NONE for segment 3
Weiwei Liu245d7912016-07-28 00:04:25 -0700322 auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
323 face.receive(nack3);
Davide Pesavento66777622020-10-09 18:46:03 -0400324 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700325
326 // Other types of Nack will trigger a failure
327 BOOST_CHECK_EQUAL(hasFailed, true);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400328 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700329}
330
331BOOST_AUTO_TEST_CASE(FinalBlockIdNotSetAtBeginning)
332{
333 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700334 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800335 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400336 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700337
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800338 // receive segment 0 without FinalBlockId
339 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400340 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700341
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800342 // interests for segment 0 - 5 have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700343 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800344 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
schneiderklausd8197df2019-03-16 11:31:40 -0700345 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, false);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800346 // pending interests: segment 1, 2, 3, 4, 5
Weiwei Liu245d7912016-07-28 00:04:25 -0700347 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
348
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800349 // receive segment 1 with FinalBlockId
350 face.receive(*makeDataWithSegment(1));
Davide Pesavento66777622020-10-09 18:46:03 -0400351 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800352 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700353 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
Weiwei Liu245d7912016-07-28 00:04:25 -0700354
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800355 // pending interests for segment 1, 4, 5 haven been removed
356 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700357}
358
359BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
360{
361 // failed to retrieve segNo while the FinalBlockId has not yet been
362 // set, and later received a FinalBlockId >= segNo, i.e. segNo is
363 // part of the content.
364
365 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700366 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800367 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400368 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800369
370 // receive segment 0 without FinalBlockId
371 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400372 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700373
374 // receive segment 1 without FinalBlockId
375 face.receive(*makeDataWithSegment(1, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400376 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800377
378 // interests for segment 0 - 7 have been sent
379 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700380
381 // receive nack with NackReason::NONE for segment 3
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800382 auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700383 face.receive(nack);
Davide Pesavento66777622020-10-09 18:46:03 -0400384 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700385
386 // error not triggered
387 // pending interests for segment > 3 haven been removed
388 BOOST_CHECK_EQUAL(hasFailed, false);
389 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
390
391 // receive segment 2 with FinalBlockId
392 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400393 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700394
395 // error triggered since segment 3 is part of the content
396 BOOST_CHECK_EQUAL(hasFailed, true);
397}
398
399BOOST_AUTO_TEST_CASE(SpuriousFailureBeforeFinalBlockIdReceived)
400{
401 // failed to retrieve segNo while the FinalBlockId has not yet been
402 // set, and later received a FinalBlockId < segNo, i.e. segNo is
403 // not part of the content, and it was actually a spurious failure
404
405 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700406 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800407 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400408 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800409
410 // receive segment 0 without FinalBlockId
411 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400412 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700413
414 // receive segment 1 without FinalBlockId
415 face.receive(*makeDataWithSegment(1, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400416 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800417
418 // interests for segment 0 - 7 have been sent
419 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700420
421 // receive nack with NackReason::NONE for segment 4
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800422 auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700423 face.receive(nack);
Davide Pesavento66777622020-10-09 18:46:03 -0400424 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700425
426 // error not triggered
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800427 // pending interests for segment > 3 have been removed
Weiwei Liu245d7912016-07-28 00:04:25 -0700428 BOOST_CHECK_EQUAL(hasFailed, false);
429 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
430
431 // receive segment 2 with FinalBlockId
432 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400433 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700434
435 // timeout segment 3
Davide Pesavento66777622020-10-09 18:46:03 -0400436 advanceClocks(time::seconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700437
438 // segment 3 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700439 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700440
441 // receive segment 3
442 face.receive(*makeDataWithSegment(3));
Davide Pesavento66777622020-10-09 18:46:03 -0400443 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700444
445 BOOST_CHECK_EQUAL(hasFailed, false);
446}
447
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500448BOOST_AUTO_TEST_CASE(SegmentInfoMaintenance)
449{
450 // test that m_segmentInfo is properly maintained when
451 // a segment is received after two consecutive timeouts
452
453 nDataSegments = 3;
454
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800455 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400456 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800457
458 // receive segment 0
459 face.receive(*makeDataWithSegment(0));
Davide Pesavento66777622020-10-09 18:46:03 -0400460 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500461
462 // receive segment 1
463 face.receive(*makeDataWithSegment(1));
Davide Pesavento66777622020-10-09 18:46:03 -0400464 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500465
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800466 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500467
468 // check if segment 2's state is FirstTimeSent
schneiderklausd8197df2019-03-16 11:31:40 -0700469 auto it = pipeline->m_segmentInfo.find(2);
470 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500471 BOOST_CHECK(it->second.state == SegmentState::FirstTimeSent);
472
473 // timeout segment 2 twice
Davide Pesavento66777622020-10-09 18:46:03 -0400474 advanceClocks(time::milliseconds(400), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500475
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800476 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500477
478 // check if segment 2's state is Retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700479 it = pipeline->m_segmentInfo.find(2);
480 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500481 BOOST_CHECK(it->second.state == SegmentState::Retransmitted);
482
483 // check if segment 2 was retransmitted twice
schneiderklausd8197df2019-03-16 11:31:40 -0700484 BOOST_CHECK_EQUAL(pipeline->m_retxCount.at(2), 2);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500485
486 // receive segment 2 the first time
487 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400488 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500489
490 // check if segment 2 was erased from m_segmentInfo
schneiderklausd8197df2019-03-16 11:31:40 -0700491 it = pipeline->m_segmentInfo.find(2);
492 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500493
494 auto prevRtt = rttEstimator.getAvgRtt();
495 auto prevRto = rttEstimator.getEstimatedRto();
496
497 // receive segment 2 the second time
498 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400499 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500500
501 // nothing changed
schneiderklausd8197df2019-03-16 11:31:40 -0700502 it = pipeline->m_segmentInfo.find(2);
503 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800504 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500505 BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
506 BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
507}
508
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400509BOOST_AUTO_TEST_CASE(PrintSummaryWithNoRttMeasurements)
510{
511 // test the console ouptut when no RTT measurement is available,
512 // to make sure a proper message will be printed out
513
514 std::stringstream ss;
515
516 // change the underlying buffer and save the old buffer
517 auto oldBuf = std::cerr.rdbuf(ss.rdbuf());
518
schneiderklausd8197df2019-03-16 11:31:40 -0700519 pipeline->printSummary();
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400520 std::string line;
521
522 bool found = false;
523 while (std::getline(ss, line)) {
524 if (line == "RTT stats unavailable") {
525 found = true;
526 break;
527 }
528 }
529 BOOST_CHECK(found);
530 std::cerr.rdbuf(oldBuf); // reset
531}
532
Ryan Wickman034f30f2018-06-06 11:11:11 -0500533BOOST_AUTO_TEST_CASE(StopsWhenFileSizeLessThanChunkSize)
534{
535 // test to see if the program doesn't hang,
536 // when transfer is complete, for files less than the chunk size
537 // (i.e. when only one segment is sent/received)
538
539 createPipeline();
540 nDataSegments = 1;
541
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800542 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400543 advanceClocks(time::nanoseconds(1));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500544
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800545 face.receive(*makeDataWithSegment(0));
Davide Pesavento66777622020-10-09 18:46:03 -0400546 advanceClocks(time::nanoseconds(1));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500547
schneiderklausd8197df2019-03-16 11:31:40 -0700548 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
549 BOOST_CHECK_EQUAL(pipeline->m_segmentInfo.size(), 0);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500550 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
551}
552
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700553BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsCubic
Davide Pesavento0b6e1db2025-04-19 19:23:11 -0400554BOOST_AUTO_TEST_SUITE_END() // Get
Weiwei Liu245d7912016-07-28 00:04:25 -0700555
Davide Pesavento0b6e1db2025-04-19 19:23:11 -0400556} // namespace ndn::tests