face: allow enabling/disabling congestion marking through config file

refs #4465

Change-Id: I888b83b1fdbe8e3fc36a902bf7af52147807d829
diff --git a/daemon/face/face-system.cpp b/daemon/face/face-system.cpp
index 6288ac0..6430796 100644
--- a/daemon/face/face-system.cpp
+++ b/daemon/face/face-system.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -89,6 +89,21 @@
   ConfigContext context;
   context.isDryRun = isDryRun;
 
+  // process general protocol factory config section
+  auto generalSection = configSection.get_child_optional("general");
+  if (generalSection) {
+    for (const auto& pair : *generalSection) {
+      const std::string& key = pair.first;
+      if (key == "enable_congestion_marking") {
+        // false by default
+        context.generalConfig.wantCongestionMarking = ConfigFile::parseYesNo(pair, "face_system.general");
+      }
+      else {
+        BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.general." + key));
+      }
+    }
+  }
+
   // process sections in protocol factories
   for (const auto& pair : m_factories) {
     const std::string& sectionName = pair.first;
@@ -123,7 +138,7 @@
       BOOST_THROW_EXCEPTION(ConfigFile::Error("Duplicate section face_system." + sectionName));
     }
 
-    if (m_factories.count(sectionName) > 0) {
+    if (sectionName == "general" || m_factories.count(sectionName) > 0) {
       continue;
     }
 
diff --git a/daemon/face/face-system.hpp b/daemon/face/face-system.hpp
index 5ea428f..1a49fce 100644
--- a/daemon/face/face-system.hpp
+++ b/daemon/face/face-system.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -80,11 +80,19 @@
   void
   setConfigFile(ConfigFile& configFile);
 
+  /** \brief configuration options from "general" section
+   */
+  struct GeneralConfig
+  {
+    bool wantCongestionMarking = false;
+  };
+
   /** \brief context for processing a config section in ProtocolFactory
    */
   class ConfigContext : noncopyable
   {
   public:
+    GeneralConfig generalConfig;
     bool isDryRun;
   };
 
diff --git a/daemon/face/tcp-channel.cpp b/daemon/face/tcp-channel.cpp
index 4c4c290..1dee521 100644
--- a/daemon/face/tcp-channel.cpp
+++ b/daemon/face/tcp-channel.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -35,10 +35,11 @@
 
 namespace ip = boost::asio::ip;
 
-TcpChannel::TcpChannel(const tcp::Endpoint& localEndpoint)
+TcpChannel::TcpChannel(const tcp::Endpoint& localEndpoint, bool wantCongestionMarking)
   : m_localEndpoint(localEndpoint)
   , m_acceptor(getGlobalIoService())
   , m_socket(getGlobalIoService())
+  , m_wantCongestionMarking(wantCongestionMarking)
 {
   setUri(FaceUri(m_localEndpoint));
   NFD_LOG_CHAN_INFO("Creating channel");
@@ -111,6 +112,7 @@
     GenericLinkService::Options options;
     options.allowLocalFields = wantLocalFields;
     options.reliabilityOptions.isEnabled = wantLpReliability;
+    options.allowCongestionMarking = m_wantCongestionMarking;
     auto linkService = make_unique<GenericLinkService>(options);
 
     auto transport = make_unique<TcpTransport>(std::move(socket), persistency);
diff --git a/daemon/face/tcp-channel.hpp b/daemon/face/tcp-channel.hpp
index ca4c522..1587b99 100644
--- a/daemon/face/tcp-channel.hpp
+++ b/daemon/face/tcp-channel.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -53,8 +53,7 @@
    * To enable creation faces upon incoming connections,
    * one needs to explicitly call TcpChannel::listen method.
    */
-  explicit
-  TcpChannel(const tcp::Endpoint& localEndpoint);
+  TcpChannel(const tcp::Endpoint& localEndpoint, bool wantCongestionMarking);
 
   bool
   isListening() const override
@@ -138,6 +137,7 @@
   boost::asio::ip::tcp::acceptor m_acceptor;
   boost::asio::ip::tcp::socket m_socket;
   std::map<tcp::Endpoint, shared_ptr<Face>> m_channelFaces;
+  bool m_wantCongestionMarking;
 };
 
 } // namespace face
diff --git a/daemon/face/tcp-factory.cpp b/daemon/face/tcp-factory.cpp
index 66335c5..fae3c54 100644
--- a/daemon/face/tcp-factory.cpp
+++ b/daemon/face/tcp-factory.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -59,6 +59,8 @@
   //   enable_v6 yes
   // }
 
