From: Remi Gacogne Date: Thu, 2 Apr 2020 16:12:56 +0000 (+0200) Subject: dnsdist: Add an option to control the size of the TCP listen queue X-Git-Tag: dnsdist-1.5.0-rc1~4^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F8994%2Fhead;p=thirdparty%2Fpdns.git dnsdist: Add an option to control the size of the TCP listen queue --- diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 6df9643197..f2423353ea 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -97,7 +97,7 @@ void resetLuaSideEffect() typedef std::unordered_map >, std::vector >, std::map > > localbind_t; -static void parseLocalBindVars(boost::optional vars, bool& reusePort, int& tcpFastOpenQueueSize, std::string& interface, std::set& cpus) +static void parseLocalBindVars(boost::optional vars, bool& reusePort, int& tcpFastOpenQueueSize, std::string& interface, std::set& cpus, int& tcpListenQueueSize) { if (vars) { if (vars->count("reusePort")) { @@ -106,6 +106,9 @@ static void parseLocalBindVars(boost::optional vars, bool& reusePor if (vars->count("tcpFastOpenQueueSize")) { tcpFastOpenQueueSize = boost::get((*vars)["tcpFastOpenQueueSize"]); } + if (vars->count("tcpListenQueueSize")) { + tcpListenQueueSize = boost::get((*vars)["tcpListenQueueSize"]); + } if (vars->count("interface")) { interface = boost::get((*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 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(new ClientState(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus))); - g_frontends.push_back(std::unique_ptr(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus))); + auto tcpCS = std::unique_ptr(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 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(new ClientState(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus))); - g_frontends.push_back(std::unique_ptr(new ClientState(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus))); + auto tcpCS = std::unique_ptr(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 cpus; std::vector 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(certFiles); @@ -1255,6 +1269,10 @@ static void setupLuaConfig(bool client, bool configCheck) /* TCP */ cs = std::unique_ptr(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 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((*vars)["idleTimeout"]); @@ -1922,6 +1941,10 @@ static void setupLuaConfig(bool client, bool configCheck) g_dohlocals.push_back(frontend); auto cs = std::unique_ptr(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 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((*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(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)); } diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index a902f39885..f7bfe4c8e4 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -1891,7 +1891,8 @@ static void setUpLocalBind(std::unique_ptr& 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()); } diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index 3848149fc8..2149661617 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -622,6 +622,7 @@ struct ClientState std::atomic tcpAvgConnectionDuration{0.0}; int udpFD{-1}; int tcpFD{-1}; + int tcpListenQueueSize{SOMAXCONN}; int fastOpenQueueSize{0}; bool muted{false}; bool tcp; diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index dca06dddd4..f010c67fc4 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -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])