catchunks: Implement CUBIC window adaptation

Also increase the RTT estimator multiplier k to 8.

Change-Id: I68c5096ac0da854f071bab5f7519b1c144f20ca1
refs: #4861
diff --git a/tests/chunks/pipeline-interests-adaptive.t.cpp b/tests/chunks/pipeline-interests-aimd.t.cpp
similarity index 97%
rename from tests/chunks/pipeline-interests-adaptive.t.cpp
rename to tests/chunks/pipeline-interests-aimd.t.cpp
index 1cc4f04..57022a6 100644
--- a/tests/chunks/pipeline-interests-adaptive.t.cpp
+++ b/tests/chunks/pipeline-interests-aimd.t.cpp
@@ -25,7 +25,7 @@
  * @author Klaus Schneider
  */
 
-#include "tools/chunks/catchunks/pipeline-interests-adaptive.hpp"
+#include "tools/chunks/catchunks/pipeline-interests-aimd.hpp"
 #include "tools/chunks/catchunks/options.hpp"
 
 #include "pipeline-interests-fixture.hpp"
@@ -36,10 +36,10 @@
 
 using namespace ndn::tests;
 
-class PipelineInterestAdaptiveFixture : public PipelineInterestsFixture
+class PipelineInterestAimdFixture : public PipelineInterestsFixture
 {
 public:
-  PipelineInterestAdaptiveFixture()
+  PipelineInterestAimdFixture()
     : opt(makePipelineOptions())
     , rttEstimator(makeRttEstimatorOptions())
   {
@@ -49,7 +49,7 @@
   void
   createPipeline()
   {
-    auto pline = make_unique<PipelineInterestsAdaptive>(face, rttEstimator, opt);
+    auto pline = make_unique<PipelineInterestsAimd>(face, rttEstimator, opt);
     pipeline = pline.get();
     setPipeline(std::move(pline));
   }
@@ -90,10 +90,10 @@
   static constexpr double MARGIN = 0.01;
 };
 
-constexpr double PipelineInterestAdaptiveFixture::MARGIN;
+constexpr double PipelineInterestAimdFixture::MARGIN;
 
 BOOST_AUTO_TEST_SUITE(Chunks)
-BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsAdaptive, PipelineInterestAdaptiveFixture)
+BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsAimd, PipelineInterestAimdFixture)
 
 BOOST_AUTO_TEST_CASE(SlowStart)
 {
@@ -608,7 +608,7 @@
 }
 
 
-BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsAdaptive
+BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsAimd
 BOOST_AUTO_TEST_SUITE_END() // Chunks
 
 } // namespace tests
diff --git a/tests/chunks/pipeline-interests-adaptive.t.cpp b/tests/chunks/pipeline-interests-cubic.t.cpp
similarity index 86%
copy from tests/chunks/pipeline-interests-adaptive.t.cpp
copy to tests/chunks/pipeline-interests-cubic.t.cpp
index 1cc4f04..b42728b 100644
--- a/tests/chunks/pipeline-interests-adaptive.t.cpp
+++ b/tests/chunks/pipeline-interests-cubic.t.cpp
@@ -25,7 +25,7 @@
  * @author Klaus Schneider
  */
 
-#include "tools/chunks/catchunks/pipeline-interests-adaptive.hpp"
+#include "tools/chunks/catchunks/pipeline-interests-cubic.hpp"
 #include "tools/chunks/catchunks/options.hpp"
 
 #include "pipeline-interests-fixture.hpp"
@@ -36,10 +36,10 @@
 
 using namespace ndn::tests;
 
