blob: 03e3f9de144133238ef8560e8ea48f4ed2692763 [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-cubic.hpp"
Weiwei Liu245d7912016-07-28 00:04:25 -070029#include "tools/chunks/catchunks/options.hpp"
30
31#include "pipeline-interests-fixture.hpp"
32
33namespace ndn {
34namespace chunks {
Weiwei Liu245d7912016-07-28 00:04:25 -070035namespace tests {
36
37using namespace ndn::tests;
38
Klaus Schneider9e5122b2019-03-19 17:03:25 -070039class PipelineInterestCubicFixture : public PipelineInterestsFixture
Weiwei Liu245d7912016-07-28 00:04:25 -070040{
41public:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070042 PipelineInterestCubicFixture()
Davide Pesaventof6991e12018-01-08 20:58:50 -050043 : opt(makePipelineOptions())
Weiwei Liu245d7912016-07-28 00:04:25 -070044 , rttEstimator(makeRttEstimatorOptions())
45 {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000046 createPipeline();
47 }
48
49 void
50 createPipeline()
51 {
Klaus Schneider9e5122b2019-03-19 17:03:25 -070052 auto pline = make_unique<PipelineInterestsCubic>(face, rttEstimator, opt);
schneiderklausd8197df2019-03-16 11:31:40 -070053 pipeline = pline.get();
Weiwei Liu245d7912016-07-28 00:04:25 -070054 setPipeline(std::move(pline));
55 }
56
57private:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070058 static PipelineInterestsCubic::Options
Weiwei Liu245d7912016-07-28 00:04:25 -070059 makePipelineOptions()
60 {
Klaus Schneider9e5122b2019-03-19 17:03:25 -070061 PipelineInterestsCubic::Options pipelineOptions;
Davide Pesaventof6991e12018-01-08 20:58:50 -050062 pipelineOptions.isQuiet = true;
63 pipelineOptions.isVerbose = false;
Weiwei Liu245d7912016-07-28 00:04:25 -070064 pipelineOptions.disableCwa = false;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000065 pipelineOptions.ignoreCongMarks = false;
Weiwei Liu245d7912016-07-28 00:04:25 -070066 pipelineOptions.resetCwndToInit = false;
67 pipelineOptions.initCwnd = 1.0;
68 pipelineOptions.aiStep = 1.0;
69 pipelineOptions.mdCoef = 0.5;
70 pipelineOptions.initSsthresh = std::numeric_limits<int>::max();
Klaus Schneider9e5122b2019-03-19 17:03:25 -070071 pipelineOptions.cubicBeta = 0.7;
72 pipelineOptions.enableFastConv = false;
Weiwei Liu245d7912016-07-28 00:04:25 -070073 return pipelineOptions;
74 }
75
76 static RttEstimator::Options
77 makeRttEstimatorOptions()
78 {
79 RttEstimator::Options rttOptions;
80 rttOptions.alpha = 0.125;
81 rttOptions.beta = 0.25;
Klaus Schneider9e5122b2019-03-19 17:03:25 -070082 rttOptions.k = 8;
Davide Pesaventoba560662019-06-26 22:45:44 -040083 rttOptions.initialRto = 1_s;
84 rttOptions.minRto = 200_ms;
85 rttOptions.maxRto = 4_s;
86 rttOptions.rtoBackoffMultiplier = 2;
Weiwei Liu245d7912016-07-28 00:04:25 -070087 return rttOptions;
88 }
89
90protected:
Klaus Schneider9e5122b2019-03-19 17:03:25 -070091 PipelineInterestsCubic::Options opt;
Weiwei Liu245d7912016-07-28 00:04:25 -070092 RttEstimator rttEstimator;
Klaus Schneider9e5122b2019-03-19 17:03:25 -070093 PipelineInterestsCubic* pipeline;
Davide Pesaventoba560662019-06-26 22:45:44 -040094 static constexpr double MARGIN = 0.001;
Weiwei Liu245d7912016-07-28 00:04:25 -070095};
96
Klaus Schneider9e5122b2019-03-19 17:03:25 -070097constexpr double PipelineInterestCubicFixture::MARGIN;
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +000098
Weiwei Liu245d7912016-07-28 00:04:25 -070099BOOST_AUTO_TEST_SUITE(Chunks)
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700100BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsCubic, PipelineInterestCubicFixture)
Weiwei Liu245d7912016-07-28 00:04:25 -0700101
102BOOST_AUTO_TEST_CASE(SlowStart)
103{
104 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700105 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, 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);
Weiwei Liu245d7912016-07-28 00:04:25 -0700109 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400110 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700111
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800112 for (uint64_t i = 0; i < nDataSegments - 1; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700113 face.receive(*makeDataWithSegment(i));
114 advanceClocks(io, time::nanoseconds(1));
schneiderklausd8197df2019-03-16 11:31:40 -0700115 BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, 1, MARGIN);
116 preCwnd = pipeline->m_cwnd;
Weiwei Liu245d7912016-07-28 00:04:25 -0700117 }
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400118
119 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700120}
121
Weiwei Liu245d7912016-07-28 00:04:25 -0700122
123BOOST_AUTO_TEST_CASE(Timeout)
124{
125 nDataSegments = 8;
schneiderklausd8197df2019-03-16 11:31:40 -0700126 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Weiwei Liu245d7912016-07-28 00:04:25 -0700127
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800128 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700129 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400130 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700131
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800132 // receive segment 0, 1, and 2
133 for (uint64_t i = 0; i < 3; ++i) {
Weiwei Liu245d7912016-07-28 00:04:25 -0700134 face.receive(*makeDataWithSegment(i));
135 advanceClocks(io, time::nanoseconds(1));
136 }
137
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400138 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 3);
schneiderklausd8197df2019-03-16 11:31:40 -0700139 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800140 BOOST_CHECK_EQUAL(face.sentInterests.size(), 7); // request for segment 7 has been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700141
142 advanceClocks(io, time::milliseconds(100));
143
144 // receive segment 4
145 face.receive(*makeDataWithSegment(4));
146 advanceClocks(io, time::nanoseconds(1));
147
148 // receive segment 5
149 face.receive(*makeDataWithSegment(5));
150 advanceClocks(io, time::nanoseconds(1));
151
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400152 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700153 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800154 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700155
schneiderklausd8197df2019-03-16 11:31:40 -0700156 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
157 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 0);
158 BOOST_CHECK_EQUAL(pipeline->m_nMarkDecr, 0);
159 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 0);
160 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
161 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 0);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700162
163 // timeout segment 3 & 6
Weiwei Liu245d7912016-07-28 00:04:25 -0700164 advanceClocks(io, time::milliseconds(150));
schneiderklausd8197df2019-03-16 11:31:40 -0700165 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700166 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700167 BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
168 BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700169
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400170 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700171 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drop to 0.7x of previous size
172 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700173
174 // receive segment 6, retransmit 3
175 face.receive(*makeDataWithSegment(6));
176 advanceClocks(io, time::nanoseconds(1));
177
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400178 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700179 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // congestion avoidance
schneiderklausd8197df2019-03-16 11:31:40 -0700180 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
181 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700182
schneiderklausd8197df2019-03-16 11:31:40 -0700183 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
184 BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
185 BOOST_CHECK_EQUAL(pipeline->m_nTimeouts,
186 pipeline->m_nRetransmitted + pipeline->m_nSkippedRetx);
schneiderklaus8ff3abd2019-03-12 22:15:12 -0700187
Weiwei Liu245d7912016-07-28 00:04:25 -0700188}
189
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000190BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
191{
192 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700193 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000194
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800195 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000196 advanceClocks(io, time::nanoseconds(1));
197 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
198
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800199 // receive segments 0 to 4
200 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000201 face.receive(*makeDataWithSegment(i));
202 advanceClocks(io, time::nanoseconds(1));
203 }
204
205 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700206 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000207
208 // receive segment 5 with congestion mark
209 face.receive(*makeDataWithSegmentAndCongMark(5));
210 advanceClocks(io, time::nanoseconds(1));
211
212 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700213 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drops to 1/2 of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800214 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000215
216 // receive the last segment with congestion mark
217 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
218 advanceClocks(io, time::nanoseconds(1));
219
220 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700221 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // conservative window adaption (window size should not decrease)
schneiderklausd8197df2019-03-16 11:31:40 -0700222 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000223
224 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700225 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
226 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000227
228 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700229 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000230}
231
232BOOST_AUTO_TEST_CASE(CongestionMarksWithoutCwa)
233{
234 opt.disableCwa = true;
235 createPipeline();
236
237 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700238 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000239
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800240 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000241 advanceClocks(io, time::nanoseconds(1));
242 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
243
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800244 // receive segments 0 to 4
245 for (uint64_t i = 0; i < 5; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000246 face.receive(*makeDataWithSegment(i));
247 advanceClocks(io, time::nanoseconds(1));
248 }
249
250 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700251 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000252
253 // receive segment 5 with congestion mark
254 face.receive(*makeDataWithSegmentAndCongMark(5));
255 advanceClocks(io, time::nanoseconds(1));
256
257 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700258 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drops to 1/2 of previous size
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800259 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000260
261 // receive the last segment with congestion mark
262 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
263 advanceClocks(io, time::nanoseconds(1));
264
265 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700266 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.94,
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000267 MARGIN); // window size should decrease, as cwa is disabled
schneiderklausd8197df2019-03-16 11:31:40 -0700268 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000269
270 // make sure no interest is retransmitted for marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700271 BOOST_CHECK_EQUAL(pipeline->m_retxCount[5], 0);
272 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000273
274 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700275 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 2);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000276}
277
278BOOST_AUTO_TEST_CASE(IgnoreCongestionMarks)
279{
280 opt.ignoreCongMarks = true;
281 createPipeline();
282
283 nDataSegments = 7;
schneiderklausd8197df2019-03-16 11:31:40 -0700284 BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000285
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800286 run(name);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000287 advanceClocks(io, time::nanoseconds(1));
288 BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
289
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800290 // receive segments 0 to 5
291 for (uint64_t i = 0; i < 6; ++i) {
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000292 face.receive(*makeDataWithSegment(i));
293 advanceClocks(io, time::nanoseconds(1));
294 }
295
296 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700297 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800298 BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000299
300 // receive the last segment with congestion mark
301 face.receive(*makeDataWithSegmentAndCongMark(nDataSegments - 1));
302 advanceClocks(io, time::nanoseconds(1));
303
304 BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700305 BOOST_CHECK_CLOSE(pipeline->m_cwnd, 8.0, MARGIN); // window size increases
schneiderklausd8197df2019-03-16 11:31:40 -0700306 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000307
308 // make sure no interest is retransmitted for marked data packet
schneiderklausd8197df2019-03-16 11:31:40 -0700309 BOOST_CHECK_EQUAL(pipeline->m_retxCount[nDataSegments - 1], 0);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000310
311 // check number of received marked data packets
schneiderklausd8197df2019-03-16 11:31:40 -0700312 BOOST_CHECK_EQUAL(pipeline->m_nCongMarks, 1);
Chavoosh Ghasemi641f5932017-11-06 22:45:11 +0000313}
314
Weiwei Liu245d7912016-07-28 00:04:25 -0700315BOOST_AUTO_TEST_CASE(Nack)
316{
317 nDataSegments = 5;
schneiderklausd8197df2019-03-16 11:31:40 -0700318 pipeline->m_cwnd = 10.0;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800319 run(name);
320 advanceClocks(io, time::nanoseconds(1));
321
322 face.receive(*makeDataWithSegment(0));
Weiwei Liu245d7912016-07-28 00:04:25 -0700323 advanceClocks(io, time::nanoseconds(1));
324
325 face.receive(*makeDataWithSegment(1));
326 advanceClocks(io, time::nanoseconds(1));
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400327
328 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800329 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 10);
Weiwei Liu245d7912016-07-28 00:04:25 -0700330
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800331 // receive a nack with NackReason::DUPLICATE for segment 1
Weiwei Liu245d7912016-07-28 00:04:25 -0700332 auto nack1 = makeNack(face.sentInterests[1], lp::NackReason::DUPLICATE);
333 face.receive(nack1);
334 advanceClocks(io, time::nanoseconds(1));
335
336 // nack1 is ignored
337 BOOST_CHECK_EQUAL(hasFailed, false);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400338 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700339 BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
Weiwei Liu245d7912016-07-28 00:04:25 -0700340
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800341 // receive a nack with NackReason::CONGESTION for segment 2
Weiwei Liu245d7912016-07-28 00:04:25 -0700342 auto nack2 = makeNack(face.sentInterests[2], lp::NackReason::CONGESTION);
343 face.receive(nack2);
344 advanceClocks(io, time::nanoseconds(1));
345
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800346 // segment 2 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700347 BOOST_CHECK_EQUAL(pipeline->m_retxCount[2], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700348
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800349 // receive a nack with NackReason::NONE for segment 3
Weiwei Liu245d7912016-07-28 00:04:25 -0700350 auto nack3 = makeNack(face.sentInterests[3], lp::NackReason::NONE);
351 face.receive(nack3);
352 advanceClocks(io, time::nanoseconds(1));
353
354 // Other types of Nack will trigger a failure
355 BOOST_CHECK_EQUAL(hasFailed, true);
Davide Pesaventoe9c69852017-11-04 18:08:37 -0400356 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700357}
358
359BOOST_AUTO_TEST_CASE(FinalBlockIdNotSetAtBeginning)
360{
361 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700362 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800363 run(name);
Weiwei Liu245d7912016-07-28 00:04:25 -0700364 advanceClocks(io, time::nanoseconds(1));
365
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800366 // receive segment 0 without FinalBlockId
367 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700368 advanceClocks(io, time::nanoseconds(1));
369
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800370 // interests for segment 0 - 5 have been sent
Weiwei Liu245d7912016-07-28 00:04:25 -0700371 BOOST_CHECK_EQUAL(face.sentInterests.size(), 6);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800372 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 1);
schneiderklausd8197df2019-03-16 11:31:40 -0700373 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, false);
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800374 // pending interests: segment 1, 2, 3, 4, 5
Weiwei Liu245d7912016-07-28 00:04:25 -0700375 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 5);
376
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800377 // receive segment 1 with FinalBlockId
378 face.receive(*makeDataWithSegment(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700379 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800380 BOOST_CHECK_EQUAL(pipeline->m_nReceived, 2);
schneiderklausd8197df2019-03-16 11:31:40 -0700381 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
Weiwei Liu245d7912016-07-28 00:04:25 -0700382
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800383 // pending interests for segment 1, 4, 5 haven been removed
384 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
Weiwei Liu245d7912016-07-28 00:04:25 -0700385}
386
387BOOST_AUTO_TEST_CASE(FailureBeforeFinalBlockIdReceived)
388{
389 // failed to retrieve segNo while the FinalBlockId has not yet been
390 // set, and later received a FinalBlockId >= segNo, i.e. segNo is
391 // part of the content.
392
393 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700394 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800395 run(name);
396 advanceClocks(io, time::nanoseconds(1));
397
398 // receive segment 0 without FinalBlockId
399 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700400 advanceClocks(io, time::nanoseconds(1));
401
402 // receive segment 1 without FinalBlockId
403 face.receive(*makeDataWithSegment(1, false));
404 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800405
406 // interests for segment 0 - 7 have been sent
407 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700408
409 // receive nack with NackReason::NONE for segment 3
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800410 auto nack = makeNack(face.sentInterests[3], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700411 face.receive(nack);
412 advanceClocks(io, time::nanoseconds(1));
413
414 // error not triggered
415 // pending interests for segment > 3 haven been removed
416 BOOST_CHECK_EQUAL(hasFailed, false);
417 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 1);
418
419 // receive segment 2 with FinalBlockId
420 face.receive(*makeDataWithSegment(2));
421 advanceClocks(io, time::nanoseconds(1));
422
423 // error triggered since segment 3 is part of the content
424 BOOST_CHECK_EQUAL(hasFailed, true);
425}
426
427BOOST_AUTO_TEST_CASE(SpuriousFailureBeforeFinalBlockIdReceived)
428{
429 // failed to retrieve segNo while the FinalBlockId has not yet been
430 // set, and later received a FinalBlockId < segNo, i.e. segNo is
431 // not part of the content, and it was actually a spurious failure
432
433 nDataSegments = 4;
schneiderklausd8197df2019-03-16 11:31:40 -0700434 pipeline->m_cwnd = 4;
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800435 run(name);
436 advanceClocks(io, time::nanoseconds(1));
437
438 // receive segment 0 without FinalBlockId
439 face.receive(*makeDataWithSegment(0, false));
Weiwei Liu245d7912016-07-28 00:04:25 -0700440 advanceClocks(io, time::nanoseconds(1));
441
442 // receive segment 1 without FinalBlockId
443 face.receive(*makeDataWithSegment(1, false));
444 advanceClocks(io, time::nanoseconds(1));
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800445
446 // interests for segment 0 - 7 have been sent
447 BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 8);
Weiwei Liu245d7912016-07-28 00:04:25 -0700448
449 // receive nack with NackReason::NONE for segment 4
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800450 auto nack = makeNack(face.sentInterests[4], lp::NackReason::NONE);
Weiwei Liu245d7912016-07-28 00:04:25 -0700451 face.receive(nack);
452 advanceClocks(io, time::nanoseconds(1));
453
454 // error not triggered
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800455 // pending interests for segment > 3 have been removed
Weiwei Liu245d7912016-07-28 00:04:25 -0700456 BOOST_CHECK_EQUAL(hasFailed, false);
457 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 2);
458
459 // receive segment 2 with FinalBlockId
460 face.receive(*makeDataWithSegment(2));
461 advanceClocks(io, time::nanoseconds(1));
462
463 // timeout segment 3
Davide Pesavento958896e2017-01-19 00:52:04 -0500464 advanceClocks(io, time::seconds(1));
Weiwei Liu245d7912016-07-28 00:04:25 -0700465
466 // segment 3 is retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700467 BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
Weiwei Liu245d7912016-07-28 00:04:25 -0700468
469 // receive segment 3
470 face.receive(*makeDataWithSegment(3));
471 advanceClocks(io, time::nanoseconds(1));
472
473 BOOST_CHECK_EQUAL(hasFailed, false);
474}
475
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500476BOOST_AUTO_TEST_CASE(SegmentInfoMaintenance)
477{
478 // test that m_segmentInfo is properly maintained when
479 // a segment is received after two consecutive timeouts
480
481 nDataSegments = 3;
482
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800483 run(name);
484 advanceClocks(io, time::nanoseconds(1));
485
486 // receive segment 0
487 face.receive(*makeDataWithSegment(0));
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500488 advanceClocks(io, time::nanoseconds(1));
489
490 // receive segment 1
491 face.receive(*makeDataWithSegment(1));
492 advanceClocks(io, time::nanoseconds(1));
493
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800494 BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500495
496 // check if segment 2's state is FirstTimeSent
schneiderklausd8197df2019-03-16 11:31:40 -0700497 auto it = pipeline->m_segmentInfo.find(2);
498 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500499 BOOST_CHECK(it->second.state == SegmentState::FirstTimeSent);
500
501 // timeout segment 2 twice
502 advanceClocks(io, time::milliseconds(400), 3);
503
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800504 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500505
506 // check if segment 2's state is Retransmitted
schneiderklausd8197df2019-03-16 11:31:40 -0700507 it = pipeline->m_segmentInfo.find(2);
508 BOOST_REQUIRE(it != pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500509 BOOST_CHECK(it->second.state == SegmentState::Retransmitted);
510
511 // check if segment 2 was retransmitted twice
schneiderklausd8197df2019-03-16 11:31:40 -0700512 BOOST_CHECK_EQUAL(pipeline->m_retxCount.at(2), 2);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500513
514 // receive segment 2 the first time
515 face.receive(*makeDataWithSegment(2));
516 advanceClocks(io, time::nanoseconds(1));
517
518 // check if segment 2 was erased from m_segmentInfo
schneiderklausd8197df2019-03-16 11:31:40 -0700519 it = pipeline->m_segmentInfo.find(2);
520 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500521
522 auto prevRtt = rttEstimator.getAvgRtt();
523 auto prevRto = rttEstimator.getEstimatedRto();
524
525 // receive segment 2 the second time
526 face.receive(*makeDataWithSegment(2));
527 advanceClocks(io, time::nanoseconds(1));
528
529 // nothing changed
schneiderklausd8197df2019-03-16 11:31:40 -0700530 it = pipeline->m_segmentInfo.find(2);
531 BOOST_CHECK(it == pipeline->m_segmentInfo.end());
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800532 BOOST_CHECK_EQUAL(face.sentInterests.size(), 5);
Ryan Wickman2c9933c2018-06-12 11:51:51 -0500533 BOOST_CHECK_EQUAL(rttEstimator.getAvgRtt(), prevRtt);
534 BOOST_CHECK_EQUAL(rttEstimator.getEstimatedRto(), prevRto);
535}
536
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400537BOOST_AUTO_TEST_CASE(PrintSummaryWithNoRttMeasurements)
538{
539 // test the console ouptut when no RTT measurement is available,
540 // to make sure a proper message will be printed out
541
542 std::stringstream ss;
543
544 // change the underlying buffer and save the old buffer
545 auto oldBuf = std::cerr.rdbuf(ss.rdbuf());
546
schneiderklausd8197df2019-03-16 11:31:40 -0700547 pipeline->printSummary();
Chavoosh Ghasemi75309ae2018-03-26 14:46:24 -0400548 std::string line;
549
550 bool found = false;
551 while (std::getline(ss, line)) {
552 if (line == "RTT stats unavailable") {
553 found = true;
554 break;
555 }
556 }
557 BOOST_CHECK(found);
558 std::cerr.rdbuf(oldBuf); // reset
559}
560
Ryan Wickman034f30f2018-06-06 11:11:11 -0500561BOOST_AUTO_TEST_CASE(StopsWhenFileSizeLessThanChunkSize)
562{
563 // test to see if the program doesn't hang,
564 // when transfer is complete, for files less than the chunk size
565 // (i.e. when only one segment is sent/received)
566
567 createPipeline();
568 nDataSegments = 1;
569
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800570 run(name);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500571 advanceClocks(io, time::nanoseconds(1));
572
Chavoosh Ghasemi5cb67012019-02-15 09:56:57 -0800573 face.receive(*makeDataWithSegment(0));
Ryan Wickman034f30f2018-06-06 11:11:11 -0500574 advanceClocks(io, time::nanoseconds(1));
575
schneiderklausd8197df2019-03-16 11:31:40 -0700576 BOOST_CHECK_EQUAL(pipeline->m_hasFinalBlockId, true);
577 BOOST_CHECK_EQUAL(pipeline->m_segmentInfo.size(), 0);
Ryan Wickman034f30f2018-06-06 11:11:11 -0500578 BOOST_CHECK_EQUAL(face.getNPendingInterests(), 0);
579}
580
581
Klaus Schneider9e5122b2019-03-19 17:03:25 -0700582BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsCubic
Weiwei Liu245d7912016-07-28 00:04:25 -0700583BOOST_AUTO_TEST_SUITE_END() // Chunks
584
585} // namespace tests
Weiwei Liu245d7912016-07-28 00:04:25 -0700586} // namespace chunks
587} // namespace ndn