+  m_wantCongestionMarking = context.generalConfig.wantCongestionMarking;
+
   if (!configSection) {
     if (!context.isDryRun && !m_channels.empty()) {
       NFD_LOG_WARN("Cannot disable tcp4 and tcp6 channels after initialization");
@@ -178,7 +180,7 @@
   if (it != m_channels.end())
     return it->second;
 
-  auto channel = make_shared<TcpChannel>(endpoint);
+  auto channel = make_shared<TcpChannel>(endpoint, m_wantCongestionMarking);
   m_channels[endpoint] = channel;
   return channel;
 }
diff --git a/daemon/face/tcp-factory.hpp b/daemon/face/tcp-factory.hpp
index f67de85..7fbac39 100644
--- a/daemon/face/tcp-factory.hpp
+++ b/daemon/face/tcp-factory.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -73,6 +73,7 @@
 
 private:
   std::map<tcp::Endpoint, shared_ptr<TcpChannel>> m_channels;
+  bool m_wantCongestionMarking;
 };
 
 } // namespace face
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index 6ecaeaf..3f3271e 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -36,10 +36,12 @@
 namespace ip = boost::asio::ip;
 
 UdpChannel::UdpChannel(const udp::Endpoint& localEndpoint,
-                       time::nanoseconds idleTimeout)
+                       time::nanoseconds idleTimeout,
+                       bool wantCongestionMarking)
   : m_localEndpoint(localEndpoint)
   , m_socket(getGlobalIoService())
   , m_idleFaceTimeout(idleTimeout)
+  , m_wantCongestionMarking(wantCongestionMarking)
 {
   setUri(FaceUri(m_localEndpoint));
   NFD_LOG_CHAN_INFO("Creating channel");
@@ -161,6 +163,7 @@
 
   GenericLinkService::Options options;
   options.reliabilityOptions.isEnabled = wantLpReliability;
+  options.allowCongestionMarking = m_wantCongestionMarking;
   auto linkService = make_unique<GenericLinkService>(options);
   auto transport = make_unique<UnicastUdpTransport>(std::move(socket), persistency, m_idleFaceTimeout);
   auto face = make_shared<Face>(std::move(linkService), std::move(transport));
diff --git a/daemon/face/udp-channel.hpp b/daemon/face/udp-channel.hpp
index 471a971..4441370 100644
--- a/daemon/face/udp-channel.hpp
+++ b/daemon/face/udp-channel.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -48,7 +48,8 @@
    * The created socket is bound to \p localEndpoint.
    */
   UdpChannel(const udp::Endpoint& localEndpoint,
-             time::nanoseconds idleTimeout);
+             time::nanoseconds idleTimeout,
+             bool wantCongestionMarking);
 
   bool
   isListening() const override
@@ -120,6 +121,7 @@
   std::array<uint8_t, ndn::MAX_NDN_PACKET_SIZE> m_receiveBuffer;
   std::map<udp::Endpoint, shared_ptr<Face>> m_channelFaces;
   const time::nanoseconds m_idleFaceTimeout; ///< Timeout for automatic closure of idle on-demand faces
+  bool m_wantCongestionMarking;
 };
 
 } // namespace face
diff --git a/daemon/face/udp-factory.cpp b/daemon/face/udp-factory.cpp
index 2024cd6..0a377ab 100644
--- a/daemon/face/udp-factory.cpp
+++ b/daemon/face/udp-factory.cpp
@@ -80,6 +80,8 @@
   //   }
   // }
 
+  m_wantCongestionMarking = context.generalConfig.wantCongestionMarking;
+
   uint16_t port = 6363;
   bool enableV4 = false;
   bool enableV6 = false;
@@ -292,7 +294,7 @@
                                 ", endpoint already allocated for a UDP multicast face"));
   }
 
-  auto channel = std::make_shared<UdpChannel>(localEndpoint, idleTimeout);
+  auto channel = std::make_shared<UdpChannel>(localEndpoint, idleTimeout, m_wantCongestionMarking);
   m_channels[localEndpoint] = channel;
 
   return channel;
@@ -345,7 +347,9 @@
   ip::udp::socket txSock(getGlobalIoService());
   MulticastUdpTransport::openTxSocket(txSock, udp::Endpoint(localAddress, 0), netif);
 
-  auto linkService = make_unique<GenericLinkService>();
+  GenericLinkService::Options options;
+  options.allowCongestionMarking = m_wantCongestionMarking;
+  auto linkService = make_unique<GenericLinkService>(options);
   auto transport = make_unique<MulticastUdpTransport>(mcastEp, std::move(rxSock), std::move(txSock),
                                                       m_mcastConfig.linkType);
   auto face = make_shared<Face>(std::move(linkService), std::move(transport));
