model+helper+examples: Enable configurability of NFD parameters using StackHelper

Refs: #2353, #2220
diff --git a/examples/ndn-congestion-alt-topo-plugin.cpp b/examples/ndn-congestion-alt-topo-plugin.cpp
index f79bf5d..db0afc7 100644
--- a/examples/ndn-congestion-alt-topo-plugin.cpp
+++ b/examples/ndn-congestion-alt-topo-plugin.cpp
@@ -69,9 +69,8 @@
 
   // Install NDN stack on all nodes
   ndn::StackHelper ndnHelper;
-  ndnHelper.SetContentStoreChoice(false);
-  ndnHelper.SetContentStore("ns3::ndn::cs::Lru", "MaxSize",
-                            "1"); // ! Attention ! If set to 0, then MaxSize is infinite
+  ndnHelper.SetOldContentStore("ns3::ndn::cs::Lru", "MaxSize",
+                               "1"); // ! Attention ! If set to 0, then MaxSize is infinite
   ndnHelper.InstallAll();
 
   // Set BestRoute strategy
diff --git a/examples/ndn-congestion-topo-plugin.cpp b/examples/ndn-congestion-topo-plugin.cpp
index 11fed0e..ba40c7a 100644
--- a/examples/ndn-congestion-topo-plugin.cpp
+++ b/examples/ndn-congestion-topo-plugin.cpp
@@ -57,8 +57,7 @@
 
   // Install NDN stack on all nodes
   ndn::StackHelper ndnHelper;
-  ndnHelper.SetContentStoreChoice(false);
-  ndnHelper.SetContentStore("ns3::ndn::cs::Lru", "MaxSize", "10000");
+  ndnHelper.SetOldContentStore("ns3::ndn::cs::Lru", "MaxSize", "10000");
   ndnHelper.InstallAll();
 
   // Choosing forwarding strategy
diff --git a/examples/ndn-simple-wifi.cpp b/examples/ndn-simple-wifi.cpp
index 8230e18..0afaa14 100644
--- a/examples/ndn-simple-wifi.cpp
+++ b/examples/ndn-simple-wifi.cpp
@@ -105,8 +105,7 @@
   ndn::StackHelper ndnHelper;
   // ndnHelper.AddNetDeviceFaceCreateCallback (WifiNetDevice::GetTypeId (), MakeCallback
   // (MyNetDeviceFaceCallback));
-  ndnHelper.SetContentStoreChoice(false);
-  ndnHelper.SetContentStore("ns3::ndn::cs::Lru", "MaxSize", "1000");
+  ndnHelper.SetOldContentStore("ns3::ndn::cs::Lru", "MaxSize", "1000");
   ndnHelper.SetDefaultRoutes(true);
   ndnHelper.Install(nodes);
 
diff --git a/examples/ndn-tree-cs-tracers.cpp b/examples/ndn-tree-cs-tracers.cpp
index a2059b2..cee7302 100644
--- a/examples/ndn-tree-cs-tracers.cpp
+++ b/examples/ndn-tree-cs-tracers.cpp
@@ -67,11 +67,10 @@
   topologyReader.SetFileName("src/ndnSIM/examples/topologies/topo-tree.txt");
   topologyReader.Read();
 
-  // Install CCNx stack on all nodes
+  // Install NDN stack on all nodes
   ndn::StackHelper ndnHelper;
-  ndnHelper.SetContentStoreChoice(false);
-  ndnHelper.SetContentStore("ns3::ndn::cs::Lru", "MaxSize",
-                            "100"); // default ContentStore parameters
+  ndnHelper.SetOldContentStore("ns3::ndn::cs::Lru", "MaxSize",
+                               "100"); // default ContentStore parameters
   ndnHelper.InstallAll();
 
   // Choosing forwarding strategy
diff --git a/examples/ndn-tree-with-l2tracer.cpp b/examples/ndn-tree-with-l2tracer.cpp
index 52b8e8d..ab80675 100644
--- a/examples/ndn-tree-with-l2tracer.cpp
+++ b/examples/ndn-tree-with-l2tracer.cpp
@@ -38,8 +38,7 @@
   /****************************************************************************/
   // Install NDN stack on all nodes
   ndn::StackHelper ndnHelper;
