mgmt: refactor management modules to conform to NFD Management Protocol

Refactor management protocol specific option types to ControlParameters
Add control parameter field enforcement
Add missing control response "success" message bodies
Update fib management protocol response codes and behavior
Merge local control header manager into face manager
Refactor references of nfd::LocalControlHeaderFeature enum to ndn::nfd::LocalControlFeature
Remove "control-header" privilege from default configuration

refs: #1397, #1399, #1400

Change-Id: Id042daf00b3cee1f1c7fa38d2e4a4ff6d95c15c6
diff --git a/daemon/face/local-face.hpp b/daemon/face/local-face.hpp
index 7023efb..d16a64f 100644
--- a/daemon/face/local-face.hpp
+++ b/daemon/face/local-face.hpp
@@ -8,48 +8,50 @@
 #define NFD_FACE_LOCAL_FACE_HPP
 
 #include "face.hpp"
+#include <ndn-cpp-dev/management/nfd-control-parameters.hpp>
 
 namespace nfd {
 
-/* \brief indicates a feature in LocalControlHeader
- */
-enum LocalControlHeaderFeature
-{
-  /// any feature
-  LOCAL_CONTROL_HEADER_FEATURE_ANY,
-  /// in-faceid
-  LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID,
-  /// out-faceid
-  LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID,
-  /// upper bound of enum
-  LOCAL_CONTROL_HEADER_FEATURE_MAX
-};
-
+using ndn::nfd::LocalControlFeature;
+using ndn::nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID;
+using ndn::nfd::LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID;
 
 /** \brief represents a face
  */
 class LocalFace : public Face
 {
 public:
+
   explicit
   LocalFace(const FaceUri& uri);
 
-  /** \brief get whether a LocalControlHeader feature is enabled
+  /** \brief get whether any LocalControlHeader feature is enabled
    *
-   *  \param feature The feature. Cannot be LOCAL_CONTROL_HEADER_FEATURE_MAX
-   *  LOCAL_CONTROL_HEADER_FEATURE_ANY returns true if any feature is enabled.
+   * \returns true if any feature is enabled.
    */
   bool
-  isLocalControlHeaderEnabled(LocalControlHeaderFeature feature =
-                              LOCAL_CONTROL_HEADER_FEATURE_ANY) const;
+  isLocalControlHeaderEnabled() const;
+
+  /** \brief get whether a specific LocalControlHeader feature is enabled
+   *
+   *  \param feature The feature.
+   *  \returns true if the specified feature is enabled.
+   */
+  bool
+  isLocalControlHeaderEnabled(LocalControlFeature feature) const;
 
   /** \brief enable or disable a LocalControlHeader feature
    *
-   *  \param feature The feature. Cannot be LOCAL_CONTROL_HEADER_FEATURE_ANY
-   *                                     or LOCAL_CONTROL_HEADER_FEATURE_MAX
+   *  \param feature The feature. Cannot be LOCAL_CONTROL_FEATURE_ANY
+   *                                     or LOCAL_CONTROL_FEATURE_MAX
    */
   void
-  setLocalControlHeaderFeature(LocalControlHeaderFeature feature, bool enabled = true);
+  setLocalControlHeaderFeature(LocalControlFeature feature, bool enabled = true);
+
+public:
+
+  static const size_t LOCAL_CONTROL_FEATURE_MAX = 3; /// upper bound of LocalControlFeature enum
+  static const size_t LOCAL_CONTROL_FEATURE_ANY = 0; /// any feature
 
 protected:
   // statically overridden from Face
@@ -84,26 +86,31 @@
 inline
 LocalFace::LocalFace(const FaceUri& uri)
   : Face(uri, true)
-  , m_localControlHeaderFeatures(LOCAL_CONTROL_HEADER_FEATURE_MAX)
+  , m_localControlHeaderFeatures(LocalFace::LOCAL_CONTROL_FEATURE_MAX)
 {
 }
 
 inline bool
-LocalFace::isLocalControlHeaderEnabled(LocalControlHeaderFeature feature) const
+LocalFace::isLocalControlHeaderEnabled() const
 {
-  BOOST_ASSERT(feature < m_localControlHeaderFeatures.size());
+  return m_localControlHeaderFeatures[LOCAL_CONTROL_FEATURE_ANY];
+}
+
+inline bool
+LocalFace::isLocalControlHeaderEnabled(LocalControlFeature feature) const
+{
+  BOOST_ASSERT(0 < feature && feature < m_localControlHeaderFeatures.size());
   return m_localControlHeaderFeatures[feature];
 }
 
 inline void
-LocalFace::setLocalControlHeaderFeature(LocalControlHeaderFeature feature, bool enabled/* = true*/)
+LocalFace::setLocalControlHeaderFeature(LocalControlFeature feature, bool enabled/* = true*/)
 {
-  BOOST_ASSERT(feature > LOCAL_CONTROL_HEADER_FEATURE_ANY &&
-               feature < m_localControlHeaderFeatures.size());
+  BOOST_ASSERT(0 < feature && feature < m_localControlHeaderFeatures.size());
+
   m_localControlHeaderFeatures[feature] = enabled;
 
-  BOOST_STATIC_ASSERT(LOCAL_CONTROL_HEADER_FEATURE_ANY == 0);
-  m_localControlHeaderFeatures[LOCAL_CONTROL_HEADER_FEATURE_ANY] =
+  m_localControlHeaderFeatures[LOCAL_CONTROL_FEATURE_ANY] =
     std::find(m_localControlHeaderFeatures.begin() + 1,
               m_localControlHeaderFeatures.end(), true) <
               m_localControlHeaderFeatures.end();
@@ -127,7 +134,7 @@
         {
           i->getLocalControlHeader().wireDecode(element,
             false,
-            this->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
+            this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
         }
 
       this->onReceiveInterest(*i);
@@ -162,7 +169,7 @@
   if (!this->isLocalControlHeaderEnabled())
     return true;
 
-  return header.empty(this->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID),
+  return header.empty(this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
                       false);
 }
 
@@ -171,7 +178,7 @@
 LocalFace::filterAndEncodeLocalControlHeader(const Packet& packet)
 {
   return packet.getLocalControlHeader().wireEncode(packet,
-           this->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID),
+           this->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
            false);
 }
 
diff --git a/daemon/main.cpp b/daemon/main.cpp
index 8abdba6..44880b2 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -10,7 +10,6 @@
 #include "mgmt/internal-face.hpp"
 #include "mgmt/fib-manager.hpp"
 #include "mgmt/face-manager.hpp"
-#include "mgmt/local-control-header-manager.hpp"
 #include "mgmt/strategy-choice-manager.hpp"
 #include "mgmt/status-server.hpp"
 #include "mgmt/config-file.hpp"
@@ -31,7 +30,6 @@
 static Forwarder* g_forwarder;
 static FibManager* g_fibManager;
 static FaceManager* g_faceManager;
-static LocalControlHeaderManager* g_localControlHeaderManager;
 static StrategyChoiceManager* g_strategyChoiceManager;
 static StatusServer* g_statusServer;
 static shared_ptr<InternalFace> g_internalFace;
@@ -100,10 +98,6 @@
   g_faceManager = new FaceManager(g_forwarder->getFaceTable(), g_internalFace);
   g_faceManager->setConfigFile(config);
 
-  g_localControlHeaderManager =
-    new LocalControlHeaderManager(bind(&Forwarder::getFace, g_forwarder, _1),
-                                  g_internalFace);
-
   g_strategyChoiceManager = new StrategyChoiceManager(g_forwarder->getStrategyChoice(),
                                                       g_internalFace);
 
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 4028ad5..ea92898 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -31,7 +31,7 @@
 const size_t FaceManager::COMMAND_UNSIGNED_NCOMPS =
   FaceManager::COMMAND_PREFIX.size() +
   1 + // verb
-  1;  // verb options
+  1;  // verb parameters
 
 const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
   FaceManager::COMMAND_UNSIGNED_NCOMPS +
@@ -40,14 +40,24 @@
 const FaceManager::SignedVerbAndProcessor FaceManager::SIGNED_COMMAND_VERBS[] =
   {
     SignedVerbAndProcessor(
-                     Name::Component("create"),
-                     &FaceManager::createFace
-                     ),
+                           Name::Component("create"),
+                           &FaceManager::createFace
+                           ),
 
     SignedVerbAndProcessor(
-                     Name::Component("destroy"),
-                     &FaceManager::destroyFace
-                     ),
+                           Name::Component("destroy"),
+                           &FaceManager::destroyFace
+                           ),
+
+    SignedVerbAndProcessor(
+                           Name::Component("enable-local-control"),
+                           &FaceManager::enableLocalControl
+                           ),
+
+    SignedVerbAndProcessor(
+                           Name::Component("disable-local-control"),
+                           &FaceManager::disableLocalControl
+                           ),
   };
 
 const FaceManager::UnsignedVerbAndProcessor FaceManager::UNSIGNED_COMMAND_VERBS[] =
