]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add an option to control the size of the TCP listen queue 8994/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 2 Apr 2020 16:12:56 +0000 (18:12 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 2 Apr 2020 16:12:56 +0000 (18:12 +0200)
pdns/dnsdist-lua.cc
pdns/dnsdist.cc
pdns/dnsdist.hh
pdns/dnsdistdist/docs/reference/config.rst

index 6df96431978fbbe3fc9b12faff81d0a0aaa9d1db..f2423353ea38d88c0d6ec65430a887aee423fb44 100644 (file)
@@ -97,7 +97,7 @@ void resetLuaSideEffect()
 
 typedef std::unordered_map<std::string, boost::variant<bool, int, std::string, std::vector<std::pair<int,int> >, std::vector<std::pair<int, std::string> >, std::map<std::string,std::string>  > > localbind_t;
 
-static void parseLocalBindVars(boost::optional<localbind_t> vars, bool& reusePort, int& tcpFastOpenQueueSize, std::string& interface, std::set<int>& cpus)
+static void parseLocalBindVars(boost::optional<localbind_t> vars, bool& reusePort, int& tcpFastOpenQueueSize, std::string& interface, std::set<int>& cpus, int& tcpListenQueueSize)
 {
   if (vars) {
     if (vars->count("reusePort")) {
@@ -106,6 +106,9 @@ static void parseLocalBindVars(boost::optional<localbind_t> vars, bool& reusePor
     if (vars->count("tcpFastOpenQueueSize")) {
       tcpFastOpenQueueSize = boost::get<int>((*vars)["tcpFastOpenQueueSize"]);
     }
+    if (vars->count("tcpListenQueueSize")) {
+      tcpListenQueueSize = boost::get<int>((*vars)["tcpListenQueueSize"]);
+    }
     if (vars->count("interface")) {
       interface = boost::get<std::string>((*vars)["interface"]);
     }
@@ -575,10 +578,11 @@ static void setupLuaConfig(bool client, bool configCheck)
       }
       bool reusePort = false;
       int tcpFastOpenQueueSize = 0;
+      int tcpListenQueueSize = 0;
       std::string interface;
       std::set<int> cpus;
 
-      parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus);
+      parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize);
 
       try {
        ComboAddress loc(addr, 53);
@@ -594,7 +598,11 @@ static void setupLuaConfig(bool client, bool configCheck)
 
         // only works pre-startup, so no sync necessary
         g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus)));
-        g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus)));
+        auto tcpCS = std::unique_ptr<ClientState>(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus));
+        if (tcpListenQueueSize > 0) {
+          tcpCS->tcpListenQueueSize = tcpListenQueueSize;
+        }
+        g_frontends.push_back(std::move(tcpCS));
       }
       catch(const std::exception& e) {
        g_outputBuffer="Error: "+string(e.what())+"\n";
@@ -611,16 +619,21 @@ static void setupLuaConfig(bool client, bool configCheck)
       }
       bool reusePort = false;
       int tcpFastOpenQueueSize = 0;
+      int tcpListenQueueSize = 0;
       std::string interface;
       std::set<int> cpus;
 
-      parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus);
+      parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize);
 
       try {
        ComboAddress loc(addr, 53);
         // only works pre-startup, so no sync necessary
         g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus)));
