dns_random.hh \
dnscrypt.cc dnscrypt.hh \
dnsdist-async.cc dnsdist-async.hh \
- dnsdist-backend.cc \
+ dnsdist-backend.cc dnsdist-backend.hh \
dnsdist-backoff.hh \
dnsdist-cache.cc dnsdist-cache.hh \
dnsdist-carbon.cc dnsdist-carbon.hh \
dns.cc dns.hh \
dnscrypt.cc dnscrypt.hh \
dnsdist-async.cc dnsdist-async.hh \
- dnsdist-backend.cc \
+ dnsdist-backend.cc dnsdist-backend.hh \
dnsdist-backoff.hh \
dnsdist-cache.cc dnsdist-cache.hh \
dnsdist-concurrent-connections.hh \
*/
#include "config.h"
#include "dnsdist.hh"
+#include "dnsdist-backend.hh"
#include "dnsdist-backoff.hh"
#include "dnsdist-metrics.hh"
#include "dnsdist-nghttp2.hh"
}
*servers = std::move(newServers);
}
+
+namespace dnsdist::backend
+{
+void registerNewBackend(std::shared_ptr<DownstreamState>& backend)
+{
+ dnsdist::configuration::updateRuntimeConfiguration([&backend](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto& backends = config.d_backends;
+ backends.push_back(backend);
+ std::stable_sort(backends.begin(), backends.end(), [](const std::shared_ptr<DownstreamState>& lhs, const std::shared_ptr<DownstreamState>& rhs) {
+ return lhs->d_config.order < rhs->d_config.order;
+ });
+ });
+}
+}
--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+
+#include <memory>
+
+struct DownstreamState;
+
+namespace dnsdist::backend
+{
+void registerNewBackend(std::shared_ptr<DownstreamState>& backend);
+}
}
}
- auto states = g_dstates.getLocal();
- for (const auto& state : *states) {
+ for (const auto& state : dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends) {
string serverName = state->getName().empty() ? state->d_config.remote.toStringWithPort() : state->getName();
boost::replace_all(serverName, ".", "_");
string base = namespace_name;
class ServerPolicy;
struct ServerPool;
+struct DownstreamState;
+
+using servers_t = std::vector<std::shared_ptr<DownstreamState>>;
namespace dnsdist::configuration
{
a RCU-like mechanism */
struct RuntimeConfiguration
{
+ servers_t d_backends;
std::map<std::string, std::shared_ptr<ServerPool>> d_pools;
std::shared_ptr<ServerPolicy> d_lbPolicy;
NetmaskGroup d_ACL;
#include "config.h"
#include "dnsdist-discovery.hh"
+#include "dnsdist-backend.hh"
#include "dnsdist.hh"
#include "dnsdist-random.hh"
#include "dnsparser.hh"
newServer->start();
- auto states = g_dstates.getCopy();
- states.push_back(newServer);
/* remove the existing backend if needed */
if (!backend.keepAfterUpgrade) {
- for (auto it = states.begin(); it != states.end(); ++it) {
- if (*it == backend.d_ds) {
- states.erase(it);
- break;
+ dnsdist::configuration::updateRuntimeConfiguration([&backend](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto& backends = config.d_backends;
+ for (auto backendIt = backends.begin(); backendIt != backends.end(); ++backendIt) {
+ if (*backendIt == backend.d_ds) {
+ backends.erase(backendIt);
+ break;
+ }
}
- }
+ });
for (const string& poolName : backend.d_ds->d_config.pools) {
removeServerFromPool(poolName, backend.d_ds);
removeServerFromPool("", backend.d_ds);
}
- std::stable_sort(states.begin(), states.end(), [](const decltype(newServer)& a, const decltype(newServer)& b) {
- return a->d_config.order < b->d_config.order;
- });
+ dnsdist::backend::registerNewBackend(newServer);
- g_dstates.setState(states);
if (!backend.keepAfterUpgrade) {
backend.d_ds->stop();
}
fmt = boost::format("%-3d %-20.20s %-20.20s %-20d %-20d %-25d %-25d %-20d %-20d %-20d %-20d %-20d %-20d %-20d %-20d %-20f %-20f");
ret << (fmt % "#" % "Name" % "Address" % "Connections" % "Max concurrent conn" % "Died sending query" % "Died reading response" % "Gave up" % "Read timeouts" % "Write timeouts" % "Connect timeouts" % "Too many conn" % "Total connections" % "Reused connections" % "TLS resumptions" % "Avg queries/conn" % "Avg duration") << endl;
- auto states = g_dstates.getLocal();
counter = 0;
- for (const auto& backend : *states) {
+ for (const auto& backend : dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends) {
ret << (fmt % counter % backend->getName() % backend->d_config.remote.toStringWithPort() % backend->tcpCurrentConnections % backend->tcpMaxConcurrentConnections % backend->tcpDiedSendingQuery % backend->tcpDiedReadingResponse % backend->tcpGaveUp % backend->tcpReadTimeouts % backend->tcpWriteTimeouts % backend->tcpConnectTimeouts % backend->tcpTooManyConcurrentConnections % backend->tcpNewConnections % backend->tcpReusedConnections % backend->tlsResumptions % backend->tcpAvgQueriesPerConnection % backend->tcpAvgConnectionDuration) << endl;
++counter;
}
#include <vector>
#include "dnsdist.hh"
+#include "dnsdist-backend.hh"
#include "dnsdist-carbon.hh"
#include "dnsdist-concurrent-connections.hh"
#include "dnsdist-configuration.hh"
}
}
- auto states = g_dstates.getCopy();
- states.push_back(ret);
- std::stable_sort(states.begin(), states.end(), [](const decltype(ret)& lhs, const decltype(ret)& rhs) {
- return lhs->d_config.order < rhs->d_config.order;
- });
- g_dstates.setState(states);
+ dnsdist::backend::registerNewBackend(ret);
+
checkAllParametersConsumed("newServer", vars);
return ret;
});
[](boost::variant<std::shared_ptr<DownstreamState>, int, std::string> var) {
setLuaSideEffect();
shared_ptr<DownstreamState> server = nullptr;
- auto states = g_dstates.getCopy();
if (auto* rem = boost::get<shared_ptr<DownstreamState>>(&var)) {
server = *rem;
}
else if (auto* str = boost::get<std::string>(&var)) {
const auto uuid = getUniqueID(*str);
- for (auto& state : states) {
+ for (auto& state : dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends) {
if (*state->d_config.id == uuid) {
server = state;
}
}
else {
int idx = boost::get<int>(var);
- server = states.at(idx);
+ server = dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends.at(idx);
}
if (!server) {
throw std::runtime_error("unable to locate the requested server");
}
/* the server might also be in the default pool */
removeServerFromPool("", server);
- states.erase(remove(states.begin(), states.end(), server), states.end());
- g_dstates.setState(states);
+
+ dnsdist::configuration::updateRuntimeConfiguration([&server](dnsdist::configuration::RuntimeConfiguration& config) {
+ config.d_backends.erase(std::remove(config.d_backends.begin(), config.d_backends.end(), server), config.d_backends.end());
+ });
+
server->stop();
});
uint64_t totQueries{0};
uint64_t totDrops{0};
int counter = 0;
- auto states = g_dstates.getLocal();
- for (const auto& backend : *states) {
+ for (const auto& backend : dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends) {
string status = backend->getStatus();
string pools;
for (const auto& pool : backend->d_config.pools) {
setLuaNoSideEffect();
LuaArray<std::shared_ptr<DownstreamState>> ret;
int count = 1;
- for (const auto& backend : g_dstates.getCopy()) {
+ for (const auto& backend : dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends) {
ret.emplace_back(count++, backend);
}
return ret;
if (client) {
return std::make_shared<DownstreamState>(ComboAddress());
}
- auto states = g_dstates.getCopy();
+ const auto& states = dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends;
if (auto* str = boost::get<std::string>(&identifier)) {
const auto uuid = getUniqueID(*str);
for (auto& state : states) {
/* get a copy of the shared_ptrs so they are not
destroyed while we process the request */
- auto dstates = g_dstates.getLocal();
+ auto backends = dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends;
s_servers.clear();
- s_servers.reserve(dstates->size());
- for (const auto& server : *dstates) {
- s_servers.push_back(server);
+ s_servers.reserve(backends.size());
+ for (const auto& server : backends) {
+ s_servers.push_back(std::move(server));
}
return backendStatTable_get_next_data_point(loop_context,
output << "dnsdist_latency_sum " << dnsdist::metrics::g_stats.latencySum << "\n";
output << "dnsdist_latency_count " << dnsdist::metrics::g_stats.latencyCount << "\n";
- auto states = g_dstates.getLocal();
const string statesbase = "dnsdist_server_";
// clang-format off
output << "# HELP " << statesbase << "healthcheckfailuresinvalid " << "Number of health check attempts where the DNS response was invalid" << "\n";
output << "# TYPE " << statesbase << "healthcheckfailuresinvalid " << "counter" << "\n";
- for (const auto& state : *states) {
+ for (const auto& state : dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends) {
string serverName;
if (state->getName().empty()) {
Json::array servers;
{
- auto localServers = g_dstates.getLocal();
- servers.reserve(localServers->size());
- for (const auto& server : *localServers) {
+ const auto& localServers = dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends;
+ servers.reserve(localServers.size());
+ for (const auto& server : localServers) {
addServerToJSON(servers, num++, server);
}
}
Rings g_rings;
-GlobalStateHolder<servers_t> g_dstates;
-
// we are not willing to receive a bigger UDP response than that, no matter what
static constexpr size_t s_maxUDPResponsePacketSize{4096U};
static size_t const s_initialUDPPacketBufferSize = s_maxUDPResponsePacketSize + DNSCRYPT_MAX_RESPONSE_PADDING_AND_MAC_SIZE;
.tv_sec = 0,
.tv_usec = 0
};
- auto states = g_dstates.getLocal(); // this points to the actual shared_ptrs!
for (;;) {
timeval now{};
}
std::unique_ptr<FDMultiplexer> mplexer{nullptr};
- for (const auto& dss : *states) {
+ // this points to the actual shared_ptrs!
+ const auto servers = dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends;
+ for (const auto& dss : servers) {
dss->updateStatisticsInfo();
dss->handleUDPTimeouts();
}
if (!mplexer) {
- mplexer = std::unique_ptr<FDMultiplexer>(FDMultiplexer::getMultiplexerSilent(states->size()));
+ mplexer = std::unique_ptr<FDMultiplexer>(FDMultiplexer::getMultiplexerSilent(servers.size()));
}
if (!queueHealthCheck(mplexer, dss)) {
const auto immutableConfig = dnsdist::configuration::getImmutableConfiguration();
/* stdin, stdout, stderr */
rlim_t requiredFDsCount = 3;
- auto backends = g_dstates.getLocal();
+ const auto backends = dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends;
/* UDP sockets to backends */
size_t backendUDPSocketsCount = 0;
- for (const auto& backend : *backends) {
+ for (const auto& backend : backends) {
backendUDPSocketsCount += backend->sockets.size();
}
requiredFDsCount += backendUDPSocketsCount;
/* TCP sockets to backends */
if (immutableConfig.d_maxTCPClientThreads > 0) {
- requiredFDsCount += (backends->size() * immutableConfig.d_maxTCPClientThreads);
+ requiredFDsCount += (backends.size() * immutableConfig.d_maxTCPClientThreads);
}
/* listening sockets */
requiredFDsCount += udpBindsCount;
for (const auto& chain : dnsdist::rules::getResponseRuleChains()) {
chain.holder.setState({});
}
- g_dstates.setState({});
dnsdist::configuration::updateRuntimeConfiguration([](dnsdist::configuration::RuntimeConfiguration& config) {
config.d_lbPolicy = std::make_shared<ServerPolicy>();
config.d_pools.clear();
+ config.d_backends.clear();
});
clearWebHandlers();
dnsdist::lua::hooks::clearMaintenanceHooks();
if (precompute) {
vinfolog("Pre-computing hashes for consistent hash load-balancing policy");
// pre compute hashes
- auto backends = g_dstates.getLocal();
- for (const auto& backend : *backends) {
+ for (const auto& backend : dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends) {
if (backend->d_config.d_weight < 100) {
vinfolog("Warning, the backend '%s' has a very low weight (%d), which will not yield a good distribution of queries with the 'chashed' policy. Please consider raising it to at least '100'.", backend->getName(), backend->d_config.d_weight);
}
auto ret = std::make_shared<DownstreamState>(std::move(config), nullptr, true);
addServerToPool("", ret);
ret->start();
- g_dstates.modify([&ret](servers_t& servers) { servers.push_back(std::move(ret)); });
+ dnsdist::configuration::updateRuntimeConfiguration([&ret](dnsdist::configuration::RuntimeConfiguration& config) {
+ config.d_backends.push_back(std::move(ret));
+ });
}
}
- if (g_dstates.getLocal()->empty()) {
+ if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends.empty()) {
errlog("No downstream servers defined: all packets will get dropped");
// you might define them later, but you need to know
}
checkFileDescriptorsLimits(udpBindsCount, tcpBindsCount);
{
- auto states = g_dstates.getCopy(); // it is a copy, but the internal shared_ptrs are the real deal
+ const auto states = dnsdist::configuration::getCurrentRuntimeConfiguration().d_backends; // it is a copy, but the internal shared_ptrs are the real deal
auto mplexer = std::unique_ptr<FDMultiplexer>(FDMultiplexer::getMultiplexerSilent(states.size()));
for (auto& dss : states) {
return latencyUsec;
}
};
-using servers_t = vector<std::shared_ptr<DownstreamState>>;
void responderThread(std::shared_ptr<DownstreamState> dss);
extern RecursiveLockGuarded<LuaContext> g_lua;
extern GlobalStateHolder<SuffixMatchTree<DynBlock>> g_dynblockSMT;
-extern GlobalStateHolder<servers_t> g_dstates;
-
extern std::vector<shared_ptr<TLSFrontend>> g_tlslocals;
extern std::vector<shared_ptr<DOHFrontend>> g_dohlocals;
extern std::vector<shared_ptr<DOQFrontend>> g_doqlocals;
struct LocalHolders
{
LocalHolders() :
- ruleactions(dnsdist::rules::getRuleChainHolder(dnsdist::rules::RuleChain::Rules).getLocal()), cacheMissRuleActions(dnsdist::rules::getRuleChainHolder(dnsdist::rules::RuleChain::CacheMissRules).getLocal()), cacheHitRespRuleactions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::CacheHitResponseRules).getLocal()), cacheInsertedRespRuleActions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::CacheInsertedResponseRules).getLocal()), selfAnsweredRespRuleactions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::SelfAnsweredResponseRules).getLocal()), servers(g_dstates.getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal())
+ ruleactions(dnsdist::rules::getRuleChainHolder(dnsdist::rules::RuleChain::Rules).getLocal()), cacheMissRuleActions(dnsdist::rules::getRuleChainHolder(dnsdist::rules::RuleChain::CacheMissRules).getLocal()), cacheHitRespRuleactions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::CacheHitResponseRules).getLocal()), cacheInsertedRespRuleActions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::CacheInsertedResponseRules).getLocal()), selfAnsweredRespRuleactions(dnsdist::rules::getResponseRuleChainHolder(dnsdist::rules::ResponseRuleChain::SelfAnsweredResponseRules).getLocal()), dynNMGBlock(g_dynblockNMG.getLocal()), dynSMTBlock(g_dynblockSMT.getLocal())
{
}
LocalStateHolder<vector<dnsdist::rules::ResponseRuleAction>> cacheHitRespRuleactions;
LocalStateHolder<vector<dnsdist::rules::ResponseRuleAction>> cacheInsertedRespRuleActions;
LocalStateHolder<vector<dnsdist::rules::ResponseRuleAction>> selfAnsweredRespRuleactions;
- LocalStateHolder<servers_t> servers;
LocalStateHolder<NetmaskTree<DynBlock, AddressAndPortRange>> dynNMGBlock;
LocalStateHolder<SuffixMatchTree<DynBlock>> dynSMTBlock;
};
#include "dnsdist-tcp-downstream.hh"
#include "dnsdist-tcp-upstream.hh"
-GlobalStateHolder<NetmaskGroup> g_ACL;
-GlobalStateHolder<servers_t> g_dstates;
-
const bool TCPIOHandler::s_disableConnectForUnitTests = true;
bool checkDNSCryptQuery(const ClientState& cs, PacketBuffer& query, std::unique_ptr<DNSCryptQuery>& dnsCryptQuery, time_t now, bool tcp)