@@ -75,11 +85,11 @@
   , m_statusPublisher(m_faceTable, m_face, LIST_COMMAND_PREFIX)
   , m_notificationStream(m_face, EVENTS_COMMAND_PREFIX)
   , m_signedVerbDispatch(SIGNED_COMMAND_VERBS,
-                   SIGNED_COMMAND_VERBS +
-                   (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
+                         SIGNED_COMMAND_VERBS +
+                         (sizeof(SIGNED_COMMAND_VERBS) / sizeof(SignedVerbAndProcessor)))
   , m_unsignedVerbDispatch(UNSIGNED_COMMAND_VERBS,
-                   UNSIGNED_COMMAND_VERBS +
-                   (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
+                           UNSIGNED_COMMAND_VERBS +
+                           (sizeof(UNSIGNED_COMMAND_VERBS) / sizeof(UnsignedVerbAndProcessor)))
 
 {
   face->setInterestFilter("/localhost/nfd/faces",
@@ -528,7 +538,7 @@
       (unsignedVerbProcessor->second)(this, boost::cref(request));
     }
   else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
-      commandNComps < COMMAND_SIGNED_NCOMPS)
+           commandNComps < COMMAND_SIGNED_NCOMPS)
     {
       NFD_LOG_INFO("command result: unsigned verb: " << command);
       sendResponse(command, 401, "Signature required");
@@ -551,20 +561,21 @@
 FaceManager::onValidatedFaceRequest(const shared_ptr<const Interest>& request)
 {
   const Name& command = request->getName();
-  const Name::Component& verb = command.get(COMMAND_PREFIX.size());
+  const Name::Component& verb = command[COMMAND_PREFIX.size()];
+  const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
 
   SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find(verb);
   if (signedVerbProcessor != m_signedVerbDispatch.end())
     {
-      ndn::nfd::FaceManagementOptions options;
-      if (!extractOptions(*request, options))
+      ControlParameters parameters;
+      if (!extractParameters(parameterComponent, parameters))
         {
           sendResponse(command, 400, "Malformed command");
           return;
         }
 
       NFD_LOG_INFO("command result: processing verb: " << verb);
-      (signedVerbProcessor->second)(this, command, options);
+      (signedVerbProcessor->second)(this, *request, parameters);
     }
   else
     {
@@ -574,28 +585,6 @@
 
 }
 
-bool
-FaceManager::extractOptions(const Interest& request,
-                            ndn::nfd::FaceManagementOptions& extractedOptions)
-{
-  const Name& command = request.getName();
-  const size_t optionCompIndex =
-    COMMAND_PREFIX.size() + 1;
-
-  try
-    {
-      Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
-      extractedOptions.wireDecode(rawOptions);
-    }
-  catch (const ndn::Tlv::Error& e)
-    {
-      NFD_LOG_INFO("Bad command option parse: " << command);
-      return false;
-    }
-  NFD_LOG_DEBUG("Options parsed OK");
-  return true;
-}
-
 void
 FaceManager::addCreatedFaceToForwarder(const shared_ptr<Face>& newFace)
 {
@@ -606,16 +595,13 @@
 
 void
 FaceManager::onCreated(const Name& requestName,
-                       ndn::nfd::FaceManagementOptions& options,
+                       ControlParameters& parameters,
                        const shared_ptr<Face>& newFace)
 {
   addCreatedFaceToForwarder(newFace);
+  parameters.setFaceId(newFace->getId());
 
-  options.setFaceId(newFace->getId());
-
-  ndn::nfd::ControlResponse response;
-  setResponse(response, 200, "Success", options.wireEncode());
-  sendResponse(requestName, response);
+  sendResponse(requestName, 200, "Success", parameters.wireEncode());
 }
 
 void
@@ -626,11 +612,12 @@
 }
 
 void
-FaceManager::createFace(const Name& requestName,
-                        ndn::nfd::FaceManagementOptions& options)
+FaceManager::createFace(const Interest& request,
+                        ControlParameters& parameters)
 {
+  const Name& requestName = request.getName();
   FaceUri uri;
-  if (!uri.parse(options.getUri()))
+  if (!parameters.hasUri() || !uri.parse(parameters.getUri()))
     {
       sendResponse(requestName, 400, "Malformed command");
       return;
@@ -644,24 +631,29 @@
     }
 
   factory->second->createFace(uri,
-                              bind(&FaceManager::onCreated, this, requestName, options, _1),
+                              bind(&FaceManager::onCreated, this, requestName, parameters, _1),
                               bind(&FaceManager::onConnectFailed, this, requestName, _1));
 }
 
 
 void
-FaceManager::destroyFace(const Name& requestName,
-                         ndn::nfd::FaceManagementOptions& options)
+FaceManager::destroyFace(const Interest& request,
+                         ControlParameters& parameters)
 {
-  shared_ptr<Face> target = m_faceTable.get(options.getFaceId());
+  const Name& requestName = request.getName();
+  if (!parameters.hasFaceId())
+    {
+      sendResponse(requestName, 400, "Malformed command");
+      return;
+    }
+
+  shared_ptr<Face> target = m_faceTable.get(parameters.getFaceId());
   if (static_cast<bool>(target))
     {
       target->close();
     }
 
-  ndn::nfd::ControlResponse response;
-  setResponse(response, 200, "Success", options.wireEncode());
-  sendResponse(requestName, response);
+  sendResponse(requestName, 200, "Success", parameters.wireEncode());
 }
 
 void
@@ -689,6 +681,70 @@
 }
 
 
+bool
+FaceManager::validateLocalControlParameters(const Interest& request,
+                                            ControlParameters& parameters,
+                                            shared_ptr<LocalFace>& outFace,
+                                            LocalControlFeature& outFeature)
+{
+  if (!parameters.hasLocalControlFeature() ||
+      (parameters.getLocalControlFeature() != LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID &&
+       parameters.getLocalControlFeature() != LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID))
+    {
+      NFD_LOG_INFO("command result: malformed");
+      sendResponse(request.getName(), 400, "Malformed command");
+      return false;
+    }
+
+  shared_ptr<Face> face = m_faceTable.get(request.getIncomingFaceId());
+
+  if (!static_cast<bool>(face))
+    {
+      NFD_LOG_INFO("command result: faceid " << parameters.getFaceId() << " not found");
+      sendResponse(request.getName(), 410, "Requested face not found");
+      return false;
+    }
+  else if (!face->isLocal())
+    {
+      NFD_LOG_INFO("command result: cannot enable local control on non-local faceid " << parameters.getFaceId());
+      sendResponse(request.getName(), 412, "Requested face is non-local");
+      return false;
+    }
+
+  outFace = dynamic_pointer_cast<LocalFace>(face);
+  outFeature = static_cast<LocalControlFeature>(parameters.getLocalControlFeature());
+
+  return true;
+}
+
+void
+FaceManager::enableLocalControl(const Interest& request,
+                                ControlParameters& parameters)
+{
+  shared_ptr<LocalFace> face;
+  LocalControlFeature feature;
+
+  if (validateLocalControlParameters(request, parameters, face, feature))
+    {
+      face->setLocalControlHeaderFeature(feature, true);
+      sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
+    }
+}
+
+void
+FaceManager::disableLocalControl(const Interest& request,
+                                 ControlParameters& parameters)
+{
+  shared_ptr<LocalFace> face;
+  LocalControlFeature feature;
+
+  if (validateLocalControlParameters(request, parameters, face, feature))
+    {
+      face->setLocalControlHeaderFeature(feature, false);
+      sendResponse(request.getName(), 200, "Success", parameters.wireEncode());
+    }
+}
+
 void
 FaceManager::listFaces(const Interest& request)
 {
diff --git a/daemon/mgmt/face-manager.hpp b/daemon/mgmt/face-manager.hpp
index d489dff..7312bba 100644
--- a/daemon/mgmt/face-manager.hpp
+++ b/daemon/mgmt/face-manager.hpp
@@ -9,6 +9,7 @@
 
 #include "common.hpp"
 #include "face/face.hpp"
+#include "face/local-face.hpp"
 #include "mgmt/app-face.hpp"
 #include "mgmt/manager-base.hpp"
 #include "mgmt/config-file.hpp"
@@ -16,7 +17,7 @@
 #include "mgmt/notification-stream.hpp"
 #include "fw/face-table.hpp"
 
-#include <ndn-cpp-dev/management/nfd-face-management-options.hpp>
+#include <ndn-cpp-dev/management/nfd-control-parameters.hpp>
 #include <ndn-cpp-dev/management/nfd-control-response.hpp>
 
 namespace nfd {
@@ -25,6 +26,7 @@
 
 class ProtocolFactory;
 class NetworkInterfaceInfo;
+class LocalFace;
 
 class FaceManager : public ManagerBase
 {
@@ -63,26 +65,36 @@
   onValidatedFaceRequest(const shared_ptr<const Interest>& request);
 
   VIRTUAL_WITH_TESTS void
-  createFace(const Name& requestName,
-             ndn::nfd::FaceManagementOptions& options);
+  createFace(const Interest& request,
+             ControlParameters& parameters);
 
   VIRTUAL_WITH_TESTS void
-  destroyFace(const Name& requestName,
-              ndn::nfd::FaceManagementOptions& options);
+  destroyFace(const Interest& request,
+              ControlParameters& parameters);
+
+  VIRTUAL_WITH_TESTS bool
+  validateLocalControlParameters(const Interest& request,
+                                 ControlParameters& parameters,
+                                 shared_ptr<LocalFace>& outFace,
+                                 LocalControlFeature& outFeature);
+
+  VIRTUAL_WITH_TESTS void
+  enableLocalControl(const Interest& request,
+                     ControlParameters& parambeters);
+
+  VIRTUAL_WITH_TESTS void
+  disableLocalControl(const Interest& request,
+                      ControlParameters& parameters);
 
   void
   ignoreUnsignedVerb(const Interest& request);
 
-  bool
-  extractOptions(const Interest& request,
-                 ndn::nfd::FaceManagementOptions& extractedOptions);
-
   void
   addCreatedFaceToForwarder(const shared_ptr<Face>& newFace);
 
   void
   onCreated(const Name& requestName,
-            ndn::nfd::FaceManagementOptions& options,
+            ControlParameters& parameters,
             const shared_ptr<Face>& newFace);
 
   void
@@ -131,8 +143,8 @@
   NotificationStream m_notificationStream;
 
   typedef function<void(FaceManager*,
-                        const Name&,
-                        ndn::nfd::FaceManagementOptions&)> SignedVerbProcessor;
+                        const Interest&,
+                        ControlParameters&)> SignedVerbProcessor;
 
   typedef std::map<Name::Component, SignedVerbProcessor> SignedVerbDispatchTable;
   typedef std::pair<Name::Component, SignedVerbProcessor> SignedVerbAndProcessor;
@@ -149,7 +161,7 @@
   static const Name COMMAND_PREFIX; // /localhost/nfd/faces
 
   // number of components in an invalid signed command (i.e. should be signed, but isn't)
-  // (/localhost/nfd/faces + verb + options) = 5
+  // (/localhost/nfd/faces + verb + parameters) = 5
   static const size_t COMMAND_UNSIGNED_NCOMPS;
 
   // number of components in a valid signed command.
diff --git a/daemon/mgmt/fib-manager.cpp b/daemon/mgmt/fib-manager.cpp
index 9ce7a6f..b1b869b 100644
--- a/daemon/mgmt/fib-manager.cpp
+++ b/daemon/mgmt/fib-manager.cpp
@@ -22,7 +22,7 @@
 const size_t FibManager::COMMAND_UNSIGNED_NCOMPS =
   FibManager::COMMAND_PREFIX.size() +
   1 + // verb
-  1;  // verb options
+  1;  // verb parameters
 
 const size_t FibManager::COMMAND_SIGNED_NCOMPS =
   FibManager::COMMAND_UNSIGNED_NCOMPS +
@@ -92,13 +92,13 @@
       (unsignedVerbProcessor->second)(this, boost::cref(request));
     }
   else if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
-      commandNComps < COMMAND_SIGNED_NCOMPS)
+           commandNComps < COMMAND_SIGNED_NCOMPS)
     {
       NFD_LOG_INFO("command result: unsigned verb: " << command);
       sendResponse(command, 401, "Signature required");
     }
   else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
-      !COMMAND_PREFIX.isPrefixOf(command))
+           !COMMAND_PREFIX.isPrefixOf(command))
     {
       NFD_LOG_INFO("command result: malformed");
       sendResponse(command, 400, "Malformed command");
@@ -115,22 +115,30 @@
 FibManager::onValidatedFibRequest(const shared_ptr<const Interest>& request)
 {
   const Name& command = request->getName();
-  const Name::Component& verb = command.get(COMMAND_PREFIX.size());
+  const Name::Component& verb = command[COMMAND_PREFIX.size()];
+  const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
 
   SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find (verb);
   if (signedVerbProcessor != m_signedVerbDispatch.end())
     {
-      FibManagementOptions options;
-      if (!extractOptions(*request, options))
+      ControlParameters parameters;
+      if (!extractParameters(parameterComponent, parameters) ||
+          !parameters.hasName() ||
+          !parameters.hasFaceId())
         {
           NFD_LOG_INFO("command result: malformed verb: " << verb);
           sendResponse(command, 400, "Malformed command");
           return;
         }
 
+      if (parameters.getFaceId() == 0)
+        {
+          parameters.setFaceId(request->getIncomingFaceId());
+        }
+
       NFD_LOG_INFO("command result: processing verb: " << verb);
       ControlResponse response;
-      (signedVerbProcessor->second)(this, options, response);
+      (signedVerbProcessor->second)(this, parameters, response);
       sendResponse(command, response);
     }
   else
@@ -140,98 +148,70 @@
     }
 }
 
-bool
-FibManager::extractOptions(const Interest& request,
-                           FibManagementOptions& extractedOptions)
-{
-  const Name& command = request.getName();
-  const size_t optionCompIndex = COMMAND_PREFIX.size() + 1;
 
-  try
-    {
-      Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
-      extractedOptions.wireDecode(rawOptions);
-    }
-  catch (const ndn::Tlv::Error& e)
-    {
-      NFD_LOG_INFO("Bad command option parse: " << command);
-      return false;
-    }
-
-  if (extractedOptions.getFaceId() == 0)
-    {
-      extractedOptions.setFaceId(request.getIncomingFaceId());
-    }
-
-  NFD_LOG_DEBUG("Options parsed OK");
-  return true;
-}
 
 void
-FibManager::addNextHop(const FibManagementOptions& options,
+FibManager::addNextHop(ControlParameters& parameters,
                        ControlResponse& response)
 {
-  NFD_LOG_DEBUG("add-nexthop prefix: " << options.getName()
-                << " faceid: " << options.getFaceId()
-                << " cost: " << options.getCost());
+  if (!parameters.hasCost())
+    {
+      parameters.setCost(0);
+    }
 
-  shared_ptr<Face> nextHopFace = m_getFace(options.getFaceId());
+  const Name& prefix = parameters.getName();
+  FaceId faceId = parameters.getFaceId();
+  uint64_t cost = parameters.getCost();
+
+  NFD_LOG_DEBUG("add-nexthop prefix: " << prefix
+                << " faceid: " << faceId
+                << " cost: " << cost);
+
+  shared_ptr<Face> nextHopFace = m_getFace(faceId);
   if (static_cast<bool>(nextHopFace))
     {
-      shared_ptr<fib::Entry> entry = m_managedFib.insert(options.getName()).first;
+      shared_ptr<fib::Entry> entry = m_managedFib.insert(prefix).first;
 
-      entry->addNextHop(nextHopFace, options.getCost());
+      entry->addNextHop(nextHopFace, cost);
 
       NFD_LOG_INFO("add-nexthop result: OK"
-                   << " prefix:" << options.getName()
-                   << " faceid: " << options.getFaceId()
-                   << " cost: " << options.getCost());
-      setResponse(response, 200, "Success", options.wireEncode());
+                   << " prefix:" << prefix
+                   << " faceid: " << faceId
+                   << " cost: " << cost);
+
+      setResponse(response, 200, "Success", parameters.wireEncode());
     }
   else
     {
-      NFD_LOG_INFO("add-nexthop result: FAIL reason: unknown-faceid: " << options.getFaceId());
-      setResponse(response, 404, "Face not found");
+      NFD_LOG_INFO("add-nexthop result: FAIL reason: unknown-faceid: " << faceId);
+      setResponse(response, 410, "Face not found");
     }
 }
 
 void
