mgmt: make congestion marking parameters optional

refs #4465

Change-Id: I5ab07ecd4f1b7f4c948ba359513e65ac2e96c943
diff --git a/src/mgmt/nfd/control-command.cpp b/src/mgmt/nfd/control-command.cpp
index 472f329..9f978f0 100644
--- a/src/mgmt/nfd/control-command.cpp
+++ b/src/mgmt/nfd/control-command.cpp
@@ -112,8 +112,8 @@
     .required(CONTROL_PARAMETER_URI)
     .required(CONTROL_PARAMETER_LOCAL_URI)
     .required(CONTROL_PARAMETER_FACE_PERSISTENCY)
-    .required(CONTROL_PARAMETER_BASE_CONGESTION_MARKING_INTERVAL)
-    .required(CONTROL_PARAMETER_DEFAULT_CONGESTION_THRESHOLD)
+    .optional(CONTROL_PARAMETER_BASE_CONGESTION_MARKING_INTERVAL)
+    .optional(CONTROL_PARAMETER_DEFAULT_CONGESTION_THRESHOLD)
     .required(CONTROL_PARAMETER_FLAGS);
 }
 
@@ -148,8 +148,8 @@
   m_responseValidator
     .required(CONTROL_PARAMETER_FACE_ID)
     .required(CONTROL_PARAMETER_FACE_PERSISTENCY)
-    .required(CONTROL_PARAMETER_BASE_CONGESTION_MARKING_INTERVAL)
-    .required(CONTROL_PARAMETER_DEFAULT_CONGESTION_THRESHOLD)
+    .optional(CONTROL_PARAMETER_BASE_CONGESTION_MARKING_INTERVAL)
+    .optional(CONTROL_PARAMETER_DEFAULT_CONGESTION_THRESHOLD)
     .required(CONTROL_PARAMETER_FLAGS);
 }
 
diff --git a/src/mgmt/nfd/face-status.cpp b/src/mgmt/nfd/face-status.cpp
index 0a284cd..0c127ae 100644
--- a/src/mgmt/nfd/face-status.cpp
+++ b/src/mgmt/nfd/face-status.cpp
@@ -32,9 +32,7 @@
 BOOST_CONCEPT_ASSERT((StatusDatasetItem<FaceStatus>));
 
 FaceStatus::FaceStatus()
-  : m_baseCongestionMarkingInterval(0)
-  , m_defaultCongestionThreshold(0)
-  , m_nInInterests(0)
+  : m_nInInterests(0)
   , m_nInData(0)
   , m_nInNacks(0)
   , m_nOutInterests(0)
@@ -65,10 +63,14 @@
   totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NInNacks, m_nInNacks);
   totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NInData, m_nInData);
   totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NInInterests, m_nInInterests);
-  totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::DefaultCongestionThreshold,
-                                                m_defaultCongestionThreshold);
-  totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::BaseCongestionMarkingInterval,
-                                                m_baseCongestionMarkingInterval.count());
+  if (m_defaultCongestionThreshold) {
+    totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::DefaultCongestionThreshold,
+                                                  *m_defaultCongestionThreshold);
+  }
+  if (m_baseCongestionMarkingInterval) {
+    totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::BaseCongestionMarkingInterval,
+                                                  m_baseCongestionMarkingInterval->count());
+  }
   totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::LinkType, m_linkType);
   totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::FacePersistency, m_facePersistency);
   totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::FaceScope, m_faceScope);
@@ -170,11 +172,11 @@
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::BaseCongestionMarkingInterval) {
-    m_baseCongestionMarkingInterval = time::nanoseconds(readNonNegativeInteger(*val));
+    m_baseCongestionMarkingInterval.emplace(readNonNegativeInteger(*val));
     ++val;
   }
   else {
-    BOOST_THROW_EXCEPTION(Error("missing required BaseCongestionMarkingInterval field"));
+    m_baseCongestionMarkingInterval = nullopt;
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::DefaultCongestionThreshold) {
@@ -182,7 +184,7 @@
     ++val;
   }
   else {
-    BOOST_THROW_EXCEPTION(Error("missing required DefaultCongestionThreshold field"));
+    m_defaultCongestionThreshold = nullopt;
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::NInInterests) {
@@ -283,6 +285,14 @@
 }
 
 FaceStatus&
+FaceStatus::unsetBaseCongestionMarkingInterval()
+{
+  m_wire.reset();
+  m_baseCongestionMarkingInterval = nullopt;
+  return *this;
+}
+
+FaceStatus&
 FaceStatus::setDefaultCongestionThreshold(uint64_t threshold)
 {
   m_wire.reset();
@@ -291,6 +301,14 @@
 }
 
 FaceStatus&