-class PipelineInterestAdaptiveFixture : public PipelineInterestsFixture
+class PipelineInterestCubicFixture : public PipelineInterestsFixture
 {
 public:
-  PipelineInterestAdaptiveFixture()
+  PipelineInterestCubicFixture()
     : opt(makePipelineOptions())
     , rttEstimator(makeRttEstimatorOptions())
   {
@@ -49,16 +49,16 @@
   void
   createPipeline()
   {
-    auto pline = make_unique<PipelineInterestsAdaptive>(face, rttEstimator, opt);
+    auto pline = make_unique<PipelineInterestsCubic>(face, rttEstimator, opt);
     pipeline = pline.get();
     setPipeline(std::move(pline));
   }
 
 private:
-  static PipelineInterestsAdaptive::Options
+  static PipelineInterestsCubic::Options
   makePipelineOptions()
   {
-    PipelineInterestsAdaptive::Options pipelineOptions;
+    PipelineInterestsCubic::Options pipelineOptions;
     pipelineOptions.isQuiet = true;
     pipelineOptions.isVerbose = false;
     pipelineOptions.disableCwa = false;
@@ -68,6 +68,8 @@
     pipelineOptions.aiStep = 1.0;
     pipelineOptions.mdCoef = 0.5;
     pipelineOptions.initSsthresh = std::numeric_limits<int>::max();
+    pipelineOptions.cubicBeta = 0.7;
+    pipelineOptions.enableFastConv = false;
     return pipelineOptions;
   }
 
@@ -77,28 +79,27 @@
     RttEstimator::Options rttOptions;
     rttOptions.alpha = 0.125;
     rttOptions.beta = 0.25;
-    rttOptions.k = 4;
+    rttOptions.k = 8;
     rttOptions.minRto = Milliseconds(200);
     rttOptions.maxRto = Milliseconds(4000);
     return rttOptions;
   }
 
 protected:
-  PipelineInterestsAdaptive::Options opt;
+  PipelineInterestsCubic::Options opt;
   RttEstimator rttEstimator;
-  PipelineInterestsAdaptive* pipeline;
+  PipelineInterestsCubic* pipeline;
   static constexpr double MARGIN = 0.01;
 };
 
-constexpr double PipelineInterestAdaptiveFixture::MARGIN;
+constexpr double PipelineInterestCubicFixture::MARGIN;
 
 BOOST_AUTO_TEST_SUITE(Chunks)
-BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsAdaptive, PipelineInterestAdaptiveFixture)
+BOOST_FIXTURE_TEST_SUITE(TestPipelineInterestsCubic, PipelineInterestCubicFixture)
 
 BOOST_AUTO_TEST_CASE(SlowStart)
 {
   nDataSegments = 4;
-  pipeline->m_ssthresh = 8.0;
   BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
 
   double preCwnd = pipeline->m_cwnd;
@@ -116,39 +117,10 @@
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
 }
 
-BOOST_AUTO_TEST_CASE(CongestionAvoidance)
-{
-  nDataSegments = 7;
-  pipeline->m_ssthresh = 4.0;
-  BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
-
-  double preCwnd = pipeline->m_cwnd;
-  run(name);
-  advanceClocks(io, time::nanoseconds(1));
-  BOOST_CHECK_EQUAL(face.sentInterests.size(), 1);
-
-  for (uint64_t i = 0; i < pipeline->m_ssthresh; ++i) { // slow start
-    face.receive(*makeDataWithSegment(i));
-    advanceClocks(io, time::nanoseconds(1));
-    preCwnd = pipeline->m_cwnd;
-  }
-
-  BOOST_CHECK_CLOSE(preCwnd, 4.25, MARGIN);
-
-  for (uint64_t i = pipeline->m_ssthresh; i < nDataSegments - 1; ++i) { // congestion avoidance
-    face.receive(*makeDataWithSegment(i));
-    advanceClocks(io, time::nanoseconds(1));
-    BOOST_CHECK_CLOSE(pipeline->m_cwnd - preCwnd, opt.aiStep / floor(pipeline->m_cwnd), MARGIN);
-    preCwnd = pipeline->m_cwnd;
-  }
-
-  BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments - 1);
-}
 
 BOOST_AUTO_TEST_CASE(Timeout)
 {
   nDataSegments = 8;
-  pipeline->m_ssthresh = 4.0;
   BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
 
   run(name);
@@ -176,7 +148,7 @@
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.5, MARGIN);
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
   BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all the segment requests have been sent
 
   BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 0);