-FibManager::removeNextHop(const FibManagementOptions& options,
+FibManager::removeNextHop(ControlParameters& parameters,
                           ControlResponse& response)
 {
-  NFD_LOG_DEBUG("remove-nexthop prefix: " << options.getName()
-                << " faceid: " << options.getFaceId());
+  NFD_LOG_DEBUG("remove-nexthop prefix: " << parameters.getName()
+                << " faceid: " << parameters.getFaceId());
 
-  shared_ptr<Face> faceToRemove = m_getFace(options.getFaceId());
+  shared_ptr<Face> faceToRemove = m_getFace(parameters.getFaceId());
   if (static_cast<bool>(faceToRemove))
     {
-      shared_ptr<fib::Entry> entry = m_managedFib.findExactMatch(options.getName());
+      shared_ptr<fib::Entry> entry = m_managedFib.findExactMatch(parameters.getName());
       if (static_cast<bool>(entry))
         {
           entry->removeNextHop(faceToRemove);
-          NFD_LOG_INFO("remove-nexthop result: OK prefix: " << options.getName()
-                       << " faceid: " << options.getFaceId());
+          NFD_LOG_INFO("remove-nexthop result: OK prefix: " << parameters.getName()
+                       << " faceid: " << parameters.getFaceId());
 
           if (!entry->hasNextHops())
             {
               m_managedFib.erase(*entry);
             }
-
-          setResponse(response, 200, "Success", options.wireEncode());
-        }
-      else
-        {
-          NFD_LOG_INFO("remove-nexthop result: FAIL reason: unknown-prefix: "
-                       << options.getName());
-          setResponse(response, 404, "Prefix not found");
         }
     }
-  else
-    {
-      NFD_LOG_INFO("remove-nexthop result: FAIL reason: unknown-faceid: "
-                   << options.getFaceId());
-      setResponse(response, 404, "Face not found");
-    }
+  setResponse(response, 200, "Success", parameters.wireEncode());
 }
 
 void
diff --git a/daemon/mgmt/fib-manager.hpp b/daemon/mgmt/fib-manager.hpp
index 10b4fb2..5ce6e86 100644
--- a/daemon/mgmt/fib-manager.hpp
+++ b/daemon/mgmt/fib-manager.hpp
@@ -14,12 +14,8 @@
 #include "mgmt/manager-base.hpp"
 #include "mgmt/fib-enumeration-publisher.hpp"
 
-#include <ndn-cpp-dev/management/nfd-fib-management-options.hpp>
-
 namespace nfd {
 
-using ndn::nfd::FibManagementOptions;
-
 class Forwarder;
 class Fib;
 
@@ -45,29 +41,16 @@
   onValidatedFibRequest(const shared_ptr<const Interest>& request);
 
   void
-  insertEntry(const FibManagementOptions& options,
-              ControlResponse& response);
-
-
-  void
-  deleteEntry(const FibManagementOptions& options,
-              ControlResponse& response);
-
-  void
-  addNextHop(const FibManagementOptions& options,
+  addNextHop(ControlParameters& parameters,
              ControlResponse& response);
 
   void
-  removeNextHop(const FibManagementOptions& options,
+  removeNextHop(ControlParameters& parameters,
                 ControlResponse& response);
 
   void
   listEntries(const Interest& request);
 
-  bool
-  extractOptions(const Interest& request,
-                 FibManagementOptions& extractedOptions);
-
 private:
 
   Fib& m_managedFib;
@@ -75,7 +58,7 @@
   FibEnumerationPublisher m_fibEnumerationPublisher;
 
   typedef function<void(FibManager*,
-                        const FibManagementOptions&,
+                        ControlParameters&,
                         ControlResponse&)> SignedVerbProcessor;
 
   typedef std::map<Name::Component, SignedVerbProcessor> SignedVerbDispatchTable;
@@ -94,7 +77,7 @@
   static const Name COMMAND_PREFIX; // /localhost/nfd/fib
 
   // number of components in an invalid, but not malformed, unsigned command.
-  // (/localhost/nfd/fib + verb + options) = 5
+  // (/localhost/nfd/fib + verb + parameters) = 5
   static const size_t COMMAND_UNSIGNED_NCOMPS;
 
   // number of components in a valid signed Interest.
diff --git a/daemon/mgmt/local-control-header-manager.cpp b/daemon/mgmt/local-control-header-manager.cpp
deleted file mode 100644
index aae1d0c..0000000
--- a/daemon/mgmt/local-control-header-manager.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (C) 2014 Named Data Networking Project
- * See COPYING for copyright and distribution information.
- */
-
-#include "local-control-header-manager.hpp"
-#include "face/local-face.hpp"
-#include "mgmt/internal-face.hpp"
-
-namespace nfd {
-
-NFD_LOG_INIT("LocalControlHeaderManager");
-
-const Name LocalControlHeaderManager::COMMAND_PREFIX = "/localhost/nfd/control-header";
-
-const size_t LocalControlHeaderManager::COMMAND_UNSIGNED_NCOMPS =
-  LocalControlHeaderManager::COMMAND_PREFIX.size() +
-  1 + // control-module
-  1; // verb
-
-const size_t LocalControlHeaderManager::COMMAND_SIGNED_NCOMPS =
-  LocalControlHeaderManager::COMMAND_UNSIGNED_NCOMPS +
-  4; // (timestamp, nonce, signed info tlv, signature tlv)
-
-
-LocalControlHeaderManager::LocalControlHeaderManager(function<shared_ptr<Face>(FaceId)> getFace,
-                                                     shared_ptr<InternalFace> face)
-  : ManagerBase(face, CONTROL_HEADER_PRIVILEGE),
-    m_getFace(getFace)
-{
-  face->setInterestFilter("/localhost/nfd/control-header",
-                          bind(&LocalControlHeaderManager::onLocalControlHeaderRequest, this, _2));
-}
-
-
-
-void
-LocalControlHeaderManager::onLocalControlHeaderRequest(const Interest& request)
-{
-  const Name& command = request.getName();
-  const size_t commandNComps = command.size();
-
-  if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
-      commandNComps < COMMAND_SIGNED_NCOMPS)
-    {
-      NFD_LOG_INFO("command result: unsigned verb: " << command);
-      sendResponse(command, 401, "Signature required");
-
-      return;
-    }
-  else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
-      !COMMAND_PREFIX.isPrefixOf(command))
-    {
-      NFD_LOG_INFO("command result: malformed");
-      sendResponse(command, 400, "Malformed command");
-      return;
-    }
-
-  validate(request,
-             bind(&LocalControlHeaderManager::onCommandValidated,
-                    this, _1),
-             bind(&ManagerBase::onCommandValidationFailed,
-                    this, _1, _2));
-
-
-}
-
-void
-LocalControlHeaderManager::onCommandValidated(const shared_ptr<const Interest>& command)
-{
-  static const Name::Component MODULE_IN_FACEID("in-faceid");
-  static const Name::Component MODULE_NEXTHOP_FACEID("nexthop-faceid");
-  static const Name::Component VERB_ENABLE("enable");
-  static const Name::Component VERB_DISABLE("disable");
-
-  shared_ptr<LocalFace> face =
-    dynamic_pointer_cast<LocalFace>(m_getFace(command->getIncomingFaceId()));
-
-  if (!static_cast<bool>(face))
-    {
-      NFD_LOG_INFO("command result: command to enable control header on non-local face");
-      sendResponse(command->getName(), 400, "Command not supported on the requested face");
-      return;
-    }
-
-  const Name& commandName = command->getName();
-  const Name::Component& module = commandName[COMMAND_PREFIX.size()];
-  const Name::Component& verb = commandName[COMMAND_PREFIX.size() + 1];
-
-  if (module == MODULE_IN_FACEID)
-    {
-      if (verb == VERB_ENABLE)
-        {
-          face->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID, true);
-          sendResponse(commandName, 200, "Success");
-        }
-      else if (verb == VERB_DISABLE)
-        {
-          face->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID, false);
-          sendResponse(commandName, 200, "Success");
-        }
-      else
-        {
-          NFD_LOG_INFO("command result: unsupported verb: " << verb);
-          sendResponse(commandName, 501, "Unsupported");
-        }
-    }
-  else if (module == MODULE_NEXTHOP_FACEID)
-    {
-      if (verb == VERB_ENABLE)
-        {
-          face->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID, true);
-          sendResponse(commandName, 200, "Success");
-        }
-      else if (verb == VERB_DISABLE)
-        {
-          face->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID, false);
-          sendResponse(commandName, 200, "Success");
-        }
-      else
-        {
-          NFD_LOG_INFO("command result: unsupported verb: " << verb);
-          sendResponse(commandName, 501, "Unsupported");
-        }
-    }
-  else
-    {
-      NFD_LOG_INFO("command result: unsupported module: " << module);
-      sendResponse(commandName, 501, "Unsupported");
-    }
-}
-
-} // namespace nfd
-
diff --git a/daemon/mgmt/local-control-header-manager.hpp b/daemon/mgmt/local-control-header-manager.hpp
deleted file mode 100644
index 0aa5d63..0000000
--- a/daemon/mgmt/local-control-header-manager.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (C) 2014 Named Data Networking Project
- * See COPYING for copyright and distribution information.
- */
-
-#ifndef NFD_MGMT_LOCAL_CONTROL_HEADER_MANAGER_HPP
-#define NFD_MGMT_LOCAL_CONTROL_HEADER_MANAGER_HPP
-
-#include "common.hpp"
-#include "face/face.hpp"
-#include "mgmt/app-face.hpp"
-#include "mgmt/manager-base.hpp"
-
-namespace nfd {
-
-const std::string CONTROL_HEADER_PRIVILEGE = "control-header"; // config file privilege name
-
-class LocalControlHeaderManager : public ManagerBase
-{
-public:
-  LocalControlHeaderManager(function<shared_ptr<Face>(FaceId)> getFace,
-                            shared_ptr<InternalFace> face);
-
-  void
-  onLocalControlHeaderRequest(const Interest& request);
-
-  void
-  onCommandValidated(const shared_ptr<const Interest>& command);
-
-private:
-  function<shared_ptr<Face>(FaceId)> m_getFace;
-
-  static const Name COMMAND_PREFIX; // /localhost/nfd/control-header
-
-  // number of components in an invalid, but not malformed, unsigned command.
-  // (/localhost/nfd/control-header + control-module + verb) = 5
-  static const size_t COMMAND_UNSIGNED_NCOMPS;
-
-  // number of components in a valid signed Interest.
-  // UNSIGNED_NCOMPS + 4 command Interest components = 9
-  static const size_t COMMAND_SIGNED_NCOMPS;
-};
-
-} // namespace nfd
-
-#endif // NFD_MGMT_LOCAL_CONTROL_HEADER_MANAGER_HPP
-
-
-
diff --git a/daemon/mgmt/manager-base.cpp b/daemon/mgmt/manager-base.cpp
index ad26e53..af5fc37 100644
--- a/daemon/mgmt/manager-base.cpp
+++ b/daemon/mgmt/manager-base.cpp
@@ -21,6 +21,24 @@
 
 }
 
