From: Pierre Imai Date: Tue, 19 Apr 2016 07:17:07 +0000 (+0900) Subject: Add dumpsys support to ResolverController X-Git-Tag: android-x86-7.1-r1~39^2~9 X-Git-Url: http://git.osdn.net/view?p=android-x86%2Fsystem-netd.git;a=commitdiff_plain;h=3a272070fc318ef1a7a5a04e500483f1a7c629a8 Add dumpsys support to ResolverController BUG: 25731675 Change-Id: I1c715368b1f2d5e732528cd226b3f69792b75321 --- diff --git a/server/NetworkController.cpp b/server/NetworkController.cpp index 7c2a826..8b1f84e 100644 --- a/server/NetworkController.cpp +++ b/server/NetworkController.cpp @@ -38,6 +38,7 @@ #include "cutils/misc.h" #include "resolv_netid.h" +#include "Controllers.h" #include "DummyNetwork.h" #include "DumpWriter.h" #include "Fwmark.h" @@ -525,6 +526,8 @@ void NetworkController::dump(DumpWriter& dw) { dw.incIndent(); for (const auto& i : mNetworks) { dw.println(i.second->toString().c_str()); + android::net::gCtls->resolverCtrl.dump(dw, i.first); + dw.blankline(); } dw.decIndent(); diff --git a/server/ResolverController.cpp b/server/ResolverController.cpp index 20c9302..41913d3 100644 --- a/server/ResolverController.cpp +++ b/server/ResolverController.cpp @@ -33,8 +33,10 @@ #include #include +#include #include +#include "DumpWriter.h" #include "ResolverController.h" #include "ResolverStats.h" @@ -189,3 +191,57 @@ int ResolverController::getResolverInfo(int32_t netId, std::vector* (*params)[INetd::RESOLVER_PARAMS_MAX_SAMPLES] = res_params.max_samples; return 0; } + +void ResolverController::dump(DumpWriter& dw, unsigned netId) { + // No lock needed since Bionic's resolver locks all accessed data structures internally. + using android::net::ResolverStats; + std::vector servers; + std::vector domains; + __res_params params; + std::vector stats; + time_t now = time(nullptr); + int rv = getDnsInfo(netId, &servers, &domains, ¶ms, &stats); + dw.incIndent(); + if (rv != 0) { + dw.println("getDnsInfo() failed for netid %u", netId); + } else { + if (servers.empty()) { + dw.println("No DNS servers defined"); + } else { + dw.println("DNS servers: # IP (total, successes, errors, timeouts, internal errors, " + "RTT avg, last sample)"); + dw.incIndent(); + for (size_t i = 0 ; i < servers.size() ; ++i) { + if (i < stats.size()) { + const ResolverStats& s = stats[i]; + int total = s.successes + s.errors + s.timeouts + s.internal_errors; + if (total > 0) { + int time_delta = (s.last_sample_time > 0) ? now - s.last_sample_time : -1; + dw.println("%s (%d, %d, %d, %d, %d, %dms, %ds)%s", servers[i].c_str(), + total, s.successes, s.errors, s.timeouts, s.internal_errors, + s.rtt_avg, time_delta, s.usable ? "" : " BROKEN"); + } else { + dw.println("%s ", servers[i].c_str()); + } + } else { + dw.println("%s ", servers[i].c_str()); + } + } + dw.decIndent(); + } + if (domains.empty()) { + dw.println("No search domains defined"); + } else { + std::string domains_str = android::base::Join(domains, ", "); + dw.println("search domains: %s", domains_str.c_str()); + } + if (params.sample_validity != 0) { + dw.println("DNS parameters: sample validity = %us, success threshold = %u%%, " + "samples (min, max) = (%u, %u)", params.sample_validity, + static_cast(params.success_threshold), + static_cast(params.min_samples), + static_cast(params.max_samples)); + } + } + dw.decIndent(); +} diff --git a/server/ResolverController.h b/server/ResolverController.h index a3810d4..d0c984f 100644 --- a/server/ResolverController.h +++ b/server/ResolverController.h @@ -22,6 +22,7 @@ #include struct __res_params; +class DumpWriter; namespace android { namespace net { @@ -55,6 +56,7 @@ public: int getResolverInfo(int32_t netId, std::vector* servers, std::vector* domains, std::vector* params, std::vector* stats); + void dump(DumpWriter& dw, unsigned netId); }; #endif /* _RESOLVER_CONTROLLER_H_ */ diff --git a/tests/netd_test.cpp b/tests/netd_test.cpp index ef91266..d2d1428 100644 --- a/tests/netd_test.cpp +++ b/tests/netd_test.cpp @@ -124,6 +124,50 @@ bool expectNetdResult(int expected, const char* sockname, const char* format, .. return (200 <= expected && expected < 300); } +class AddrInfo { + public: + AddrInfo() : ai_(nullptr), error_(0) {} + + AddrInfo(const char* node, const char* service, const addrinfo& hints) : ai_(nullptr) { + init(node, service, hints); + } + + AddrInfo(const char* node, const char* service) : ai_(nullptr) { + init(node, service); + } + + ~AddrInfo() { clear(); } + + int init(const char* node, const char* service, const addrinfo& hints) { + clear(); + error_ = getaddrinfo(node, service, &hints, &ai_); + return error_; + } + + int init(const char* node, const char* service) { + clear(); + error_ = getaddrinfo(node, service, nullptr, &ai_); + return error_; + } + + void clear() { + if (ai_ != nullptr) { + freeaddrinfo(ai_); + ai_ = nullptr; + error_ = 0; + } + } + + const addrinfo& operator*() const { return *ai_; } + const addrinfo* get() const { return ai_; } + const addrinfo* operator&() const { return ai_; } + int error() const { return error_; } + + private: + addrinfo* ai_; + int error_; +}; + class ResolverTest : public ::testing::Test { protected: struct Mapping { @@ -471,57 +515,66 @@ TEST_F(ResolverTest, GetAddrInfo) { dns.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4"); dns.addMapping(host_name, ns_type::ns_t_aaaa, "::1.2.3.4"); ASSERT_TRUE(dns.startServer()); - std::vector servers = { listen_addr }; - ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, mDefaultParams)); - - dns.clearQueries(); - EXPECT_EQ(0, getaddrinfo("howdy", nullptr, nullptr, &result)); - size_t found = GetNumQueries(dns, host_name); - EXPECT_LE(1U, found); - // Could be A or AAAA - std::string result_str = ToString(result); - EXPECT_TRUE(result_str == "1.2.3.4" || result_str == "::1.2.3.4") - << ", result_str='" << result_str << "'"; - // TODO: Use ScopedAddrinfo or similar once it is available in a common header file. - if (result) { - freeaddrinfo(result); - result = nullptr; - } - // Verify that the name is cached. - EXPECT_EQ(0, getaddrinfo("howdy", nullptr, nullptr, &result)); - found = GetNumQueries(dns, host_name); - EXPECT_LE(1U, found); - result_str = ToString(result); - EXPECT_TRUE(result_str == "1.2.3.4" || result_str == "::1.2.3.4") - << result_str; - if (result) { - freeaddrinfo(result); - result = nullptr; - } - - // Change the DNS resolver, ensure that queries are no longer cached. - dns.clearQueries(); test::DNSResponder dns2(listen_addr2, listen_srv, 250, ns_rcode::ns_r_servfail, 1.0); dns2.addMapping(host_name, ns_type::ns_t_a, "1.2.3.4"); dns2.addMapping(host_name, ns_type::ns_t_aaaa, "::1.2.3.4"); ASSERT_TRUE(dns2.startServer()); - servers = { listen_addr2 }; - ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, mDefaultParams)); - EXPECT_EQ(0, getaddrinfo("howdy", nullptr, nullptr, &result)); - found = GetNumQueries(dns, host_name); - size_t found2 = GetNumQueries(dns2, host_name); - EXPECT_EQ(0U, found); - EXPECT_LE(1U, found2); - - // Could be A or AAAA - result_str = ToString(result); - EXPECT_TRUE(result_str == "1.2.3.4" || result_str == "::1.2.3.4") - << ", result_str='" << result_str << "'"; - if (result) { - freeaddrinfo(result); - result = nullptr; + + for (size_t i = 0 ; i < 1000 ; ++i) { + std::vector servers = { listen_addr }; + ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, mDefaultParams)); + dns.clearQueries(); + dns2.clearQueries(); + + EXPECT_EQ(0, getaddrinfo("howdy", nullptr, nullptr, &result)); + size_t found = GetNumQueries(dns, host_name); + EXPECT_LE(1U, found); + // Could be A or AAAA + std::string result_str = ToString(result); + EXPECT_TRUE(result_str == "1.2.3.4" || result_str == "::1.2.3.4") + << ", result_str='" << result_str << "'"; + // TODO: Use ScopedAddrinfo or similar once it is available in a common header file. + if (result) { + freeaddrinfo(result); + result = nullptr; + } + + // Verify that the name is cached. + size_t old_found = found; + EXPECT_EQ(0, getaddrinfo("howdy", nullptr, nullptr, &result)); + found = GetNumQueries(dns, host_name); + EXPECT_LE(1U, found); + EXPECT_EQ(old_found, found); + result_str = ToString(result); + EXPECT_TRUE(result_str == "1.2.3.4" || result_str == "::1.2.3.4") + << result_str; + if (result) { + freeaddrinfo(result); + result = nullptr; + } + + // Change the DNS resolver, ensure that queries are no longer cached. + servers = { listen_addr2 }; + ASSERT_TRUE(SetResolversForNetwork(mDefaultSearchDomains, servers, mDefaultParams)); + dns.clearQueries(); + dns2.clearQueries(); + + EXPECT_EQ(0, getaddrinfo("howdy", nullptr, nullptr, &result)); + found = GetNumQueries(dns, host_name); + size_t found2 = GetNumQueries(dns2, host_name); + EXPECT_EQ(0U, found); + EXPECT_LE(1U, found2); + + // Could be A or AAAA + result_str = ToString(result); + EXPECT_TRUE(result_str == "1.2.3.4" || result_str == "::1.2.3.4") + << ", result_str='" << result_str << "'"; + if (result) { + freeaddrinfo(result); + result = nullptr; + } } dns.stopServer(); dns2.stopServer();