@@ -189,20 +161,20 @@
   // timeout segment 3 & 6
   advanceClocks(io, time::milliseconds(150));
   BOOST_CHECK_EQUAL(pipeline->m_nTimeouts, 2);
-  BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 1);
+  BOOST_CHECK_EQUAL(pipeline->m_nRetransmitted, 2);
   BOOST_CHECK_EQUAL(pipeline->m_nLossDecr, 1);
   BOOST_CHECK_EQUAL(pipeline->m_nSkippedRetx, 0);
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.25, MARGIN); // window size drop to 1/2 of previous size
-  BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 1);
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drop to 0.7x of previous size
+  BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
 
   // receive segment 6, retransmit 3
   face.receive(*makeDataWithSegment(6));
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.75, MARGIN); // congestion avoidance
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // congestion avoidance
   BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
   BOOST_CHECK_EQUAL(pipeline->m_retxCount[3], 1);
 
@@ -216,7 +188,6 @@
 BOOST_AUTO_TEST_CASE(CongestionMarksWithCwa)
 {
   nDataSegments = 7;
-  pipeline->m_ssthresh = 4.0;
   BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
 
   run(name);
@@ -230,14 +201,14 @@
   }
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.5, MARGIN);
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
 
   // receive segment 5 with congestion mark
   face.receive(*makeDataWithSegmentAndCongMark(5));
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.25, MARGIN); // window size drops to 1/2 of previous size
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drops to 1/2 of previous size
   BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
 
   // receive the last segment with congestion mark
@@ -245,7 +216,7 @@
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.25, MARGIN); // conservative window adaption (window size should not decrease)
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // conservative window adaption (window size should not decrease)
   BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
 
   // make sure no interest is retransmitted for marked data packets
@@ -262,7 +233,6 @@
   createPipeline();
 
   nDataSegments = 7;
-  pipeline->m_ssthresh = 4.0;
   BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
 
   run(name);
@@ -276,14 +246,14 @@
   }
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 5);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.5, MARGIN);
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 6.0, MARGIN);
 
   // receive segment 5 with congestion mark
   face.receive(*makeDataWithSegmentAndCongMark(5));
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.25, MARGIN); // window size drops to 1/2 of previous size
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.2, MARGIN); // window size drops to 1/2 of previous size
   BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
 
   // receive the last segment with congestion mark
@@ -291,7 +261,7 @@
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, PipelineInterestsAdaptive::MIN_SSTHRESH,
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 2.94,
                     MARGIN); // window size should decrease, as cwa is disabled
   BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
 
@@ -309,7 +279,6 @@
   createPipeline();
 
   nDataSegments = 7;
-  pipeline->m_ssthresh = 4.0;
   BOOST_REQUIRE_CLOSE(pipeline->m_cwnd, 1, MARGIN);
 
   run(name);
@@ -323,7 +292,7 @@
   }
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, 6);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 4.75, MARGIN);
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 7.0, MARGIN);
   BOOST_CHECK_EQUAL(face.sentInterests.size(), nDataSegments); // all interests have been sent
 
   // receive the last segment with congestion mark
@@ -331,7 +300,7 @@
   advanceClocks(io, time::nanoseconds(1));
 
   BOOST_CHECK_EQUAL(pipeline->m_nReceived, nDataSegments);
-  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 5.0, MARGIN); // window size increases
+  BOOST_CHECK_CLOSE(pipeline->m_cwnd, 8.0, MARGIN); // window size increases
   BOOST_CHECK_EQUAL(pipeline->m_retxQueue.size(), 0);
 
   // make sure no interest is retransmitted for marked data packet
@@ -608,7 +577,7 @@
 }
 
 
-BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsAdaptive
+BOOST_AUTO_TEST_SUITE_END() // TestPipelineInterestsCubic
 BOOST_AUTO_TEST_SUITE_END() // Chunks
 
 } // namespace tests