+bool
+ManagerBase::extractParameters(const Name::Component& parameterComponent,
+                               ControlParameters& extractedParameters)
+{
+  try
+    {
+      Block rawParameters = parameterComponent.blockFromValue();
+      extractedParameters.wireDecode(rawParameters);
+    }
+  catch (const ndn::Tlv::Error& e)
+    {
+      return false;
+    }
+
+  NFD_LOG_DEBUG("Parameters parsed OK");
+  return true;
+}
+
 void
 ManagerBase::sendResponse(const Name& name,
                           uint32_t code,
@@ -32,6 +50,17 @@
 
 void
 ManagerBase::sendResponse(const Name& name,
+                          uint32_t code,
+                          const std::string& text,
+                          const Block& body)
+{
+  ControlResponse response(code, text);
+  response.setBody(body);
+  sendResponse(name, response);
+}
+
+void
+ManagerBase::sendResponse(const Name& name,
                           const ControlResponse& response)
 {
   NFD_LOG_DEBUG("responding"
diff --git a/daemon/mgmt/manager-base.hpp b/daemon/mgmt/manager-base.hpp
index 9522812..46e34b6 100644
--- a/daemon/mgmt/manager-base.hpp
+++ b/daemon/mgmt/manager-base.hpp
@@ -8,15 +8,17 @@
 #define NFD_MGMT_MANAGER_BASE_HPP
 
 #include "common.hpp"
-#include <ndn-cpp-dev/management/nfd-control-response.hpp>
 
 #include "mgmt/command-validator.hpp"
 #include "mgmt/internal-face.hpp"
 
+#include <ndn-cpp-dev/management/nfd-control-response.hpp>
+#include <ndn-cpp-dev/management/nfd-control-parameters.hpp>
 
 namespace nfd {
 
 using ndn::nfd::ControlResponse;
+using ndn::nfd::ControlParameters;
 
 class InternalFace;
 
@@ -40,6 +42,10 @@
 
 protected:
 
+  static bool
+  extractParameters(const Name::Component& parameterComponent,
+                    ControlParameters& extractedParameters);
+
   void
   setResponse(ControlResponse& response,
               uint32_t code,
@@ -59,6 +65,12 @@
                uint32_t code,
                const std::string& text);
 
+  void
+  sendResponse(const Name& name,
+               uint32_t code,
+               const std::string& text,
+               const Block& body);
+
 PUBLIC_WITH_TESTS_ELSE_PROTECTED:
   void
   addInterestRule(const std::string& regex,
diff --git a/daemon/mgmt/strategy-choice-manager.cpp b/daemon/mgmt/strategy-choice-manager.cpp
index cd4dc5b..bbedd34 100644
--- a/daemon/mgmt/strategy-choice-manager.cpp
+++ b/daemon/mgmt/strategy-choice-manager.cpp
@@ -17,7 +17,7 @@
 const size_t StrategyChoiceManager::COMMAND_UNSIGNED_NCOMPS =
   StrategyChoiceManager::COMMAND_PREFIX.size() +
   1 + // verb
-  1;  // verb options
+  1;  // verb parameters
 
 const size_t StrategyChoiceManager::COMMAND_SIGNED_NCOMPS =
   StrategyChoiceManager::COMMAND_UNSIGNED_NCOMPS +
@@ -71,23 +71,24 @@
   static const Name::Component VERB_UNSET("unset");
 
   const Name& command = request->getName();
+  const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
 
-  ndn::nfd::StrategyChoiceOptions options;
-  if (!extractOptions(*request, options))
+  ControlParameters parameters;
+  if (!extractParameters(parameterComponent, parameters) || !parameters.hasName())
     {
       sendResponse(command, 400, "Malformed command");
       return;
     }
 
-  const Name::Component& verb = command.get(COMMAND_PREFIX.size());
+  const Name::Component& verb = command[COMMAND_PREFIX.size()];
   ControlResponse response;
   if (verb == VERB_SET)
     {
-      setStrategy(options, response);
+      setStrategy(parameters, response);
     }
   else if (verb == VERB_UNSET)
     {
-      unsetStrategy(options, response);
+      unsetStrategy(parameters, response);
     }
   else
     {
@@ -97,47 +98,30 @@
   sendResponse(command, response);
 }
 
-bool
-StrategyChoiceManager::extractOptions(const Interest& request,
-                                      ndn::nfd::StrategyChoiceOptions& extractedOptions)
-{
-  const Name& command = request.getName();
-  const size_t optionCompIndex =
-    COMMAND_PREFIX.size() + 1;
-
-  try
-    {
-      Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
-      extractedOptions.wireDecode(rawOptions);
-    }
-  catch (const ndn::Tlv::Error& e)
-    {
-      NFD_LOG_INFO("Bad command option parse: " << command);
-      return false;
-    }
-
-  NFD_LOG_DEBUG("Options parsed OK");
-  return true;
-}
-
 void
-StrategyChoiceManager::setStrategy(const ndn::nfd::StrategyChoiceOptions& options,
+StrategyChoiceManager::setStrategy(const ControlParameters& parameters,
                                    ControlResponse& response)
 {
-  const Name& prefix = options.getName();
-  const Name& selectedStrategy = options.getStrategy();
+  if (!parameters.hasStrategy())
+    {
+      setResponse(response, 400, "Malformed command");
+      return;
+    }
+
+  const Name& prefix = parameters.getName();
+  const Name& selectedStrategy = parameters.getStrategy();
 
   if (!m_strategyChoice.hasStrategy(selectedStrategy))
     {
       NFD_LOG_INFO("strategy-choice result: FAIL reason: unknown-strategy: "
-                   << options.getStrategy());
+                   << parameters.getStrategy());
       setResponse(response, 504, "Unsupported strategy");
       return;
     }
 
   if (m_strategyChoice.insert(prefix, selectedStrategy))
     {
-      setResponse(response, 200, "Success", options.wireEncode());
+      setResponse(response, 200, "Success", parameters.wireEncode());
     }
   else
     {
@@ -146,22 +130,22 @@
 }
 
 void
-StrategyChoiceManager::unsetStrategy(const ndn::nfd::StrategyChoiceOptions& options,
+StrategyChoiceManager::unsetStrategy(const ControlParameters& parameters,
                                      ControlResponse& response)
 {
   static const Name ROOT_PREFIX;
 
-  const Name& prefix = options.getName();
+  const Name& prefix = parameters.getName();
   if (prefix == ROOT_PREFIX)
     {
       NFD_LOG_INFO("strategy-choice result: FAIL reason: unknown-prefix: "
-                   << options.getName());
+                   << parameters.getName());
       setResponse(response, 403, "Cannot unset root prefix strategy");
       return;
     }
 
   m_strategyChoice.erase(prefix);
-  setResponse(response, 200, "Success", options.wireEncode());
+  setResponse(response, 200, "Success", parameters.wireEncode());
 }
 
 
diff --git a/daemon/mgmt/strategy-choice-manager.hpp b/daemon/mgmt/strategy-choice-manager.hpp
index 2232588..d884786 100644
--- a/daemon/mgmt/strategy-choice-manager.hpp
+++ b/daemon/mgmt/strategy-choice-manager.hpp
@@ -9,7 +9,7 @@
 
 #include "mgmt/manager-base.hpp"
 
-#include <ndn-cpp-dev/management/nfd-strategy-choice-options.hpp>
+#include <ndn-cpp-dev/management/nfd-control-parameters.hpp>
 
 namespace nfd {
 
@@ -33,18 +33,12 @@
   void
   onValidatedStrategyChoiceRequest(const shared_ptr<const Interest>& request);
 
-  bool
-  extractOptions(const Interest& request,
-                   ndn::nfd::StrategyChoiceOptions& extractedOptions);
-
-
-
   void
-  setStrategy(const ndn::nfd::StrategyChoiceOptions& options,
+  setStrategy(const ControlParameters& parameters,
               ControlResponse& response);
 
   void
-  unsetStrategy(const ndn::nfd::StrategyChoiceOptions& options,
+  unsetStrategy(const ControlParameters& parameters,
                 ControlResponse& response);
 private:
 
@@ -53,7 +47,7 @@
   static const Name COMMAND_PREFIX; // /localhost/nfd/strategy-choice
 
   // number of components in an invalid, but not malformed, unsigned command.
-  // (/localhost/nfd/strategy-choice + verb + options) = 5
+  // (/localhost/nfd/strategy-choice + verb + parameters) = 5
   static const size_t COMMAND_UNSIGNED_NCOMPS;
 
   // number of components in a valid signed Interest.
diff --git a/daemon/table/fib-nexthop.cpp b/daemon/table/fib-nexthop.cpp
index 6fec93f..8e068e6 100644
--- a/daemon/table/fib-nexthop.cpp
+++ b/daemon/table/fib-nexthop.cpp
@@ -26,12 +26,12 @@
 }
 
 void
-NextHop::setCost(uint32_t cost)
+NextHop::setCost(uint64_t cost)
 {
   m_cost = cost;
 }
 
-uint32_t
+uint64_t
 NextHop::getCost() const
 {
   return m_cost;
diff --git a/daemon/table/fib-nexthop.hpp b/daemon/table/fib-nexthop.hpp
index 72fa687..de29c0f 100644
--- a/daemon/table/fib-nexthop.hpp
+++ b/daemon/table/fib-nexthop.hpp
@@ -28,14 +28,14 @@
   getFace() const;
 
   void
-  setCost(uint32_t cost);
+  setCost(uint64_t cost);
 
-  uint32_t
+  uint64_t
   getCost() const;
 
 private:
   shared_ptr<Face> m_face;
-  uint32_t m_cost;
+  uint64_t m_cost;
 };
 
 } // namespace fib
diff --git a/nfd.conf.sample.in b/nfd.conf.sample.in
index 3bc3db5..3cbfc0f 100644
--- a/nfd.conf.sample.in
+++ b/nfd.conf.sample.in
@@ -103,7 +103,6 @@
     certfile keys/default.ndncert ; NDN identity certificate file
     privileges ; set of privileges granted to this identity
     {
-      control-header
       faces
       fib
       strategy-choice
diff --git a/tests/face/face.cpp b/tests/face/face.cpp
index d48ed70..1ad6f52 100644
--- a/tests/face/face.cpp
+++ b/tests/face/face.cpp
@@ -28,17 +28,16 @@
   
   BOOST_CHECK_EQUAL(face.isLocalControlHeaderEnabled(), false);
   
-  face.setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID, true);
+  face.setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID, true);
   BOOST_CHECK_EQUAL(face.isLocalControlHeaderEnabled(), true);
+  BOOST_CHECK_EQUAL(face.isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID), true);
   BOOST_CHECK_EQUAL(face.isLocalControlHeaderEnabled(
-                         LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID), true);
-  BOOST_CHECK_EQUAL(face.isLocalControlHeaderEnabled(
-                         LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID), false);
+                         LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID), false);
   
-  face.setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID, false);
+  face.setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID, false);
   BOOST_CHECK_EQUAL(face.isLocalControlHeaderEnabled(), false);
   BOOST_CHECK_EQUAL(face.isLocalControlHeaderEnabled(
-                         LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID), false);
+                         LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID), false);
 }
 
 BOOST_AUTO_TEST_CASE(Counters)
diff --git a/tests/face/unix-stream.cpp b/tests/face/unix-stream.cpp
index 285b85f..da474f6 100644
--- a/tests/face/unix-stream.cpp
+++ b/tests/face/unix-stream.cpp
@@ -328,17 +328,17 @@
   data1.setSignature(fakeSignature);
   data2.setSignature(fakeSignature);
 
-  m_face1->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID);
-  m_face1->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID);
+  m_face1->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
+  m_face1->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
 
