static Endpoint newEndpoint(const std::string& address, std::string ourName, uint64_t interval, const std::string& namespace_name, const std::string& instance_name);
static void run(const std::vector<Endpoint>& endpoints);
- static void addEndpointAtRuntime(const Endpoint& endpoint);
};
}
#include <optional>
#include <string>
+#include "config.h"
#include "credentials.hh"
#include "dnsdist-carbon.hh"
#include "dnsdist-query-count.hh"
uint64_t d_maxTCPClientThreads{0};
size_t d_maxTCPConnectionsPerClient{0};
size_t d_udpVectorSize{1};
+ size_t d_ringsCapacity{10000};
+ size_t d_ringsNumberOfShards{10};
+ size_t d_ringsNbLockTries{5};
uint32_t d_socketUDPSendBuffer{0};
uint32_t d_socketUDPRecvBuffer{0};
uint32_t d_hashPerturbation{0};
uint8_t d_udpTimeout{2};
bool d_randomizeUDPSocketsToBackend{false};
bool d_randomizeIDsToBackend{false};
+ bool d_ringsRecordQueries{true};
+ bool d_ringsRecordResponses{true};
};
/* this part of the configuration can be updated at runtime via
{
rules::RuleChains d_ruleChains;
servers_t d_backends;
+#ifndef DISABLE_CARBON
std::vector<dnsdist::Carbon::Endpoint> d_carbonEndpoints;
+#endif /* DISABLE_CARBON */
std::map<std::string, std::shared_ptr<ServerPool>> d_pools;
std::shared_ptr<const CredentialsHolder> d_webPassword;
std::shared_ptr<const CredentialsHolder> d_webAPIKey;
#include "dnsdist-metrics.hh"
#include "sholder.hh"
+#ifndef DISABLE_DYNBLOCKS
static GlobalStateHolder<ClientAddressDynamicRules> s_dynblockNMG;
static GlobalStateHolder<SuffixDynamicRules> s_dynblockSMT;
-#ifndef DISABLE_DYNBLOCKS
void DynBlockRulesGroup::apply(const timespec& now)
{
counts_t counts;
const std::function<void(dnsdist::configuration::Configuration& config, uint64_t value)> mutator;
const size_t maximumValue{std::numeric_limits<uint64_t>::max()};
};
- static const std::vector<UnsignedIntegerImmutableConfigurationItems> unsignedIntegerImmutableConfigItems{
+ static const std::vector<UnsignedIntegerImmutableConfigurationItems> unsignedIntegerImmutableConfigItems
+ {
{"setMaxTCPQueuedConnections", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxTCPQueuedConnections = newValue; }, std::numeric_limits<uint16_t>::max()},
- {"setMaxTCPClientThreads", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxTCPClientThreads = newValue; }, std::numeric_limits<uint16_t>::max()},
- {"setMaxTCPConnectionsPerClient", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxTCPConnectionsPerClient = newValue; }, std::numeric_limits<uint64_t>::max()},
- {"setTCPInternalPipeBufferSize", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_tcpInternalPipeBufferSize = newValue; }, std::numeric_limits<uint64_t>::max()},
- {"setMaxCachedTCPConnectionsPerDownstream", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingTCPMaxIdlePerBackend = newValue; }, std::numeric_limits<uint16_t>::max()},
- {"setTCPDownstreamCleanupInterval", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingTCPCleanupInterval = newValue; }, std::numeric_limits<uint32_t>::max()},
- {"setTCPDownstreamMaxIdleTime", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingTCPMaxIdleTime = newValue; }, std::numeric_limits<uint16_t>::max()},
+ {"setMaxTCPClientThreads", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxTCPClientThreads = newValue; }, std::numeric_limits<uint16_t>::max()},
+ {"setMaxTCPConnectionsPerClient", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxTCPConnectionsPerClient = newValue; }, std::numeric_limits<uint64_t>::max()},
+ {"setTCPInternalPipeBufferSize", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_tcpInternalPipeBufferSize = newValue; }, std::numeric_limits<uint64_t>::max()},
+ {"setMaxCachedTCPConnectionsPerDownstream", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingTCPMaxIdlePerBackend = newValue; }, std::numeric_limits<uint16_t>::max()},
+ {"setTCPDownstreamCleanupInterval", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingTCPCleanupInterval = newValue; }, std::numeric_limits<uint32_t>::max()},
+ {"setTCPDownstreamMaxIdleTime", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingTCPMaxIdleTime = newValue; }, std::numeric_limits<uint16_t>::max()},
#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
- {"setOutgoingDoHWorkerThreads", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingDoHWorkers = newValue; }, std::numeric_limits<uint16_t>::max()},
- {"setMaxIdleDoHConnectionsPerDownstream", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingDoHMaxIdlePerBackend = newValue; }, std::numeric_limits<uint16_t>::max()},
- {"setDoHDownstreamCleanupInterval", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingDoHCleanupInterval = newValue; }, std::numeric_limits<uint32_t>::max()},
- {"setDoHDownstreamMaxIdleTime", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingDoHMaxIdleTime = newValue; }, std::numeric_limits<uint16_t>::max()},
+ {"setOutgoingDoHWorkerThreads", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingDoHWorkers = newValue; }, std::numeric_limits<uint16_t>::max()},
+ {"setMaxIdleDoHConnectionsPerDownstream", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingDoHMaxIdlePerBackend = newValue; }, std::numeric_limits<uint16_t>::max()},
+ {"setDoHDownstreamCleanupInterval", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingDoHCleanupInterval = newValue; }, std::numeric_limits<uint32_t>::max()},
+ {"setDoHDownstreamMaxIdleTime", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_outgoingDoHMaxIdleTime = newValue; }, std::numeric_limits<uint16_t>::max()},
#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
- {"setMaxUDPOutstanding", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxUDPOutstanding = newValue; }, std::numeric_limits<uint16_t>::max()},
- {"setWHashedPertubation", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_hashPerturbation = newValue; }, std::numeric_limits<uint32_t>::max()},
+ {"setMaxUDPOutstanding", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_maxUDPOutstanding = newValue; }, std::numeric_limits<uint16_t>::max()},
+ {"setWHashedPertubation", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_hashPerturbation = newValue; }, std::numeric_limits<uint32_t>::max()},
#ifndef DISABLE_RECVMMSG
- {"setUDPMultipleMessagesVectorSize", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_udpVectorSize = newValue; }, std::numeric_limits<uint32_t>::max()},
+ {"setUDPMultipleMessagesVectorSize", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_udpVectorSize = newValue; }, std::numeric_limits<uint32_t>::max()},
#endif /* DISABLE_RECVMMSG */
- {"setUDPTimeout", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_udpTimeout = newValue; }, std::numeric_limits<uint8_t>::max()},
- {"setConsoleMaximumConcurrentConnections", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_consoleMaxConcurrentConnections = newValue; }, std::numeric_limits<uint32_t>::max()},
+ {"setUDPTimeout", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_udpTimeout = newValue; }, std::numeric_limits<uint8_t>::max()},
+ {"setConsoleMaximumConcurrentConnections", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_consoleMaxConcurrentConnections = newValue; }, std::numeric_limits<uint32_t>::max()},
+ {"setRingBuffersLockRetries", [](dnsdist::configuration::Configuration& config, uint64_t newValue) { config.d_ringsNbLockTries = newValue; }, std::numeric_limits<uint64_t>::max()},
};
struct DoubleImmutableConfigurationItems
});
luaCtx.writeFunction("setRingBuffersSize", [client](uint64_t capacity, boost::optional<uint64_t> numberOfShards) {
- setLuaSideEffect();
- if (!checkConfigurationTime("setRingBuffersSize")) {
+ if (client) {
return;
}
- if (!client) {
- g_rings.setCapacity(capacity, numberOfShards ? *numberOfShards : 10);
+ setLuaSideEffect();
+ try {
+ dnsdist::configuration::updateImmutableConfiguration([capacity, numberOfShards](dnsdist::configuration::Configuration& config) {
+ config.d_ringsCapacity = capacity;
+ if (numberOfShards) {
+ config.d_ringsNumberOfShards = *numberOfShards;
+ }
+ });
}
- else {
- g_rings.setCapacity(0, 1);
+ catch (const std::exception& exp) {
+ g_outputBuffer = "setRingBuffersSize cannot be used at runtime!\n";
+ errlog("setRingBuffersSize cannot be used at runtime!");
}
});
- luaCtx.writeFunction("setRingBuffersLockRetries", [](uint64_t retries) {
- setLuaSideEffect();
- g_rings.setNumberOfLockRetries(retries);
- });
-
- luaCtx.writeFunction("setRingBuffersOptions", [](const LuaAssociativeTable<boost::variant<bool, uint64_t>>& options) {
- setLuaSideEffect();
- if (!checkConfigurationTime("setRingBuffersOptions")) {
+ luaCtx.writeFunction("setRingBuffersOptions", [client](const LuaAssociativeTable<boost::variant<bool, uint64_t>>& options) {
+ if (client) {
return;
}
- if (options.count("lockRetries") > 0) {
- auto retries = boost::get<uint64_t>(options.at("lockRetries"));
- g_rings.setNumberOfLockRetries(retries);
- }
- if (options.count("recordQueries") > 0) {
- auto record = boost::get<bool>(options.at("recordQueries"));
- g_rings.setRecordQueries(record);
+ setLuaSideEffect();
+ try {
+ dnsdist::configuration::updateImmutableConfiguration([&options](dnsdist::configuration::Configuration& config) {
+ if (options.count("lockRetries") > 0) {
+ config.d_ringsNbLockTries = boost::get<uint64_t>(options.at("lockRetries"));
+ }
+ if (options.count("recordQueries") > 0) {
+ config.d_ringsRecordQueries = boost::get<bool>(options.at("recordQueries"));
+ }
+ if (options.count("recordResponses") > 0) {
+ config.d_ringsRecordResponses = boost::get<bool>(options.at("recordResponses"));
+ }
+ });
}
- if (options.count("recordResponses") > 0) {
- auto record = boost::get<bool>(options.at("recordResponses"));
- g_rings.setRecordResponses(record);
+ catch (const std::exception& exp) {
+ g_outputBuffer = "setRingBuffersOption cannot be used at runtime!\n";
+ errlog("setRingBuffersOption cannot be used at runtime!");
}
});
#endif /* DISABLE_POLICIES_BINDINGS */
luaCtx.writeFunction("setProxyProtocolACL", [](LuaTypeOrArrayOf<std::string> inp) {
- if (!checkConfigurationTime("setProxyProtocolACL")) {
- return;
- }
setLuaSideEffect();
NetmaskGroup nmg;
if (auto* str = boost::get<string>(&inp)) {
{"cpu-user-msec", getCPUTimeUser},
{"fd-usage", getOpenFileDescriptors},
{"dyn-blocked", &dynBlocked},
+#ifndef DISABLE_DYNBLOCKS
{"dyn-block-nmg-size", [](const std::string&) { return dnsdist::DynamicBlocks::getClientAddressDynamicRules().size(); }},
+#endif /* DISABLE_DYNBLOCKS */
{"security-status", &securityStatus},
{"doh-query-pipe-full", &dohQueryPipeFull},
{"doh-response-pipe-full", &dohResponsePipeFull},
#include "dnsdist-rings.hh"
-void Rings::setCapacity(size_t newCapacity, size_t numberOfShards)
-{
- if (d_initialized) {
- throw std::runtime_error("Rings::setCapacity() should not be called once the rings have been initialized");
- }
- d_capacity = newCapacity;
- d_numberOfShards = numberOfShards;
-}
-
-void Rings::init()
+void Rings::init(size_t capacity, size_t numberOfShards, size_t nbLockRetries, bool recordQueries, bool recordResponses)
{
if (d_initialized.exchange(true)) {
throw std::runtime_error("Rings::init() should only be called once");
}
+ d_capacity = capacity;
+ d_numberOfShards = numberOfShards;
+ d_nbLockTries = nbLockRetries;
+ d_recordQueries = recordQueries;
+ d_recordResponses = recordResponses;
if (d_numberOfShards <= 1) {
d_nbLockTries = 0;
}
d_nbResponseEntries = 0;
}
-void Rings::setNumberOfLockRetries(size_t retries)
-{
- if (d_numberOfShards <= 1) {
- d_nbLockTries = 0;
- }
- else {
- d_nbLockTries = retries;
- }
-}
-
-void Rings::setRecordQueries(bool record)
-{
- d_recordQueries = record;
-}
-
-void Rings::setRecordResponses(bool record)
-{
- d_recordResponses = record;
-}
-
size_t Rings::numDistinctRequestors()
{
std::set<ComboAddress, ComboAddress::addressOnlyLessThan> requestors;
LockGuarded<boost::circular_buffer<Response>> respRing;
};
- Rings(size_t capacity = 10000, size_t numberOfShards = 10, size_t nbLockTries = 5, bool keepLockingStats = false) :
- d_blockingQueryInserts(0), d_blockingResponseInserts(0), d_deferredQueryInserts(0), d_deferredResponseInserts(0), d_nbQueryEntries(0), d_nbResponseEntries(0), d_currentShardId(0), d_capacity(capacity), d_numberOfShards(numberOfShards), d_nbLockTries(nbLockTries), d_keepLockingStats(keepLockingStats)
- {
- }
-
std::unordered_map<int, vector<boost::variant<string, double>>> getTopBandwidth(unsigned int numentries);
size_t numDistinctRequestors();
- /* this function should not be called after init() has been called */
- void setCapacity(size_t newCapacity, size_t numberOfShards);
/* This function should only be called at configuration time before any query or response has been inserted */
- void init();
-
- void setNumberOfLockRetries(size_t retries);
- void setRecordQueries(bool);
- void setRecordResponses(bool);
+ void init(size_t capacity, size_t numberOfShards, size_t nbLockRetries = 5, bool recordQueries = true, bool recordResponses = true);
size_t getNumberOfShards() const
{
#endif
return;
}
- if (d_keepLockingStats) {
+ if (s_keepLockingStats) {
++d_deferredQueryInserts;
}
}
/* out of luck, let's just wait */
- if (d_keepLockingStats) {
+ if (s_keepLockingStats) {
++d_blockingResponseInserts;
}
auto& shard = getOneShard();
insertResponseLocked(*lock, when, requestor, name, qtype, usec, size, dh, backend, protocol);
return;
}
- if (d_keepLockingStats) {
+ if (s_keepLockingStats) {
++d_deferredResponseInserts;
}
}
/* out of luck, let's just wait */
- if (d_keepLockingStats) {
+ if (s_keepLockingStats) {
++d_blockingResponseInserts;
}
auto& shard = getOneShard();
}
std::vector<std::unique_ptr<Shard>> d_shards;
- pdns::stat_t d_blockingQueryInserts;
- pdns::stat_t d_blockingResponseInserts;
- pdns::stat_t d_deferredQueryInserts;
- pdns::stat_t d_deferredResponseInserts;
+ pdns::stat_t d_blockingQueryInserts{0};
+ pdns::stat_t d_blockingResponseInserts{0};
+ pdns::stat_t d_deferredQueryInserts{0};
+ pdns::stat_t d_deferredResponseInserts{0};
private:
size_t getShardId()
ring.push_back({requestor, backend, name, when, dh, usec, size, qtype, protocol});
}
- std::atomic<size_t> d_nbQueryEntries;
- std::atomic<size_t> d_nbResponseEntries;
- std::atomic<size_t> d_currentShardId;
+ static constexpr bool s_keepLockingStats{false};
+
+ std::atomic<size_t> d_nbQueryEntries{0};
+ std::atomic<size_t> d_nbResponseEntries{0};
+ std::atomic<size_t> d_currentShardId{0};
std::atomic<bool> d_initialized{false};
- size_t d_capacity;
- size_t d_numberOfShards;
- size_t d_nbLockTries = 5;
- bool d_keepLockingStats{false};
+ size_t d_capacity{10000};
+ size_t d_numberOfShards{10};
+ size_t d_nbLockTries{5};
bool d_recordQueries{true};
bool d_recordResponses{true};
};
#include "credentials.hh"
#include "dnsdist-prometheus.hh"
+#include "sstuff.hh"
namespace dnsdist::webserver
{
config.d_pools.clear();
config.d_backends.clear();
});
- clearWebHandlers();
+ dnsdist::webserver::clearWebHandlers();
dnsdist::lua::hooks::clearMaintenanceHooks();
}
#endif /* defined(COVERAGE) || (defined(__SANITIZE_ADDRESS__) && defined(HAVE_LEAK_SANITIZER_INTERFACE)) */
if (dnsdist::g_asyncHolder) {
dnsdist::g_asyncHolder->stop();
}
+
+ for (auto& backend : dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends) {
+ backend->stop();
+ }
+
{
auto lock = g_lua.lock();
cleanupLuaObjects();
#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
}
- g_rings.init();
+ {
+ const auto& config = dnsdist::configuration::getImmutableConfiguration();
+ g_rings.init(config.d_ringsCapacity, config.d_ringsNumberOfShards, config.d_ringsNbLockTries, config.d_ringsRecordQueries, config.d_ringsRecordResponses);
+ }
for (auto& frontend : g_frontends) {
setUpLocalBind(frontend);
gettime(&now);
g_rings.reset();
- g_rings.init();
+ g_rings.init(10000, 10);
BOOST_CHECK_EQUAL(g_rings.getNumberOfQueryEntries(), 0U);
g_rings.insertQuery(now, requestor1, qname, qtype, size, dh, protocol);
TestFixture()
{
g_rings.reset();
- g_rings.init();
+ g_rings.init(10000, 10);
}
~TestFixture()
{
/* 100k entries, one shard */
g_rings.reset();
- g_rings.setCapacity(1000000, 1);
- g_rings.init();
+ g_rings.init(1000000, 1);
size_t numberOfSeconds = 10;
size_t blockDuration = 60;
g_rings.reset();
/* 10M entries, only one shard */
- g_rings.setCapacity(10000000, 1);
- g_rings.init();
+ g_rings.init(10000000, 1);
{
DynBlockRulesGroup dbrg;
static void test_ring(size_t maxEntries, size_t numberOfShards, size_t nbLockTries)
{
- Rings rings(maxEntries, numberOfShards, nbLockTries);
- rings.init();
+ Rings rings;
+ rings.init(maxEntries, numberOfShards, nbLockTries);
size_t entriesPerShard = maxEntries / numberOfShards;
BOOST_CHECK_EQUAL(rings.getNumberOfShards(), numberOfShards);
dnsdist::Protocol protocol = dnsdist::Protocol::DoUDP;
dnsdist::Protocol outgoingProtocol = dnsdist::Protocol::DoUDP;
- Rings rings(numberOfEntries, numberOfShards, lockAttempts, true);
- rings.init();
+ Rings rings;
+ rings.init(numberOfEntries, numberOfShards, lockAttempts, true);
#if defined(DNSDIST_RINGS_WITH_MACADDRESS)
Rings::Query query({requestor, qname, now, dh, size, qtype, protocol, dnsdist::MacAddress(), false});
#else