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)
diff --git a/tests/daemon/face/ethernet-factory.t.cpp b/tests/daemon/face/ethernet-factory.t.cpp
index 8bdc139..70a9d5f 100644
--- a/tests/daemon/face/ethernet-factory.t.cpp
+++ b/tests/daemon/face/ethernet-factory.t.cpp
@@ -439,7 +439,7 @@
   createFace(factory,
              FaceUri("ether://[00:00:5e:00:53:5e]"),
              FaceUri("dev://eth0"),
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 504, "No channels available to connect"});
 
   SKIP_IF_ETHERNET_NETIF_COUNT_LT(1);
@@ -448,25 +448,31 @@
   createFace(factory,
              FaceUri("ether://[00:00:5e:00:53:5e]"),
              localUri,
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
              FaceUri("ether://[00:00:5e:00:53:5e]"),
              localUri,
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
              FaceUri("ether://[00:00:5e:00:53:53]"),
              localUri,
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
              FaceUri("ether://[00:00:5e:00:53:57]"),
              localUri,
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, true},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, true, false},
+             {CreateFaceExpectedResult::SUCCESS, 0, ""});
+
+  createFace(factory,
+             FaceUri("ether://[00:00:5e:00:53:5b]"),
+             localUri,
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, true},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 }
 
@@ -475,35 +481,35 @@
   createFace(factory,
              FaceUri("ether://[00:00:5e:00:53:5e]"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Creation of unicast Ethernet faces requires a LocalUri with dev:// scheme"});
 
   createFace(factory,
              FaceUri("ether://[00:00:5e:00:53:5e]"),
              FaceUri("udp4://127.0.0.1:20071"),
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Creation of unicast Ethernet faces requires a LocalUri with dev:// scheme"});
 
   createFace(factory,
              FaceUri("ether://[00:00:5e:00:53:5e]"),
              FaceUri("dev://eth0"),
-             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Outgoing Ethernet faces do not support on-demand persistency"});
 
   createFace(factory,
              FaceUri("ether://[01:00:5e:90:10:5e]"),
              FaceUri("dev://eth0"),
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Cannot create multicast Ethernet faces"});
 
   createFace(factory,
              FaceUri("ether://[00:00:5e:00:53:5e]"),
              FaceUri("dev://eth0"),
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, true, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, true, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Local fields can only be enabled on faces with local scope"});
 }
diff --git a/tests/daemon/face/factory-test-common.hpp b/tests/daemon/face/factory-test-common.hpp
index 6ea56bf..795bdf3 100644
--- a/tests/daemon/face/factory-test-common.hpp
+++ b/tests/daemon/face/factory-test-common.hpp
@@ -36,12 +36,19 @@
 
 struct TestFaceParams : public FaceParams
 {
-  TestFaceParams(ndn::nfd::FacePersistency persistency, bool wantLocalFields,
-                 bool wantLpReliability) noexcept
+  TestFaceParams(ndn::nfd::FacePersistency persistency,
+                 ndn::optional<time::nanoseconds> baseCongestionMarkingInterval,
+                 ndn::optional<uint64_t> defaultCongestionThreshold,
+                 bool wantLocalFields,
+                 bool wantLpReliability,
+                 boost::logic::tribool wantCongestionMarking) noexcept
   {
     this->persistency = persistency;
+    this->baseCongestionMarkingInterval = baseCongestionMarkingInterval;
+    this->defaultCongestionThreshold = defaultCongestionThreshold;
     this->wantLocalFields = wantLocalFields;
     this->wantLpReliability = wantLpReliability;
+    this->wantCongestionMarking = wantCongestionMarking;
   }
 };
 
diff --git a/tests/daemon/face/tcp-factory.t.cpp b/tests/daemon/face/tcp-factory.t.cpp
index 934229f..3785111 100644
--- a/tests/daemon/face/tcp-factory.t.cpp
+++ b/tests/daemon/face/tcp-factory.t.cpp
@@ -172,7 +172,7 @@
   createFace(factory,
              FaceUri("tcp4://127.0.0.1:6363"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 504, "No channels available to connect"});
 
   createChannel("127.0.0.1", "20071");
@@ -180,25 +180,31 @@
   createFace(factory,
              FaceUri("tcp4://127.0.0.1:6363"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
              FaceUri("tcp4://127.0.0.1:6363"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
              FaceUri("tcp4://127.0.0.1:20072"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
              FaceUri("tcp4://127.0.0.1:20073"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, true},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, true, false},
+             {CreateFaceExpectedResult::SUCCESS, 0, ""});
+
+  createFace(factory,
+             FaceUri("tcp4://127.0.0.1:20073"),
+             {},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, true},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 }
 
@@ -209,21 +215,21 @@
   createFace(factory,
              FaceUri("tcp4://127.0.0.1:20072"),
              FaceUri("tcp4://127.0.0.1:20071"),
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Unicast TCP faces cannot be created with a LocalUri"});
 
   createFace(factory,
              FaceUri("tcp4://127.0.0.1:20072"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Outgoing TCP faces do not support on-demand persistency"});
 
   createFace(factory,
              FaceUri("tcp4://198.51.100.100:6363"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, true, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, true, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Local fields can only be enabled on faces with local scope"});
 }
diff --git a/tests/daemon/face/udp-factory.t.cpp b/tests/daemon/face/udp-factory.t.cpp
index 7303f5c..ee5a3f4 100644
--- a/tests/daemon/face/udp-factory.t.cpp
+++ b/tests/daemon/face/udp-factory.t.cpp
@@ -877,7 +877,7 @@
   createFace(factory,
              FaceUri("udp4://127.0.0.1:6363"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 504, "No channels available to connect"});
 
   createChannel("127.0.0.1", 20071);
@@ -885,25 +885,31 @@
   createFace(factory,
              FaceUri("udp4://127.0.0.1:6363"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
              FaceUri("udp4://127.0.0.1:6363"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
              FaceUri("udp4://127.0.0.1:20072"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 
   createFace(factory,
              FaceUri("udp4://127.0.0.1:20073"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, true},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, true, false},
+             {CreateFaceExpectedResult::SUCCESS, 0, ""});
+
+  createFace(factory,
+             FaceUri("udp4://127.0.0.1:20073"),
+             {},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, true},
              {CreateFaceExpectedResult::SUCCESS, 0, ""});
 }
 
@@ -914,28 +920,28 @@
   createFace(factory,
              FaceUri("udp4://127.0.0.1:20072"),
              FaceUri("udp4://127.0.0.1:20071"),
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Unicast UDP faces cannot be created with a LocalUri"});
 
   createFace(factory,
              FaceUri("udp4://127.0.0.1:20072"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Outgoing UDP faces do not support on-demand persistency"});
 
   createFace(factory,
              FaceUri("udp4://233.252.0.1:23252"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Cannot create multicast UDP faces"});
 
   createFace(factory,
              FaceUri("udp4://127.0.0.1:20072"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, true, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, true, false, false},
              {CreateFaceExpectedResult::FAILURE, 406,
               "Local fields can only be enabled on faces with local scope"});
 }
diff --git a/tests/daemon/face/unix-stream-factory.t.cpp b/tests/daemon/face/unix-stream-factory.t.cpp
index 79eefa6..b07e5bf 100644
--- a/tests/daemon/face/unix-stream-factory.t.cpp
+++ b/tests/daemon/face/unix-stream-factory.t.cpp
@@ -125,19 +125,19 @@
   createFace(factory,
              FaceUri("unix:///var/run/nfd.sock"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
   createFace(factory,
              FaceUri("unix:///var/run/nfd.sock"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
   createFace(factory,
              FaceUri("unix:///var/run/nfd.sock"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 }
 
diff --git a/tests/daemon/face/websocket-factory.t.cpp b/tests/daemon/face/websocket-factory.t.cpp
index bb8a378..9ba5d5d 100644
--- a/tests/daemon/face/websocket-factory.t.cpp
+++ b/tests/daemon/face/websocket-factory.t.cpp
@@ -196,19 +196,19 @@
   createFace(factory,
              FaceUri("ws://127.0.0.1:20070"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_ON_DEMAND, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
   createFace(factory,
              FaceUri("ws://127.0.0.1:20070"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 
   createFace(factory,
              FaceUri("ws://127.0.0.1:20070"),
              {},
-             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, false, false},
+             {ndn::nfd::FACE_PERSISTENCY_PERMANENT, {}, {}, false, false, false},
              {CreateFaceExpectedResult::FAILURE, 406, "Unsupported protocol"});
 }
 
diff --git a/tests/daemon/mgmt/face-manager-create-face.t.cpp b/tests/daemon/mgmt/face-manager-create-face.t.cpp
index 4274efa..698a525 100644
--- a/tests/daemon/mgmt/face-manager-create-face.t.cpp
+++ b/tests/daemon/mgmt/face-manager-create-face.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,7 @@
  */
 
 #include "mgmt/face-manager.hpp"
+#include "face/generic-link-service.hpp"
 #include "face-manager-command-fixture.hpp"
 #include "nfd-manager-common-fixture.hpp"
 
@@ -192,7 +193,7 @@
   getParameters()
   {
     return ControlParameters()
-      .setUri("tcp4://127.0.0.1:26363")
+      .setUri("udp4://127.0.0.1:26363")
       .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
       .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true);
   }
@@ -205,12 +206,42 @@
   getParameters()
   {
     return ControlParameters()
-      .setUri("tcp4://127.0.0.1:26363")
+      .setUri("udp4://127.0.0.1:26363")
       .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
       .setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, false);
   }
 };
 
+class TcpFaceCongestionMarkingEnabled
+{
+public:
+  static ControlParameters
+  getParameters()
+  {
+    return ControlParameters()
+      .setUri("tcp4://127.0.0.1:26363")
+      .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
+      .setBaseCongestionMarkingInterval(50_ms)
+      .setDefaultCongestionThreshold(1000)
+      .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, true);
+  }
+};
+
+class TcpFaceCongestionMarkingDisabled
+{
+public:
+  static ControlParameters
+  getParameters()
+  {
+    return ControlParameters()
+      .setUri("tcp4://127.0.0.1:26363")
+      .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT)
+      .setBaseCongestionMarkingInterval(50_ms)
+      .setDefaultCongestionThreshold(1000)
+      .setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, false);
+  }
+};
+
 class FaceUriMalformed
 {
 public:
@@ -262,6 +293,8 @@
                     mpl::pair<TcpFaceLpReliabilityDisabled, CommandSuccess>,
                     mpl::pair<UdpFaceLpReliabilityEnabled, CommandSuccess>,
                     mpl::pair<UdpFaceLpReliabilityDisabled, CommandSuccess>,
+                    mpl::pair<TcpFaceCongestionMarkingEnabled, CommandSuccess>,
+                    mpl::pair<TcpFaceCongestionMarkingDisabled, CommandSuccess>,
                     mpl::pair<FaceUriMalformed, CommandFailure<400>>,
                     mpl::pair<FaceUriNonCanonical, CommandFailure<400>>,
                     mpl::pair<FaceUriUnsupportedScheme, CommandFailure<406>>>;
@@ -297,11 +330,30 @@
                             actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED));
           BOOST_CHECK_EQUAL(expectedParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED),
                             actualParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED));
+          BOOST_CHECK_EQUAL(expectedParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED),
+                            actualParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
         }
         else {
           // local fields are disabled by default
           BOOST_CHECK_EQUAL(actualParams.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED), false);
           BOOST_CHECK_EQUAL(actualParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED), false);
+          BOOST_CHECK_EQUAL(actualParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED), false);
+        }
+
+        if (expectedParams.hasBaseCongestionMarkingInterval()) {
+          BOOST_CHECK_EQUAL(expectedParams.getBaseCongestionMarkingInterval(),
+                            actualParams.getBaseCongestionMarkingInterval());
+        }
+        else {
+          BOOST_CHECK_EQUAL(actualParams.getBaseCongestionMarkingInterval(), 100_ms);
+        }
+
+        if (expectedParams.hasDefaultCongestionThreshold()) {
+          BOOST_CHECK_EQUAL(expectedParams.getDefaultCongestionThreshold(),
+                            actualParams.getDefaultCongestionThreshold());
+        }
+        else {
+          BOOST_CHECK_EQUAL(actualParams.getDefaultCongestionThreshold(), 65536);
         }
       }
       else {
@@ -327,7 +379,7 @@
   });
 
   this->node1.face.receive(req);
-  this->advanceClocks(time::milliseconds(1), 5);
+  this->advanceClocks(1_ms, 5);
 
   BOOST_CHECK(hasCallbackFired);
 }
@@ -340,7 +392,7 @@
     // create face
     Interest req = makeControlCommandRequest("/localhost/nfd/faces/create", FaceType::getParameters());
     this->node1.face.receive(req);
-    this->advanceClocks(time::milliseconds(1), 5);
+    this->advanceClocks(1_ms, 5);
   }
 
   // find the created face
@@ -365,12 +417,17 @@
         BOOST_CHECK_EQUAL(foundFace->getId(), actualParams.getFaceId());
         BOOST_CHECK_EQUAL(foundFace->getRemoteUri().toString(), actualParams.getUri());
         BOOST_CHECK_EQUAL(foundFace->getPersistency(), actualParams.getFacePersistency());
+        auto linkService = dynamic_cast<face::GenericLinkService*>(foundFace->getLinkService());
+        BOOST_CHECK_EQUAL(linkService->getOptions().baseCongestionMarkingInterval,
+                          actualParams.getBaseCongestionMarkingInterval());
+        BOOST_CHECK_EQUAL(linkService->getOptions().defaultCongestionThreshold,
+                          actualParams.getDefaultCongestionThreshold());
 
         hasCallbackFired = true;
       });
 
     this->node1.face.receive(req);
-    this->advanceClocks(time::milliseconds(1), 5);
+    this->advanceClocks(1_ms, 5);
 
     BOOST_CHECK(hasCallbackFired);
   }
diff --git a/tests/daemon/mgmt/face-manager-update-face.t.cpp b/tests/daemon/mgmt/face-manager-update-face.t.cpp
index 9a6825e..dd34fd8 100644
--- a/tests/daemon/mgmt/face-manager-update-face.t.cpp
+++ b/tests/daemon/mgmt/face-manager-update-face.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -32,6 +32,8 @@
 
 #include <thread>
 
+#include <boost/logic/tribool.hpp>
+
 namespace nfd {
 namespace tests {
 
@@ -54,15 +56,31 @@
   void
   createFace(const std::string& uri = "tcp4://127.0.0.1:26363",
              ndn::nfd::FacePersistency persistency = ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+             ndn::optional<time::nanoseconds> baseCongestionMarkingInterval = {},
+             ndn::optional<uint64_t> defaultCongestionThreshold = {},
              bool enableLocalFields = false,
-             bool enableReliability = false)
+             bool enableReliability = false,
+             boost::logic::tribool enableCongestionMarking = boost::logic::indeterminate)
   {
     ControlParameters params;
     params.setUri(uri);
     params.setFacePersistency(persistency);
+
+    if (baseCongestionMarkingInterval) {
+      params.setBaseCongestionMarkingInterval(*baseCongestionMarkingInterval);
+    }
+
+    if (defaultCongestionThreshold) {
+      params.setDefaultCongestionThreshold(*defaultCongestionThreshold);
+    }
+
     params.setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, enableLocalFields);
     params.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, enableReliability);
 
+    if (!boost::logic::indeterminate(enableCongestionMarking)) {
+      params.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, enableCongestionMarking);
+    }
+
     createFace(params);
   }
 