-  ndnHelper.SetContentStoreChoice(false);
-  ndnHelper.SetContentStore("ns3::ndn::cs::Lru", "MaxSize", "1000");
+  ndnHelper.SetOldContentStore("ns3::ndn::cs::Lru", "MaxSize", "1000");
   ndnHelper.InstallAll();
   /****************************************************************************/
   // Installing global routing interface on all nodes
diff --git a/helper/ndn-fib-helper.cpp b/helper/ndn-fib-helper.cpp
index 6218aeb..dddcc8a 100644
--- a/helper/ndn-fib-helper.cpp
+++ b/helper/ndn-fib-helper.cpp
@@ -59,7 +59,7 @@
   commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
-  StackHelper::getKeyChain().signWithSha256(*command);
+  StackHelper::getKeyChain().sign(*command);
 
   Ptr<L3Protocol> l3protocol = node->GetObject<L3Protocol>();
   shared_ptr<nfd::FibManager> fibManager = l3protocol->getFibManager();
@@ -77,7 +77,7 @@
   commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
-  StackHelper::getKeyChain().signWithSha256(*command);
+  StackHelper::getKeyChain().sign(*command);
 
   Ptr<L3Protocol> L3protocol = node->GetObject<L3Protocol>();
   shared_ptr<nfd::FibManager> fibManager = L3protocol->getFibManager();
diff --git a/helper/ndn-stack-helper.cpp b/helper/ndn-stack-helper.cpp
index 5e2038c..6e45281 100644
--- a/helper/ndn-stack-helper.cpp
+++ b/helper/ndn-stack-helper.cpp
@@ -41,7 +41,7 @@
 
 StackHelper::StackHelper()
   : m_needSetDefaultRoutes(false)
-  , m_shouldUseNfdCs(true)
+  , m_maxCsSize(100)
 {
   setCustomNdnCxxClocks();
 
@@ -96,14 +96,13 @@
 }
 
 void
-StackHelper::SetContentStore(const std::string& contentStore, const std::string& attr1,
-                             const std::string& value1, const std::string& attr2,
-                             const std::string& value2, const std::string& attr3,
-                             const std::string& value3, const std::string& attr4,
-                             const std::string& value4)
+StackHelper::SetOldContentStore(const std::string& contentStore, const std::string& attr1,
+                                const std::string& value1, const std::string& attr2,
+                                const std::string& value2, const std::string& attr3,
+                                const std::string& value3, const std::string& attr4,
+                                const std::string& value4)
 {
-  NS_ASSERT_MSG(m_shouldUseNfdCs == false,
-                "First choose not to use NFD's CS and then select the replacement policy");
+  m_maxCsSize = 0;
 
   m_contentStoreFactory.SetTypeId(contentStore);
   if (attr1 != "")
@@ -117,15 +116,9 @@
 }
 
 void
-StackHelper::SetContentStoreChoice(bool shouldUseNfdCs)
+StackHelper::setCsSize(size_t maxSize)
 {
-  m_shouldUseNfdCs = shouldUseNfdCs;
-}
-
-bool
-StackHelper::shouldUseNfdCs() const
-{
-  return m_shouldUseNfdCs;
+  m_maxCsSize = maxSize;
 }
 
 Ptr<FaceContainer>
@@ -157,12 +150,15 @@
 
   Ptr<L3Protocol> ndn = m_ndnFactory.Create<L3Protocol>();
 
+  ndn->getConfig().put("tables.cs_max_packets", (m_maxCsSize == 0) ? 1 : m_maxCsSize);
+
   // NFD initialization
-  ndn->initialize(m_shouldUseNfdCs);
+  ndn->initialize();
 
   // Create and aggregate content store if NFD's contest store has been disabled
-  if (!m_shouldUseNfdCs)
+  if (m_maxCsSize == 0) {
     ndn->AggregateObject(m_contentStoreFactory.Create<ContentStore>());
+  }
 
   // Aggregate L3Protocol on node (must be after setting ndnSIM CS)
   node->AggregateObject(ndn);
diff --git a/helper/ndn-stack-helper.hpp b/helper/ndn-stack-helper.hpp
index 63cc564..836a6b4 100644
--- a/helper/ndn-stack-helper.hpp
+++ b/helper/ndn-stack-helper.hpp
@@ -61,7 +61,7 @@
  * attribute or a set of functionality that may be of interest to many other
  * classes.
  */
