fw: rename RetransmissionSuppression to RetxSuppressionFixed

This commit also declares RetxSuppression base class as the API
for any retransmission suppression decision algorithms,
so that other algorithms can be introduced.

refs #1913

Change-Id: I5539565d2dd238d1421f5bd828fde4ecfba0a820
diff --git a/daemon/fw/access-strategy.cpp b/daemon/fw/access-strategy.cpp
index ece5a83..e726d27 100644
--- a/daemon/fw/access-strategy.cpp
+++ b/daemon/fw/access-strategy.cpp
@@ -50,16 +50,15 @@
                                      shared_ptr<fib::Entry> fibEntry,
                                      shared_ptr<pit::Entry> pitEntry)
 {
-  RetransmissionSuppression::Result suppressResult =
-      m_retransmissionSuppression.decide(inFace, interest, *pitEntry);
+  RetxSuppression::Result suppressResult = m_retxSuppression.decide(inFace, interest, *pitEntry);
   switch (suppressResult) {
-  case RetransmissionSuppression::NEW:
+  case RetxSuppression::NEW:
     this->afterReceiveNewInterest(inFace, interest, fibEntry, pitEntry);
     break;
-  case RetransmissionSuppression::FORWARD:
+  case RetxSuppression::FORWARD:
     this->afterReceiveRetxInterest(inFace, interest, fibEntry, pitEntry);
     break;
-  case RetransmissionSuppression::SUPPRESS:
+  case RetxSuppression::SUPPRESS:
     NFD_LOG_DEBUG(interest << " interestFrom " << inFace.getId() << " retx-suppress");
     break;
   default:
diff --git a/daemon/fw/access-strategy.hpp b/daemon/fw/access-strategy.hpp
index 7410b51..5fadc85 100644
--- a/daemon/fw/access-strategy.hpp
+++ b/daemon/fw/access-strategy.hpp
@@ -28,7 +28,7 @@
 
 #include "strategy.hpp"
 #include "rtt-estimator.hpp"
-#include "retransmission-suppression.hpp"
+#include "retx-suppression-fixed.hpp"
 #include <unordered_set>
 #include <unordered_map>
 
@@ -167,7 +167,7 @@
 
 private:
   FaceInfoTable m_fit;
-  RetransmissionSuppression m_retransmissionSuppression;
+  RetxSuppressionFixed m_retxSuppression;
   signal::ScopedConnection m_removeFaceInfoConn;
 };
 
diff --git a/daemon/fw/best-route-strategy2.cpp b/daemon/fw/best-route-strategy2.cpp
index bd58590..8aca86a 100644
--- a/daemon/fw/best-route-strategy2.cpp
+++ b/daemon/fw/best-route-strategy2.cpp
@@ -103,9 +103,9 @@
   const fib::NextHopList& nexthops = fibEntry->getNextHops();
   fib::NextHopList::const_iterator it = nexthops.end();
 
-  RetransmissionSuppression::Result suppression =
-      m_retransmissionSuppression.decide(inFace, interest, *pitEntry);
-  if (suppression == RetransmissionSuppression::NEW) {
+  RetxSuppression::Result suppression =
+      m_retxSuppression.decide(inFace, interest, *pitEntry);
+  if (suppression == RetxSuppression::NEW) {
     // forward to nexthop with lowest cost except downstream
     it = std::find_if(nexthops.begin(), nexthops.end(),
       bind(&predicate_NextHop_eligible, pitEntry, _1, inFace.getId(),
@@ -124,7 +124,7 @@
     return;
   }
 
-  if (suppression == RetransmissionSuppression::SUPPRESS) {
+  if (suppression == RetxSuppression::SUPPRESS) {
     NFD_LOG_DEBUG(interest << " from=" << inFace.getId()
                            << " suppressed");
     return;
diff --git a/daemon/fw/best-route-strategy2.hpp b/daemon/fw/best-route-strategy2.hpp
index 5a0f3be..603be0e 100644
--- a/daemon/fw/best-route-strategy2.hpp
+++ b/daemon/fw/best-route-strategy2.hpp
@@ -27,7 +27,7 @@
 #define NFD_DAEMON_FW_BEST_ROUTE_STRATEGY2_HPP
 
 #include "strategy.hpp"
-#include "retransmission-suppression.hpp"
+#include "retx-suppression-fixed.hpp"
 
 namespace nfd {
 namespace fw {
@@ -55,7 +55,7 @@
   static const Name STRATEGY_NAME;
 
 private:
-  RetransmissionSuppression m_retransmissionSuppression;
+  RetxSuppressionFixed m_retxSuppression;
 };
 
 } // namespace fw
diff --git a/daemon/fw/retransmission-suppression.cpp b/daemon/fw/retx-suppression-fixed.cpp
similarity index 79%
rename from daemon/fw/retransmission-suppression.cpp
rename to daemon/fw/retx-suppression-fixed.cpp
index be1ff0b..74f2302 100644
--- a/daemon/fw/retransmission-suppression.cpp
+++ b/daemon/fw/retx-suppression-fixed.cpp
@@ -23,17 +23,22 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "retransmission-suppression.hpp"
+#include "retx-suppression-fixed.hpp"
 
 namespace nfd {
 namespace fw {
 
-/// \todo don't use fixed interval; make it adaptive or use exponential back-off #1913
-const time::milliseconds RetransmissionSuppression::MIN_RETRANSMISSION_INTERVAL(100);
+const time::milliseconds RetxSuppressionFixed::DEFAULT_MIN_RETX_INTERVAL(100);
 
-RetransmissionSuppression::Result
-RetransmissionSuppression::decide(const Face& inFace, const Interest& interest,
-                                  const pit::Entry& pitEntry)
+RetxSuppressionFixed::RetxSuppressionFixed(const time::milliseconds& minRetxInterval)
+  : m_minRetxInterval(minRetxInterval)
+{
+  BOOST_ASSERT(minRetxInterval > time::milliseconds::zero());
+}
+
+RetxSuppression::Result
+RetxSuppressionFixed::decide(const Face& inFace, const Interest& interest,
+                             const pit::Entry& pitEntry) const
 {
   bool isNewPitEntry = !pitEntry.hasUnexpiredOutRecords();
   if (isNewPitEntry) {
@@ -51,7 +56,7 @@
 
   time::steady_clock::TimePoint now = time::steady_clock::now();
   time::steady_clock::Duration sinceLastOutgoing = now - lastOutgoing->getLastRenewed();
-  bool shouldSuppress = sinceLastOutgoing < MIN_RETRANSMISSION_INTERVAL;
+  bool shouldSuppress = sinceLastOutgoing < m_minRetxInterval;
   return shouldSuppress ? SUPPRESS : FORWARD;
 }
 
diff --git a/daemon/fw/retransmission-suppression.hpp b/daemon/fw/retx-suppression-fixed.hpp
similarity index 67%
copy from daemon/fw/retransmission-suppression.hpp
copy to daemon/fw/retx-suppression-fixed.hpp
index 4553433..f88c83e 100644
--- a/daemon/fw/retransmission-suppression.hpp
+++ b/daemon/fw/retx-suppression-fixed.hpp
@@ -23,44 +23,38 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NFD_DAEMON_FW_RETRANSMISSION_SUPPRESSION_HPP
-#define NFD_DAEMON_FW_RETRANSMISSION_SUPPRESSION_HPP
+#ifndef NFD_DAEMON_FW_RETX_SUPPRESSION_FIXED_HPP
+#define NFD_DAEMON_FW_RETX_SUPPRESSION_FIXED_HPP
 
-#include "strategy.hpp"
+#include "retx-suppression.hpp"
 
 namespace nfd {
 namespace fw {
 
-/** \brief helper for consumer retransmission suppression
+/** \brief a retransmission suppression decision algorithm that
+ *         suppresses retransmissions within a fixed duration
  */
-class RetransmissionSuppression : noncopyable
+class RetxSuppressionFixed : public RetxSuppression
 {
 public:
-  enum Result {
-    /** \brief Interest is new (not a retransmission)
-     */
-    NEW,
-
-    /** \brief Interest is retransmission and should be forwarded
-     */
-    FORWARD,
-
-    /** \brief Interest is retransmission and should be suppressed
-     */
-    SUPPRESS
-  };
+  explicit
+  RetxSuppressionFixed(const time::milliseconds& minRetxInterval = DEFAULT_MIN_RETX_INTERVAL);
 
   /** \brief determines whether Interest is a retransmission,
    *         and if so, whether it shall be forwarded or suppressed
    */
-  Result
-  decide(const Face& inFace, const Interest& interest, const pit::Entry& pitEntry);
+  virtual Result
+  decide(const Face& inFace, const Interest& interest,
+         const pit::Entry& pitEntry) const DECL_OVERRIDE;
 
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  static const time::milliseconds MIN_RETRANSMISSION_INTERVAL;
+public:
+  static const time::milliseconds DEFAULT_MIN_RETX_INTERVAL;
+
+private:
+  const time::milliseconds m_minRetxInterval;
 };
 
 } // namespace fw
 } // namespace nfd
 
-#endif // NFD_DAEMON_FW_RETRANSMISSION_SUPPRESSION_HPP
+#endif // NFD_DAEMON_FW_RETX_SUPPRESSION_FIXED_HPP
diff --git a/daemon/fw/retransmission-suppression.hpp b/daemon/fw/retx-suppression.hpp
similarity index 85%
rename from daemon/fw/retransmission-suppression.hpp
rename to daemon/fw/retx-suppression.hpp
index 4553433..06aaf94 100644
--- a/daemon/fw/retransmission-suppression.hpp
+++ b/daemon/fw/retx-suppression.hpp
@@ -23,8 +23,8 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NFD_DAEMON_FW_RETRANSMISSION_SUPPRESSION_HPP
-#define NFD_DAEMON_FW_RETRANSMISSION_SUPPRESSION_HPP
+#ifndef NFD_DAEMON_FW_RETX_SUPPRESSION_HPP
+#define NFD_DAEMON_FW_RETX_SUPPRESSION_HPP
 
 #include "strategy.hpp"
 
@@ -33,7 +33,7 @@
 
 /** \brief helper for consumer retransmission suppression
  */
-class RetransmissionSuppression : noncopyable
+class RetxSuppression : noncopyable
 {
 public:
   enum Result {
@@ -53,14 +53,11 @@
   /** \brief determines whether Interest is a retransmission,
    *         and if so, whether it shall be forwarded or suppressed
    */
-  Result
-  decide(const Face& inFace, const Interest& interest, const pit::Entry& pitEntry);
-
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  static const time::milliseconds MIN_RETRANSMISSION_INTERVAL;
+  virtual Result
+  decide(const Face& inFace, const Interest& interest, const pit::Entry& pitEntry) const = 0;
 };
 
 } // namespace fw
 } // namespace nfd
 
-#endif // NFD_DAEMON_FW_RETRANSMISSION_SUPPRESSION_HPP
+#endif // NFD_DAEMON_FW_RETX_SUPPRESSION_HPP
diff --git a/tests/daemon/fw/best-route-strategy2.cpp b/tests/daemon/fw/best-route-strategy2.cpp
index 687bfcb..5357bc8 100644
--- a/tests/daemon/fw/best-route-strategy2.cpp
+++ b/tests/daemon/fw/best-route-strategy2.cpp
@@ -62,13 +62,13 @@
   shared_ptr<pit::Entry> pitEntry = pit.insert(*interest).first;
 
   const time::nanoseconds TICK = time::duration_cast<time::nanoseconds>(
-    fw::RetransmissionSuppression::MIN_RETRANSMISSION_INTERVAL * 0.01);
+    fw::RetxSuppressionFixed::DEFAULT_MIN_RETX_INTERVAL * 0.01);
   const time::nanoseconds RETRANSMISSION_10P = time::duration_cast<time::nanoseconds>(
-    fw::RetransmissionSuppression::MIN_RETRANSMISSION_INTERVAL * 0.1); // 10%
+    fw::RetxSuppressionFixed::DEFAULT_MIN_RETX_INTERVAL * 0.1); // 10%
   const time::nanoseconds RETRANSMISSION_70P = time::duration_cast<time::nanoseconds>(
-    fw::RetransmissionSuppression::MIN_RETRANSMISSION_INTERVAL * 0.7); // 70%
+    fw::RetxSuppressionFixed::DEFAULT_MIN_RETX_INTERVAL * 0.7); // 70%
   const time::nanoseconds RETRANSMISSION_2 = time::duration_cast<time::nanoseconds>(
-    fw::RetransmissionSuppression::MIN_RETRANSMISSION_INTERVAL * 2.0); // x2
+    fw::RetxSuppressionFixed::DEFAULT_MIN_RETX_INTERVAL * 2.0); // x2
 
   // first Interest goes to nexthop with lowest FIB cost,
   // however face1 is downstream so it cannot be used
@@ -78,7 +78,7 @@
   BOOST_CHECK_EQUAL(strategy.m_sendInterestHistory.back().get<1>(), face2);
 
   // downstream retransmits frequently, but the strategy should not send Interests
-  // more often than MIN_RETRANSMISSION_INTERVAL
+  // more often than DEFAULT_MIN_RETX_INTERVAL
   scheduler::EventId retxFrom4Evt;
   size_t nSentLast = strategy.m_sendInterestHistory.size();
   time::steady_clock::TimePoint timeSentLast = time::steady_clock::now();
@@ -99,7 +99,7 @@
     retxFrom4Evt = scheduler::schedule(RETRANSMISSION_10P, periodicalRetxFrom4);
   };
   periodicalRetxFrom4();
-  this->advanceClocks(TICK, fw::RetransmissionSuppression::MIN_RETRANSMISSION_INTERVAL * 16);
+  this->advanceClocks(TICK, fw::RetxSuppressionFixed::DEFAULT_MIN_RETX_INTERVAL * 16);
   scheduler::cancel(retxFrom4Evt);
 
   // nexthops for accepted retransmissions: follow FIB cost,
diff --git a/tests/daemon/fw/retransmission-suppression.cpp b/tests/daemon/fw/retx-suppression.cpp
similarity index 84%
rename from tests/daemon/fw/retransmission-suppression.cpp
rename to tests/daemon/fw/retx-suppression.cpp
index c1ba968..e4417ce 100644
--- a/tests/daemon/fw/retransmission-suppression.cpp
+++ b/tests/daemon/fw/retx-suppression.cpp
@@ -23,7 +23,8 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "fw/retransmission-suppression.hpp"
+#include "fw/retx-suppression.hpp"
+#include "fw/retx-suppression-fixed.hpp"
 #include "strategy-tester.hpp"
 
 #include "tests/test-common.hpp"
@@ -32,15 +33,17 @@
 namespace nfd {
 namespace tests {
 
-using fw::RetransmissionSuppression;
+using fw::RetxSuppression;
+using fw::RetxSuppressionFixed;
 
-BOOST_FIXTURE_TEST_SUITE(FwRetransmissionSuppression, UnitTestTimeFixture)
+BOOST_FIXTURE_TEST_SUITE(FwRetxSuppression, UnitTestTimeFixture)
 
-BOOST_AUTO_TEST_CASE(Basic)
+BOOST_AUTO_TEST_CASE(Fixed)
 {
   Forwarder forwarder;
   Pit& pit = forwarder.getPit();
-  RetransmissionSuppression rs;
+  static const time::milliseconds MIN_RETX_INTERVAL(200);
+  RetxSuppressionFixed rs(MIN_RETX_INTERVAL);
 
   shared_ptr<DummyFace> face1 = make_shared<DummyFace>();
   shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
@@ -52,36 +55,36 @@
   shared_ptr<Interest> interest = makeInterest("ndn:/0JiimvmxK8");
   shared_ptr<pit::Entry> pitEntry = pit.insert(*interest).first;
 
-  const time::nanoseconds RETRANSMISSION_10P = time::duration_cast<time::nanoseconds>(
-    fw::RetransmissionSuppression::MIN_RETRANSMISSION_INTERVAL * 0.1);
+  const time::nanoseconds RETRANSMISSION_10P =
+      time::duration_cast<time::nanoseconds>(MIN_RETX_INTERVAL * 0.1);
 
   // @ time 0
   pitEntry->insertOrUpdateInRecord(face1, *interest);
-  BOOST_CHECK_EQUAL(rs.decide(*face1, *interest, *pitEntry), RetransmissionSuppression::NEW);
+  BOOST_CHECK_EQUAL(rs.decide(*face1, *interest, *pitEntry), RetxSuppression::NEW);
   pitEntry->insertOrUpdateOutRecord(face3, *interest);
 
   this->advanceClocks(RETRANSMISSION_10P, 5); // @ time 0.5 interval
   pitEntry->insertOrUpdateInRecord(face1, *interest);
-  BOOST_CHECK_EQUAL(rs.decide(*face1, *interest, *pitEntry), RetransmissionSuppression::SUPPRESS);
+  BOOST_CHECK_EQUAL(rs.decide(*face1, *interest, *pitEntry), RetxSuppression::SUPPRESS);
   pitEntry->insertOrUpdateInRecord(face2, *interest);
-  BOOST_CHECK_EQUAL(rs.decide(*face2, *interest, *pitEntry), RetransmissionSuppression::SUPPRESS);
+  BOOST_CHECK_EQUAL(rs.decide(*face2, *interest, *pitEntry), RetxSuppression::SUPPRESS);
 
   this->advanceClocks(RETRANSMISSION_10P, 6); // @ time 1.1 interval
   pitEntry->insertOrUpdateInRecord(face2, *interest);
-  BOOST_CHECK_EQUAL(rs.decide(*face2, *interest, *pitEntry), RetransmissionSuppression::FORWARD);
+  BOOST_CHECK_EQUAL(rs.decide(*face2, *interest, *pitEntry), RetxSuppression::FORWARD);
   // but strategy decides not to forward
 
   this->advanceClocks(RETRANSMISSION_10P, 1); // @ time 1.2 interval
   pitEntry->insertOrUpdateInRecord(face1, *interest);
-  BOOST_CHECK_EQUAL(rs.decide(*face1, *interest, *pitEntry), RetransmissionSuppression::FORWARD);
+  BOOST_CHECK_EQUAL(rs.decide(*face1, *interest, *pitEntry), RetxSuppression::FORWARD);
   // retransmission suppress shall still give clearance for forwarding
   pitEntry->insertOrUpdateOutRecord(face3, *interest); // and strategy forwards
 
   this->advanceClocks(RETRANSMISSION_10P, 2); // @ time 1.4 interval
   pitEntry->insertOrUpdateInRecord(face1, *interest);
-  BOOST_CHECK_EQUAL(rs.decide(*face1, *interest, *pitEntry), RetransmissionSuppression::SUPPRESS);
+  BOOST_CHECK_EQUAL(rs.decide(*face1, *interest, *pitEntry), RetxSuppression::SUPPRESS);
   pitEntry->insertOrUpdateInRecord(face2, *interest);
-  BOOST_CHECK_EQUAL(rs.decide(*face2, *interest, *pitEntry), RetransmissionSuppression::SUPPRESS);
+  BOOST_CHECK_EQUAL(rs.decide(*face2, *interest, *pitEntry), RetxSuppression::SUPPRESS);
 }
 
 BOOST_AUTO_TEST_SUITE_END()