-  BOOST_CHECK(m_face1->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-  BOOST_CHECK(m_face1->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
+  BOOST_CHECK(m_face1->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+  BOOST_CHECK(m_face1->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
 
-  m_face2->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID);
-  m_face2->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID);
+  m_face2->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
+  m_face2->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
 
-  BOOST_CHECK(m_face2->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-  BOOST_CHECK(m_face2->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
+  BOOST_CHECK(m_face2->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+  BOOST_CHECK(m_face2->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
 
   ////////////////////////////////////////////////////////
 
diff --git a/tests/fw/client-control-strategy.cpp b/tests/fw/client-control-strategy.cpp
index 51534a4..326bd77 100644
--- a/tests/fw/client-control-strategy.cpp
+++ b/tests/fw/client-control-strategy.cpp
@@ -25,7 +25,7 @@
   shared_ptr<DummyFace> face2 = make_shared<DummyFace>();
   shared_ptr<DummyFace> face3 = make_shared<DummyFace>();
   shared_ptr<DummyLocalFace> face4 = make_shared<DummyLocalFace>();
-  face4->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID);
+  face4->setLocalControlHeaderFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
   forwarder.addFace(face1);
   forwarder.addFace(face2);
   forwarder.addFace(face3);
diff --git a/tests/mgmt/face-manager.cpp b/tests/mgmt/face-manager.cpp
index 5a46097..9cfca66 100644
--- a/tests/mgmt/face-manager.cpp
+++ b/tests/mgmt/face-manager.cpp
@@ -672,14 +672,14 @@
 
 BOOST_AUTO_TEST_CASE(UnsignedCommand)
 {
-  ndn::nfd::FaceManagementOptions options;
-  options.setUri("tcp://127.0.0.1");
+  ControlParameters parameters;
+  parameters.setUri("tcp://127.0.0.1");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("create");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
 
@@ -694,14 +694,14 @@
 
 BOOST_FIXTURE_TEST_CASE(UnauthorizedCommand, UnauthorizedCommandFixture<FaceManagerFixture>)
 {
-  ndn::nfd::FaceManagementOptions options;
-  options.setUri("tcp://127.0.0.1");
+  ControlParameters parameters;
+  parameters.setUri("tcp://127.0.0.1");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("create");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -733,13 +733,13 @@
 
 BOOST_FIXTURE_TEST_CASE(UnsupportedCommand, AuthorizedCommandFixture<FaceManagerFixture>)
 {
-  ndn::nfd::FaceManagementOptions options;
+  ControlParameters parameters;
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("unsupported");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -768,15 +768,15 @@
   }
 
   virtual void
-  createFace(const Name& requestName,
-             ndn::nfd::FaceManagementOptions& options)
+  createFace(const Interest& request,
+             ControlParameters& parameters)
   {
     m_createFaceFired = true;
   }
 
   virtual void
-  destroyFace(const Name& requestName,
-              ndn::nfd::FaceManagementOptions& options)
+  destroyFace(const Interest& request,
+              ControlParameters& parameters)
   {
     m_destroyFaceFired = true;
   }
@@ -809,7 +809,7 @@
 {
   Name commandName("/localhost/nfd/faces");
   commandName.append("create");
-  commandName.append("NotReallyOptions");
+  commandName.append("NotReallyParameters");
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -826,14 +826,14 @@
 BOOST_FIXTURE_TEST_CASE(ValidatedFaceRequestCreateFace,
                         AuthorizedCommandFixture<ValidatedFaceRequestFixture>)
 {
-  ndn::nfd::FaceManagementOptions options;
-  options.setUri("tcp://127.0.0.1");
+  ControlParameters parameters;
+  parameters.setUri("tcp://127.0.0.1");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("create");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -845,14 +845,14 @@
 BOOST_FIXTURE_TEST_CASE(ValidatedFaceRequestDestroyFace,
                         AuthorizedCommandFixture<ValidatedFaceRequestFixture>)
 {
-  ndn::nfd::FaceManagementOptions options;
-  options.setUri("tcp://127.0.0.1");
+  ControlParameters parameters;
+  parameters.setUri("tcp://127.0.0.1");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("destroy");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -879,6 +879,379 @@
   FaceTable m_faceTable;
 };
 
+class LocalControlFixture : public FaceTableFixture,
+                            public TestFaceManagerCommon,
+                            public FaceManager
+{
+public:
+  LocalControlFixture()
+    : FaceManager(FaceTableFixture::m_faceTable, TestFaceManagerCommon::m_face)
+  {
+  }
+};
+
+BOOST_FIXTURE_TEST_CASE(LocalControlInFaceId,
+                        AuthorizedCommandFixture<LocalControlFixture>)
+{
+  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
+  BOOST_REQUIRE(dummy->isLocal());
+  FaceTableFixture::m_faceTable.add(dummy);
+
+  ControlParameters parameters;
+  parameters.setFaceId(dummy->getId());
+  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name enable("/localhost/nfd/faces/enable-local-control");
+  enable.append(encodedParameters);
+
+  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
+  enableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*enableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         enableCommand->getName(), 200, "Success", encodedParameters);
+
+  onValidatedFaceRequest(enableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+
+  TestFaceManagerCommon::m_face->onReceiveData.clear();
+  resetCallbackFired();
+
+  Name disable("/localhost/nfd/faces/disable-local-control");
+  disable.append(encodedParameters);
+
+  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
+  disableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*disableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         disableCommand->getName(), 200, "Success", encodedParameters);
+
+  onValidatedFaceRequest(disableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+}
+
+BOOST_FIXTURE_TEST_CASE(LocalControlInFaceIdFaceNotFound,
+                        AuthorizedCommandFixture<LocalControlFixture>)
+{
+  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
+  BOOST_REQUIRE(dummy->isLocal());
+  FaceTableFixture::m_faceTable.add(dummy);
+
+  ControlParameters parameters;
+  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name enable("/localhost/nfd/faces/enable-local-control");
+  enable.append(encodedParameters);
+
+  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
+  enableCommand->setIncomingFaceId(dummy->getId() + 100);
+
+  generateCommand(*enableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         enableCommand->getName(), 410, "Requested face not found");
+
+  onValidatedFaceRequest(enableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+
+  TestFaceManagerCommon::m_face->onReceiveData.clear();
+  resetCallbackFired();
+
+  Name disable("/localhost/nfd/faces/disable-local-control");
+  disable.append(encodedParameters);
+
+  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
+  disableCommand->setIncomingFaceId(dummy->getId() + 100);
+
+  generateCommand(*disableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         disableCommand->getName(), 410, "Requested face not found");
+
+  onValidatedFaceRequest(disableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+}
+
+BOOST_FIXTURE_TEST_CASE(LocalControlMissingFeature,
+                        AuthorizedCommandFixture<LocalControlFixture>)
+{
+  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
+  BOOST_REQUIRE(dummy->isLocal());
+  FaceTableFixture::m_faceTable.add(dummy);
+
+  ControlParameters parameters;
+  parameters.setFaceId(dummy->getId());
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name enable("/localhost/nfd/faces/enable-local-control");
+  enable.append(encodedParameters);
+
+  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
+  enableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*enableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         enableCommand->getName(), 400, "Malformed command");
+
+  onValidatedFaceRequest(enableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+
+  TestFaceManagerCommon::m_face->onReceiveData.clear();
+  resetCallbackFired();
+
+  Name disable("/localhost/nfd/faces/disable-local-control");
+  disable.append(encodedParameters);
+
+  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
+  disableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*disableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         disableCommand->getName(), 400, "Malformed command");
+
+  onValidatedFaceRequest(disableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+}
+
+BOOST_FIXTURE_TEST_CASE(LocalControlInFaceIdNonLocal,
+                        AuthorizedCommandFixture<LocalControlFixture>)
+{
+  shared_ptr<DummyFace> dummy = make_shared<DummyFace>();
+  BOOST_REQUIRE(!dummy->isLocal());
+  FaceTableFixture::m_faceTable.add(dummy);
+
+  ControlParameters parameters;
+  parameters.setFaceId(dummy->getId());
+  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name enable("/localhost/nfd/faces/enable-local-control");
+  enable.append(encodedParameters);
+
+  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
+  enableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*enableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         enableCommand->getName(), 412, "Requested face is non-local");
+
+  onValidatedFaceRequest(enableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+
+  TestFaceManagerCommon::m_face->onReceiveData.clear();
+  resetCallbackFired();
+
+  Name disable("/localhost/nfd/faces/disable-local-control");
+  enable.append(encodedParameters);
+
+  shared_ptr<Interest> disableCommand(make_shared<Interest>(enable));
+  disableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*disableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         disableCommand->getName(), 412, "Requested face is non-local");
+
+  onValidatedFaceRequest(disableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_FIXTURE_TEST_CASE(LocalControlNextHopFaceId,
+                        AuthorizedCommandFixture<LocalControlFixture>)
+{
+  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
+  BOOST_REQUIRE(dummy->isLocal());
+  FaceTableFixture::m_faceTable.add(dummy);
+
+  ControlParameters parameters;
+  parameters.setFaceId(dummy->getId());
+  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name enable("/localhost/nfd/faces/enable-local-control");
+  enable.append(encodedParameters);
+
+  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
+  enableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*enableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         enableCommand->getName(), 200, "Success", encodedParameters);
+
+  onValidatedFaceRequest(enableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+
+
+  TestFaceManagerCommon::m_face->onReceiveData.clear();
+  resetCallbackFired();
+
+  Name disable("/localhost/nfd/faces/disable-local-control");
+  disable.append(encodedParameters);
+
+  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
+  disableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*disableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         disableCommand->getName(), 200, "Success", encodedParameters);
+
+  onValidatedFaceRequest(disableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+}
+
+BOOST_FIXTURE_TEST_CASE(LocalControlNextHopFaceIdFaceNotFound,
+                        AuthorizedCommandFixture<LocalControlFixture>)
+{
+  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
+  BOOST_REQUIRE(dummy->isLocal());
+  FaceTableFixture::m_faceTable.add(dummy);
+
+  ControlParameters parameters;
+  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name enable("/localhost/nfd/faces/enable-local-control");
+  enable.append(encodedParameters);
+
+  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
+  enableCommand->setIncomingFaceId(dummy->getId() + 100);
+
+  generateCommand(*enableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         enableCommand->getName(), 410, "Requested face not found");
+
+  onValidatedFaceRequest(enableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+
+
+  TestFaceManagerCommon::m_face->onReceiveData.clear();
+  resetCallbackFired();
+
+  Name disable("/localhost/nfd/faces/disable-local-control");
+  disable.append(encodedParameters);
+
+  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
+  disableCommand->setIncomingFaceId(dummy->getId() + 100);
+
+  generateCommand(*disableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         disableCommand->getName(), 410, "Requested face not found");
+
+  onValidatedFaceRequest(disableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
+  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
+}
+
+BOOST_FIXTURE_TEST_CASE(LocalControlNextHopFaceIdNonLocal,
+                        AuthorizedCommandFixture<LocalControlFixture>)
+{
+  shared_ptr<DummyFace> dummy = make_shared<DummyFace>();
+  BOOST_REQUIRE(!dummy->isLocal());
+  FaceTableFixture::m_faceTable.add(dummy);
+
+  ControlParameters parameters;
+  parameters.setFaceId(dummy->getId());
+  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name enable("/localhost/nfd/faces/enable-local-control");
+  enable.append(encodedParameters);
+
+  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
+  enableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*enableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         enableCommand->getName(), 412, "Requested face is non-local");
+
+  onValidatedFaceRequest(enableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+
+  TestFaceManagerCommon::m_face->onReceiveData.clear();
+  resetCallbackFired();
+
+  Name disable("/localhost/nfd/faces/disable-local-control");
+  disable.append(encodedParameters);
+
+  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
+  disableCommand->setIncomingFaceId(dummy->getId());
+
+  generateCommand(*disableCommand);
+
+  TestFaceManagerCommon::m_face->onReceiveData +=
+    bind(&LocalControlFixture::validateControlResponse, this, _1,
+         disableCommand->getName(), 412, "Requested face is non-local");
+
+  onValidatedFaceRequest(disableCommand);
+
+  BOOST_REQUIRE(didCallbackFire());
+}
+
 class FaceFixture : public FaceTableFixture,
                     public TestFaceManagerCommon,
                     public FaceManager
@@ -971,14 +1344,14 @@
 
 BOOST_FIXTURE_TEST_CASE(CreateFaceBadUri, AuthorizedCommandFixture<FaceFixture>)
 {
-  ndn::nfd::FaceManagementOptions options;
-  options.setUri("tcp:/127.0.0.1");
+  ControlParameters parameters;
+  parameters.setUri("tcp:/127.0.0.1");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("create");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -987,23 +1360,45 @@
     bind(&FaceFixture::validateControlResponse, this, _1,
          command->getName(), 400, "Malformed command");
 
-  createFace(command->getName(), options);
+  createFace(*command, parameters);
+
+  BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_FIXTURE_TEST_CASE(CreateFaceMissingUri, AuthorizedCommandFixture<FaceFixture>)
+{
+  ControlParameters parameters;
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name commandName("/localhost/nfd/faces");
+  commandName.append("create");
+  commandName.append(encodedParameters);
+
+  shared_ptr<Interest> command(make_shared<Interest>(commandName));
+  generateCommand(*command);
+
+  getFace()->onReceiveData +=
+    bind(&FaceFixture::validateControlResponse, this, _1,
+         command->getName(), 400, "Malformed command");
+
+  createFace(*command, parameters);
 
   BOOST_REQUIRE(didCallbackFire());
 }
 
 BOOST_FIXTURE_TEST_CASE(CreateFaceUnknownScheme, AuthorizedCommandFixture<FaceFixture>)
 {
-  ndn::nfd::FaceManagementOptions options;
+  ControlParameters parameters;
   // this will be an unsupported protocol because no factories have been
   // added to the face manager
-  options.setUri("tcp://127.0.0.1");
+  parameters.setUri("tcp://127.0.0.1");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("create");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -1012,28 +1407,28 @@
     bind(&FaceFixture::validateControlResponse, this, _1,
          command->getName(), 501, "Unsupported protocol");
 
-  createFace(command->getName(), options);
+  createFace(*command, parameters);
 
   BOOST_REQUIRE(didCallbackFire());
 }
 
 BOOST_FIXTURE_TEST_CASE(OnCreated, AuthorizedCommandFixture<FaceFixture>)
 {
-  ndn::nfd::FaceManagementOptions options;
-  options.setUri("tcp://127.0.0.1");
+  ControlParameters parameters;
+  parameters.setUri("tcp://127.0.0.1");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("create");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
 
-  ndn::nfd::FaceManagementOptions resultOptions;
-  resultOptions.setUri("tcp://127.0.0.1");
-  resultOptions.setFaceId(1);
+  ControlParameters resultParameters;
+  resultParameters.setUri("tcp://127.0.0.1");
+  resultParameters.setFaceId(1);
 
   shared_ptr<DummyFace> dummy(make_shared<DummyFace>());
 
@@ -1042,14 +1437,14 @@
                                                     dummy->getUri().toString(),
                                                     0);
 
-  Block encodedResultOptions(resultOptions.wireEncode());
+  Block encodedResultParameters(resultParameters.wireEncode());
 
   getFace()->onReceiveData +=
     bind(&FaceFixture::callbackDispatch, this, _1,
-                                        command->getName(), 200, "Success",
-                                        encodedResultOptions, expectedFaceEvent);
+         command->getName(), 200, "Success",
+         encodedResultParameters, expectedFaceEvent);
 
-  onCreated(command->getName(), options, dummy);
+  onCreated(command->getName(), parameters, dummy);
 
   BOOST_REQUIRE(didCallbackFire());
   BOOST_REQUIRE(didReceiveNotication());
@@ -1057,14 +1452,14 @@
 
 BOOST_FIXTURE_TEST_CASE(OnConnectFailed, AuthorizedCommandFixture<FaceFixture>)
 {
-  ndn::nfd::FaceManagementOptions options;
-  options.setUri("tcp://127.0.0.1");
+  ControlParameters parameters;
+  parameters.setUri("tcp://127.0.0.1");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("create");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -1085,15 +1480,15 @@
   shared_ptr<DummyFace> dummy(make_shared<DummyFace>());
   FaceTableFixture::m_faceTable.add(dummy);
 
-  ndn::nfd::FaceManagementOptions options;
-  options.setUri("tcp://127.0.0.1");
-  options.setFaceId(dummy->getId());
+  ControlParameters parameters;
+  parameters.setUri("tcp://127.0.0.1");
+  parameters.setFaceId(dummy->getId());
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/faces");
   commandName.append("destroy");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -1104,9 +1499,9 @@
 
   getFace()->onReceiveData +=
     bind(&FaceFixture::callbackDispatch, this, _1,
-         command->getName(), 200, "Success", boost::ref(encodedOptions), expectedFaceEvent);
+         command->getName(), 200, "Success", boost::ref(encodedParameters), expectedFaceEvent);
 
-  destroyFace(command->getName(), options);
+  destroyFace(*command, parameters);
 
   BOOST_REQUIRE(didCallbackFire());
   BOOST_REQUIRE(didReceiveNotication());
diff --git a/tests/mgmt/fib-manager.cpp b/tests/mgmt/fib-manager.cpp
index f388f47..5076e0d 100644
--- a/tests/mgmt/fib-manager.cpp
+++ b/tests/mgmt/fib-manager.cpp
@@ -97,7 +97,7 @@
                                   expectedCode, expectedText, control);
 
     BOOST_REQUIRE(!control.getBody().empty());
-    BOOST_REQUIRE(control.getBody().value_size() == expectedBody.value_size());
+    BOOST_REQUIRE_EQUAL(control.getBody().value_size(), expectedBody.value_size());
 
     BOOST_CHECK(memcmp(control.getBody().value(), expectedBody.value(),
                        expectedBody.value_size()) == 0);
@@ -253,16 +253,16 @@
 {
   shared_ptr<InternalFace> face = getInternalFace();
 
-  FibManagementOptions options;
-  options.setName("/hello");
-  options.setFaceId(1);
-  options.setCost(1);
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(1);
+  parameters.setCost(1);
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("unsupported");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -282,16 +282,16 @@
 
   shared_ptr<InternalFace> face = getInternalFace();
 
-  FibManagementOptions options;
-  options.setName("/hello");
-  options.setFaceId(1);
-  options.setCost(101);
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(1);
+  parameters.setCost(101);
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("add-nexthop");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   Interest command(commandName);
 
@@ -312,16 +312,16 @@
 
   shared_ptr<InternalFace> face = getInternalFace();
 
-  FibManagementOptions options;
-  options.setName("/hello");
-  options.setFaceId(1);
-  options.setCost(101);
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(1);
+  parameters.setCost(101);
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("add-nexthop");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -344,7 +344,7 @@
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("add-nexthop");
-  commandName.append("NotReallyOptions");
+  commandName.append("NotReallyParameters");
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -364,23 +364,23 @@
 
   shared_ptr<InternalFace> face = getInternalFace();
 
-  FibManagementOptions options;
-  options.setName("/hello");
-  options.setFaceId(1000);
-  options.setCost(101);
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(1000);
+  parameters.setCost(101);
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("add-nexthop");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
 
   face->onReceiveData +=
     bind(&FibManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 404, "Face not found");
+         command->getName(), 410, "Face not found");
 
   getFibManager().onFibRequest(*command);
 
@@ -394,23 +394,23 @@
 
   shared_ptr<InternalFace> face = getInternalFace();
 
-  FibManagementOptions options;
-  options.setName("/hello");
-  options.setFaceId(0);
-  options.setCost(101);
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(0);
+  parameters.setCost(101);
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("add-nexthop");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
-  FibManagementOptions expectedOptions;
-  expectedOptions.setName("/hello");
-  expectedOptions.setFaceId(1);
-  expectedOptions.setCost(101);
+  ControlParameters expectedParameters;
+  expectedParameters.setName("/hello");
+  expectedParameters.setFaceId(1);
+  expectedParameters.setCost(101);
 
-  Block encodedExpectedOptions(expectedOptions.wireEncode());
+  Block encodedExpectedParameters(expectedParameters.wireEncode());
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   command->setIncomingFaceId(1);
@@ -418,7 +418,7 @@
 
   face->onReceiveData +=
     bind(&FibManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 200, "Success", encodedExpectedOptions);
+         command->getName(), 200, "Success", encodedExpectedParameters);
 
   getFibManager().onFibRequest(*command);
 
@@ -432,23 +432,23 @@
 
   shared_ptr<InternalFace> face = getInternalFace();
 
-  FibManagementOptions options;
-  options.setName("/hello");
-  options.setFaceId(1);
-  options.setCost(101);
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(1);
+  parameters.setCost(101);
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("add-nexthop");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
 
   face->onReceiveData +=
     bind(&FibManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 200, "Success", encodedOptions);
+         command->getName(), 200, "Success", encodedParameters);
 
   getFibManager().onFibRequest(*command);
 
@@ -456,6 +456,40 @@
   BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 101));
 }
 
+BOOST_AUTO_TEST_CASE(AddNextHopVerbImplicitCost)
+{
+  addFace(make_shared<DummyFace>());
+
+  shared_ptr<InternalFace> face = getInternalFace();
+
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(1);
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name commandName("/localhost/nfd/fib");
+  commandName.append("add-nexthop");
+  commandName.append(encodedParameters);
+
+  shared_ptr<Interest> command(make_shared<Interest>(commandName));
+  generateCommand(*command);
+
+  ControlParameters resultParameters;
+  resultParameters.setName("/hello");
+  resultParameters.setFaceId(1);
+  resultParameters.setCost(0);
+
+  face->onReceiveData +=
+    bind(&FibManagerFixture::validateControlResponse, this, _1,
+         command->getName(), 200, "Success", resultParameters.wireEncode());
+
+  getFibManager().onFibRequest(*command);
+
+  BOOST_REQUIRE(didCallbackFire());
+  BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 0));
+}
+
 BOOST_AUTO_TEST_CASE(AddNextHopVerbAddToExisting)
 {
   addFace(make_shared<DummyFace>());
@@ -464,23 +498,23 @@
   for (int i = 1; i <= 2; i++)
     {
 
-      FibManagementOptions options;
-      options.setName("/hello");
-      options.setFaceId(1);
-      options.setCost(100 + i);
+      ControlParameters parameters;
+      parameters.setName("/hello");
+      parameters.setFaceId(1);
+      parameters.setCost(100 + i);
 
-      Block encodedOptions(options.wireEncode());
+      Block encodedParameters(parameters.wireEncode());
 
       Name commandName("/localhost/nfd/fib");
       commandName.append("add-nexthop");
-      commandName.append(encodedOptions);
+      commandName.append(encodedParameters);
 
       shared_ptr<Interest> command(make_shared<Interest>(commandName));
       generateCommand(*command);
 
       face->onReceiveData +=
         bind(&FibManagerFixture::validateControlResponse, this, _1,
-             command->getName(), 200, "Success", encodedOptions);
+             command->getName(), 200, "Success", encodedParameters);
 
       getFibManager().onFibRequest(*command);
       BOOST_REQUIRE(didCallbackFire());
@@ -510,25 +544,25 @@
   addFace(make_shared<DummyFace>());
   shared_ptr<InternalFace> face = getInternalFace();
 
-  FibManagementOptions options;
-  options.setName("/hello");
-  options.setFaceId(1);
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(1);
 
   {
-    options.setCost(1);
+    parameters.setCost(1);
 
-    Block encodedOptions(options.wireEncode());
+    Block encodedParameters(parameters.wireEncode());
 
     Name commandName("/localhost/nfd/fib");
     commandName.append("add-nexthop");
-    commandName.append(encodedOptions);
+    commandName.append(encodedParameters);
 
     shared_ptr<Interest> command(make_shared<Interest>(commandName));
     generateCommand(*command);
 
     face->onReceiveData +=
       bind(&FibManagerFixture::validateControlResponse, this, _1,
-           command->getName(), 200, "Success", encodedOptions);
+           command->getName(), 200, "Success", encodedParameters);
 
     getFibManager().onFibRequest(*command);
 
@@ -539,20 +573,20 @@
   face->onReceiveData.clear();
 
   {
-    options.setCost(102);
+    parameters.setCost(102);
 
-    Block encodedOptions(options.wireEncode());
+    Block encodedParameters(parameters.wireEncode());
 
     Name commandName("/localhost/nfd/fib");
     commandName.append("add-nexthop");
-    commandName.append(encodedOptions);
+    commandName.append(encodedParameters);
 
     shared_ptr<Interest> command(make_shared<Interest>(commandName));
     generateCommand(*command);
 
     face->onReceiveData +=
       bind(&FibManagerFixture::validateControlResponse, this, _1,
-           command->getName(), 200, "Success", encodedOptions);
+           command->getName(), 200, "Success", encodedParameters);
 
     getFibManager().onFibRequest(*command);
 
@@ -578,151 +612,59 @@
     }
 }
 
-// BOOST_AUTO_TEST_CASE(Insert)
-// {
-//   addFace(make_shared<DummyFace>());
-//   addFace(make_shared<DummyFace>());
-//   shared_ptr<InternalFace> face = getInternalFace();
+BOOST_AUTO_TEST_CASE(AddNextHopVerbMissingPrefix)
+{
+  addFace(make_shared<DummyFace>());
 
-//   {
-//     FibManagementOptions options;
-//     options.setName("/hello");
-//     options.setFaceId(1);
-//     options.setCost(101);
+  shared_ptr<InternalFace> face = getInternalFace();
 
-//     Block encodedOptions(options.wireEncode());
+  ControlParameters parameters;
+  parameters.setFaceId(1);
 
-//     Name commandName("/localhost/nfd/fib");
-//     commandName.append("add-nexthop");
-//     commandName.append(encodedOptions);
+  Block encodedParameters(parameters.wireEncode());
 
-//     shared_ptr<Interest> command(make_shared<Interest>(commandName));
-//     generateCommand(*command);
+  Name commandName("/localhost/nfd/fib");
+  commandName.append("add-nexthop");
+  commandName.append(encodedParameters);
 
-//     face->onReceiveData +=
-//       bind(&FibManagerFixture::validateControlResponse, this, _1,
-//            command->getName(), 200, "Success", encodedOptions);
+  shared_ptr<Interest> command(make_shared<Interest>(commandName));
+  generateCommand(*command);
 
-//     getFibManager().onFibRequest(*command);
-//   }
+  face->onReceiveData +=
+    bind(&FibManagerFixture::validateControlResponse, this, _1,
+         command->getName(), 400, "Malformed command");
 
-//   BOOST_REQUIRE(didCallbackFire());
+  getFibManager().onFibRequest(*command);
 
-//   shared_ptr<fib::Entry> entry = getFib().findExactMatch("/hello");
-//   if (static_cast<bool>(entry))
-//     {
-//       const fib::NextHopList& hops = entry->getNextHops();
-//       BOOST_CHECK_EQUAL(hops.size(), 1);
-//     }
+  BOOST_REQUIRE(didCallbackFire());
+}
 
-//   resetCallbackFired();
-//   face->onReceiveData.clear();
+BOOST_AUTO_TEST_CASE(AddNextHopVerbMissingFaceId)
+{
+  addFace(make_shared<DummyFace>());
 
-//   {
-//     FibManagementOptions options;
-//     options.setName("/hello");
-//     options.setFaceId(2);
-//     options.setCost(102);
+  shared_ptr<InternalFace> face = getInternalFace();
 
-//     Block encodedOptions(options.wireEncode());
+  ControlParameters parameters;
+  parameters.setName("/hello");
 
-//     Name commandName("/localhost/nfd/fib");
-//     commandName.append("add-nexthop");
-//     commandName.append(encodedOptions);
+  Block encodedParameters(parameters.wireEncode());
 
-//     shared_ptr<Interest> command(make_shared<Interest>(commandName));
-//     generateCommand(*command);
+  Name commandName("/localhost/nfd/fib");
+  commandName.append("add-nexthop");
+  commandName.append(encodedParameters);
 
-//     face->onReceiveData +=
-//       bind(&FibManagerFixture::validateControlResponse, this, _1,
-//            command->getName(), 200, "Success", encodedOptions);
+  shared_ptr<Interest> command(make_shared<Interest>(commandName));
+  generateCommand(*command);
 
-//     getFibManager().onFibRequest(*command);
-//   }
+  face->onReceiveData +=
+    bind(&FibManagerFixture::validateControlResponse, this, _1,
+         command->getName(), 400, "Malformed command");
 
-//   BOOST_REQUIRE(didCallbackFire());
+  getFibManager().onFibRequest(*command);
 
-//   entry = getFib().findExactMatch("/hello");
-//   if (static_cast<bool>(entry))
-//     {
-//       const fib::NextHopList& hops = entry->getNextHops();
-//       BOOST_CHECK_EQUAL(hops.size(), 2);
-//     }
-
-// }
-
-// void
-// testRemove(CommandFixture<FibManagerFixture>* fixture,
-//            FibManager& manager,
-//            Fib& fib,
-//            shared_ptr<Face> face,
-//            const Name& target)
-// {
-//   FibManagementOptions options;
-//   options.setName(target);
-
-//   Block encodedOptions(options.wireEncode());
-
-//   Name commandName("/localhost/nfd/fib");
-//   commandName.append("delete");
-//   commandName.append(encodedOptions);
-
-//   shared_ptr<Interest> command(make_shared<Interest>(commandName));
-//   fixture->generateCommand(*command);
-
-//   face->onReceiveData +=
-//     bind(&FibManagerFixture::validateControlResponse, fixture, _1,
-//          command->getName(), 200, "Success", encodedOptions);
-
-//   manager.onFibRequest(*command);
-
-//   BOOST_REQUIRE(fixture->didCallbackFire());
-
-//   if (static_cast<bool>(fib.findExactMatch(target)))
-//     {
-//       BOOST_FAIL("Found \"removed\" prefix");
-//     }
-//   face->onReceiveData.clear();
-// }
-
-// BOOST_AUTO_TEST_CASE(Delete)
-// {
-//   shared_ptr<InternalFace> face = getInternalFace();
-//   FibManager& manager = getFibManager();
-//   Fib& fib = getFib();
-
-//   fib.insert("/a");
-//   fib.insert("/a/b");
-//   fib.insert("/a/b/c");
-
-//   testRemove(this, manager, fib, face, "/");
-
-//   if (!static_cast<bool>(fib.findExactMatch("/a")) ||
-//       !static_cast<bool>(fib.findExactMatch("/a/b")) ||
-//       !static_cast<bool>(fib.findExactMatch("/a/b/c")))
-//     {
-//       BOOST_FAIL("Removed incorrect entry");
-//     }
-
-//   testRemove(this, manager, fib, face, "/a/b");
-
-//   if (!static_cast<bool>(fib.findExactMatch("/a")) ||
-//       !static_cast<bool>(fib.findExactMatch("/a/b/c")))
-//     {
-//       BOOST_FAIL("Removed incorrect entry");
-//     }
-
-//   testRemove(this, manager, fib, face, "/a/b/c");
-
-//   if (!static_cast<bool>(fib.findExactMatch("/a")))
-//     {
-//       BOOST_FAIL("Removed incorrect entry");
-//     }
-
-//   testRemove(this, manager, fib, face, "/a");
-
-//   testRemove(this, manager, fib, face, "/does/not/exist");
-// }
+  BOOST_REQUIRE(didCallbackFire());
+}
 
 bool
 removedNextHopWithCost(const Fib& fib, const Name& prefix, size_t oldSize, uint32_t cost)
@@ -746,22 +688,22 @@
                   const Name& targetName,
                   FaceId targetFace)
 {
-  FibManagementOptions options;
-  options.setName(targetName);
-  options.setFaceId(targetFace);
+  ControlParameters parameters;
+  parameters.setName(targetName);
+  parameters.setFaceId(targetFace);
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("remove-nexthop");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   fixture->generateCommand(*command);
 
   face->onReceiveData +=
     bind(&FibManagerFixture::validateControlResponse, fixture, _1,
-         command->getName(), 200, "Success", encodedOptions);
+         command->getName(), 200, "Success", encodedParameters);
 
   manager.onFibRequest(*command);
 
@@ -803,54 +745,108 @@
   BOOST_CHECK(!static_cast<bool>(getFib().findExactMatch("/hello")));
 }
 
-BOOST_AUTO_TEST_CASE(RemoveNoFace)
+BOOST_AUTO_TEST_CASE(RemoveFaceNotFound)
 {
   shared_ptr<InternalFace> face = getInternalFace();
 
-  FibManagementOptions options;
-  options.setName("/hello");
-  options.setFaceId(1);
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(1);
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("remove-nexthop");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
 
   face->onReceiveData +=
     bind(&FibManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 404, "Face not found");
+         command->getName(), 200, "Success", encodedParameters);
 
   getFibManager().onFibRequest(*command);
 
   BOOST_REQUIRE(didCallbackFire());
 }
 
-BOOST_AUTO_TEST_CASE(RemoveNoPrefix)
+BOOST_AUTO_TEST_CASE(RemovePrefixNotFound)
 {
   addFace(make_shared<DummyFace>());
 
   shared_ptr<InternalFace> face = getInternalFace();
 
-  FibManagementOptions options;
-  options.setName("/hello");
-  options.setFaceId(1);
+  ControlParameters parameters;
+  parameters.setName("/hello");
+  parameters.setFaceId(1);
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/fib");
   commandName.append("remove-nexthop");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
 
   face->onReceiveData +=
     bind(&FibManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 404, "Prefix not found");
+         command->getName(), 200, "Success", encodedParameters);
+
+  getFibManager().onFibRequest(*command);
+
+  BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(RemoveMissingPrefix)
+{
+  addFace(make_shared<DummyFace>());
+
+  shared_ptr<InternalFace> face = getInternalFace();
+
+  ControlParameters parameters;
+  parameters.setFaceId(1);
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name commandName("/localhost/nfd/fib");
+  commandName.append("remove-nexthop");
+  commandName.append(encodedParameters);
+
+  shared_ptr<Interest> command(make_shared<Interest>(commandName));
+  generateCommand(*command);
+
+  face->onReceiveData +=
+    bind(&FibManagerFixture::validateControlResponse, this, _1,
+         command->getName(), 400, "Malformed command");
+
+  getFibManager().onFibRequest(*command);
+
+  BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(RemoveMissingFaceId)
+{
+  addFace(make_shared<DummyFace>());
+
+  shared_ptr<InternalFace> face = getInternalFace();
+
+  ControlParameters parameters;
+  parameters.setName("/hello");
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name commandName("/localhost/nfd/fib");
+  commandName.append("remove-nexthop");
+  commandName.append(encodedParameters);
+
+  shared_ptr<Interest> command(make_shared<Interest>(commandName));
+  generateCommand(*command);
+
+  face->onReceiveData +=
+    bind(&FibManagerFixture::validateControlResponse, this, _1,
+         command->getName(), 400, "Malformed command");
 
   getFibManager().onFibRequest(*command);
 
diff --git a/tests/mgmt/local-control-header-manager.cpp b/tests/mgmt/local-control-header-manager.cpp
deleted file mode 100644
index 168f43f..0000000
--- a/tests/mgmt/local-control-header-manager.cpp
+++ /dev/null
@@ -1,348 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (C) 2014 Named Data Networking Project
- * See COPYING for copyright and distribution information.
- */
-
-#include "mgmt/local-control-header-manager.hpp"
-#include "mgmt/internal-face.hpp"
-#include "tests/face/dummy-face.hpp"
-
-#include "tests/test-common.hpp"
-#include "validation-common.hpp"
-
-namespace nfd {
-namespace tests {
-
-NFD_LOG_INIT("LocalControlHeaderManagerTest");
-
-class LocalControlHeaderManagerFixture : protected BaseFixture
-{
-public:
-
-  shared_ptr<Face>
-  getFace(FaceId id)
-  {
-    if (id > 0 && static_cast<size_t>(id) <= m_faces.size())
-      {
-        return m_faces[id - 1];
-      }
-    NFD_LOG_DEBUG("No face found returning NULL");
-    return shared_ptr<DummyFace>();
-  }
-
-  void
-  addFace(shared_ptr<Face> face)
-  {
-    m_faces.push_back(face);
-  }
-
-  shared_ptr<InternalFace>
-  getInternalFace()
-  {
-    return m_face;
-  }
-
-  LocalControlHeaderManager&
-  getManager()
-  {
-    return m_manager;
-  }
-
-  void
-  addInterestRule(const std::string& regex,
-                  ndn::IdentityCertificate& certificate)
-  {
-    m_manager.addInterestRule(regex, certificate);
-  }
-
-  void
-  validateControlResponse(const Data& response,
-                          const Name& expectedName,
-                          uint32_t expectedCode,
-                          const std::string& expectedText)
-  {
-    m_callbackFired = true;
-
-    ControlResponse control;
-    Block controlRaw = response.getContent().blockFromValue();
-
-    control.wireDecode(controlRaw);
-
-    NFD_LOG_DEBUG("received control response"
-                  << " Name: " << response.getName()
-                  << " code: " << control.getCode()
-                  << " text: " << control.getText());
-
-    BOOST_CHECK_EQUAL(response.getName(), expectedName);
-    BOOST_CHECK_EQUAL(control.getCode(), expectedCode);
-    BOOST_CHECK_EQUAL(control.getText(), expectedText);
-
-    if (!control.getBody().empty())
-      {
-        BOOST_FAIL("found unexpected control response body");
-      }
-  }
-
-  bool
-  didCallbackFire()
-  {
-    return m_callbackFired;
-  }
-
-  void
-  resetCallbackFired()
-  {
-    m_callbackFired = false;
-  }
-
-protected:
-  LocalControlHeaderManagerFixture()
-    : m_face(make_shared<InternalFace>()),
-      m_manager(bind(&LocalControlHeaderManagerFixture::getFace, this, _1),
-                m_face),
-      m_callbackFired(false)
-  {
-  }
-
-private:
-  shared_ptr<InternalFace> m_face;
-  LocalControlHeaderManager m_manager;
-  std::vector<shared_ptr<Face> > m_faces;
-  bool m_callbackFired;
-};
-
-template <typename T> class AuthorizedCommandFixture:
-    public CommandFixture<T>
-{
-public:
-  AuthorizedCommandFixture()
-  {
-    const std::string regex = "^<localhost><nfd><control-header>";
-    T::addInterestRule(regex, *CommandFixture<T>::m_certificate);
-  }
-
-  virtual
-  ~AuthorizedCommandFixture()
-  {
-  }
-};
-
-BOOST_FIXTURE_TEST_SUITE(MgmtLocalControlHeaderManager,
-                         AuthorizedCommandFixture<LocalControlHeaderManagerFixture>)
-
-BOOST_AUTO_TEST_CASE(InFaceId)
-{
-  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
-  addFace(dummy);
-
-  Name enable("/localhost/nfd/control-header/in-faceid/enable");
-  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
-  enableCommand->setIncomingFaceId(1);
-
-  generateCommand(*enableCommand);
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         enableCommand->getName(), 200, "Success");
-
-  getManager().onLocalControlHeaderRequest(*enableCommand);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_REQUIRE(dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
-
-  getInternalFace()->onReceiveData.clear();
-  resetCallbackFired();
-
-  Name disable("/localhost/nfd/control-header/in-faceid/disable");
-  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
-  disableCommand->setIncomingFaceId(1);
-
-  generateCommand(*disableCommand);
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         disableCommand->getName(), 200, "Success");
-
-  getManager().onLocalControlHeaderRequest(*disableCommand);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
-}
-
-BOOST_AUTO_TEST_CASE(NextHopFaceId)
-{
-  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
-  addFace(dummy);
-
-  Name enable("/localhost/nfd/control-header/nexthop-faceid/enable");
-
-  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
-  enableCommand->setIncomingFaceId(1);
-  generateCommand(*enableCommand);
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         enableCommand->getName(), 200, "Success");
-
-  getManager().onLocalControlHeaderRequest(*enableCommand);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_REQUIRE(dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-
-  getInternalFace()->onReceiveData.clear();
-  resetCallbackFired();
-
-  Name disable("/localhost/nfd/control-header/nexthop-faceid/disable");
-  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
-  disableCommand->setIncomingFaceId(1);
-
-  generateCommand(*disableCommand);
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         disableCommand->getName(), 200, "Success");
-
-  getManager().onLocalControlHeaderRequest(*disableCommand);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-}
-
-BOOST_AUTO_TEST_CASE(ShortCommand)
-{
-  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
-  addFace(dummy);
-
-  Name commandName("/localhost/nfd/control-header");
-  Interest command(commandName);
-  command.setIncomingFaceId(1);
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         commandName, 400, "Malformed command");
-
-  getManager().onLocalControlHeaderRequest(command);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
-}
-
-BOOST_AUTO_TEST_CASE(ShortCommandModule)
-{
-  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
-  addFace(dummy);
-
-  Name commandName("/localhost/nfd/control-header/in-faceid");
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         commandName, 400, "Malformed command");
-
-  Interest command(commandName);
-  command.setIncomingFaceId(1);
-  getManager().onLocalControlHeaderRequest(command);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
-}
-
-BOOST_AUTO_TEST_CASE(UnsupportedModule)
-{
-  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
-  addFace(dummy);
-
-  Name commandName("/localhost/nfd/control-header/madeup/moremadeup");
-  shared_ptr<Interest> command(make_shared<Interest>(commandName));
-  command->setIncomingFaceId(1);
-
-  generateCommand(*command);
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 501, "Unsupported");
-
-  getManager().onLocalControlHeaderRequest(*command);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
-}
-
-BOOST_AUTO_TEST_CASE(InFaceIdUnsupportedVerb)
-{
-  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
-  addFace(dummy);
-
-  Name commandName("/localhost/nfd/control-header/in-faceid/madeup");
-  shared_ptr<Interest> command(make_shared<Interest>(commandName));
-  command->setIncomingFaceId(1);
-
-
-  generateCommand(*command);
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 501, "Unsupported");
-
-  getManager().onLocalControlHeaderRequest(*command);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
-}
-
-BOOST_AUTO_TEST_CASE(NextHopFaceIdUnsupportedVerb)
-{
-  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
-  addFace(dummy);
-
-  Name commandName("/localhost/nfd/control-header/nexthop-faceid/madeup");
-  shared_ptr<Interest> command(make_shared<Interest>(commandName));
-  command->setIncomingFaceId(1);
-
-  generateCommand(*command);
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 501, "Unsupported");
-
-  getManager().onLocalControlHeaderRequest(*command);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID));
-}
-
-BOOST_FIXTURE_TEST_CASE(UnauthorizedCommand,
-                        UnauthorizedCommandFixture<LocalControlHeaderManagerFixture>)
-{
-  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
-  addFace(dummy);
-
-  Name enable("/localhost/nfd/control-header/in-faceid/enable");
-  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
-  enableCommand->setIncomingFaceId(1);
-
-  generateCommand(*enableCommand);
-
-  getInternalFace()->onReceiveData +=
-    bind(&LocalControlHeaderManagerFixture::validateControlResponse, this, _1,
-         enableCommand->getName(), 403, "Unauthorized command");
-
-  getManager().onLocalControlHeaderRequest(*enableCommand);
-
-  BOOST_REQUIRE(didCallbackFire());
-  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID));
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace nfd
diff --git a/tests/mgmt/manager-base.cpp b/tests/mgmt/manager-base.cpp
index fb10973..4e690a9 100644
--- a/tests/mgmt/manager-base.cpp
+++ b/tests/mgmt/manager-base.cpp
@@ -37,6 +37,15 @@
   void
   testSendResponse(const Name& name,
                    uint32_t code,
+                   const std::string& text,
+                   const Block& body)
+  {
+    sendResponse(name, code, text, body);
+  }
+
+  void
+  testSendResponse(const Name& name,
+                   uint32_t code,
                    const std::string& text)
   {
     sendResponse(name, code, text);
@@ -77,6 +86,34 @@
     BOOST_REQUIRE(control.getText() == expectedText);
   }
 
