DownstreamState::s_randomizeSockets = randomized;
});
+ luaCtx.writeFunction("setRandomizedIdsOverUDP", [](bool randomized) {
+ DownstreamState::s_randomizeIDs = randomized;
+ });
+
#if defined(HAVE_LIBSSL)
luaCtx.writeFunction("loadTLSEngine", [client](const std::string& engineName, boost::optional<std::string> defaultString) {
if (client) {
return;
}
- unsigned int idOffset = (ss->idOffset++) % ss->idStates.size();
- IDState* ids = &ss->idStates[idOffset];
- ids->age = 0;
- DOHUnitUniquePtr du(nullptr, DOHUnit::release);
-
- /* that means that the state was in use, possibly with an allocated
- DOHUnit that we will need to handle, but we can't touch it before
- confirming that we now own this state */
- if (ids->isInUse()) {
- du = DOHUnitUniquePtr(ids->du, DOHUnit::release);
- }
-
- /* we atomically replace the value, we now own this state */
- if (!ids->markAsUsed()) {
- /* the state was not in use.
- we reset 'du' because it might have still been in use when we read it. */
- du.release();
- ++ss->outstanding;
- }
- else {
- /* we are reusing a state, no change in outstanding but if there was an existing DOHUnit we need
- to handle it because it's about to be overwritten. */
- ids->du = nullptr;
- ++ss->reuseds;
- ++g_stats.downstreamTimeouts;
- handleDOHTimeout(std::move(du));
- }
+ unsigned int idOffset = 0;
+ int64_t generation;
+ IDState* ids = ss->getIDState(idOffset, generation);
ids->cs = &cs;
ids->origFD = cs.udpFD;
bool passCrossProtocolQuery(std::unique_ptr<CrossProtocolQuery>&& cpq);
int pickSocketForSending();
void pickSocketsReadyForReceiving(std::vector<int>& ready);
+ IDState* getIDState(unsigned int& id, int64_t& generation);
dnsdist::Protocol getProtocol() const
{
}
static bool s_randomizeSockets;
+ static bool s_randomizeIDs;
};
using servers_t =vector<std::shared_ptr<DownstreamState>>;
}
bool DownstreamState::s_randomizeSockets{false};
+bool DownstreamState::s_randomizeIDs{false};
+
+IDState* DownstreamState::getIDState(unsigned int& selectedID, int64_t& generation)
+{
+ DOHUnitUniquePtr du(nullptr, DOHUnit::release);
+ IDState* ids = nullptr;
+ if (s_randomizeIDs) {
+ /* if the state is already in use we will retry,
+ up to 5 five times. The last selected one is used
+ even if it was already in use */
+ size_t remainingAttempts = 5;
+ do {
+ selectedID = dnsdist::getRandomValue(idStates.size());
+ ids = &idStates[selectedID];
+ remainingAttempts--;
+ }
+ while (ids->isInUse() && remainingAttempts > 0);
+ }
+ else {
+ selectedID = (idOffset++) % idStates.size();
+ ids = &idStates[selectedID];
+ }
+
+ ids->age = 0;
+
+ /* that means that the state was in use, possibly with an allocated
+ DOHUnit that we will need to handle, but we can't touch it before
+ confirming that we now own this state */
+ if (ids->isInUse()) {
+ du = DOHUnitUniquePtr(ids->du, DOHUnit::release);
+ }
+
+ /* we atomically replace the value, we now own this state */
+ generation = ids->generation++;
+ if (!ids->markAsUsed(generation)) {
+ /* the state was not in use.
+ we reset 'du' because it might have still been in use when we read it. */
+ du.release();
+ ++outstanding;
+ }
+ else {
+ /* we are reusing a state, no change in outstanding but if there was an existing DOHUnit we need
+ to handle it because it's about to be overwritten. */
+ ids->du = nullptr;
+ ++reuseds;
+ ++g_stats.downstreamTimeouts;
+ handleDOHTimeout(std::move(du));
+ }
+
+ return ids;
+}
size_t ServerPool::countServers(bool upOnly)
{
}
ComboAddress dest = du->ids.origDest;
- unsigned int idOffset = (du->downstream->idOffset++) % du->downstream->idStates.size();
- IDState* ids = &du->downstream->idStates[idOffset];
- ids->age = 0;
- DOHUnit* oldDU = nullptr;
- if (ids->isInUse()) {
- /* that means that the state was in use, possibly with an allocated
- DOHUnit that we will need to handle, but we can't touch it before
- confirming that we now own this state */
- oldDU = ids->du;
- }
-
- /* we atomically replace the value, we now own this state */
- int64_t generation = ids->generation++;
- if (!ids->markAsUsed(generation)) {
- /* the state was not in use.
- we reset 'oldDU' because it might have still been in use when we read it. */
- oldDU = nullptr;
- ++du->downstream->outstanding;
- }
- else {
- ids->du = nullptr;
- /* we are reusing a state, no change in outstanding but if there was an existing DOHUnit we need
- to handle it because it's about to be overwritten. */
- ++du->downstream->reuseds;
- ++g_stats.downstreamTimeouts;
- handleDOHTimeout(DOHUnitUniquePtr(oldDU, DOHUnit::release));
- }
+ unsigned int idOffset = 0;
+ int64_t generation;
+ IDState* ids = du->downstream->getIDState(idOffset, generation);
ids->origFD = 0;
/* increase the ref count since we are about to store the pointer */
}
#endif /* HAVE_DNS_OVER_HTTPS */
+void handleDOHTimeout(DOHUnitUniquePtr&& oldDU)
+{
+}
+
std::string DNSQuestion::getTrailingData() const
{
return "";