+FaceStatus::unsetDefaultCongestionThreshold()
+{
+  m_wire.reset();
+  m_defaultCongestionThreshold = nullopt;
+  return *this;
+}
+
+FaceStatus&
 FaceStatus::setNInInterests(uint64_t nInInterests)
 {
   m_wire.reset();
@@ -366,8 +384,12 @@
       a.getFlags() == b.getFlags() &&
       a.hasExpirationPeriod() == b.hasExpirationPeriod() &&
       (!a.hasExpirationPeriod() || a.getExpirationPeriod() == b.getExpirationPeriod()) &&
-      a.getBaseCongestionMarkingInterval() == b.getBaseCongestionMarkingInterval() &&
-      a.getDefaultCongestionThreshold() == b.getDefaultCongestionThreshold() &&
+      a.hasBaseCongestionMarkingInterval() == b.hasBaseCongestionMarkingInterval() &&
+      (!a.hasBaseCongestionMarkingInterval() ||
+       a.getBaseCongestionMarkingInterval() == b.getBaseCongestionMarkingInterval()) &&
+      a.hasDefaultCongestionThreshold() == b.hasDefaultCongestionThreshold() &&
+      (!a.hasDefaultCongestionThreshold() ||
+       a.getDefaultCongestionThreshold() == b.getDefaultCongestionThreshold()) &&
       a.getNInInterests() == b.getNInInterests() &&
       a.getNInData() == b.getNInData() &&
       a.getNInNacks() == b.getNInNacks() &&
@@ -394,10 +416,17 @@
 
   os << "     FaceScope: " << status.getFaceScope() << ",\n"
      << "     FacePersistency: " << status.getFacePersistency() << ",\n"
-     << "     LinkType: " << status.getLinkType() << ",\n"
-     << "     BaseCongestionMarkingInterval: " << status.getBaseCongestionMarkingInterval() << ",\n"
-     << "     DefaultCongestionThreshold: " << status.getDefaultCongestionThreshold() << " bytes,\n"
-     << "     Flags: " << AsHex{status.getFlags()} << ",\n"
+     << "     LinkType: " << status.getLinkType() << ",\n";
+
+  if (status.hasBaseCongestionMarkingInterval()) {
+    os << "     BaseCongestionMarkingInterval: " << status.getBaseCongestionMarkingInterval() << ",\n";
+  }
+
+  if (status.hasDefaultCongestionThreshold()) {
+    os << "     DefaultCongestionThreshold: " << status.getDefaultCongestionThreshold() << " bytes,\n";
+  }
+
+  os << "     Flags: " << AsHex{status.getFlags()} << ",\n"
      << "     Counters: {Interests: {in: " << status.getNInInterests() << ", "
      << "out: " << status.getNOutInterests() << "},\n"
      << "                Data: {in: " << status.getNInData() << ", "
diff --git a/src/mgmt/nfd/face-status.hpp b/src/mgmt/nfd/face-status.hpp
index 7835dba..30a97f5 100644
--- a/src/mgmt/nfd/face-status.hpp
+++ b/src/mgmt/nfd/face-status.hpp
@@ -77,21 +77,38 @@
   FaceStatus&
   unsetExpirationPeriod();
 
+  bool
+  hasBaseCongestionMarkingInterval() const
+  {
+    return !!m_baseCongestionMarkingInterval;
+  }
+
   time::nanoseconds
   getBaseCongestionMarkingInterval() const
   {
-    return m_baseCongestionMarkingInterval;
+    BOOST_ASSERT(hasBaseCongestionMarkingInterval());
+    return *m_baseCongestionMarkingInterval;
   }
 
   FaceStatus&
   setBaseCongestionMarkingInterval(time::nanoseconds interval);
 
+  FaceStatus&
+  unsetBaseCongestionMarkingInterval();
+
+  bool
+  hasDefaultCongestionThreshold() const
+  {
+    return !!m_defaultCongestionThreshold;
+  }
+
   /** \brief get default congestion threshold (measured in bytes)
    */
   uint64_t
   getDefaultCongestionThreshold() const
   {
-    return m_defaultCongestionThreshold;
+    BOOST_ASSERT(hasDefaultCongestionThreshold());
+    return *m_defaultCongestionThreshold;
   }
 
   /** \brief set default congestion threshold (measured in bytes)
@@ -99,6 +116,9 @@
   FaceStatus&
   setDefaultCongestionThreshold(uint64_t threshold);
 
+  FaceStatus&
+  unsetDefaultCongestionThreshold();
+
   uint64_t
   getNInInterests() const
   {
@@ -173,8 +193,8 @@
 
 private:
   optional<time::milliseconds> m_expirationPeriod;
-  time::nanoseconds m_baseCongestionMarkingInterval;
-  uint64_t m_defaultCongestionThreshold;
+  optional<time::nanoseconds> m_baseCongestionMarkingInterval;
+  optional<uint64_t> m_defaultCongestionThreshold;
   uint64_t m_nInInterests;
   uint64_t m_nInData;
   uint64_t m_nInNacks;
diff --git a/tests/unit-tests/mgmt/nfd/controller.t.cpp b/tests/unit-tests/mgmt/nfd/controller.t.cpp
index e80f7ea..e9a3c4f 100644
--- a/tests/unit-tests/mgmt/nfd/controller.t.cpp
+++ b/tests/unit-tests/mgmt/nfd/controller.t.cpp
@@ -76,9 +76,7 @@
       .setUri("tcp4://192.0.2.1:6363")
       .setLocalUri("tcp4://192.0.2.2:10847")
       .setFacePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT)
-      .setFlags(0x7)
-      .setBaseCongestionMarkingInterval(12_ns)
-      .setDefaultCongestionThreshold(10);
+      .setFlags(0x7);
   return resp;
 }
 
diff --git a/tests/unit-tests/mgmt/nfd/face-status.t.cpp b/tests/unit-tests/mgmt/nfd/face-status.t.cpp
index 0f16a12..3cae12a 100644
--- a/tests/unit-tests/mgmt/nfd/face-status.t.cpp
+++ b/tests/unit-tests/mgmt/nfd/face-status.t.cpp
@@ -109,8 +109,6 @@
                     "     FaceScope: non-local,\n"
                     "     FacePersistency: persistent,\n"
                     "     LinkType: point-to-point,\n"
-                    "     BaseCongestionMarkingInterval: 0 nanoseconds,\n"
-                    "     DefaultCongestionThreshold: 0 bytes,\n"
                     "     Flags: 0x0,\n"
                     "     Counters: {Interests: {in: 0, out: 0},\n"
                     "                Data: {in: 0, out: 0},\n"