+  void
+  validateControlResponse(const Data& response,
+                          const Name& expectedName,
+                          uint32_t expectedCode,
+                          const std::string& expectedText,
+                          const Block& expectedBody)
+  {
+    m_callbackFired = true;
+    Block controlRaw = response.getContent().blockFromValue();
+
+    ControlResponse control;
+    control.wireDecode(controlRaw);
+
+    NFD_LOG_DEBUG("received control response"
+                  << " name: " << response.getName()
+                  << " code: " << control.getCode()
+                  << " text: " << control.getText());
+
+    BOOST_REQUIRE(response.getName() == expectedName);
+    BOOST_REQUIRE(control.getCode() == expectedCode);
+    BOOST_REQUIRE(control.getText() == expectedText);
+
+    BOOST_REQUIRE(control.getBody().value_size() == expectedBody.value_size());
+
+    BOOST_CHECK(memcmp(control.getBody().value(), expectedBody.value(),
+                       expectedBody.value_size()) == 0);
+  }
+
   bool
   didCallbackFire()
   {
@@ -104,6 +141,19 @@
   BOOST_CHECK_EQUAL(response.getText(), "test");
 }
 
+BOOST_AUTO_TEST_CASE(SendResponse4Arg)
+{
+  ndn::nfd::ControlParameters parameters;
+  parameters.setName("/test/body");
+
+  getInternalFace()->onReceiveData +=
+    bind(&ManagerBaseTest::validateControlResponse, this, _1,
+         "/response", 100, "test", parameters.wireEncode());
+
+  testSendResponse("/response", 100, "test", parameters.wireEncode());
+  BOOST_REQUIRE(didCallbackFire());
+}
+
 
 BOOST_AUTO_TEST_CASE(SendResponse3Arg)
 {
@@ -115,7 +165,6 @@
   BOOST_REQUIRE(didCallbackFire());
 }
 