-class StackHelper {
+class StackHelper : boost::noncopyable {
 public:
   /**
    * \brief Create a new NdnStackHelper with a default NDN_FLOODING forwarding stategy
@@ -87,25 +87,14 @@
    * @param contentStoreClass string, representing class of the content store
    */
   void
-  SetContentStore(const std::string& contentStoreClass, const std::string& attr1 = "",
+  SetOldContentStore(const std::string& contentStoreClass, const std::string& attr1 = "",
                   const std::string& value1 = "", const std::string& attr2 = "",
                   const std::string& value2 = "", const std::string& attr3 = "",
                   const std::string& value3 = "", const std::string& attr4 = "",
                   const std::string& value4 = "");
 
-  /**
-   * @brief Set to use native NFD's content store or ndnSIM provided CS implementations
-   *
-   * @note ndnSIM CS implementations have limited support for NDN selectors
-   */
   void
-  SetContentStoreChoice(const bool shouldUseNfdCs);
-
-  /**
-   * @brief Check if stack is using native NFD content store implementation
-   */
-  bool
-  shouldUseNfdCs() const;
+  setCsSize(size_t maxSize);
 
   typedef Callback<shared_ptr<NetDeviceFace>, Ptr<Node>, Ptr<L3Protocol>, Ptr<NetDevice>>
     NetDeviceFaceCreateCallback;
@@ -214,16 +203,11 @@
   setCustomNdnCxxClocks();
 
 private:
-  StackHelper(const StackHelper&);
-  StackHelper&
-  operator=(const StackHelper& o);
-
-private:
   ObjectFactory m_ndnFactory;
   ObjectFactory m_contentStoreFactory;
 
   bool m_needSetDefaultRoutes;
-  bool m_shouldUseNfdCs;
+  size_t m_maxCsSize;
 
   typedef std::list<std::pair<TypeId, NetDeviceFaceCreateCallback>> NetDeviceCallbackList;
   NetDeviceCallbackList m_netDeviceCallbacks;
diff --git a/helper/ndn-strategy-choice-helper.cpp b/helper/ndn-strategy-choice-helper.cpp
index 53e0209..53ba544 100644
--- a/helper/ndn-strategy-choice-helper.cpp
+++ b/helper/ndn-strategy-choice-helper.cpp
@@ -39,7 +39,7 @@
   commandName.append(encodedParameters);
 
   shared_ptr<Interest> command(make_shared<Interest>(commandName));
-  StackHelper::getKeyChain().signWithSha256(*command);
+  StackHelper::getKeyChain().sign(*command);
   Ptr<L3Protocol> L3protocol = node->GetObject<L3Protocol>();
   auto strategyChoiceManager = L3protocol->getStrategyChoiceManager();
   strategyChoiceManager->onStrategyChoiceRequest(*command);
diff --git a/model/ndn-l3-protocol.cpp b/model/ndn-l3-protocol.cpp
index afcab43..dc487bc 100644
--- a/model/ndn-l3-protocol.cpp
+++ b/model/ndn-l3-protocol.cpp
@@ -36,7 +36,7 @@
 #include "../helper/ndn-stack-helper.hpp"
 #include "cs/ndn-content-store.hpp"
 
-#include <boost/foreach.hpp>
+#include <boost/property_tree/info_parser.hpp>
 
 #include "ns3/ndnSIM/NFD/daemon/fw/forwarder.hpp"
 #include "ns3/ndnSIM/NFD/daemon/mgmt/internal-face.hpp"
@@ -83,6 +83,61 @@
 
 class L3Protocol::Impl {
 private:
+  Impl()
+  {
+    // Do not modify initial config file. Use helpers to set specific NFD parameters
+    std::string initialConfig =
+      "general\n"
+      "{\n"
+      "}\n"
+      "\n"
+      "tables\n"
+      "{\n"
+      "  cs_max_packets 100\n"
+      "\n"
+      "  strategy_choice\n"
+      "  {\n"
+      "    /               /localhost/nfd/strategy/best-route\n"
+      "    /localhost      /localhost/nfd/strategy/broadcast\n"
+      "    /localhost/nfd  /localhost/nfd/strategy/best-route\n"
+      "    /ndn/broadcast  /localhost/nfd/strategy/broadcast\n"
+      "  }\n"
+      "}\n"
+      "\n"
+      // "face_system\n"
+      // "{\n"
+      // "}\n"
+      "\n"
+      "authorizations\n"
+      "{\n"
+      "  authorize\n"
+      "  {\n"
+      "    certfile any\n"
+      "    privileges\n"
+      "    {\n"
+      "      faces\n"
+      "      fib\n"
+      "      strategy-choice\n"
+      "    }\n"
+      "  }\n"
+      "}\n"
+      "\n"
+      "rib\n"
+      "{\n"
+      "  localhost_security\n"
+      "  {\n"
+      "    trust-anchor\n"
+      "    {\n"
+      "      type any\n"
+      "    }\n"
+      "  }\n"
+      "}\n"
+      "\n";
+
+    std::istringstream input(initialConfig);
+    boost::property_tree::read_info(input, m_config);
+  }
+
   friend class L3Protocol;
 
   shared_ptr<nfd::Forwarder> m_forwarder;
@@ -93,6 +148,8 @@
   shared_ptr<nfd::StrategyChoiceManager> m_strategyChoiceManager;
   shared_ptr<nfd::StatusServer> m_statusServer;
 
+  nfd::ConfigSection m_config;
+
   Ptr<ContentStore> m_csFromNdnSim;
 };
 
@@ -108,11 +165,11 @@
 }
 
 void
-L3Protocol::initialize(bool shouldUseNfdCs)
+L3Protocol::initialize()
 {
   m_impl->m_forwarder = make_shared<nfd::Forwarder>();
 
-  initializeManagement(shouldUseNfdCs);
+  initializeManagement();
 
   m_impl->m_forwarder->getFaceTable().addReserved(make_shared<nfd::NullFace>(), nfd::FACEID_NULL);
   m_impl->m_forwarder->getFaceTable().addReserved(make_shared<nfd::NullFace>(
@@ -120,41 +177,75 @@
                                                   nfd::FACEID_CONTENT_STORE);
 }
 
-void
-L3Protocol::initializeManagement(bool shouldUseNfdCs)
+class IgnoreSections
 {
-  m_impl->m_internalFace = make_shared<nfd::InternalFace>();
+public:
+  IgnoreSections(const std::vector<std::string>& ignored)
+    : m_ignored(ignored)
+  {
+  }
 
-  m_impl->m_fibManager =
-    make_shared<nfd::FibManager>(ref(m_impl->m_forwarder->getFib()),
-                                 bind(&nfd::Forwarder::getFace, m_impl->m_forwarder.get(), _1),
-                                 m_impl->m_internalFace, std::ref(StackHelper::getKeyChain()));
+  void
+  operator()(const std::string& filename, const std::string& sectionName,
+             const nfd::ConfigSection& section, bool isDryRun)
 
-  m_impl->m_faceManager =
-    make_shared<nfd::FaceManager>(ref(m_impl->m_forwarder->getFaceTable()), m_impl->m_internalFace,
-                                  std::ref(StackHelper::getKeyChain()));
+  {
+    if (std::find(m_ignored.begin(), m_ignored.end(), sectionName) == m_ignored.end()) {
+      nfd::ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
+    }
+  }
+private:
+  std::vector<std::string> m_ignored;
+};
+
+void
+L3Protocol::initializeManagement()
+{
+  auto keyChain = std::ref(StackHelper::getKeyChain());
+  auto& forwarder = m_impl->m_forwarder;
+  using namespace nfd;
+
+  m_impl->m_internalFace = make_shared<InternalFace>();
+
+  m_impl->m_fibManager = make_shared<FibManager>(std::ref(forwarder->getFib()),
+                                                 bind(&Forwarder::getFace, forwarder.get(), _1),
+                                                 m_impl->m_internalFace, keyChain);
+
+  m_impl->m_faceManager = make_shared<FaceManager>(std::ref(forwarder->getFaceTable()),
+                                                   m_impl->m_internalFace,
+                                                   keyChain);
 
   m_impl->m_strategyChoiceManager =
-    make_shared<nfd::StrategyChoiceManager>(ref(m_impl->m_forwarder->getStrategyChoice()),
-                                            m_impl->m_internalFace,
-                                            std::ref(StackHelper::getKeyChain()));
+    make_shared<StrategyChoiceManager>(std::ref(forwarder->getStrategyChoice()),
+                                       m_impl->m_internalFace,
+                                       keyChain);
 
-  m_impl->m_statusServer =
-    make_shared<nfd::StatusServer>(m_impl->m_internalFace, ref(*m_impl->m_forwarder),
-                                   std::ref(StackHelper::getKeyChain()));
+  m_impl->m_statusServer = make_shared<StatusServer>(m_impl->m_internalFace,
+                                                     ref(*forwarder),
+                                                     keyChain);
 
-  nfd::TablesConfigSection tablesConfig(m_impl->m_forwarder->getCs(),
-                                        m_impl->m_forwarder->getPit(),
-                                        m_impl->m_forwarder->getFib(),
-                                        m_impl->m_forwarder->getStrategyChoice(),
-                                        m_impl->m_forwarder->getMeasurements());
+  ConfigFile config((IgnoreSections({"general", "log", "rib"})));
 
-  m_impl->m_forwarder->getFaceTable().addReserved(m_impl->m_internalFace,
-                                                  nfd::FACEID_INTERNAL_FACE);
+  TablesConfigSection tablesConfig(forwarder->getCs(),
+                                   forwarder->getPit(),
+                                   forwarder->getFib(),
+                                   forwarder->getStrategyChoice(),
+                                   forwarder->getMeasurements());
+  tablesConfig.setConfigFile(config);
+
+  m_impl->m_internalFace->getValidator().setConfigFile(config);
+
+  forwarder->getFaceTable().addReserved(m_impl->m_internalFace, FACEID_INTERNAL_FACE);
+
+  m_impl->m_faceManager->setConfigFile(config);
+
+  // apply config
+  config.parse(m_impl->m_config, false, "ndnSIM.conf");
+
+  tablesConfig.ensureTablesAreConfigured();
 
   // add FIB entry for NFD Management Protocol
-  shared_ptr<::nfd::fib::Entry> entry =
-    m_impl->m_forwarder->getFib().insert("/localhost/nfd").first;
+  shared_ptr<fib::Entry> entry = forwarder->getFib().insert("/localhost/nfd").first;
   entry->addNextHop(m_impl->m_internalFace, 0);
 }
 
@@ -176,6 +267,12 @@
   return m_impl->m_strategyChoiceManager;
 }
 
+nfd::ConfigSection&
+L3Protocol::getConfig()
+{
+  return m_impl->m_config;
+}
+
 /*
  * This method is called by AddAgregate and completes the aggregation
  * by setting the node in the ndn stack
diff --git a/model/ndn-l3-protocol.hpp b/model/ndn-l3-protocol.hpp
index 13f6106..11de1b8 100644
--- a/model/ndn-l3-protocol.hpp
+++ b/model/ndn-l3-protocol.hpp
@@ -31,10 +31,13 @@
 #include "ns3/nstime.h"
 #include "ns3/traced-callback.h"
 
+#include <boost/property_tree/ptree_fwd.hpp>
+
 namespace nfd {
 class Forwarder;
 class FibManager;
 class StrategyChoiceManager;
+typedef boost::property_tree::ptree ConfigSection;
 } // namespace nfd
 
 namespace ns3 {
@@ -90,7 +93,7 @@
    * \brief Initialize NFD instance
    */
   void
-  initialize(bool shouldUseNfdCs);
+  initialize();
 
   /**
    * \brief Get smart pointer to nfd::Forwarder installed on the node
@@ -142,6 +145,12 @@
   shared_ptr<Face>
   getFaceByNetDevice(Ptr<NetDevice> netDevice) const;
 
+  /**
+   * \brief Get NFD config (boost::property_tree)
+   */
+  nfd::ConfigSection&
+  getConfig();
+
 protected:
   virtual void
   DoDispose(void); ///< @brief Do cleanup
@@ -157,7 +166,7 @@
 
 private:
   void
-  initializeManagement(bool isNfd);
+  initializeManagement();
 
 private:
   class Impl;