OSDN Git Service

Add dumpsys support to ResolverController
authorPierre Imai <imaipi@google.com>
Tue, 19 Apr 2016 07:17:07 +0000 (16:17 +0900)
committerPierre Imai <imaipi@google.com>
Thu, 28 Apr 2016 08:28:21 +0000 (17:28 +0900)
BUG: 25731675

Change-Id: I1c715368b1f2d5e732528cd226b3f69792b75321

server/NetworkController.cpp
server/ResolverController.cpp
server/ResolverController.h
tests/netd_test.cpp

index 7c2a826..8b1f84e 100644 (file)
@@ -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();
 
index 20c9302..41913d3 100644 (file)
 #include <resolv_params.h>
 #include <resolv_stats.h>
 
+#include <android-base/strings.h>
 #include <android/net/INetd.h>
 
+#include "DumpWriter.h"
 #include "ResolverController.h"
 #include "ResolverStats.h"
 
@@ -189,3 +191,57 @@ int ResolverController::getResolverInfo(int32_t netId, std::vector<std::string>*
     (*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<std::string> servers;
+    std::vector<std::string> domains;
+    __res_params params;
+    std::vector<ResolverStats> stats;
+    time_t now = time(nullptr);
+    int rv = getDnsInfo(netId, &servers, &domains, &params, &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 <no data>", servers[i].c_str());
+                    }
+                } else {
+                    dw.println("%s <no stats>", 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<unsigned>(params.success_threshold),
+                    static_cast<unsigned>(params.min_samples),
+                    static_cast<unsigned>(params.max_samples));
+        }
+    }
+    dw.decIndent();
+}
index a3810d4..d0c984f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/in.h>
 
 struct __res_params;
+class DumpWriter;
 
 namespace android {
 namespace net {
@@ -55,6 +56,7 @@ public:
     int getResolverInfo(int32_t netId, std::vector<std::string>* servers,
             std::vector<std::string>* domains, std::vector<int32_t>* params,
             std::vector<int32_t>* stats);
+    void dump(DumpWriter& dw, unsigned netId);
 };
 
 #endif /* _RESOLVER_CONTROLLER_H_ */
index ef91266..d2d1428 100644 (file)
@@ -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<std::string> 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<std::string> 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();