return d_qpsLimiter ? d_qpsLimiter->getRate() : 0U;
}
-size_t ServerPool::countServers(bool upOnly)
+size_t ServerPool::countServers(bool upOnly) const
{
- std::shared_ptr<const ServerPolicy::NumberedServerVector> servers = nullptr;
- {
- auto lock = d_servers.read_lock();
- servers = *lock;
- }
-
size_t count = 0;
- for (const auto& server : *servers) {
+ for (const auto& server : d_servers) {
if (!upOnly || std::get<1>(server)->isUp() ) {
count++;
}
return count;
}
-size_t ServerPool::poolLoad()
+size_t ServerPool::poolLoad() const
{
- std::shared_ptr<const ServerPolicy::NumberedServerVector> servers = nullptr;
- {
- auto lock = d_servers.read_lock();
- servers = *lock;
- }
-
size_t load = 0;
- for (const auto& server : *servers) {
+ for (const auto& server : d_servers) {
size_t serverOutstanding = std::get<1>(server)->outstanding.load();
load += serverOutstanding;
}
return load;
}
-const std::shared_ptr<const ServerPolicy::NumberedServerVector> ServerPool::getServers()
+const ServerPolicy::NumberedServerVector& ServerPool::getServers() const
{
- std::shared_ptr<const ServerPolicy::NumberedServerVector> result;
- {
- result = *(d_servers.read_lock());
- }
- return result;
+ return d_servers;
}
-void ServerPool::addServer(shared_ptr<DownstreamState>& server)
+void ServerPool::addServer(std::shared_ptr<DownstreamState>& server)
{
- auto servers = d_servers.write_lock();
- /* we can't update the content of the shared pointer directly even when holding the lock,
- as other threads might hold a copy. We can however update the pointer as long as we hold the lock. */
- unsigned int count = static_cast<unsigned int>((*servers)->size());
- auto newServers = ServerPolicy::NumberedServerVector(*(*servers));
- newServers.emplace_back(++count, server);
+ unsigned int count = static_cast<unsigned int>(d_servers.size());
+ d_servers.emplace_back(++count, server);
/* we need to reorder based on the server 'order' */
- std::stable_sort(newServers.begin(), newServers.end(), [](const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& a, const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& b) {
+ std::stable_sort(d_servers.begin(), d_servers.end(), [](const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& a, const std::pair<unsigned int,std::shared_ptr<DownstreamState> >& b) {
return a.second->d_config.order < b.second->d_config.order;
});
/* and now we need to renumber for Lua (custom policies) */
size_t idx = 1;
- for (auto& serv : newServers) {
+ for (auto& serv : d_servers) {
serv.first = idx++;
}
- *servers = std::make_shared<const ServerPolicy::NumberedServerVector>(std::move(newServers));
- if ((*servers)->size() == 1) {
+ if (d_servers.size() == 1) {
d_tcpOnly = server->isTCPOnly();
}
else if (!server->isTCPOnly()) {
void ServerPool::removeServer(shared_ptr<DownstreamState>& server)
{
- auto servers = d_servers.write_lock();
- /* we can't update the content of the shared pointer directly even when holding the lock,
- as other threads might hold a copy. We can however update the pointer as long as we hold the lock. */
- auto newServers = std::make_shared<ServerPolicy::NumberedServerVector>(*(*servers));
size_t idx = 1;
bool found = false;
bool tcpOnly = true;
- for (auto it = newServers->begin(); it != newServers->end();) {
+ for (auto it = d_servers.begin(); it != d_servers.end();) {
if (found) {
tcpOnly = tcpOnly && it->second->isTCPOnly();
/* we need to renumber the servers placed
it++;
}
else if (it->second == server) {
- it = newServers->erase(it);
+ it = d_servers.erase(it);
found = true;
} else {
tcpOnly = tcpOnly && it->second->isTCPOnly();
}
}
d_tcpOnly = tcpOnly;
- *servers = std::move(newServers);
}
namespace dnsdist::backend
base += ".pools.";
base += poolName;
base += ".";
- const std::shared_ptr<ServerPool> pool = entry.second;
+ const ServerPool& pool = entry.second;
str << base << "servers"
- << " " << pool->countServers(false) << " " << now << "\r\n";
+ << " " << pool.countServers(false) << " " << now << "\r\n";
str << base << "servers-up"
- << " " << pool->countServers(true) << " " << now << "\r\n";
- if (pool->packetCache != nullptr) {
- const auto& cache = pool->packetCache;
+ << " " << pool.countServers(true) << " " << now << "\r\n";
+ if (pool.packetCache != nullptr) {
+ const auto& cache = pool.packetCache;
str << base << "cache-size"
<< " " << cache->getMaxEntries() << " " << now << "\r\n";
str << base << "cache-entries"
}
for (const auto& pool : globalConfig.pools) {
- std::shared_ptr<ServerPool> poolObj = createPoolIfNotExists(std::string(pool.name));
- if (!pool.packet_cache.empty()) {
- poolObj->packetCache = getRegisteredTypeByName<DNSDistPacketCache>(pool.packet_cache);
- }
- if (!pool.policy.empty()) {
- poolObj->policy = getRegisteredTypeByName<ServerPolicy>(pool.policy);
- }
+ dnsdist::configuration::updateRuntimeConfiguration([&pool](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto [poolIt, inserted] = config.d_pools.emplace(std::string(pool.name), ServerPool());
+ if (inserted) {
+ vinfolog("Creating pool %s", pool.name);
+ }
+
+ if (!pool.packet_cache.empty()) {
+ poolIt->second.packetCache = getRegisteredTypeByName<DNSDistPacketCache>(pool.packet_cache);
+ }
+ if (!pool.policy.empty()) {
+ poolIt->second.policy = getRegisteredTypeByName<ServerPolicy>(pool.policy);
+ }
+ });
}
loadRulesConfiguration(globalConfig);
#include "dnsdist-carbon.hh"
#include "dnsdist-query-count.hh"
#include "dnsdist-rule-chains.hh"
+#include "dnsdist-server-pool.hh"
#include "iputils.hh"
class ServerPolicy;
#ifndef DISABLE_CARBON
std::vector<dnsdist::Carbon::Endpoint> d_carbonEndpoints;
#endif /* DISABLE_CARBON */
- std::unordered_map<std::string, std::shared_ptr<ServerPool>> d_pools;
+ std::unordered_map<std::string, ServerPool> d_pools;
std::shared_ptr<const CredentialsHolder> d_webPassword;
std::shared_ptr<const CredentialsHolder> d_webAPIKey;
std::optional<std::unordered_map<std::string, std::string>> d_webCustomHeaders;
return wrandom(candidates, dnsq);
}
-std::shared_ptr<const ServerPolicy::NumberedServerVector> getDownstreamCandidates(const std::string& poolName)
+const ServerPolicy::NumberedServerVector& getDownstreamCandidates(const std::string& poolName)
{
- std::shared_ptr<ServerPool> pool = getPool(poolName);
- return pool->getServers();
+ return getPool(poolName).getServers();
}
-std::shared_ptr<ServerPool> createPoolIfNotExists(const string& poolName)
+const ServerPool& createPoolIfNotExists(const string& poolName)
{
{
const auto& pools = dnsdist::configuration::getCurrentRuntimeConfiguration().d_pools;
vinfolog("Creating pool %s", poolName);
}
- auto pool = std::make_shared<ServerPool>();
- dnsdist::configuration::updateRuntimeConfiguration([&poolName,&pool](dnsdist::configuration::RuntimeConfiguration& config) {
- config.d_pools.emplace(poolName, pool);
+ dnsdist::configuration::updateRuntimeConfiguration([&poolName](dnsdist::configuration::RuntimeConfiguration& config) {
+ config.d_pools.emplace(poolName, ServerPool());
});
- return pool;
+ {
+ const auto& pools = dnsdist::configuration::getCurrentRuntimeConfiguration().d_pools;
+ const auto poolIt = pools.find(poolName);
+ return poolIt->second;
+ }
}
void setPoolPolicy(const string& poolName, std::shared_ptr<ServerPolicy> policy)
{
- std::shared_ptr<ServerPool> pool = createPoolIfNotExists(poolName);
if (!poolName.empty()) {
vinfolog("Setting pool %s server selection policy to %s", poolName, policy->getName());
} else {
vinfolog("Setting default pool server selection policy to %s", policy->getName());
}
- pool->policy = std::move(policy);
+
+ dnsdist::configuration::updateRuntimeConfiguration([&poolName, &policy](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto [poolIt, inserted] = config.d_pools.emplace(poolName, ServerPool());
+ poolIt->second.policy = std::move(policy);
+ });
}
void addServerToPool(const string& poolName, std::shared_ptr<DownstreamState> server)
{
- std::shared_ptr<ServerPool> pool = createPoolIfNotExists(poolName);
if (!poolName.empty()) {
vinfolog("Adding server to pool %s", poolName);
} else {
vinfolog("Adding server to default pool");
}
- pool->addServer(server);
+
+ dnsdist::configuration::updateRuntimeConfiguration([&poolName, &server](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto [poolIt, inserted] = config.d_pools.emplace(poolName, ServerPool());
+ poolIt->second.addServer(server);
+ });
}
void removeServerFromPool(const string& poolName, std::shared_ptr<DownstreamState> server)
{
- std::shared_ptr<ServerPool> pool = getPool(poolName);
-
if (!poolName.empty()) {
vinfolog("Removing server from pool %s", poolName);
}
vinfolog("Removing server from default pool");
}
- pool->removeServer(server);
+ dnsdist::configuration::updateRuntimeConfiguration([&poolName, &server](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto [poolIt, inserted] = config.d_pools.emplace(poolName, ServerPool());
+ poolIt->second.removeServer(server);
+ });
}
-std::shared_ptr<ServerPool> getPool(const std::string& poolName)
+const ServerPool& getPool(const std::string& poolName)
{
const auto& pools = dnsdist::configuration::getCurrentRuntimeConfiguration().d_pools;
auto poolIt = pools.find(poolName);
struct ServerPool;
using pools_t = std::map<std::string, std::shared_ptr<ServerPool>>;
-std::shared_ptr<ServerPool> getPool(const std::string& poolName);
-std::shared_ptr<ServerPool> createPoolIfNotExists(const string& poolName);
+const ServerPool& getPool(const std::string& poolName);
+const ServerPool& createPoolIfNotExists(const string& poolName);
void setPoolPolicy(const string& poolName, std::shared_ptr<ServerPolicy> policy);
void addServerToPool(const string& poolName, std::shared_ptr<DownstreamState> server);
void removeServerFromPool(const string& poolName, std::shared_ptr<DownstreamState> server);
-std::shared_ptr<const ServerPolicy::NumberedServerVector> getDownstreamCandidates(const std::string& poolName);
+const ServerPolicy::NumberedServerVector& getDownstreamCandidates(const std::string& poolName);
std::shared_ptr<DownstreamState> firstAvailable(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq);
#endif /* DISABLE_POLICIES_BINDINGS */
/* ServerPool */
- luaCtx.registerFunction<void (std::shared_ptr<ServerPool>::*)(std::shared_ptr<DNSDistPacketCache>)>("setCache", [](const std::shared_ptr<ServerPool>& pool, std::shared_ptr<DNSDistPacketCache> cache) {
+ luaCtx.registerFunction<void (std::shared_ptr<dnsdist::lua::LuaServerPoolObject>::*)(std::shared_ptr<DNSDistPacketCache>)>("setCache", [](const std::shared_ptr<dnsdist::lua::LuaServerPoolObject>& pool, std::shared_ptr<DNSDistPacketCache> cache) {
if (pool) {
- pool->packetCache = std::move(cache);
+ dnsdist::configuration::updateRuntimeConfiguration([&pool, &cache](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto poolIt = config.d_pools.find(pool->poolName);
+ if (poolIt == config.d_pools.end()) {
+ /* this might happen if the Server Pool has been removed in the meantime, let's gracefully ignore it */
+ return;
+ }
+ poolIt->second.packetCache = std::move(cache);
+ });
+ }
+ });
+ luaCtx.registerFunction<std::shared_ptr<DNSDistPacketCache> (std::shared_ptr<dnsdist::lua::LuaServerPoolObject>::*)() const>("getCache", [](const std::shared_ptr<dnsdist::lua::LuaServerPoolObject>& pool) {
+ std::shared_ptr<DNSDistPacketCache> cache;
+ if (pool) {
+ dnsdist::configuration::updateRuntimeConfiguration([&pool, &cache](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto poolIt = config.d_pools.find(pool->poolName);
+ /* this might happen if the Server Pool has been removed in the meantime, let's gracefully ignore it */
+ if (poolIt != config.d_pools.end()) {
+ cache = poolIt->second.packetCache;
+ }
+ });
+ }
+ return cache;
+ });
+ luaCtx.registerFunction<void (std::shared_ptr<dnsdist::lua::LuaServerPoolObject>::*)()>("unsetCache", [](const std::shared_ptr<dnsdist::lua::LuaServerPoolObject>& pool) {
+ if (pool) {
+ dnsdist::configuration::updateRuntimeConfiguration([&pool](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto poolIt = config.d_pools.find(pool->poolName);
+ if (poolIt == config.d_pools.end()) {
+ /* this might happen if the Server Pool has been removed in the meantime, let's gracefully ignore it */
+ return;
+ }
+ poolIt->second.packetCache.reset();
+ });
}
});
- luaCtx.registerFunction("getCache", &ServerPool::getCache);
- luaCtx.registerFunction<void (std::shared_ptr<ServerPool>::*)()>("unsetCache", [](const std::shared_ptr<ServerPool>& pool) {
+ luaCtx.registerFunction<bool (std::shared_ptr<dnsdist::lua::LuaServerPoolObject>::*)() const>("getECS", [](const std::shared_ptr<dnsdist::lua::LuaServerPoolObject>& pool) {
+ bool ecs = false;
if (pool) {
- pool->packetCache = nullptr;
+ dnsdist::configuration::updateRuntimeConfiguration([&pool, &ecs](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto poolIt = config.d_pools.find(pool->poolName);
+ /* this might happen if the Server Pool has been removed in the meantime, let's gracefully ignore it */
+ if (poolIt != config.d_pools.end()) {
+ ecs = poolIt->second.getECS();
+ }
+ });
+ }
+ return ecs;
+ });
+ luaCtx.registerFunction<void (std::shared_ptr<dnsdist::lua::LuaServerPoolObject>::*)(bool ecs)>("setECS", [](std::shared_ptr<dnsdist::lua::LuaServerPoolObject>& pool, bool ecs) {
+ if (pool) {
+ dnsdist::configuration::updateRuntimeConfiguration([&pool, ecs](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto poolIt = config.d_pools.find(pool->poolName);
+ if (poolIt == config.d_pools.end()) {
+ /* this might happen if the Server Pool has been removed in the meantime, let's gracefully ignore it */
+ return;
+ }
+ poolIt->second.setECS(ecs);
+ });
}
});
- luaCtx.registerFunction("getECS", &ServerPool::getECS);
- luaCtx.registerFunction("setECS", &ServerPool::setECS);
#ifndef DISABLE_DOWNSTREAM_BINDINGS
/* DownstreamState */
return 0;
}
- auto pool = poolIt->second;
- if (!pool->packetCache) {
+ const auto& pool = poolIt->second;
+ if (!pool.packetCache) {
return 0;
}
- auto domains = pool->packetCache->getDomainsContainingRecords(ca);
+ auto domains = pool.packetCache->getDomainsContainingRecords(ca);
if (domains.size() == 0) {
return 0;
}
return 0;
}
- auto pool = poolIt->second;
- if (!pool->packetCache) {
+ const auto& pool = poolIt->second;
+ if (!pool.packetCache) {
return 0;
}
- auto addresses = pool->packetCache->getRecordsForDomain(name);
+ auto addresses = pool.packetCache->getRecordsForDomain(name);
if (addresses.size() == 0) {
return 0;
}
});
luaCtx.writeFunction("getPoolServers", [](const string& pool) {
- // coverity[auto_causes_copy]
- const auto poolServers = getDownstreamCandidates(pool);
- return *poolServers;
+ return getDownstreamCandidates(pool);
});
luaCtx.writeFunction("getServer", [client](boost::variant<unsigned int, std::string> identifier) -> boost::optional<std::shared_ptr<DownstreamState>> {
const auto pools = dnsdist::configuration::getCurrentRuntimeConfiguration().d_pools;
for (const auto& entry : pools) {
const string& name = entry.first;
- const std::shared_ptr<ServerPool> pool = entry.second;
- string cache = pool->packetCache != nullptr ? pool->packetCache->toString() : "";
+ const auto& pool = entry.second;
+ string cache = pool.packetCache != nullptr ? pool.packetCache->toString() : "";
string policy = defaultPolicyName;
- if (pool->policy != nullptr) {
- policy = pool->policy->getName();
+ if (pool.policy != nullptr) {
+ policy = pool.policy->getName();
}
string servers;
- const auto poolServers = pool->getServers();
- for (const auto& server : *poolServers) {
+ const auto& poolServers = pool.getServers();
+ for (const auto& server : poolServers) {
if (!servers.empty()) {
servers += ", ";
}
luaCtx.writeFunction("getPool", [client](const string& poolName) {
if (client) {
- return std::make_shared<ServerPool>();
+ return std::make_shared<dnsdist::lua::LuaServerPoolObject>(poolName);
}
- std::shared_ptr<ServerPool> pool = createPoolIfNotExists(poolName);
- return pool;
+ bool created = false;
+ dnsdist::configuration::updateRuntimeConfiguration([&poolName, &created](dnsdist::configuration::RuntimeConfiguration& config) {
+ auto [poolIt, inserted] = config.d_pools.emplace(poolName, ServerPool());
+ created = inserted;
+ });
+
+ if (created) {
+ vinfolog("Creating pool %s", poolName);
+ }
+
+ return std::make_shared<dnsdist::lua::LuaServerPoolObject>(poolName);
});
luaCtx.writeFunction("setVerboseLogDestination", [](const std::string& dest) {
luaCtx.writeFunction("showPoolServerPolicy", [](const std::string& pool) {
setLuaSideEffect();
auto poolObj = getPool(pool);
- if (poolObj->policy == nullptr) {
+ if (poolObj.policy == nullptr) {
g_outputBuffer = dnsdist::configuration::getCurrentRuntimeConfiguration().d_lbPolicy->getName() + "\n";
}
else {
- g_outputBuffer = poolObj->policy->getName() + "\n";
+ g_outputBuffer = poolObj.policy->getName() + "\n";
}
});
#endif /* DISABLE_POLICIES_BINDINGS */
return std::nullopt;
}
+
+struct LuaServerPoolObject
+{
+ LuaServerPoolObject(std::string name) :
+ poolName(std::move(name))
+ {
+ }
+
+ std::string poolName;
+};
}
namespace dnsdist::configuration::lua
bool matches(const DNSQuestion* dnsQuestion) const override
{
(void)dnsQuestion;
- return (getPool(d_poolname)->countServers(true) > 0);
+ return (getPool(d_poolname).countServers(true) > 0);
}
string toString() const override
bool matches(const DNSQuestion* dnsQuestion) const override
{
(void)dnsQuestion;
- return (getPool(d_poolname)->poolLoad()) > d_limit;
+ return (getPool(d_poolname).poolLoad()) > d_limit;
}
string toString() const override
--- /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>
+
+#include "dnsdist-lbpolicies.hh"
+
+class DNSDistPacketCache;
+
+struct ServerPool
+{
+ const std::shared_ptr<DNSDistPacketCache> getCache() const
+ {
+ return packetCache;
+ }
+
+ bool getECS() const
+ {
+ return d_useECS;
+ }
+
+ void setECS(bool useECS)
+ {
+ d_useECS = useECS;
+ }
+
+ size_t poolLoad() const;
+ size_t countServers(bool upOnly) const;
+ const ServerPolicy::NumberedServerVector& getServers() const;
+ void addServer(std::shared_ptr<DownstreamState>& server);
+ void removeServer(std::shared_ptr<DownstreamState>& server);
+ bool isTCPOnly() const
+ {
+ return d_tcpOnly;
+ }
+
+ std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
+ std::shared_ptr<ServerPolicy> policy{nullptr};
+
+private:
+ ServerPolicy::NumberedServerVector d_servers;
+ bool d_useECS{false};
+ bool d_tcpOnly{false};
+};
poolName = "_default_";
}
const string label = "{pool=\"" + poolName + "\"}";
- const std::shared_ptr<ServerPool> pool = entry.second;
- output << "dnsdist_pool_servers" << label << " " << pool->countServers(false) << "\n";
- output << "dnsdist_pool_active_servers" << label << " " << pool->countServers(true) << "\n";
+ const auto& pool = entry.second;
+ output << "dnsdist_pool_servers" << label << " " << pool.countServers(false) << "\n";
+ output << "dnsdist_pool_active_servers" << label << " " << pool.countServers(true) << "\n";
- if (pool->packetCache != nullptr) {
- const auto& cache = pool->packetCache;
+ if (pool.packetCache != nullptr) {
+ const auto& cache = pool.packetCache;
output << cachebase << "cache_size" <<label << " " << cache->getMaxEntries() << "\n";
output << cachebase << "cache_entries" <<label << " " << cache->getEntriesCount() << "\n";
const auto& localPools = dnsdist::configuration::getCurrentRuntimeConfiguration().d_pools;
pools.reserve(localPools.size());
for (const auto& pool : localPools) {
- const auto& cache = pool.second->packetCache;
+ const auto& cache = pool.second.packetCache;
Json::object entry{
{"id", num++},
{"name", pool.first},
- {"serversCount", (double)pool.second->countServers(false)},
+ {"serversCount", (double)pool.second.countServers(false)},
{"cacheSize", (double)(cache ? cache->getMaxEntries() : 0)},
{"cacheEntries", (double)(cache ? cache->getEntriesCount() : 0)},
{"cacheHits", (double)(cache ? cache->getHits() : 0)},
}
const auto& pool = poolIt->second;
- const auto& cache = pool->packetCache;
+ const auto& cache = pool.packetCache;
Json::object entry{
{"name", poolName->second},
- {"serversCount", (double)pool->countServers(false)},
+ {"serversCount", (double)pool.countServers(false)},
{"cacheSize", (double)(cache ? cache->getMaxEntries() : 0)},
{"cacheEntries", (double)(cache ? cache->getEntriesCount() : 0)},
{"cacheHits", (double)(cache ? cache->getHits() : 0)},
Json::array servers;
int num = 0;
- for (const auto& server : *pool->getServers()) {
+ for (const auto& server : pool.getServers()) {
addServerToJSON(servers, num, server.second);
num++;
}
type = QType::chartocode(expungeType->second.c_str());
}
- std::shared_ptr<ServerPool> pool;
+ std::optional<ServerPool> pool;
try {
pool = getPool(poolName->second);
}
return ProcessQueryResult::SendAnswer;
}
-static void selectBackendForOutgoingQuery(DNSQuestion& dnsQuestion, const std::shared_ptr<ServerPool>& serverPool, std::shared_ptr<DownstreamState>& selectedBackend)
+static void selectBackendForOutgoingQuery(DNSQuestion& dnsQuestion, const ServerPool& serverPool, std::shared_ptr<DownstreamState>& selectedBackend)
{
- std::shared_ptr<ServerPolicy> poolPolicy = serverPool->policy;
- const auto& policy = poolPolicy != nullptr ? *poolPolicy : *dnsdist::configuration::getCurrentRuntimeConfiguration().d_lbPolicy;
- const auto servers = serverPool->getServers();
- selectedBackend = policy.getSelectedBackend(*servers, dnsQuestion);
+ const auto& policy = serverPool.policy != nullptr ? *serverPool.policy : *dnsdist::configuration::getCurrentRuntimeConfiguration().d_lbPolicy;
+ const auto& servers = serverPool.getServers();
+ selectedBackend = policy.getSelectedBackend(servers, dnsQuestion);
}
ProcessQueryResult processQueryAfterRules(DNSQuestion& dnsQuestion, std::shared_ptr<DownstreamState>& selectedBackend)
if (dnsQuestion.getHeader()->qr) { // something turned it into a response
return handleQueryTurnedIntoSelfAnsweredResponse(dnsQuestion);
}
- std::shared_ptr<ServerPool> serverPool = getPool(dnsQuestion.ids.poolName);
- dnsQuestion.ids.packetCache = serverPool->packetCache;
+ const auto& serverPool = getPool(dnsQuestion.ids.poolName);
+ dnsQuestion.ids.packetCache = serverPool.packetCache;
selectBackendForOutgoingQuery(dnsQuestion, serverPool, selectedBackend);
bool willBeForwardedOverUDP = !dnsQuestion.overTCP() || dnsQuestion.ids.protocol == dnsdist::Protocol::DoH;
if (selectedBackend && selectedBackend->isTCPOnly()) {
willBeForwardedOverUDP = false;
}
else if (!selectedBackend) {
- willBeForwardedOverUDP = !serverPool->isTCPOnly();
+ willBeForwardedOverUDP = !serverPool.isTCPOnly();
}
uint32_t allowExpired = selectedBackend ? 0 : dnsdist::configuration::getCurrentRuntimeConfiguration().d_staleCacheEntriesTTL;
dnsQuestion.ids.dnssecOK = (dnsdist::getEDNSZ(dnsQuestion) & EDNS_HEADER_FLAG_DO) != 0;
}
- if (dnsQuestion.useECS && ((selectedBackend && selectedBackend->d_config.useECS) || (!selectedBackend && serverPool->getECS()))) {
+ if (dnsQuestion.useECS && ((selectedBackend && selectedBackend->d_config.useECS) || (!selectedBackend && serverPool.getECS()))) {
// we special case our cache in case a downstream explicitly gave us a universally valid response with a 0 scope
// we need ECS parsing (parseECS) to be true so we can be sure that the initial incoming query did not have an existing
// ECS option, which would make it unsuitable for the zero-scope feature.
/* let's be nice and allow the selection of a different pool,
but no second cache-lookup for you */
if (dnsQuestion.ids.poolName != existingPool) {
- serverPool = getPool(dnsQuestion.ids.poolName);
- dnsQuestion.ids.packetCache = serverPool->packetCache;
- selectBackendForOutgoingQuery(dnsQuestion, serverPool, selectedBackend);
+ const auto& newServerPool = getPool(dnsQuestion.ids.poolName);
+ dnsQuestion.ids.packetCache = newServerPool.packetCache;
+ selectBackendForOutgoingQuery(dnsQuestion, newServerPool, selectedBackend);
}
}
for (const auto& entry : pools) {
const auto& pool = entry.second;
- auto packetCache = pool->packetCache;
+ const auto& packetCache = pool.packetCache;
if (!packetCache) {
continue;
}
has all its backends down) */
if (packetCache->keepStaleData() && !iter->second) {
/* so far all pools had at least one backend up */
- if (pool->countServers(true) == 0) {
+ if (pool.countServers(true) == 0) {
iter->second = true;
}
}
}
else {
for (const auto& entry : currentConfig.d_pools) {
- if (entry.second->policy != nullptr && entry.second->policy->getName() == "chashed") {
+ if (entry.second.policy != nullptr && entry.second.policy->getName() == "chashed") {
precompute = true;
break;
}
void responderThread(std::shared_ptr<DownstreamState> dss);
-class DNSDistPacketCache;
-
-struct ServerPool
-{
- ServerPool() :
- d_servers(std::make_shared<const ServerPolicy::NumberedServerVector>())
- {
- }
-
- ~ServerPool()
- {
- }
-
- const std::shared_ptr<DNSDistPacketCache> getCache() const { return packetCache; };
-
- bool getECS() const
- {
- return d_useECS;
- }
-
- void setECS(bool useECS)
- {
- d_useECS = useECS;
- }
-
- std::shared_ptr<DNSDistPacketCache> packetCache{nullptr};
- std::shared_ptr<ServerPolicy> policy{nullptr};
-
- size_t poolLoad();
- size_t countServers(bool upOnly);
- const std::shared_ptr<const ServerPolicy::NumberedServerVector> getServers();
- void addServer(shared_ptr<DownstreamState>& server);
- void removeServer(shared_ptr<DownstreamState>& server);
- bool isTCPOnly() const
- {
- // coverity[missing_lock]
- return d_tcpOnly;
- }
-
-private:
- SharedLockGuarded<std::shared_ptr<const ServerPolicy::NumberedServerVector>> d_servers;
- bool d_useECS{false};
- bool d_tcpOnly{false};
-};
-
enum ednsHeaderFlags
{
EDNS_HEADER_FLAG_NONE = 0,
packetCache->insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
std::string poolName("test-pool");
- auto testPool = std::make_shared<ServerPool>();
- testPool->packetCache = packetCache;
+ auto testPool = ServerPool();
+ testPool.packetCache = packetCache;
std::string poolWithNoCacheName("test-pool-without-cache");
- auto testPoolWithNoCache = std::make_shared<ServerPool>();
+ auto testPoolWithNoCache = ServerPool();
dnsdist::configuration::updateRuntimeConfiguration([&poolName, &testPool, &poolWithNoCacheName, &testPoolWithNoCache](dnsdist::configuration::RuntimeConfiguration& config) {
config.d_pools.emplace(poolName, testPool);
config.d_pools.emplace(poolWithNoCacheName, testPoolWithNoCache);