mgmt+tools: allow MTU overrides on existing faces

refs #5056

Change-Id: I464a0c68773290bf1cfd0bf2afc4344e79fbb614
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index fd5f3aa..a6ff3df 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -117,7 +117,7 @@
     faceParams.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
   }
   if (parameters.hasMtu()) {
-    // Cap this value at the maximum representable value in an ssize_t
+    // The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
     faceParams.mtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
   }
   faceParams.wantLocalFields = parameters.hasFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED) &&
@@ -167,6 +167,7 @@
   ControlParameters params;
   params.setFaceId(face.getId())
         .setFacePersistency(face.getPersistency());
+  copyMtu(face, params);
 
   auto linkService = dynamic_cast<face::GenericLinkService*>(face.getLinkService());
   if (linkService != nullptr) {
@@ -188,8 +189,6 @@
   params.setUri(face.getRemoteUri().toString())
         .setLocalUri(face.getLocalUri().toString());
 
-  copyMtu(face, params);
-
   return params;
 }
 
@@ -244,6 +243,11 @@
     options.defaultCongestionThreshold = parameters.getDefaultCongestionThreshold();
   }
 
+  if (parameters.hasMtu()) {
+    // The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
+    options.overrideMtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), parameters.getMtu());
+  }
+
   linkService->setOptions(options);
 }
 
@@ -293,6 +297,19 @@
     }
   }
 
+  // check whether the requested MTU override is valid (if it's present)
+  if (parameters.hasMtu()) {
+    auto mtu = parameters.getMtu();
+    // The face system limits MTUs to ssize_t, but the management protocol uses uint64_t
+    auto actualMtu = std::min<uint64_t>(std::numeric_limits<ssize_t>::max(), mtu);
+    auto linkService = dynamic_cast<face::GenericLinkService*>(face->getLinkService());
+    if (linkService == nullptr || !linkService->canOverrideMtuTo(actualMtu)) {
+      NFD_LOG_TRACE("cannot override face MTU to " << mtu);
+      areParamsValid = false;
+      response.setMtu(mtu);
+    }
+  }
+
   if (!areParamsValid) {
     done(ControlResponse(409, "Invalid properties specified").setBody(response.wireEncode()));
     return;