blob: efb634a461b29e5f0ba6364d9d02f7d467bebb68 [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/*
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -08003 * Copyright (c) 2016-2019, 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
32namespace ndn {
33namespace chunks {
Weiwei Liu245d7912016-07-28 00:04:25 -070034namespace tests {
35
36using namespace ndn::tests;
37
Klaus Schneider9e5122b2019-03-19 17:03:25 -070038class PipelineInterestAimdFixture : public PipelineInterestsFixture
Weiwei Liu245d7912016-07-28 00:04:25 -070039{
40public:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070041 PipelineInterestAimdFixture()
Davide Pesavento97a33b22019-10-17 22:10:47 -040042 : rttEstimator(makeRttEstimatorOptions())
Weiwei Liu245d7912016-07-28 00:04:25 -070043 {
Davide Pesavento97a33b22019-10-17 22:10:47 -040044 opt.isQuiet = true;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000045 createPipeline();
46 }
47
48 void
49 createPipeline()
50 {
Klaus Schneider9e5122b2019-03-19 17:03:25 -070051 auto pline = make_unique<PipelineInterestsAimd>(face, rttEstimator, opt);
schneiderklausd8197df2019-03-16 11:31:40 -070052 pipeline = pline.get();
Weiwei Liu245d7912016-07-28 00:04:25 -070053 setPipeline(std::move(pline));
54 }
55
56private:
Davide Pesavento5e3773d2019-08-22 15:35:08 -040057 static shared_ptr<RttEstimatorWithStats::Options>
Weiwei Liu245d7912016-07-28 00:04:25 -070058 makeRttEstimatorOptions()
59 {
Davide Pesavento5e3773d2019-08-22 15:35:08 -040060 auto rttOptions = make_shared<RttEstimatorWithStats::Options>();
61 rttOptions->alpha = 0.125;
62 rttOptions->beta = 0.25;
63 rttOptions->k = 4;
64 rttOptions->initialRto = 1_s;
65 rttOptions->minRto = 200_ms;
66 rttOptions->maxRto = 4_s;
67 rttOptions->rtoBackoffMultiplier = 2;
Weiwei Liu245d7912016-07-28 00:04:25 -070068 return rttOptions;
69 }
70
71protected:
Davide Pesavento97a33b22019-10-17 22:10:47 -040072 Options opt;
Davide Pesavento5e3773d2019-08-22 15:35:08 -040073 RttEstimatorWithStats rttEstimator;
schneiderklausd8197df2019-03-16 11:31:40 -070074 PipelineInterestsAdaptive* pipeline;
Davide Pesaventoba560662019-06-26 22:45:44 -040075 static constexpr double MARGIN = 0.001;
Weiwei Liu245d7912016-07-28 00:04:25 -070076};
77
Klaus Schneider9e5122b2019-03-19 17:03:25 -070078constexpr double PipelineInterestAimdFixture::MARGIN;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000079
Weiwei Liu245d7912016-07-28 00:04:25 -070080BOOST_AUTO_TEST_SUITE(Chunks)
Klaus Schneider9e5122b2019-03-19 17:03:25 -070081BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsAimd, PipelineInterestAimdFixture)
Weiwei Liu245d7912016-07-28 00:04:25 -070082
83BOOST_AUTO_TEST_CASE(SlowStart)
84{
85 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -070086 pipeline->m_ssthresh = 8.0;
87 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -070088
schneiderklausd8197df2019-03-16 11:31:40 -070089 double preCwnd = pipeline->m_cwnd;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080090 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -070091 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -040092 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -070093
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -080094 for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -070095 face.receive(*makeDataWithSegment(i));
96 advanceClocks(io, time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -070097 BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, 1, MARGIN);
98 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -070099 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400100
101 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700102}
103
104BOOST_AUTO_TEST_CASE(CongestionAvoidance)
105{
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800106 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700107 pipeline->m_ssthresh = 4.0;
108 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700109
schneiderklausd8197df2019-03-16 11:31:40 -0700110 double preCwnd = pipeline->m_cwnd;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800111 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700112 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400113 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700114
schneiderklausd8197df2019-03-16 11:31:40 -0700115 for (uint64_t i = 0; i < pipeline->m_ssthresh; ++i) { // slow start
Weiwei Liu245d7912016-07-28 00:04:25 -0700116 face.receive(*makeDataWithSegment(i));
117 advanceClocks(io, time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -0700118 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -0700119 }
120
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800121 BOOST_CHECK_CLOSE(preCwnd, 4.25, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700122
schneiderklausd8197df2019-03-16 11:31:40 -0700123 for (uint64_t i = pipeline->m_ssthresh; i < nDataSegments - 1; ++i) { // congestion avoidance
Weiwei Liu245d7912016-07-28 00:04:25 -0700124 face.receive(*makeDataWithSegment(i));
125 advanceClocks(io, time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -0700126 BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, opt.aiStep / floor(pipeline->m_cwnd), MARGIN);
127 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -0700128 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400129
130 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700131}
132
133BOOST_AUTO_TEST_CASE(Timeout)
134{
135 nDataSegments = 8;
schneiderklausd8197df2019-03-16 11:31:40 -0700136 pipeline->m_ssthresh = 4.0;
137 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700138
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800139 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700140 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400141 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700142
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800143 // receive segment 0, 1, and 2
144 for (uint64_t i = 0; i < 3; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700145 face.receive(*makeDataWithSegment(i));
146 advanceClocks(io, time::nanoseconds(1));
147 }
148
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400149 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
schneiderklausd8197df2019-03-16 11:31:40 -0700150 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800151 BOOST_CHECK_EQUAL(face.sentInterests.size(), 7); // request for segment 7 has been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700152
153 advanceClocks(io, time::milliseconds(100));
154
155 // receive segment 4
156 face.receive(*makeDataWithSegment(4));
157 advanceClocks(io, time::nanoseconds(1));
158
159 // receive segment 5
160 face.receive(*makeDataWithSegment(5));
161 advanceClocks(io, time::nanoseconds(1));
162
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400163 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
schneiderklausd8197df2019-03-16 11:31:40 -0700164 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.5, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800165 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700166
schneiderklausd8197df2019-03-16 11:31:40 -0700167 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
168 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 0);
169 BOOST_CHECK_EQUAL(pipeline->m_nMarkDecr, 0);
170 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 0);
171 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
172 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 0);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700173
174 // timeout segment 3 & 6
Weiwei Liu245d7912016-07-28 00:04:25 -0700175 advanceClocks(io, time::milliseconds(150));
schneiderklausd8197df2019-03-16 11:31:40 -0700176 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
177 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 1);
178 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
179 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700180
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400181 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
schneiderklausd8197df2019-03-16 11:31:40 -0700182 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.25, MARGIN); // window size drop to 1/2 of previous size
183 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700184
185 // receive segment 6, retransmit 3
186 face.receive(*makeDataWithSegment(6));
187 advanceClocks(io, time::nanoseconds(1));
188
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400189 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
schneiderklausd8197df2019-03-16 11:31:40 -0700190 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.75, MARGIN); // congestion avoidance
191 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
192 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700193
schneiderklausd8197df2019-03-16 11:31:40 -0700194 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
195 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
196 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts,
197 pipeline->m_nRetransmitted + pipeline->m_nSkippedRetx);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700198
Weiwei Liu245d7912016-07-28 00:04:25 -0700199}
200
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000201BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
202{
203 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700204 pipeline->m_ssthresh = 4.0;
205 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000206
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800207 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000208 advanceClocks(io, time::nanoseconds(1));
209 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
210
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800211 // receive segments 0 to 4
212 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000213 face.receive(*makeDataWithSegment(i));
214 advanceClocks(io, time::nanoseconds(1));
215 }
216
217 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
schneiderklausd8197df2019-03-16 11:31:40 -0700218 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.5, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000219
220 // receive segment 5 with congestion mark
221 face.receive(*makeDataWithSegmentAndCongMark(5));
222 advanceClocks(io, time::nanoseconds(1));
223
224 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
schneiderklausd8197df2019-03-16 11:31:40 -0700225 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.25, MARGIN); // window size drops to 1/2 of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800226 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000227
228 // receive the last segment with congestion mark
229 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
230 advanceClocks(io, time::nanoseconds(1));
231
232 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
schneiderklausd8197df2019-03-16 11:31:40 -0700233 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.25, MARGIN); // conservative window adaption (window size should not decrease)
234 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000235
236 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700237 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
238 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000239
240 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700241 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000242}
243
244BOOST_AUTO_TEST_CASE(CongestionMarksWithoutCwa)
245{
246 opt.disableCwa = true;
247 createPipeline();
248
249 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700250 pipeline->m_ssthresh = 4.0;
251 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000252
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800253 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000254 advanceClocks(io, time::nanoseconds(1));
255 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
256
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800257 // receive segments 0 to 4
258 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000259 face.receive(*makeDataWithSegment(i));
260 advanceClocks(io, time::nanoseconds(1));
261 }
262
263 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
schneiderklausd8197df2019-03-16 11:31:40 -0700264 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.5, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000265
266 // receive segment 5 with congestion mark
267 face.receive(*makeDataWithSegmentAndCongMark(5));
268 advanceClocks(io, time::nanoseconds(1));
269
270 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
schneiderklausd8197df2019-03-16 11:31:40 -0700271 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.25, MARGIN); // window size drops to 1/2 of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800272 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000273
274 // receive the last segment with congestion mark
275 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
276 advanceClocks(io, time::nanoseconds(1));
277
278 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
schneiderklausd8197df2019-03-16 11:31:40 -0700279 BOOST_CHECK_CLOSE(pipeline->m_cwnd, PipelineInterestsAdaptive::MIN_SSTHRESH,
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000280 MARGIN); // window size should decrease, as cwa is disabled
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 packets
schneiderklausd8197df2019-03-16 11:31:40 -0700284 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
285 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000286
287 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700288 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000289}
290
291BOOST_AUTO_TEST_CASE(IgnoreCongestionMarks)
292{
293 opt.ignoreCongMarks = true;
294 createPipeline();
295
296 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700297 pipeline->m_ssthresh = 4.0;
298 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000299
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800300 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000301 advanceClocks(io, time::nanoseconds(1));
302 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
303
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800304 // receive segments 0 to 5
305 for (uint64_t i = 0; i < 6; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000306 face.receive(*makeDataWithSegment(i));
307 advanceClocks(io, time::nanoseconds(1));
308 }
309
310 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
schneiderklausd8197df2019-03-16 11:31:40 -0700311 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.75, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800312 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000313
314 // receive the last segment with congestion mark
315 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
316 advanceClocks(io, time::nanoseconds(1));
317
318 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
schneiderklausd8197df2019-03-16 11:31:40 -0700319 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 5.0, MARGIN); // window size increases
320 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000321
322 // make sure no interest is retransmitted for marked data packet
schneiderklausd8197df2019-03-16 11:31:40 -0700323 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000324
325 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700326 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 1);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000327}
328
Weiwei Liu245d7912016-07-28 00:04:25 -0700329BOOST_AUTO_TEST_CASE(Nack)
330{
331 nDataSegments = 5;
schneiderklausd8197df2019-03-16 11:31:40 -0700332 pipeline->m_cwnd = 10.0;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800333 run(name);
334 advanceClocks(io, time::nanoseconds(1));
335
336 face.receive(*makeDataWithSegment(0));
Weiwei Liu245d7912016-07-28 00:04:25 -0700337 advanceClocks(io, time::nanoseconds(1));
338
339 face.receive(*makeDataWithSegment(1));
340 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400341
342 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800343 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
Weiwei Liu245d7912016-07-28 00:04:25 -0700344
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800345 // receive a nack with NackReason::DUPLICATE for segment 1
Weiwei Liu245d7912016-07-28 00:04:25 -0700346 auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
347 face.receive(nack1);
348 advanceClocks(io, time::nanoseconds(1));
349
350 // nack1 is ignored
351 BOOST_CHECK_EQUAL(hasFailed, false);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400352 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700353 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700354
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800355 // receive a nack with NackReason::CONGESTION for segment 2
Weiwei Liu245d7912016-07-28 00:04:25 -0700356 auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
357 face.receive(nack2);
358 advanceClocks(io, time::nanoseconds(1));
359
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800360 // segment 2 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700361 BOOST_CHECK_EQUAL(pipeline->m_retxCount[2], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700362
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800363 // receive a nack with NackReason::NONE for segment 3
Weiwei Liu245d7912016-07-28 00:04:25 -0700364 auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
365 face.receive(nack3);
366 advanceClocks(io, time::nanoseconds(1));
367
368 // Other types of Nack will trigger a failure
369 BOOST_CHECK_EQUAL(hasFailed, true);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400370 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700371}
372
373BOOST_AUTO_TEST_CASE(FinalBlockIdNotSetAtBeginning)
374{
375 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700376 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800377 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700378 advanceClocks(io, time::nanoseconds(1));
379
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800380 // receive segment 0 without FinalBlockId
381 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700382 advanceClocks(io, time::nanoseconds(1));
383
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800384 // interests for segment 0 - 5 have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700385 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800386 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
schneiderklausd8197df2019-03-16 11:31:40 -0700387 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, false);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800388 // pending interests: segment 1, 2, 3, 4, 5
Weiwei Liu245d7912016-07-28 00:04:25 -0700389 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
390
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800391 // receive segment 1 with FinalBlockId
392 face.receive(*makeDataWithSegment(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700393 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800394 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700395 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
Weiwei Liu245d7912016-07-28 00:04:25 -0700396
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800397 // pending interests for segment 1, 4, 5 haven been removed
398 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700399}
400
401BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
402{
403 // failed to retrieve segNo while the FinalBlockId has not yet been
404 // set, and later received a FinalBlockId >= segNo, i.e. segNo is
405 // part of the content.
406
407 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700408 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800409 run(name);
410 advanceClocks(io, time::nanoseconds(1));
411
412 // receive segment 0 without FinalBlockId
413 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700414 advanceClocks(io, time::nanoseconds(1));
415
416 // receive segment 1 without FinalBlockId
417 face.receive(*makeDataWithSegment(1, false));
418 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800419
420 // interests for segment 0 - 7 have been sent
421 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700422
423 // receive nack with NackReason::NONE for segment 3
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800424 auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700425 face.receive(nack);
426 advanceClocks(io, time::nanoseconds(1));
427
428 // error not triggered
429 // pending interests for segment > 3 haven been removed
430 BOOST_CHECK_EQUAL(hasFailed, false);
431 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
432
433 // receive segment 2 with FinalBlockId
434 face.receive(*makeDataWithSegment(2));
435 advanceClocks(io, time::nanoseconds(1));
436
437 // error triggered since segment 3 is part of the content
438 BOOST_CHECK_EQUAL(hasFailed, true);
439}
440
441BOOST_AUTO_TEST_CASE(SpuriousFailureBeforeFinalBlockIdReceived)
442{
443 // failed to retrieve segNo while the FinalBlockId has not yet been
444 // set, and later received a FinalBlockId < segNo, i.e. segNo is
445 // not part of the content, and it was actually a spurious failure
446
447 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700448 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800449 run(name);
450 advanceClocks(io, time::nanoseconds(1));
451
452 // receive segment 0 without FinalBlockId
453 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700454 advanceClocks(io, time::nanoseconds(1));
455
456 // receive segment 1 without FinalBlockId
457 face.receive(*makeDataWithSegment(1, false));
458 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800459
460 // interests for segment 0 - 7 have been sent
461 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700462
463 // receive nack with NackReason::NONE for segment 4
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800464 auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700465 face.receive(nack);
466 advanceClocks(io, time::nanoseconds(1));
467
468 // error not triggered
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800469 // pending interests for segment > 3 have been removed
Weiwei Liu245d7912016-07-28 00:04:25 -0700470 BOOST_CHECK_EQUAL(hasFailed, false);
471 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
472
473 // receive segment 2 with FinalBlockId
474 face.receive(*makeDataWithSegment(2));
475 advanceClocks(io, time::nanoseconds(1));
476
477 // timeout segment 3
Davide Pesavento958896e2017-01-19 00:52:04 -0500478 advanceClocks(io, time::seconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700479
480 // segment 3 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700481 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700482
483 // receive segment 3
484 face.receive(*makeDataWithSegment(3));
485 advanceClocks(io, time::nanoseconds(1));
486
487 BOOST_CHECK_EQUAL(hasFailed, false);
488}
489
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500490BOOST_AUTO_TEST_CASE(SegmentInfoMaintenance)
491{
492 // test that m_segmentInfo is properly maintained when
493 // a segment is received after two consecutive timeouts
494
495 nDataSegments = 3;
496
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800497 run(name);
498 advanceClocks(io, time::nanoseconds(1));
499
500 // receive segment 0
501 face.receive(*makeDataWithSegment(0));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500502 advanceClocks(io, time::nanoseconds(1));
503
504 // receive segment 1
505 face.receive(*makeDataWithSegment(1));
506 advanceClocks(io, time::nanoseconds(1));
507
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800508 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500509
510 // check if segment 2's state is FirstTimeSent
schneiderklausd8197df2019-03-16 11:31:40 -0700511 auto it = pipeline->m_segmentInfo.find(2);
512 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500513 BOOST_CHECK(it->second.state == SegmentState::FirstTimeSent);
514
515 // timeout segment 2 twice
516 advanceClocks(io, time::milliseconds(400), 3);
517
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800518 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500519
520 // check if segment 2's state is Retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700521 it = pipeline->m_segmentInfo.find(2);
522 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500523 BOOST_CHECK(it->second.state == SegmentState::Retransmitted);
524
525 // check if segment 2 was retransmitted twice
schneiderklausd8197df2019-03-16 11:31:40 -0700526 BOOST_CHECK_EQUAL(pipeline->m_retxCount.at(2), 2);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500527
528 // receive segment 2 the first time
529 face.receive(*makeDataWithSegment(2));
530 advanceClocks(io, time::nanoseconds(1));
531
532 // check if segment 2 was erased from m_segmentInfo
schneiderklausd8197df2019-03-16 11:31:40 -0700533 it = pipeline->m_segmentInfo.find(2);
534 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500535
536 auto prevRtt = rttEstimator.getAvgRtt();
537 auto prevRto = rttEstimator.getEstimatedRto();
538
539 // receive segment 2 the second time
540 face.receive(*makeDataWithSegment(2));
541 advanceClocks(io, time::nanoseconds(1));
542
543 // nothing changed
schneiderklausd8197df2019-03-16 11:31:40 -0700544 it = pipeline->m_segmentInfo.find(2);
545 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800546 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500547 BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
548 BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
549}
550
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400551BOOST_AUTO_TEST_CASE(PrintSummaryWithNoRttMeasurements)
552{
553 // test the console ouptut when no RTT measurement is available,
554 // to make sure a proper message will be printed out
555
556 std::stringstream ss;
557
558 // change the underlying buffer and save the old buffer
559 auto oldBuf = std::cerr.rdbuf(ss.rdbuf());
560
schneiderklausd8197df2019-03-16 11:31:40 -0700561 pipeline->printSummary();
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400562 std::string line;
563
564 bool found = false;
565 while (std::getline(ss, line)) {
566 if (line == "RTT stats unavailable") {
567 found = true;
568 break;
569 }
570 }
571 BOOST_CHECK(found);
572 std::cerr.rdbuf(oldBuf); // reset
573}
574
Ryan Wickman034f30f2018-06-06 11:11:11 -0500575BOOST_AUTO_TEST_CASE(StopsWhenFileSizeLessThanChunkSize)
576{
577 // test to see if the program doesn't hang,
578 // when transfer is complete, for files less than the chunk size
579 // (i.e. when only one segment is sent/received)
580
581 createPipeline();
582 nDataSegments = 1;
583
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800584 run(name);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500585 advanceClocks(io, time::nanoseconds(1));
586
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800587 face.receive(*makeDataWithSegment(0));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500588 advanceClocks(io, time::nanoseconds(1));
589
schneiderklausd8197df2019-03-16 11:31:40 -0700590 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
591 BOOST_CHECK_EQUAL(pipeline->m_segmentInfo.size(), 0);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500592 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
593}
594
595
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700596BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsAimd
Weiwei Liu245d7912016-07-28 00:04:25 -0700597BOOST_AUTO_TEST_SUITE_END() // Chunks
598
599} // namespace tests
Weiwei Liu245d7912016-07-28 00:04:25 -0700600} // namespace chunks
601} // namespace ndn