@@ -474,7 +492,8 @@
   typedef typename T::first TestType;
   typedef typename T::second ResultType;
 
-  createFace(TestType().getUri(), TestType().getPersistency(), TestType().getInitLocalFieldsEnabled());
+  createFace(TestType().getUri(), TestType().getPersistency(), {}, {},
+             TestType().getInitLocalFieldsEnabled());
 
   ControlParameters requestParams;
   requestParams.setFaceId(faceId);
@@ -601,6 +620,71 @@
   });
 }
 
+BOOST_AUTO_TEST_CASE(UpdateCongestionMarkingEnableDisable)
+{
+  createFace("udp4://127.0.0.1:26363");
+
+  ControlParameters enableParams;
+  enableParams.setFaceId(faceId);
+  enableParams.setBaseCongestionMarkingInterval(time::milliseconds(50));
+  enableParams.setDefaultCongestionThreshold(10000);
+  enableParams.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, true);
+
+  ControlParameters disableParams;
+  disableParams.setFaceId(faceId);
+  disableParams.setBaseCongestionMarkingInterval(time::milliseconds(70));
+  disableParams.setDefaultCongestionThreshold(5000);
+  disableParams.setFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED, false);
+
+  updateFace(enableParams, false, [] (const ControlResponse& actual) {
+    ControlResponse expected(200, "OK");
+    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
+    BOOST_TEST_MESSAGE(actual.getText());
+
+    if (actual.getBody().hasWire()) {
+      ControlParameters actualParams(actual.getBody());
+
+      BOOST_CHECK(actualParams.hasFaceId());
+      BOOST_CHECK(actualParams.hasFacePersistency());
+      // Check that congestion marking parameters changed
+      BOOST_REQUIRE(actualParams.hasBaseCongestionMarkingInterval());
+      BOOST_CHECK_EQUAL(actualParams.getBaseCongestionMarkingInterval(), time::milliseconds(50));
+      BOOST_REQUIRE(actualParams.hasDefaultCongestionThreshold());
+      BOOST_CHECK_EQUAL(actualParams.getDefaultCongestionThreshold(), 10000);
+      BOOST_REQUIRE(actualParams.hasFlags());
+      // Check if flags indicate congestion marking enabled
+      BOOST_CHECK(actualParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
+    }
+    else {
+      BOOST_ERROR("Enable: Response does not contain ControlParameters");
+    }
+  });
+
+  updateFace(disableParams, false, [] (const ControlResponse& actual) {
+    ControlResponse expected(200, "OK");
+    BOOST_CHECK_EQUAL(actual.getCode(), expected.getCode());
+    BOOST_TEST_MESSAGE(actual.getText());
+
+    if (actual.getBody().hasWire()) {
+      ControlParameters actualParams(actual.getBody());
+
+      BOOST_CHECK(actualParams.hasFaceId());
+      BOOST_CHECK(actualParams.hasFacePersistency());
+      // Check that congestion marking parameters changed, even though feature disabled
+      BOOST_REQUIRE(actualParams.hasBaseCongestionMarkingInterval());
+      BOOST_CHECK_EQUAL(actualParams.getBaseCongestionMarkingInterval(), time::milliseconds(70));
+      BOOST_REQUIRE(actualParams.hasDefaultCongestionThreshold());
+      BOOST_CHECK_EQUAL(actualParams.getDefaultCongestionThreshold(), 5000);
+      BOOST_REQUIRE(actualParams.hasFlags());
+      // Check if flags indicate marking disabled
+      BOOST_CHECK(!actualParams.getFlagBit(ndn::nfd::BIT_CONGESTION_MARKING_ENABLED));
+    }
+    else {
+      BOOST_ERROR("Disable: Response does not contain ControlParameters");
+    }
+  });
+}
+
 BOOST_AUTO_TEST_CASE(SelfUpdating)
 {
   createFace();