blob: 094602117bd7d7490764d1f61e347f1f24881d80 [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 Pesaventob3570c62022-02-19 19:19:00 -05003 * Copyright (c) 2016-2022, 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-aimd.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 PipelineInterestAimdFixture : 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 PipelineInterestAimdFixture()
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 {
Klaus Schneider9e5122b2019-03-19 17:03:25 -070048 auto pline = make_unique<PipelineInterestsAimd>(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 Pesavento5e3773d2019-08-22 15:35:08 -040054 static shared_ptr<RttEstimatorWithStats::Options>
Weiwei Liu245d7912016-07-28 00:04:25 -070055 makeRttEstimatorOptions()
56 {
Davide Pesavento5e3773d2019-08-22 15:35:08 -040057 auto rttOptions = make_shared<RttEstimatorWithStats::Options>();
58 rttOptions->alpha = 0.125;
59 rttOptions->beta = 0.25;
60 rttOptions->k = 4;
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()};
schneiderklausd8197df2019-03-16 11:31:40 -070071 PipelineInterestsAdaptive* pipeline;
Davide Pesaventoba560662019-06-26 22:45:44 -040072 static constexpr double MARGIN = 0.001;
Weiwei Liu245d7912016-07-28 00:04:25 -070073};
74
Klaus Schneider9e5122b2019-03-19 17:03:25 -070075constexpr double PipelineInterestAimdFixture::MARGIN;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000076
Weiwei Liu245d7912016-07-28 00:04:25 -070077BOOST_AUTO_TEST_SUITE(Chunks)
Klaus Schneider9e5122b2019-03-19 17:03:25 -070078BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsAimd, PipelineInterestAimdFixture)
Weiwei Liu245d7912016-07-28 00:04:25 -070079
80BOOST_AUTO_TEST_CASE(SlowStart)
81{
82 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -070083 pipeline->m_ssthresh = 8.0;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -070084 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -070085
schneiderklausd8197df2019-03-16 11:31:40 -070086 double preCwnd = pipeline->m_cwnd;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080087 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -040088 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -070089 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -070090
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080091 for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -070092 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -040093 advanceClocks(time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -070094 BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, 1, MARGIN);
95 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -070096 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -040097
98 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
Weiwei Liu245d7912016-07-28 00:04:25 -070099}
100
101BOOST_AUTO_TEST_CASE(CongestionAvoidance)
102{
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800103 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700104 pipeline->m_ssthresh = 4.0;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700105 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700106
schneiderklausd8197df2019-03-16 11:31:40 -0700107 double preCwnd = pipeline->m_cwnd;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800108 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400109 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700110 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700111
schneiderklausd8197df2019-03-16 11:31:40 -0700112 for (uint64_t i = 0; i < pipeline->m_ssthresh; ++i) { // slow start
Weiwei Liu245d7912016-07-28 00:04:25 -0700113 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400114 advanceClocks(time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -0700115 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -0700116 }
117
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700118 BOOST_CHECK_CLOSE(preCwnd, 4.5, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700119
schneiderklausd8197df2019-03-16 11:31:40 -0700120 for (uint64_t i = pipeline->m_ssthresh; i < nDataSegments - 1; ++i) { // congestion avoidance
Weiwei Liu245d7912016-07-28 00:04:25 -0700121 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400122 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700123 BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, opt.aiStep / floor(preCwnd), MARGIN);
schneiderklausd8197df2019-03-16 11:31:40 -0700124 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -0700125 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400126
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700127 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments -1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700128}
129
130BOOST_AUTO_TEST_CASE(Timeout)
131{
132 nDataSegments = 8;
schneiderklausd8197df2019-03-16 11:31:40 -0700133 pipeline->m_ssthresh = 4.0;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700134 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700135
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800136 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400137 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700138 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700139
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800140 // receive segment 0, 1, and 2
141 for (uint64_t i = 0; i < 3; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700142 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400143 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700144 }
145
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400146 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700147 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.25, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800148 BOOST_CHECK_EQUAL(face.sentInterests.size(), 7); // request for segment 7 has been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700149
Davide Pesavento66777622020-10-09 18:46:03 -0400150 advanceClocks(time::milliseconds(100));
Weiwei Liu245d7912016-07-28 00:04:25 -0700151
152 // receive segment 4
153 face.receive(*makeDataWithSegment(4));
Davide Pesavento66777622020-10-09 18:46:03 -0400154 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700155
156 // receive segment 5
157 face.receive(*makeDataWithSegment(5));
Davide Pesavento66777622020-10-09 18:46:03 -0400158 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700159
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400160 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700161 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.75, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800162 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700163
schneiderklausd8197df2019-03-16 11:31:40 -0700164 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
165 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 0);
166 BOOST_CHECK_EQUAL(pipeline->m_nMarkDecr, 0);
167 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 0);
168 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
169 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 0);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700170
171 // timeout segment 3 & 6
Davide Pesavento66777622020-10-09 18:46:03 -0400172 advanceClocks(time::milliseconds(150));
schneiderklausd8197df2019-03-16 11:31:40 -0700173 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
174 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 1);
175 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
176 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700177
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400178 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700179 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.375, MARGIN); // window size drop to 1/2 of previous size
schneiderklausd8197df2019-03-16 11:31:40 -0700180 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700181
182 // receive segment 6, retransmit 3
183 face.receive(*makeDataWithSegment(6));
Davide Pesavento66777622020-10-09 18:46:03 -0400184 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700185
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400186 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700187 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.875, MARGIN); // congestion avoidance
schneiderklausd8197df2019-03-16 11:31:40 -0700188 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
189 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700190
schneiderklausd8197df2019-03-16 11:31:40 -0700191 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
192 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
193 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts,
194 pipeline->m_nRetransmitted + pipeline->m_nSkippedRetx);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700195
Weiwei Liu245d7912016-07-28 00:04:25 -0700196}
197
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000198BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
199{
200 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700201 pipeline->m_ssthresh = 4.0;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700202 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000203
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800204 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400205 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700206 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000207
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800208 // receive segments 0 to 4
209 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000210 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400211 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000212 }
213
214 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700215 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.75, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000216
217 // receive segment 5 with congestion mark
218 face.receive(*makeDataWithSegmentAndCongMark(5));
Davide Pesavento66777622020-10-09 18:46:03 -0400219 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000220
221 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700222 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.375, MARGIN); // window size drops to 1/2 of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800223 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000224
225 // receive the last segment with congestion mark
226 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400227 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000228
229 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700230 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.375, MARGIN); // conservative window adaption (window size should not decrease)
schneiderklausd8197df2019-03-16 11:31:40 -0700231 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000232
233 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700234 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
235 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000236
237 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700238 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000239}
240
241BOOST_AUTO_TEST_CASE(CongestionMarksWithoutCwa)
242{
243 opt.disableCwa = true;
244 createPipeline();
245
246 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700247 pipeline->m_ssthresh = 4.0;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700248 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000249
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800250 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400251 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700252 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000253
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800254 // receive segments 0 to 4
255 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000256 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400257 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000258 }
259
260 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700261 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.75, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000262
263 // receive segment 5 with congestion mark
264 face.receive(*makeDataWithSegmentAndCongMark(5));
Davide Pesavento66777622020-10-09 18:46:03 -0400265 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000266
267 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700268 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.375, MARGIN); // window size drops to 1/2 of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800269 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000270
271 // receive the last segment with congestion mark
272 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400273 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000274
275 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
schneiderklausd8197df2019-03-16 11:31:40 -0700276 BOOST_CHECK_CLOSE(pipeline->m_cwnd, PipelineInterestsAdaptive::MIN_SSTHRESH,
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000277 MARGIN); // window size should decrease, as cwa is disabled
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 packets
schneiderklausd8197df2019-03-16 11:31:40 -0700281 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
282 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000283
284 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700285 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000286}
287
288BOOST_AUTO_TEST_CASE(IgnoreCongestionMarks)
289{
290 opt.ignoreCongMarks = true;
291 createPipeline();
292
293 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700294 pipeline->m_ssthresh = 4.0;
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700295 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 2, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000296
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800297 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400298 advanceClocks(time::nanoseconds(1));
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700299 BOOST_CHECK_EQUAL(face.sentInterests.size(), 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000300
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800301 // receive segments 0 to 5
302 for (uint64_t i = 0; i < 6; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000303 face.receive(*makeDataWithSegment(i));
Davide Pesavento66777622020-10-09 18:46:03 -0400304 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000305 }
306
307 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700308 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 5.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800309 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000310
311 // receive the last segment with congestion mark
312 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
Davide Pesavento66777622020-10-09 18:46:03 -0400313 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000314
315 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider4a2e89d2019-10-27 10:04:39 -0700316 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 5.2, MARGIN); // window size increases
schneiderklausd8197df2019-03-16 11:31:40 -0700317 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000318
319 // make sure no interest is retransmitted for marked data packet
schneiderklausd8197df2019-03-16 11:31:40 -0700320 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000321
322 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700323 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 1);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000324}
325
Weiwei Liu245d7912016-07-28 00:04:25 -0700326BOOST_AUTO_TEST_CASE(Nack)
327{
328 nDataSegments = 5;
schneiderklausd8197df2019-03-16 11:31:40 -0700329 pipeline->m_cwnd = 10.0;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800330 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400331 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800332
333 face.receive(*makeDataWithSegment(0));
Davide Pesavento66777622020-10-09 18:46:03 -0400334 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700335
336 face.receive(*makeDataWithSegment(1));
Davide Pesavento66777622020-10-09 18:46:03 -0400337 advanceClocks(time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400338
339 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800340 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
Weiwei Liu245d7912016-07-28 00:04:25 -0700341
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800342 // receive a nack with NackReason::DUPLICATE for segment 1
Weiwei Liu245d7912016-07-28 00:04:25 -0700343 auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
344 face.receive(nack1);
Davide Pesavento66777622020-10-09 18:46:03 -0400345 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700346
347 // nack1 is ignored
348 BOOST_CHECK_EQUAL(hasFailed, false);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400349 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700350 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700351
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800352 // receive a nack with NackReason::CONGESTION for segment 2
Weiwei Liu245d7912016-07-28 00:04:25 -0700353 auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
354 face.receive(nack2);
Davide Pesavento66777622020-10-09 18:46:03 -0400355 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700356
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800357 // segment 2 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700358 BOOST_CHECK_EQUAL(pipeline->m_retxCount[2], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700359
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800360 // receive a nack with NackReason::NONE for segment 3
Weiwei Liu245d7912016-07-28 00:04:25 -0700361 auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
362 face.receive(nack3);
Davide Pesavento66777622020-10-09 18:46:03 -0400363 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700364
365 // Other types of Nack will trigger a failure
366 BOOST_CHECK_EQUAL(hasFailed, true);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400367 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700368}
369
370BOOST_AUTO_TEST_CASE(FinalBlockIdNotSetAtBeginning)
371{
372 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700373 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800374 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400375 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700376
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800377 // receive segment 0 without FinalBlockId
378 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400379 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700380
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800381 // interests for segment 0 - 5 have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700382 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800383 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
schneiderklausd8197df2019-03-16 11:31:40 -0700384 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, false);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800385 // pending interests: segment 1, 2, 3, 4, 5
Weiwei Liu245d7912016-07-28 00:04:25 -0700386 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
387
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800388 // receive segment 1 with FinalBlockId
389 face.receive(*makeDataWithSegment(1));
Davide Pesavento66777622020-10-09 18:46:03 -0400390 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800391 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700392 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
Weiwei Liu245d7912016-07-28 00:04:25 -0700393
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800394 // pending interests for segment 1, 4, 5 haven been removed
395 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700396}
397
398BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
399{
400 // failed to retrieve segNo while the FinalBlockId has not yet been
401 // set, and later received a FinalBlockId >= segNo, i.e. segNo is
402 // part of the content.
403
404 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700405 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800406 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400407 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800408
409 // receive segment 0 without FinalBlockId
410 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400411 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700412
413 // receive segment 1 without FinalBlockId
414 face.receive(*makeDataWithSegment(1, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400415 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800416
417 // interests for segment 0 - 7 have been sent
418 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700419
420 // receive nack with NackReason::NONE for segment 3
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800421 auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700422 face.receive(nack);
Davide Pesavento66777622020-10-09 18:46:03 -0400423 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700424
425 // error not triggered
426 // pending interests for segment > 3 haven been removed
427 BOOST_CHECK_EQUAL(hasFailed, false);
428 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
429
430 // receive segment 2 with FinalBlockId
431 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400432 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700433
434 // error triggered since segment 3 is part of the content
435 BOOST_CHECK_EQUAL(hasFailed, true);
436}
437
438BOOST_AUTO_TEST_CASE(SpuriousFailureBeforeFinalBlockIdReceived)
439{
440 // failed to retrieve segNo while the FinalBlockId has not yet been
441 // set, and later received a FinalBlockId < segNo, i.e. segNo is
442 // not part of the content, and it was actually a spurious failure
443
444 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700445 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800446 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400447 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800448
449 // receive segment 0 without FinalBlockId
450 face.receive(*makeDataWithSegment(0, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400451 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700452
453 // receive segment 1 without FinalBlockId
454 face.receive(*makeDataWithSegment(1, false));
Davide Pesavento66777622020-10-09 18:46:03 -0400455 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800456
457 // interests for segment 0 - 7 have been sent
458 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700459
460 // receive nack with NackReason::NONE for segment 4
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800461 auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700462 face.receive(nack);
Davide Pesavento66777622020-10-09 18:46:03 -0400463 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700464
465 // error not triggered
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800466 // pending interests for segment > 3 have been removed
Weiwei Liu245d7912016-07-28 00:04:25 -0700467 BOOST_CHECK_EQUAL(hasFailed, false);
468 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
469
470 // receive segment 2 with FinalBlockId
471 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400472 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700473
474 // timeout segment 3
Davide Pesavento66777622020-10-09 18:46:03 -0400475 advanceClocks(time::seconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700476
477 // segment 3 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700478 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700479
480 // receive segment 3
481 face.receive(*makeDataWithSegment(3));
Davide Pesavento66777622020-10-09 18:46:03 -0400482 advanceClocks(time::nanoseconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700483
484 BOOST_CHECK_EQUAL(hasFailed, false);
485}
486
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500487BOOST_AUTO_TEST_CASE(SegmentInfoMaintenance)
488{
489 // test that m_segmentInfo is properly maintained when
490 // a segment is received after two consecutive timeouts
491
492 nDataSegments = 3;
493
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800494 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400495 advanceClocks(time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800496
497 // receive segment 0
498 face.receive(*makeDataWithSegment(0));
Davide Pesavento66777622020-10-09 18:46:03 -0400499 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500500
501 // receive segment 1
502 face.receive(*makeDataWithSegment(1));
Davide Pesavento66777622020-10-09 18:46:03 -0400503 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500504
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800505 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500506
507 // check if segment 2's state is FirstTimeSent
schneiderklausd8197df2019-03-16 11:31:40 -0700508 auto it = pipeline->m_segmentInfo.find(2);
509 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500510 BOOST_CHECK(it->second.state == SegmentState::FirstTimeSent);
511
512 // timeout segment 2 twice
Davide Pesavento66777622020-10-09 18:46:03 -0400513 advanceClocks(time::milliseconds(400), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500514
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800515 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500516
517 // check if segment 2's state is Retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700518 it = pipeline->m_segmentInfo.find(2);
519 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500520 BOOST_CHECK(it->second.state == SegmentState::Retransmitted);
521
522 // check if segment 2 was retransmitted twice
schneiderklausd8197df2019-03-16 11:31:40 -0700523 BOOST_CHECK_EQUAL(pipeline->m_retxCount.at(2), 2);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500524
525 // receive segment 2 the first time
526 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400527 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500528
529 // check if segment 2 was erased from m_segmentInfo
schneiderklausd8197df2019-03-16 11:31:40 -0700530 it = pipeline->m_segmentInfo.find(2);
531 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500532
533 auto prevRtt = rttEstimator.getAvgRtt();
534 auto prevRto = rttEstimator.getEstimatedRto();
535
536 // receive segment 2 the second time
537 face.receive(*makeDataWithSegment(2));
Davide Pesavento66777622020-10-09 18:46:03 -0400538 advanceClocks(time::nanoseconds(1));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500539
540 // nothing changed
schneiderklausd8197df2019-03-16 11:31:40 -0700541 it = pipeline->m_segmentInfo.find(2);
542 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800543 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500544 BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
545 BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
546}
547
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400548BOOST_AUTO_TEST_CASE(PrintSummaryWithNoRttMeasurements)
549{
550 // test the console ouptut when no RTT measurement is available,
551 // to make sure a proper message will be printed out
552
553 std::stringstream ss;
554
555 // change the underlying buffer and save the old buffer
556 auto oldBuf = std::cerr.rdbuf(ss.rdbuf());
557
schneiderklausd8197df2019-03-16 11:31:40 -0700558 pipeline->printSummary();
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400559 std::string line;
560
561 bool found = false;
562 while (std::getline(ss, line)) {
563 if (line == "RTT stats unavailable") {
564 found = true;
565 break;
566 }
567 }
568 BOOST_CHECK(found);
569 std::cerr.rdbuf(oldBuf); // reset
570}
571
Ryan Wickman034f30f2018-06-06 11:11:11 -0500572BOOST_AUTO_TEST_CASE(StopsWhenFileSizeLessThanChunkSize)
573{
574 // test to see if the program doesn't hang,
575 // when transfer is complete, for files less than the chunk size
576 // (i.e. when only one segment is sent/received)
577
578 createPipeline();
579 nDataSegments = 1;
580
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800581 run(name);
Davide Pesavento66777622020-10-09 18:46:03 -0400582 advanceClocks(time::nanoseconds(1));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500583
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800584 face.receive(*makeDataWithSegment(0));
Davide Pesavento66777622020-10-09 18:46:03 -0400585 advanceClocks(time::nanoseconds(1));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500586
schneiderklausd8197df2019-03-16 11:31:40 -0700587 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
588 BOOST_CHECK_EQUAL(pipeline->m_segmentInfo.size(), 0);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500589 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
590}
591
592
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700593BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsAimd
Weiwei Liu245d7912016-07-28 00:04:25 -0700594BOOST_AUTO_TEST_SUITE_END() // Chunks
595
Davide Pesaventob3570c62022-02-19 19:19:00 -0500596} // namespace ndn::chunks::tests