-
 BOOST_AUTO_TEST_CASE(SendResponse2Arg)
 {
   getInternalFace()->onReceiveData +=
diff --git a/tests/mgmt/strategy-choice-manager.cpp b/tests/mgmt/strategy-choice-manager.cpp
index 4703fb7..f24d58a 100644
--- a/tests/mgmt/strategy-choice-manager.cpp
+++ b/tests/mgmt/strategy-choice-manager.cpp
@@ -208,15 +208,15 @@
 
 BOOST_FIXTURE_TEST_CASE(UnsignedCommand, AllStrategiesFixture)
 {
-  ndn::nfd::StrategyChoiceOptions options;
-  options.setName("/test");
-  options.setStrategy("/localhost/nfd/strategy/best-route");
+  ControlParameters parameters;
+  parameters.setName("/test");
+  parameters.setStrategy("/localhost/nfd/strategy/best-route");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/strategy-choice");
   commandName.append("set");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
 
@@ -232,15 +232,15 @@
 BOOST_FIXTURE_TEST_CASE(UnauthorizedCommand,
                         UnauthorizedCommandFixture<StrategyChoiceManagerFixture>)
 {
-  ndn::nfd::StrategyChoiceOptions options;
-  options.setName("/test");
-  options.setStrategy("/localhost/nfd/strategy/best-route");
+  ControlParameters parameters;
+  parameters.setName("/test");
+  parameters.setStrategy("/localhost/nfd/strategy/best-route");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/strategy-choice");
   commandName.append("set");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -256,14 +256,15 @@
 
 BOOST_AUTO_TEST_CASE(UnsupportedVerb)
 {
-  ndn::nfd::StrategyChoiceOptions options;
-  options.setStrategy("/localhost/nfd/strategy/test-strategy-b");
+  ControlParameters parameters;
+  parameters.setName("/test");
+  parameters.setStrategy("/localhost/nfd/strategy/test-strategy-b");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/strategy-choice");
   commandName.append("unsupported");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -281,7 +282,7 @@
 {
   Name commandName("/localhost/nfd/strategy-choice");
   commandName.append("set");
-  commandName.append("NotReallyOptions");
+  commandName.append("NotReallyParameters");
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -297,43 +298,86 @@
 
 BOOST_AUTO_TEST_CASE(SetStrategies)
 {
-  ndn::nfd::StrategyChoiceOptions options;
-  options.setName("/test");
-  options.setStrategy("/localhost/nfd/strategy/test-strategy-b");
+  ControlParameters parameters;
+  parameters.setName("/test");
+  parameters.setStrategy("/localhost/nfd/strategy/test-strategy-b");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/strategy-choice");
   commandName.append("set");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
 
   getFace()->onReceiveData +=
     bind(&StrategyChoiceManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 200, "Success", encodedOptions);
+         command->getName(), 200, "Success", encodedParameters);
 
   getManager().onValidatedStrategyChoiceRequest(command);
 
   BOOST_REQUIRE(didCallbackFire());
   fw::Strategy& strategy = getStrategyChoice().findEffectiveStrategy("/test");
   BOOST_REQUIRE_EQUAL(strategy.getName(), "/localhost/nfd/strategy/test-strategy-b");
+}
 
-  resetCallbackFired();
-  getFace()->onReceiveData.clear();
+BOOST_AUTO_TEST_CASE(SetStrategiesMissingName)
+{
+  ControlParameters parameters;
+  parameters.setStrategy("/localhost/nfd/strategy/test-strategy-b");
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name commandName("/localhost/nfd/strategy-choice");
+  commandName.append("set");
+  commandName.append(encodedParameters);
+
+  shared_ptr<Interest> command(make_shared<Interest>(commandName));
+
+  getFace()->onReceiveData +=
+    bind(&StrategyChoiceManagerFixture::validateControlResponse, this, _1,
+         command->getName(), 400, "Malformed command");
+
+  getManager().onValidatedStrategyChoiceRequest(command);
+
+  BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(SetStrategiesMissingStrategy)
+{
+  ControlParameters parameters;
+  parameters.setName("/test");
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name commandName("/localhost/nfd/strategy-choice");
+  commandName.append("set");
+  commandName.append(encodedParameters);
+
+  shared_ptr<Interest> command(make_shared<Interest>(commandName));
+
+  getFace()->onReceiveData +=
+    bind(&StrategyChoiceManagerFixture::validateControlResponse, this, _1,
+         command->getName(), 400, "Malformed command");
+
+  getManager().onValidatedStrategyChoiceRequest(command);
+
+  BOOST_REQUIRE(didCallbackFire());
+  fw::Strategy& strategy = getStrategyChoice().findEffectiveStrategy("/test");
+  BOOST_REQUIRE_EQUAL(strategy.getName(), "/localhost/nfd/strategy/test-strategy-a");
 }
 
 BOOST_AUTO_TEST_CASE(SetUnsupportedStrategy)
 {
-  ndn::nfd::StrategyChoiceOptions options;
-  options.setName("/test");
-  options.setStrategy("/localhost/nfd/strategy/unit-test-doesnotexist");
+  ControlParameters parameters;
+  parameters.setName("/test");
+  parameters.setStrategy("/localhost/nfd/strategy/unit-test-doesnotexist");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/strategy-choice");
   commandName.append("set");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -370,15 +414,15 @@
 // BOOST_FIXTURE_TEST_CASE(SetNotInstalled, DefaultStrategyOnlyFixture)
 // {
 //   BOOST_REQUIRE(!getStrategyChoice().hasStrategy("/localhost/nfd/strategy/test-strategy-b"));
-//   ndn::nfd::StrategyChoiceOptions options;
-//   options.setName("/test");
-//   options.setStrategy("/localhost/nfd/strategy/test-strategy-b");
+//   ControlParameters parameters;
+//   parameters.setName("/test");
+//   parameters.setStrategy("/localhost/nfd/strategy/test-strategy-b");
 
-//   Block encodedOptions(options.wireEncode());
+//   Block encodedParameters(parameters.wireEncode());
 
 //   Name commandName("/localhost/nfd/strategy-choice");
 //   commandName.append("set");
-//   commandName.append(encodedOptions);
+//   commandName.append(encodedParameters);
 
 //   shared_ptr<Interest> command(make_shared<Interest>(commandName));
 //   generateCommand(*command);
@@ -396,25 +440,25 @@
 
 BOOST_AUTO_TEST_CASE(Unset)
 {
-  ndn::nfd::StrategyChoiceOptions options;
-  options.setName("/test");
+  ControlParameters parameters;
+  parameters.setName("/test");
 
   BOOST_REQUIRE(m_strategyChoice.insert("/test", "/localhost/nfd/strategy/test-strategy-b"));
   BOOST_REQUIRE_EQUAL(m_strategyChoice.findEffectiveStrategy("/test").getName(),
                       "/localhost/nfd/strategy/test-strategy-b");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/strategy-choice");
   commandName.append("unset");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
 
   getFace()->onReceiveData +=
     bind(&StrategyChoiceManagerFixture::validateControlResponse, this, _1,
-         command->getName(), 200, "Success", encodedOptions);
+         command->getName(), 200, "Success", encodedParameters);
 
   getManager().onValidatedStrategyChoiceRequest(command);
 
@@ -426,14 +470,14 @@
 
 BOOST_AUTO_TEST_CASE(UnsetRoot)
 {
-  ndn::nfd::StrategyChoiceOptions options;
-  options.setName("/");
+  ControlParameters parameters;
+  parameters.setName("/");
 
-  Block encodedOptions(options.wireEncode());
+  Block encodedParameters(parameters.wireEncode());
 
   Name commandName("/localhost/nfd/strategy-choice");
   commandName.append("unset");
-  commandName.append(encodedOptions);
+  commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
   generateCommand(*command);
@@ -450,6 +494,35 @@
                     "/localhost/nfd/strategy/test-strategy-a");
 }
 
+BOOST_AUTO_TEST_CASE(UnsetMissingName)
+{
+  ControlParameters parameters;
+
+  BOOST_REQUIRE(m_strategyChoice.insert("/test", "/localhost/nfd/strategy/test-strategy-b"));
+  BOOST_REQUIRE_EQUAL(m_strategyChoice.findEffectiveStrategy("/test").getName(),
+                      "/localhost/nfd/strategy/test-strategy-b");
+
+  Block encodedParameters(parameters.wireEncode());
+
+  Name commandName("/localhost/nfd/strategy-choice");
+  commandName.append("unset");
+  commandName.append(encodedParameters);
+
+  shared_ptr<Interest> command(make_shared<Interest>(commandName));
+  generateCommand(*command);
+
+  getFace()->onReceiveData +=
+    bind(&StrategyChoiceManagerFixture::validateControlResponse, this, _1,
+         command->getName(), 400, "Malformed command");
+
+  getManager().onValidatedStrategyChoiceRequest(command);
+
+  BOOST_REQUIRE(didCallbackFire());
+
+  BOOST_CHECK_EQUAL(m_strategyChoice.findEffectiveStrategy("/test").getName(),
+                    "/localhost/nfd/strategy/test-strategy-b");
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // namespace tests