From: Otto Moerbeek Date: Mon, 2 May 2022 09:32:15 +0000 (+0200) Subject: Move edns table to a shared table X-Git-Tag: auth-4.8.0-alpha0~55^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f60018544683d8f8f703dfb123adeb29e72f68f6;p=thirdparty%2Fpdns.git Move edns table to a shared table --- diff --git a/pdns/rec_channel_rec.cc b/pdns/rec_channel_rec.cc index 1f76636a02..09219c1644 100644 --- a/pdns/rec_channel_rec.cc +++ b/pdns/rec_channel_rec.cc @@ -971,11 +971,6 @@ static uint64_t getNegCacheSize() return g_negCache->size(); } -uint64_t* pleaseGetEDNSStatusesSize() -{ - return new uint64_t(SyncRes::getEDNSStatusesSize()); -} - uint64_t* pleaseGetConcurrentQueries() { return new uint64_t(getMT() ? getMT()->numProcesses() : 0); @@ -1977,7 +1972,7 @@ RecursorControlChannel::Answer RecursorControlParser::getAnswer(int s, const str return doDumpToFile(s, pleaseDumpDoTProbeMap, cmd, false); } if (cmd == "dump-ednsstatus" || cmd == "dump-edns") { - return doDumpToFile(s, pleaseDumpEDNSMap, cmd); + return doDumpToFile(s, pleaseDumpEDNSMap, cmd, false); } if (cmd == "dump-nsspeeds") { return doDumpToFile(s, pleaseDumpNSSpeeds, cmd, false); diff --git a/pdns/recursordist/rec-main.cc b/pdns/recursordist/rec-main.cc index 07d9e94dd6..f07d29939c 100644 --- a/pdns/recursordist/rec-main.cc +++ b/pdns/recursordist/rec-main.cc @@ -984,7 +984,7 @@ static void doStats(void) << SyncRes::getThrottledServersSize() << ", ns speeds: " << SyncRes::getNSSpeedsSize() << ", failed ns: " << SyncRes::getFailedServersSize() << ", ednsmap: " - << broadcastAccFunction(pleaseGetEDNSStatusesSize) << ", non-resolving: " + << SyncRes::getEDNSStatusesSize() << ", non-resolving: " << SyncRes::getNonResolvingNSSize() << ", saved-parentsets: " << SyncRes::getSaveParentsNSSetsSize() << endl; @@ -1010,7 +1010,7 @@ static void doStats(void) "throttle-entries", Logging::Loggable(SyncRes::getThrottledServersSize()), "nsspeed-entries", Logging::Loggable(SyncRes::getNSSpeedsSize()), "failed-host-entries", Logging::Loggable(SyncRes::getFailedServersSize()), - "edns-entries", Logging::Loggable(broadcastAccFunction(pleaseGetEDNSStatusesSize)), + "edns-entries", Logging::Loggable(SyncRes::getEDNSStatusesSize()), "non-resolving-nameserver-entries", Logging::Loggable(SyncRes::getNonResolvingNSSize()), "saved-parent-ns-sets-entries", Logging::Loggable(SyncRes::getSaveParentsNSSetsSize()), "outqueries-per-query", Logging::Loggable(ratePercentage(SyncRes::s_outqueries, SyncRes::s_queries))); @@ -2069,11 +2069,6 @@ static void houseKeeping(void*) }); } - static thread_local PeriodicTask pruneEDNSTask{"pruneEDNSTask", 5}; // period could likely be longer - pruneEDNSTask.runIfDue(now, [now]() { - SyncRes::pruneEDNSStatuses(now.tv_sec - 2 * 3600); - }); - static thread_local PeriodicTask pruneTCPTask{"pruneTCPTask", 5}; pruneTCPTask.runIfDue(now, [now]() { t_tcp_manager.cleanup(now); @@ -2120,6 +2115,11 @@ static void houseKeeping(void*) SyncRes::pruneNSSpeeds(now.tv_sec - 300); }); + static PeriodicTask pruneEDNSTask{"pruneEDNSTask", 5}; // period could likely be longer + pruneEDNSTask.runIfDue(now, [now]() { + SyncRes::pruneEDNSStatuses(now.tv_sec - 2 * 3600); + }); + if (SyncRes::s_max_busy_dot_probes > 0) { static PeriodicTask pruneDoTProbeMap{"pruneDoTProbeMapTask", 60}; pruneDoTProbeMap.runIfDue(now, [now]() { diff --git a/pdns/syncres.cc b/pdns/syncres.cc index dd8d494c92..3bf06b4d41 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -1060,6 +1060,67 @@ static const char* timestamp(time_t t, char* buf, size_t sz) return buf; } +struct ednsstatus_t : public multi_index_container, member>, + ordered_non_unique, member> + >> +{ + // Get a copy + ednsstatus_t getMap() const + { + return *this; + } + + void reset(index::type &ind, iterator it) + { + ind.modify(it, [](SyncRes::EDNSStatus &s) { s.mode = SyncRes::EDNSStatus::EDNSMode::UNKNOWN; s.modeSetAt = 0; }); + } + + void setMode(index::type &ind, iterator it, SyncRes::EDNSStatus::EDNSMode mode) + { + it->mode = mode; + } + + void setTS(index::type &ind, iterator it, time_t ts) + { + ind.modify(it, [ts](SyncRes::EDNSStatus &s) { s.modeSetAt = ts; }); + } + + void prune(time_t cutoff) + { + auto &ind = get(); + ind.erase(ind.begin(), ind.upper_bound(cutoff)); + } +}; + +static LockGuarded s_ednsstatus; + +SyncRes::EDNSStatus::EDNSMode SyncRes::getEDNSStatus(const ComboAddress& server) +{ + auto lock = s_ednsstatus.lock(); + const auto& it = lock->find(server); + if (it == lock->end()) { + return EDNSStatus::UNKNOWN; + } + return it->mode; +} + +uint64_t SyncRes::getEDNSStatusesSize() +{ + return s_ednsstatus.lock()->size(); +} + +void SyncRes::clearEDNSStatuses() +{ + s_ednsstatus.lock()->clear(); +} + +void SyncRes::pruneEDNSStatuses(time_t cutoff) +{ + s_ednsstatus.lock()->prune(cutoff); +} + uint64_t SyncRes::doEDNSDump(int fd) { int newfd = dup(fd); @@ -1073,11 +1134,12 @@ uint64_t SyncRes::doEDNSDump(int fd) } uint64_t count = 0; - fprintf(fp.get(),"; edns from thread follows\n;\n"); - for(const auto& eds : t_sstorage.ednsstatus) { + fprintf(fp.get(),"; edns dump follows\n;\n"); + const auto copy = s_ednsstatus.lock()->getMap(); + for (const auto& eds : copy) { count++; char tmp[26]; - fprintf(fp.get(), "%s\t%d\t%s\n", eds.address.toString().c_str(), (int)eds.mode, timestamp(eds.modeSetAt, tmp, sizeof(tmp))); + fprintf(fp.get(), "%s\t%s\t%s\n", eds.address.toString().c_str(), eds.toString().c_str(), timestamp(eds.modeSetAt, tmp, sizeof(tmp))); } return count; } @@ -1414,26 +1476,30 @@ LWResult::Result SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsM 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0 3) NOEDNS: Generates FORMERR on EDNS queries - Everybody starts out assumed to be '0'. - If '0', send out EDNS0 - If you FORMERR us, go to '3', - If no EDNS in response, go to '2' - If '1', send out EDNS0 - If FORMERR, downgrade to 3 - If '2', keep on including EDNS0, see what happens - Same behaviour as 0 - If '3', send bare queries + Everybody starts out assumed to be UNKNOWN. + If UNKNOWN, send out EDNS0 + If you FORMERR us, go to NOEDNS, + If no EDNS in response, go to EDNSIGNORANT + If EDNSOK, send out EDNS0 + If FORMERR, downgrade to NOEDNS + If EDNSIGNORANT, keep on including EDNS0, see what happens + Same behaviour as UNKNOWN + If NOEDNS, send bare queries */ - auto ednsstatus = t_sstorage.ednsstatus.insert(ip).first; // does this include port? YES - auto &ind = t_sstorage.ednsstatus.get(); - if (ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) { - t_sstorage.ednsstatus.reset(ind, ednsstatus); - // cerr<<"Resetting EDNS Status for "<insert(ip).first; // does this include port? YES + auto &ind = lock->get(); + if (ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) { + lock->reset(ind, ednsstatus); + // cerr<<"Resetting EDNS Status for "<mode; } - const SyncRes::EDNSStatus::EDNSMode *mode = &ednsstatus->mode; - const SyncRes::EDNSStatus::EDNSMode oldmode = *mode; + const SyncRes::EDNSStatus::EDNSMode oldmode = mode; int EDNSLevel = 0; auto luaconfsLocal = g_luaconfs.getLocal(); ResolveContext ctx; @@ -1444,19 +1510,21 @@ LWResult::Result SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsM #endif LWResult::Result ret; - for(int tries = 0; tries < 3; ++tries) { - // cerr<<"Remote '"<outgoingProtobufExportConfig.exportTypes, res, chained); } - // ednsstatus might be cleared, so do a new lookup - ednsstatus = t_sstorage.ednsstatus.insert(ip).first; - mode = &ednsstatus->mode; + if (ret == LWResult::Result::PermanentError || ret == LWResult::Result::OSLimitError || ret == LWResult::Result::Spoofed) { - return ret; // transport error, nothing to learn here + break; // transport error, nothing to learn here } if (ret == LWResult::Result::Timeout) { // timeout, not doing anything with it now - return ret; + break; } - else if (*mode == EDNSStatus::UNKNOWN || *mode == EDNSStatus::EDNSOK || *mode == EDNSStatus::EDNSIGNORANT ) { - if(res->d_validpacket && !res->d_haveEDNS && res->d_rcode == RCode::FormErr) { - // cerr<<"Downgrading to NOEDNS because of "<d_rcode)<<" for query to "<insert(ip).first; + mode = ednsstatus->mode; + auto &ind = lock->get(); + + if (mode != EDNSStatus::NOEDNS) { + if (res->d_validpacket && !res->d_haveEDNS && res->d_rcode == RCode::FormErr) { + mode = EDNSStatus::NOEDNS; + lock->setMode(ind, ednsstatus, mode); continue; } - else if(!res->d_haveEDNS) { - if (*mode != EDNSStatus::EDNSIGNORANT) { - t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::EDNSIGNORANT); - // cerr<<"We find that "<d_haveEDNS) { + if (mode != EDNSStatus::EDNSIGNORANT) { + mode = EDNSStatus::EDNSIGNORANT; + lock->setMode(ind, ednsstatus, mode); } } else { - t_sstorage.ednsstatus.setMode(ind, ednsstatus, EDNSStatus::EDNSOK); - // cerr<<"We find that "<setMode(ind, ednsstatus, mode); + } } } - if (oldmode != *mode || !ednsstatus->modeSetAt) { - t_sstorage.ednsstatus.setTS(ind, ednsstatus, d_now.tv_sec); + if (oldmode != mode || !ednsstatus->modeSetAt) { + lock->setTS(ind, ednsstatus, d_now.tv_sec); } - // cerr<<"Result: ret="<d_haveEDNS<<", new mode: "< domainmap_t; - struct EDNSStatus { - EDNSStatus(const ComboAddress &arg) : address(arg) {} - ComboAddress address; - time_t modeSetAt{0}; - mutable enum EDNSMode { UNKNOWN=0, EDNSOK=1, EDNSIGNORANT=2, NOEDNS=3 } mode{UNKNOWN}; - }; - - struct ednsstatus_t : public multi_index_container, member>, - ordered_non_unique, member> - >> { - void reset(index::type &ind, iterator it) { - ind.modify(it, [](EDNSStatus &s) { s.mode = EDNSStatus::EDNSMode::UNKNOWN; s.modeSetAt = 0; }); - } - void setMode(index::type &ind, iterator it, EDNSStatus::EDNSMode mode) { - it->mode = mode; - } - void setTS(index::type &ind, iterator it, time_t ts) { - ind.modify(it, [ts](EDNSStatus &s) { s.modeSetAt = ts; }); - } - - void prune(time_t cutoff) { - auto &ind = get(); - ind.erase(ind.begin(), ind.upper_bound(cutoff)); - } - - }; - struct ThreadLocalStorage { - ednsstatus_t ednsstatus; std::shared_ptr domainmap; }; @@ -242,26 +212,27 @@ public: static void clearNSSpeeds(); static float getNSSpeed(const DNSName& server, const ComboAddress& ca); - static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server) - { - const auto& it = t_sstorage.ednsstatus.find(server); - if (it == t_sstorage.ednsstatus.end()) - return EDNSStatus::UNKNOWN; + struct EDNSStatus { + EDNSStatus(const ComboAddress &arg) : address(arg) {} + ComboAddress address; + time_t modeSetAt{0}; + mutable enum EDNSMode : uint8_t { UNKNOWN = 0, EDNSOK = 1, EDNSIGNORANT = 2, NOEDNS = 3 } mode{UNKNOWN}; - return it->mode; - } - static uint64_t getEDNSStatusesSize() - { - return t_sstorage.ednsstatus.size(); - } - static void clearEDNSStatuses() - { - t_sstorage.ednsstatus.clear(); - } - static void pruneEDNSStatuses(time_t cutoff) - { - t_sstorage.ednsstatus.prune(cutoff); - } + std::string toString() const + { + const std::array modes = { "Unknown", "OK", "Ignorant", "NoEDNS" }; + unsigned int m = static_cast(mode); + if (m >= modes.size()) { + return "?"; + } + return modes.at(m); + } + }; + + static EDNSStatus::EDNSMode getEDNSStatus(const ComboAddress& server); + static uint64_t getEDNSStatusesSize(); + static void clearEDNSStatuses(); + static void pruneEDNSStatuses(time_t cutoff); static uint64_t getThrottledServersSize(); static void pruneThrottledServers(time_t now); @@ -929,7 +900,6 @@ void* pleaseSupplantAllowNotifyFor(std::shared_ptr ns); uint64_t* pleaseGetNsSpeedsSize(); uint64_t* pleaseGetFailedServersSize(); -uint64_t* pleaseGetEDNSStatusesSize(); uint64_t* pleaseGetConcurrentQueries(); uint64_t* pleaseGetThrottleSize(); uint64_t* pleaseGetPacketCacheHits();