face+mgmt: allow congestion marking parameters to be enabled and set

refs #4465

Change-Id: I9d49135ab32bacb2885b70031c573f7c8709ac1f
diff --git a/daemon/face/channel.hpp b/daemon/face/channel.hpp
index 1a5ed90..cdb7078 100644
--- a/daemon/face/channel.hpp
+++ b/daemon/face/channel.hpp
@@ -29,6 +29,8 @@
 #include "channel-log.hpp"
 #include "face.hpp"
 
+#include <boost/logic/tribool.hpp>
+
 namespace nfd {
 namespace face {
 
@@ -90,13 +92,17 @@
     : persistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
     , wantLocalFields(false)
     , wantLpReliability(false)
+    , wantCongestionMarking(boost::logic::indeterminate)
   {
   }
 
 public:
   ndn::nfd::FacePersistency persistency;
+  ndn::optional<time::nanoseconds> baseCongestionMarkingInterval;
+  ndn::optional<uint64_t> defaultCongestionThreshold;
   bool wantLocalFields;
   bool wantLpReliability;
+  boost::logic::tribool wantCongestionMarking;
 };
 
 /** \brief invokes a callback when the face is closed
diff --git a/daemon/face/tcp-channel.cpp b/daemon/face/tcp-channel.cpp
index b6f434d..821c6d7 100644
--- a/daemon/face/tcp-channel.cpp
+++ b/daemon/face/tcp-channel.cpp
@@ -105,9 +105,23 @@
     GenericLinkService::Options options;
     options.allowLocalFields = params.wantLocalFields;
     options.reliabilityOptions.isEnabled = params.wantLpReliability;
-    options.allowCongestionMarking = m_wantCongestionMarking;
-    auto linkService = make_unique<GenericLinkService>(options);
 
+    if (boost::logic::indeterminate(params.wantCongestionMarking)) {
+      // Use default value for this channel if parameter is indeterminate
+      options.allowCongestionMarking = m_wantCongestionMarking;
+    }
+    else {
+      options.allowCongestionMarking = params.wantCongestionMarking;
+    }
+
+    if (params.baseCongestionMarkingInterval) {
+      options.baseCongestionMarkingInterval = *params.baseCongestionMarkingInterval;
+    }
+    if (params.defaultCongestionThreshold) {
+      options.defaultCongestionThreshold = *params.defaultCongestionThreshold;
+    }
+
+    auto linkService = make_unique<GenericLinkService>(options);
     auto transport = make_unique<TcpTransport>(std::move(socket), params.persistency);
     face = make_shared<Face>(std::move(linkService), std::move(transport));
 
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index 624b9cd..209aa70 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -162,7 +162,22 @@
 
   GenericLinkService::Options options;
   options.reliabilityOptions.isEnabled = params.wantLpReliability;
-  options.allowCongestionMarking = m_wantCongestionMarking;
+
+  if (boost::logic::indeterminate(params.wantCongestionMarking)) {
+    // Use default value for this channel if parameter is indeterminate
+    options.allowCongestionMarking = m_wantCongestionMarking;
+  }
+  else {
+    options.allowCongestionMarking = params.wantCongestionMarking;
+  }
+
+  if (params.baseCongestionMarkingInterval) {
+    options.baseCongestionMarkingInterval = *params.baseCongestionMarkingInterval;
+  }
+  if (params.defaultCongestionThreshold) {
+    options.defaultCongestionThreshold = *params.defaultCongestionThreshold;
+  }
+
   auto linkService = make_unique<GenericLinkService>(options);
   auto transport = make_unique<UnicastUdpTransport>(std::move(socket), params.persistency, m_idleFaceTimeout);
   auto face = make_shared<Face>(std::move(linkService), std::move(transport));
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 7ddf6ea..04e80a9 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -28,6 +28,8 @@
 #include "face/protocol-factory.hpp"
 #include "fw/face-table.hpp"
 
+#include <boost/logic/tribool.hpp>
+
 #include <ndn-cxx/lp/tags.hpp>
 #include <ndn-cxx/mgmt/nfd/channel-status.hpp>
 
@@ -117,10 +119,19 @@
 
   face::FaceParams faceParams;
   faceParams.persistency = parameters.getFacePersistency();
+  if (parameters.hasBaseCongestionMarkingInterval()) {
+    faceParams.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
+  }
+  if (parameters.hasDefaultCongestionThreshold()) {
+    faceParams.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
+  }
   faceParams.wantLocalFields = parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
                                parameters.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED);
   faceParams.wantLpReliability = parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) &&
                                  parameters.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED);
+  if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
+    faceParams.wantCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
+  }
   try {
     factory->createFace({remoteUri, localUri, faceParams},
                         bind(&FaceManager::afterCreateFaceSuccess, this, parameters, _1, done),
@@ -267,6 +278,15 @@
   if (parameters.hasFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
     options.reliabilityOptions.isEnabled = parameters.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED);
   }
+  if (parameters.hasFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED)) {
+    options.allowCongestionMarking = parameters.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED);
+  }
+  if (parameters.hasBaseCongestionMarkingInterval()) {
+    options.baseCongestionMarkingInterval = parameters.getBaseCongestionMarkingInterval();
+  }
+  if (parameters.hasDefaultCongestionThreshold()) {
+    options.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
+  }
   linkService->setOptions(options);
 }
 
@@ -280,8 +300,11 @@
   ControlParameters params;
   params.setFaceId(face.getId())
         .setFacePersistency(face.getPersistency())
+        .setBaseCongestionMarkingInterval(options.baseCongestionMarkingInterval)
+        .setDefaultCongestionThreshold(options.defaultCongestionThreshold)
         .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, options.allowLocalFields, false)
-        .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, options.reliabilityOptions.isEnabled, false);
+        .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, options.reliabilityOptions.isEnabled, false)
+        .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, options.allowCongestionMarking, false);
   if (wantUris) {
     params.setUri(face.getRemoteUri().toString())
           .setLocalUri(face.getLocalUri().toString());
@@ -393,10 +416,18 @@
 
   time::steady_clock::TimePoint expirationTime = face.getExpirationTime();
   if (expirationTime != time::steady_clock::TimePoint::max()) {
-    status.setExpirationPeriod(std::max(time::milliseconds(0),
+    status.setExpirationPeriod(std::max(0_ms,
                                         time::duration_cast<time::milliseconds>(expirationTime - now)));
   }
 
+  // Get LinkService options
+  auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
+  if (linkService != nullptr) {
+    auto linkServiceOptions = linkService->getOptions();
+    status.setBaseCongestionMarkingInterval(linkServiceOptions.baseCongestionMarkingInterval);
+    status.setDefaultCongestionThreshold(linkServiceOptions.defaultCongestionThreshold);
+  }
+
   const face::FaceCounters& counters = face.getCounters();
   status.setNInInterests(counters.nInInterests)
         .setNOutInterests(counters.nOutInterests)