Loading PrivateDnsConfiguration.cpp +51 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ int PrivateDnsConfiguration::set(int32_t netId, uint32_t mark, mPrivateDnsModes[netId] = PrivateDnsMode::OFF; mPrivateDnsTransports.erase(netId); resolv_stats_set_servers_for_dot(netId, {}); mPrivateDnsValidateThreads.erase(netId); return 0; } Loading Loading @@ -155,6 +156,7 @@ void PrivateDnsConfiguration::clear(unsigned netId) { std::lock_guard guard(mPrivateDnsLock); mPrivateDnsModes.erase(netId); mPrivateDnsTransports.erase(netId); mPrivateDnsValidateThreads.erase(netId); } void PrivateDnsConfiguration::validatePrivateDnsProvider(const DnsTlsServer& server, Loading @@ -163,6 +165,10 @@ void PrivateDnsConfiguration::validatePrivateDnsProvider(const DnsTlsServer& ser tracker[server] = Validation::in_process; LOG(DEBUG) << "Server " << addrToString(&server.ss) << " marked as in_process on netId " << netId << ". Tracker now has size " << tracker.size(); // This judge must be after "tracker[server] = Validation::in_process;" if (!needValidateThread(server, netId)) { return; } // Note that capturing |server| and |netId| in this lambda create copies. std::thread validate_thread([this, server, netId, mark] { Loading Loading @@ -205,6 +211,7 @@ void PrivateDnsConfiguration::validatePrivateDnsProvider(const DnsTlsServer& ser break; } } this->cleanValidateThreadTracker(server, netId); }); validate_thread.detach(); } Loading Loading @@ -279,6 +286,50 @@ bool PrivateDnsConfiguration::recordPrivateDnsValidation(const DnsTlsServer& ser return reevaluationStatus; } bool PrivateDnsConfiguration::needValidateThread(const DnsTlsServer& server, unsigned netId) REQUIRES(mPrivateDnsLock) { // Create the thread tracker if it was not present auto threadPair = mPrivateDnsValidateThreads.find(netId); if (threadPair == mPrivateDnsValidateThreads.end()) { // No thread tracker yet for this netId. bool added; std::tie(threadPair, added) = mPrivateDnsValidateThreads.emplace(netId, ThreadTracker()); if (!added) { LOG(ERROR) << "Memory error while needValidateThread for netId " << netId; return true; } } auto& threadTracker = threadPair->second; if (threadTracker.count(server)) { LOG(DEBUG) << "Server " << addrToString(&(server.ss)) << " validate thread is already running. Thread tracker now has size " << threadTracker.size(); return false; } else { threadTracker.insert(server); LOG(DEBUG) << "Server " << addrToString(&(server.ss)) << " validate thread is not running. Thread tracker now has size " << threadTracker.size(); return true; } } void PrivateDnsConfiguration::cleanValidateThreadTracker(const DnsTlsServer& server, unsigned netId) { std::lock_guard<std::mutex> guard(mPrivateDnsLock); LOG(DEBUG) << "cleanValidateThreadTracker Server " << addrToString(&(server.ss)) << " validate thread is stopped."; auto threadPair = mPrivateDnsValidateThreads.find(netId); if (threadPair != mPrivateDnsValidateThreads.end()) { auto& threadTracker = threadPair->second; threadTracker.erase(server); LOG(DEBUG) << "Server " << addrToString(&(server.ss)) << " validate thread is stopped. Thread tracker now has size " << threadTracker.size(); } } // Start validation for newly added servers as well as any servers that have // landed in Validation::fail state. Note that servers that have failed // multiple validation attempts but for which there is still a validating Loading PrivateDnsConfiguration.h +5 −0 Original line number Diff line number Diff line Loading @@ -62,12 +62,16 @@ class PrivateDnsConfiguration { private: typedef std::map<DnsTlsServer, Validation, AddressComparator> PrivateDnsTracker; typedef std::set<DnsTlsServer, AddressComparator> ThreadTracker; void validatePrivateDnsProvider(const DnsTlsServer& server, PrivateDnsTracker& tracker, unsigned netId, uint32_t mark) REQUIRES(mPrivateDnsLock); bool recordPrivateDnsValidation(const DnsTlsServer& server, unsigned netId, bool success); bool needValidateThread(const DnsTlsServer& server, unsigned netId) REQUIRES(mPrivateDnsLock); void cleanValidateThreadTracker(const DnsTlsServer& server, unsigned netId); // Start validation for newly added servers as well as any servers that have // landed in Validation::fail state. Note that servers that have failed // multiple validation attempts but for which there is still a validating Loading @@ -79,6 +83,7 @@ class PrivateDnsConfiguration { // Structure for tracking the validation status of servers on a specific netId. // Using the AddressComparator ensures at most one entry per IP address. std::map<unsigned, PrivateDnsTracker> mPrivateDnsTransports GUARDED_BY(mPrivateDnsLock); std::map<unsigned, ThreadTracker> mPrivateDnsValidateThreads GUARDED_BY(mPrivateDnsLock); }; extern PrivateDnsConfiguration gPrivateDnsConfiguration; Loading TEST_MAPPING +1 −0 Original line number Diff line number Diff line { "presubmit": [ { "name": "resolv_integration_test" }, { "name": "resolv_gold_test" }, { "name": "resolv_unit_test" }, { "name": "resolv_stress_test" } ] Loading res_cache.cpp +14 −7 Original line number Diff line number Diff line Loading @@ -1696,13 +1696,13 @@ void resolv_populate_res_for_net(ResState* statp) { /* Resolver reachability statistics. */ static void _res_cache_add_stats_sample_locked(res_stats* stats, const res_sample* sample, static void res_cache_add_stats_sample_locked(res_stats* stats, const res_sample& sample, int max_samples) { // Note: This function expects max_samples > 0, otherwise a (harmless) modification of the // allocated but supposedly unused memory for samples[0] will happen LOG(INFO) << __func__ << ": adding sample to stats, next = " << unsigned(stats->sample_next) << ", count = " << unsigned(stats->sample_count); stats->samples[stats->sample_next] = *sample; stats->samples[stats->sample_next] = sample; if (stats->sample_count < max_samples) { ++stats->sample_count; } Loading Loading @@ -1815,15 +1815,22 @@ int resolv_cache_get_resolver_stats(unsigned netid, res_params* params, res_stat return -1; } void _resolv_cache_add_resolver_stats_sample(unsigned netid, int revision_id, int ns, const res_sample* sample, int max_samples) { if (max_samples <= 0) return; void resolv_cache_add_resolver_stats_sample(unsigned netid, int revision_id, const sockaddr* sa, const res_sample& sample, int max_samples) { if (max_samples <= 0 || sa == nullptr) return; std::lock_guard guard(cache_mutex); resolv_cache_info* info = find_cache_info_locked(netid); if (info && info->revision_id == revision_id) { _res_cache_add_stats_sample_locked(&info->nsstats[ns], sample, max_samples); const int serverNum = std::min(MAXNS, static_cast<int>(info->nameserverSockAddrs.size())); const IPSockAddr ipsa = IPSockAddr::toIPSockAddr(*sa); for (int ns = 0; ns < serverNum; ns++) { if (ipsa == info->nameserverSockAddrs.at(ns)) { res_cache_add_stats_sample_locked(&info->nsstats[ns], sample, max_samples); return; } } } } Loading res_send.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -530,7 +530,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int if (shouldRecordStats) { res_sample sample; _res_stats_set_sample(&sample, now, *rcode, delay); _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, ns, &sample, resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, nsap, sample, params.max_samples); resolv_stats_add(statp->netid, IPSockAddr::toIPSockAddr(*nsap), dnsQueryEvent); } Loading Loading @@ -564,7 +564,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int if (attempt == 0) { res_sample sample; _res_stats_set_sample(&sample, now, *rcode, delay); _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, ns, &sample, resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, nsap, sample, params.max_samples); resolv_stats_add(statp->netid, IPSockAddr::toIPSockAddr(*nsap), dnsQueryEvent); } Loading Loading
PrivateDnsConfiguration.cpp +51 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ int PrivateDnsConfiguration::set(int32_t netId, uint32_t mark, mPrivateDnsModes[netId] = PrivateDnsMode::OFF; mPrivateDnsTransports.erase(netId); resolv_stats_set_servers_for_dot(netId, {}); mPrivateDnsValidateThreads.erase(netId); return 0; } Loading Loading @@ -155,6 +156,7 @@ void PrivateDnsConfiguration::clear(unsigned netId) { std::lock_guard guard(mPrivateDnsLock); mPrivateDnsModes.erase(netId); mPrivateDnsTransports.erase(netId); mPrivateDnsValidateThreads.erase(netId); } void PrivateDnsConfiguration::validatePrivateDnsProvider(const DnsTlsServer& server, Loading @@ -163,6 +165,10 @@ void PrivateDnsConfiguration::validatePrivateDnsProvider(const DnsTlsServer& ser tracker[server] = Validation::in_process; LOG(DEBUG) << "Server " << addrToString(&server.ss) << " marked as in_process on netId " << netId << ". Tracker now has size " << tracker.size(); // This judge must be after "tracker[server] = Validation::in_process;" if (!needValidateThread(server, netId)) { return; } // Note that capturing |server| and |netId| in this lambda create copies. std::thread validate_thread([this, server, netId, mark] { Loading Loading @@ -205,6 +211,7 @@ void PrivateDnsConfiguration::validatePrivateDnsProvider(const DnsTlsServer& ser break; } } this->cleanValidateThreadTracker(server, netId); }); validate_thread.detach(); } Loading Loading @@ -279,6 +286,50 @@ bool PrivateDnsConfiguration::recordPrivateDnsValidation(const DnsTlsServer& ser return reevaluationStatus; } bool PrivateDnsConfiguration::needValidateThread(const DnsTlsServer& server, unsigned netId) REQUIRES(mPrivateDnsLock) { // Create the thread tracker if it was not present auto threadPair = mPrivateDnsValidateThreads.find(netId); if (threadPair == mPrivateDnsValidateThreads.end()) { // No thread tracker yet for this netId. bool added; std::tie(threadPair, added) = mPrivateDnsValidateThreads.emplace(netId, ThreadTracker()); if (!added) { LOG(ERROR) << "Memory error while needValidateThread for netId " << netId; return true; } } auto& threadTracker = threadPair->second; if (threadTracker.count(server)) { LOG(DEBUG) << "Server " << addrToString(&(server.ss)) << " validate thread is already running. Thread tracker now has size " << threadTracker.size(); return false; } else { threadTracker.insert(server); LOG(DEBUG) << "Server " << addrToString(&(server.ss)) << " validate thread is not running. Thread tracker now has size " << threadTracker.size(); return true; } } void PrivateDnsConfiguration::cleanValidateThreadTracker(const DnsTlsServer& server, unsigned netId) { std::lock_guard<std::mutex> guard(mPrivateDnsLock); LOG(DEBUG) << "cleanValidateThreadTracker Server " << addrToString(&(server.ss)) << " validate thread is stopped."; auto threadPair = mPrivateDnsValidateThreads.find(netId); if (threadPair != mPrivateDnsValidateThreads.end()) { auto& threadTracker = threadPair->second; threadTracker.erase(server); LOG(DEBUG) << "Server " << addrToString(&(server.ss)) << " validate thread is stopped. Thread tracker now has size " << threadTracker.size(); } } // Start validation for newly added servers as well as any servers that have // landed in Validation::fail state. Note that servers that have failed // multiple validation attempts but for which there is still a validating Loading
PrivateDnsConfiguration.h +5 −0 Original line number Diff line number Diff line Loading @@ -62,12 +62,16 @@ class PrivateDnsConfiguration { private: typedef std::map<DnsTlsServer, Validation, AddressComparator> PrivateDnsTracker; typedef std::set<DnsTlsServer, AddressComparator> ThreadTracker; void validatePrivateDnsProvider(const DnsTlsServer& server, PrivateDnsTracker& tracker, unsigned netId, uint32_t mark) REQUIRES(mPrivateDnsLock); bool recordPrivateDnsValidation(const DnsTlsServer& server, unsigned netId, bool success); bool needValidateThread(const DnsTlsServer& server, unsigned netId) REQUIRES(mPrivateDnsLock); void cleanValidateThreadTracker(const DnsTlsServer& server, unsigned netId); // Start validation for newly added servers as well as any servers that have // landed in Validation::fail state. Note that servers that have failed // multiple validation attempts but for which there is still a validating Loading @@ -79,6 +83,7 @@ class PrivateDnsConfiguration { // Structure for tracking the validation status of servers on a specific netId. // Using the AddressComparator ensures at most one entry per IP address. std::map<unsigned, PrivateDnsTracker> mPrivateDnsTransports GUARDED_BY(mPrivateDnsLock); std::map<unsigned, ThreadTracker> mPrivateDnsValidateThreads GUARDED_BY(mPrivateDnsLock); }; extern PrivateDnsConfiguration gPrivateDnsConfiguration; Loading
TEST_MAPPING +1 −0 Original line number Diff line number Diff line { "presubmit": [ { "name": "resolv_integration_test" }, { "name": "resolv_gold_test" }, { "name": "resolv_unit_test" }, { "name": "resolv_stress_test" } ] Loading
res_cache.cpp +14 −7 Original line number Diff line number Diff line Loading @@ -1696,13 +1696,13 @@ void resolv_populate_res_for_net(ResState* statp) { /* Resolver reachability statistics. */ static void _res_cache_add_stats_sample_locked(res_stats* stats, const res_sample* sample, static void res_cache_add_stats_sample_locked(res_stats* stats, const res_sample& sample, int max_samples) { // Note: This function expects max_samples > 0, otherwise a (harmless) modification of the // allocated but supposedly unused memory for samples[0] will happen LOG(INFO) << __func__ << ": adding sample to stats, next = " << unsigned(stats->sample_next) << ", count = " << unsigned(stats->sample_count); stats->samples[stats->sample_next] = *sample; stats->samples[stats->sample_next] = sample; if (stats->sample_count < max_samples) { ++stats->sample_count; } Loading Loading @@ -1815,15 +1815,22 @@ int resolv_cache_get_resolver_stats(unsigned netid, res_params* params, res_stat return -1; } void _resolv_cache_add_resolver_stats_sample(unsigned netid, int revision_id, int ns, const res_sample* sample, int max_samples) { if (max_samples <= 0) return; void resolv_cache_add_resolver_stats_sample(unsigned netid, int revision_id, const sockaddr* sa, const res_sample& sample, int max_samples) { if (max_samples <= 0 || sa == nullptr) return; std::lock_guard guard(cache_mutex); resolv_cache_info* info = find_cache_info_locked(netid); if (info && info->revision_id == revision_id) { _res_cache_add_stats_sample_locked(&info->nsstats[ns], sample, max_samples); const int serverNum = std::min(MAXNS, static_cast<int>(info->nameserverSockAddrs.size())); const IPSockAddr ipsa = IPSockAddr::toIPSockAddr(*sa); for (int ns = 0; ns < serverNum; ns++) { if (ipsa == info->nameserverSockAddrs.at(ns)) { res_cache_add_stats_sample_locked(&info->nsstats[ns], sample, max_samples); return; } } } } Loading
res_send.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -530,7 +530,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int if (shouldRecordStats) { res_sample sample; _res_stats_set_sample(&sample, now, *rcode, delay); _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, ns, &sample, resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, nsap, sample, params.max_samples); resolv_stats_add(statp->netid, IPSockAddr::toIPSockAddr(*nsap), dnsQueryEvent); } Loading Loading @@ -564,7 +564,7 @@ int res_nsend(res_state statp, const uint8_t* buf, int buflen, uint8_t* ans, int if (attempt == 0) { res_sample sample; _res_stats_set_sample(&sample, now, *rcode, delay); _resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, ns, &sample, resolv_cache_add_resolver_stats_sample(statp->netid, revision_id, nsap, sample, params.max_samples); resolv_stats_add(statp->netid, IPSockAddr::toIPSockAddr(*nsap), dnsQueryEvent); } Loading