-        g_frontends.push_back(std::unique_ptr<ClientState>(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus)));
+        auto tcpCS = std::unique_ptr<ClientState>(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus));
+        if (tcpListenQueueSize > 0) {
+          tcpCS->tcpListenQueueSize = tcpListenQueueSize;
+        }
+        g_frontends.push_back(std::move(tcpCS));
       }
       catch(std::exception& e) {
         g_outputBuffer="Error: "+string(e.what())+"\n";
@@ -1212,11 +1225,12 @@ static void setupLuaConfig(bool client, bool configCheck)
 #ifdef HAVE_DNSCRYPT
       bool reusePort = false;
       int tcpFastOpenQueueSize = 0;
+      int tcpListenQueueSize = 0;
       std::string interface;
       std::set<int> cpus;
       std::vector<DNSCryptContext::CertKeyPaths> certKeys;
 
-      parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus);
+      parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize);
 
       if (certFiles.type() == typeid(std::string) && keyFiles.type() == typeid(std::string)) {
         auto certFile = boost::get<std::string>(certFiles);
@@ -1255,6 +1269,10 @@ static void setupLuaConfig(bool client, bool configCheck)
         /* TCP */
         cs = std::unique_ptr<ClientState>(new ClientState(ComboAddress(addr, 443), true, reusePort, tcpFastOpenQueueSize, interface, cpus));
         cs->dnscryptCtx = ctx;
+        if (tcpListenQueueSize > 0) {
+          cs->tcpListenQueueSize = tcpListenQueueSize;
+        }
+
         g_frontends.push_back(std::move(cs));
       }
       catch(std::exception& e) {
@@ -1888,11 +1906,12 @@ static void setupLuaConfig(bool client, bool configCheck)
 
     bool reusePort = false;
     int tcpFastOpenQueueSize = 0;
+    int tcpListenQueueSize = 0;
     std::string interface;
     std::set<int> cpus;
 
-    if(vars) {
-      parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus);
+    if (vars) {
+      parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize);
 
       if (vars->count("idleTimeout")) {
         frontend->d_idleTimeout = boost::get<int>((*vars)["idleTimeout"]);
@@ -1922,6 +1941,10 @@ static void setupLuaConfig(bool client, bool configCheck)
     g_dohlocals.push_back(frontend);
     auto cs = std::unique_ptr<ClientState>(new ClientState(frontend->d_local, true, reusePort, tcpFastOpenQueueSize, interface, cpus));
     cs->dohFrontend = frontend;
+    if (tcpListenQueueSize > 0) {
+      cs->tcpListenQueueSize = tcpListenQueueSize;
+    }
+
     g_frontends.push_back(std::move(cs));
 #else
     throw std::runtime_error("addDOHLocal() called but DNS over HTTPS support is not present!");
@@ -2065,11 +2088,12 @@ static void setupLuaConfig(bool client, bool configCheck)
 
         bool reusePort = false;
         int tcpFastOpenQueueSize = 0;
+        int tcpListenQueueSize = 0;
         std::string interface;
         std::set<int> cpus;
 
         if (vars) {
-          parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus);
+          parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize);
 
           if (vars->count("provider")) {
             frontend->d_provider = boost::get<const string>((*vars)["provider"]);
@@ -2094,6 +2118,9 @@ static void setupLuaConfig(bool client, bool configCheck)
           // only works pre-startup, so no sync necessary
           auto cs = std::unique_ptr<ClientState>(new ClientState(frontend->d_addr, true, reusePort, tcpFastOpenQueueSize, interface, cpus));
           cs->tlsFrontend = frontend;
+          if (tcpListenQueueSize > 0) {
+            cs->tcpListenQueueSize = tcpListenQueueSize;
+          }
           g_tlslocals.push_back(cs->tlsFrontend);
           g_frontends.push_back(std::move(cs));
         }
index a902f3988530d533fd7fb0abee6b59644618ebb7..f7bfe4c8e491d17955a8777983ac178ccbbbcf97 100644 (file)
@@ -1891,7 +1891,8 @@ static void setUpLocalBind(std::unique_ptr<ClientState>& cs)
   SBind(fd, cs->local);
 
   if (cs->tcp) {
-    SListen(cs->tcpFD, SOMAXCONN);
+    SListen(cs->tcpFD, cs->tcpListenQueueSize);
+
     if (cs->tlsFrontend != nullptr) {
       warnlog("Listening on %s for TLS", cs->local.toStringWithPort());
     }
index 3848149fc8d0c774a03c280ec69c905c4bb67f69..214966161730d1900234c817bab503a1436db6d5 100644 (file)
@@ -622,6 +622,7 @@ struct ClientState
   std::atomic<double> tcpAvgConnectionDuration{0.0};
   int udpFD{-1};
   int tcpFD{-1};
+  int tcpListenQueueSize{SOMAXCONN};
   int fastOpenQueueSize{0};
   bool muted{false};
   bool tcp;
index dca06dddd4fd8f782a73c100b3526f0d0299965d..f010c67fc4325eebf869c361e5a3c76368ada436 100644 (file)
@@ -70,6 +70,9 @@ Listen Sockets
   .. versionchanged:: 1.4.0
     Removed ``doTCP`` from the options. A listen socket on TCP is always created.
 
+  .. versionchanged:: 1.5.0
+    Added ``tcpListenQueueSize`` parameter.
+
   Add to the list of listen addresses.
 
   :param str address: The IP Address with an optional port to listen on.
@@ -83,6 +86,7 @@ Listen Sockets
   * ``tcpFastOpenQueueSize=0``: int - Set the TCP Fast Open queue size, enabling TCP Fast Open when available and the value is larger than 0.
   * ``interface=""``: str - Set the network interface to use.
   * ``cpus={}``: table - Set the CPU affinity for this listener thread, asking the scheduler to run it on a single CPU id, or a set of CPU ids. This parameter is only available if the OS provides the pthread_setaffinity_np() function.
+  * ``tcpListenQueueSize=SOMAXCONN``: int - Set the size of the listen queue. Default is ``SOMAXCONN``.
 
   .. code-block:: lua
 
@@ -110,7 +114,7 @@ Listen Sockets
 
   .. versionchanged:: 1.5.0
     ``sendCacheControlHeaders``, ``sessionTimeout``, ``trustForwardedForHeader`` options added.
-    ``url`` now defaults to ``/dns-query`` instead of ``/``
+    ``url`` now defaults to ``/dns-query`` instead of ``/``. Added ``tcpListenQueueSize`` parameter.
 
   Listen on the specified address and TCP port for incoming DNS over HTTPS connections, presenting the specified X.509 certificate.
   If no certificate (or key) files are specified, listen for incoming DNS over HTTP connections instead.
@@ -145,6 +149,7 @@ Listen Sockets
   * ``keyLogFile``: str - Write the TLS keys in the specified file so that an external program can decrypt TLS exchanges, in the format described in https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. Note that this feature requires OpenSSL >= 1.1.1.
   * ``sendCacheControlHeaders``: bool - Whether to parse the response to find the lowest TTL and set a HTTP Cache-Control header accordingly. Default is true.
   * ``trustForwardedForHeader``: bool - Whether to parse any existing X-Forwarded-For header in the HTTP query and use the right-most value as the client source address and port, for ACL checks, rules, logging and so on. Default is false.
+  * ``tcpListenQueueSize=SOMAXCONN``: int - Set the size of the listen queue. Default is ``SOMAXCONN``.
 
 .. function:: addTLSLocal(address, certFile(s), keyFile(s) [, options])
 
@@ -157,7 +162,7 @@ Listen Sockets
   .. versionchanged:: 1.4.0
     ``ciphersTLS13``, ``minTLSVersion``, ``ocspResponses``, ``preferServerCiphers``, ``keyLogFile`` options added.
   .. versionchanged:: 1.5.0
-    ``sessionTimeout`` option added.
+    ``sessionTimeout`` and ``tcpListenQueueSize`` options added.
 
   Listen on the specified address and TCP port for incoming DNS over TLS connections, presenting the specified X.509 certificate.
 
@@ -186,6 +191,7 @@ Listen Sockets
   * ``minTLSVersion``: str - Minimum version of the TLS protocol to support. Possible values are 'tls1.0', 'tls1.1', 'tls1.2' and 'tls1.3'. Default is to require at least TLS 1.0. Note that this value is ignored when the GnuTLS provider is in use, and the ``ciphers`` option should be set accordingly instead. For example, 'NORMAL:!VERS-TLS1.0:!VERS-TLS1.1' will disable TLS 1.0 and 1.1.
   * ``preferServerCiphers``: bool - Whether to prefer the order of ciphers set by the server instead of the one set by the client. Default is true, meaning that the order of the server is used.
   * ``keyLogFile``: str - Write the TLS keys in the specified file so that an external program can decrypt TLS exchanges, in the format described in https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. Note that this feature requires OpenSSL >= 1.1.1.
+  * ``tcpListenQueueSize=SOMAXCONN``: int - Set the size of the listen queue. Default is ``SOMAXCONN``.
 
 .. function:: setLocal(address[, options])