mgmt: tables.cs_policy config option

refs #3148

Change-Id: Icf30bbe508c1c491949d9fcb433fdfa16842d312
diff --git a/daemon/mgmt/tables-config-section.cpp b/daemon/mgmt/tables-config-section.cpp
index 397f26c..7d355d0 100644
--- a/daemon/mgmt/tables-config-section.cpp
+++ b/daemon/mgmt/tables-config-section.cpp
@@ -50,6 +50,7 @@
   }
 
   m_forwarder.getCs().setLimit(DEFAULT_CS_MAX_PACKETS);
+  // Don't set default cs_policy because it's already created by CS itself.
   m_forwarder.setUnsolicitedDataPolicy(make_unique<fw::DefaultUnsolicitedDataPolicy>());
 
   m_isConfigured = true;
@@ -66,14 +67,25 @@
     nCsMaxPackets = ConfigFile::parseNumber<size_t>(*csMaxPacketsNode, "cs_max_packets", "tables");
   }
 
+  unique_ptr<cs::Policy> csPolicy;
+  OptionalNode csPolicyNode = section.get_child_optional("cs_policy");
+  if (csPolicyNode) {
+    std::string policyName = csPolicyNode->get_value<std::string>();
+    csPolicy = cs::Policy::create(policyName);
+    if (csPolicy == nullptr) {
+      BOOST_THROW_EXCEPTION(ConfigFile::Error(
+        "Unknown cs_policy \"" + policyName + "\" in \"tables\" section"));
+    }
+  }
+
   unique_ptr<fw::UnsolicitedDataPolicy> unsolicitedDataPolicy;
   OptionalNode unsolicitedDataPolicyNode = section.get_child_optional("cs_unsolicited_policy");
   if (unsolicitedDataPolicyNode) {
-    std::string policyKey = unsolicitedDataPolicyNode->get_value<std::string>();
-    unsolicitedDataPolicy = fw::UnsolicitedDataPolicy::create(policyKey);
+    std::string policyName = unsolicitedDataPolicyNode->get_value<std::string>();
+    unsolicitedDataPolicy = fw::UnsolicitedDataPolicy::create(policyName);
     if (unsolicitedDataPolicy == nullptr) {
       BOOST_THROW_EXCEPTION(ConfigFile::Error(
-        "Unknown cs_unsolicited_policy \"" + policyKey + "\" in \"tables\" section"));
+        "Unknown cs_unsolicited_policy \"" + policyName + "\" in \"tables\" section"));
     }
   }
   else {
@@ -94,7 +106,11 @@
     return;
   }
 
-  m_forwarder.getCs().setLimit(nCsMaxPackets);
+  Cs& cs = m_forwarder.getCs();
+  cs.setLimit(nCsMaxPackets);
+  if (cs.size() == 0 && csPolicy != nullptr) {
+    cs.setPolicy(std::move(csPolicy));
+  }
 
   m_forwarder.setUnsolicitedDataPolicy(std::move(unsolicitedDataPolicy));
 
diff --git a/daemon/mgmt/tables-config-section.hpp b/daemon/mgmt/tables-config-section.hpp
index 8afa608..d1ac1d4 100644
--- a/daemon/mgmt/tables-config-section.hpp
+++ b/daemon/mgmt/tables-config-section.hpp
@@ -38,7 +38,7 @@
  *  tables
  *  {
  *    cs_max_packets 65536
- *
+ *    cs_policy priority_fifo
  *    cs_unsolicited_policy drop-all
  *
  *    strategy_choice
@@ -58,7 +58,7 @@
  *  \endcode
  *
  *  During a configuration reload,
- *  \li cs_max_packets and cs_unsolicited_policy are applied;
+ *  \li cs_max_packets, cs_policy, and cs_unsolicited_policy are applied;
  *      defaults are used if an option is omitted.
  *  \li strategy_choice entries are inserted, but old entries are not deleted.
  *  \li network_region is applied; it's kept unchanged if the section is omitted.
diff --git a/daemon/table/cs.cpp b/daemon/table/cs.cpp
index 0dd5ca2..dd72214 100644
--- a/daemon/table/cs.cpp
+++ b/daemon/table/cs.cpp
@@ -51,9 +51,9 @@
   return Policy::create(DEFAULT_POLICY);
 }
 
-Cs::Cs(size_t nMaxPackets, unique_ptr<Policy> policy)
+Cs::Cs(size_t nMaxPackets)
 {
-  this->setPolicyImpl(std::move(policy));
+  this->setPolicyImpl(makeDefaultPolicy());
   m_policy->setLimit(nMaxPackets);
 }
 
diff --git a/daemon/table/cs.hpp b/daemon/table/cs.hpp
index 8c3e46b..03d6fdd 100644
--- a/daemon/table/cs.hpp
+++ b/daemon/table/cs.hpp
@@ -57,16 +57,13 @@
 namespace nfd {
 namespace cs {
 
-unique_ptr<Policy>
-makeDefaultPolicy();
-
 /** \brief represents the ContentStore
  */
 class Cs : noncopyable
 {
 public:
   explicit
-  Cs(size_t nMaxPackets = 10, unique_ptr<Policy> policy = makeDefaultPolicy());
+  Cs(size_t nMaxPackets = 10);
 
   /** \brief inserts a Data packet
    */