diff --git a/daemon/face/udp-factory.hpp b/daemon/face/udp-factory.hpp
index 1153a7a..62f59ee 100644
--- a/daemon/face/udp-factory.hpp
+++ b/daemon/face/udp-factory.hpp
@@ -133,6 +133,7 @@
 
 private:
   std::map<udp::Endpoint, shared_ptr<UdpChannel>> m_channels;
+  bool m_wantCongestionMarking;
 
   struct MulticastConfig
   {
diff --git a/daemon/face/unix-stream-channel.cpp b/daemon/face/unix-stream-channel.cpp
index 87af308..fcc8fe7 100644
--- a/daemon/face/unix-stream-channel.cpp
+++ b/daemon/face/unix-stream-channel.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -36,11 +36,13 @@
 
 NFD_LOG_INIT("UnixStreamChannel");
 
-UnixStreamChannel::UnixStreamChannel(const unix_stream::Endpoint& endpoint)
+UnixStreamChannel::UnixStreamChannel(const unix_stream::Endpoint& endpoint,
+                                     bool wantCongestionMarking)
   : m_endpoint(endpoint)
   , m_acceptor(getGlobalIoService())
   , m_socket(getGlobalIoService())
   , m_size(0)
+  , m_wantCongestionMarking(wantCongestionMarking)
 {
   setUri(FaceUri(m_endpoint));
   NFD_LOG_CHAN_INFO("Creating channel");
@@ -132,7 +134,9 @@
 
   NFD_LOG_CHAN_TRACE("Incoming connection via fd " << m_socket.native_handle());
 
-  auto linkService = make_unique<GenericLinkService>();
+  GenericLinkService::Options options;
+  options.allowCongestionMarking = m_wantCongestionMarking;
+  auto linkService = make_unique<GenericLinkService>(options);
   auto transport = make_unique<UnixStreamTransport>(std::move(m_socket));
   auto face = make_shared<Face>(std::move(linkService), std::move(transport));
 
diff --git a/daemon/face/unix-stream-channel.hpp b/daemon/face/unix-stream-channel.hpp
index e396d8e..6a49667 100644
--- a/daemon/face/unix-stream-channel.hpp
+++ b/daemon/face/unix-stream-channel.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -64,8 +64,7 @@
    * To enable creation of faces upon incoming connections, one
    * needs to explicitly call UnixStreamChannel::listen method.
    */
-  explicit
-  UnixStreamChannel(const unix_stream::Endpoint& endpoint);
+  UnixStreamChannel(const unix_stream::Endpoint& endpoint, bool wantCongestionMarking);
 
   ~UnixStreamChannel() override;
 
@@ -116,6 +115,7 @@
   boost::asio::local::stream_protocol::acceptor m_acceptor;
   boost::asio::local::stream_protocol::socket m_socket;
   size_t m_size;
+  bool m_wantCongestionMarking;
 };
 
 } // namespace face
diff --git a/daemon/face/unix-stream-factory.cpp b/daemon/face/unix-stream-factory.cpp
index 7c1c7d5..acbd543 100644
--- a/daemon/face/unix-stream-factory.cpp
+++ b/daemon/face/unix-stream-factory.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -54,6 +54,8 @@
   //   path /var/run/nfd.sock
   // }
 
+  m_wantCongestionMarking = context.generalConfig.wantCongestionMarking;
+
   if (!configSection) {
     if (!context.isDryRun && !m_channels.empty()) {
       NFD_LOG_WARN("Cannot disable unix channel after initialization");
@@ -102,7 +104,7 @@
   if (channel)
     return channel;
 
-  channel = make_shared<UnixStreamChannel>(endpoint);
+  channel = make_shared<UnixStreamChannel>(endpoint, m_wantCongestionMarking);
   m_channels[endpoint] = channel;
   return channel;
 }
diff --git a/daemon/face/unix-stream-factory.hpp b/daemon/face/unix-stream-factory.hpp
index fc5579c..d87ffd1 100644
--- a/daemon/face/unix-stream-factory.hpp
+++ b/daemon/face/unix-stream-factory.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -82,6 +82,7 @@
 
 private:
   std::map<unix_stream::Endpoint, shared_ptr<UnixStreamChannel>> m_channels;
+  bool m_wantCongestionMarking;
 };
 
 } // namespace face