Loading Android.bp +57 −80 Original line number Original line Diff line number Diff line Loading @@ -30,10 +30,6 @@ license { ], ], } } // Whether to enable the targets in this file that require rust toolchain. // Set to false in branches like mainline-prod where rust toolchain isn't supported. support_rust_toolchain = false cc_library_headers { cc_library_headers { name: "libnetd_resolv_headers", name: "libnetd_resolv_headers", export_include_dirs: ["include"], export_include_dirs: ["include"], Loading @@ -48,6 +44,8 @@ cc_library_headers { cc_library_headers { cc_library_headers { name: "dnsproxyd_protocol_headers", name: "dnsproxyd_protocol_headers", sdk_version: "29", min_sdk_version: "29", export_include_dirs: ["include/dnsproxyd_protocol"], export_include_dirs: ["include/dnsproxyd_protocol"], apex_available: [ apex_available: [ "//apex_available:platform", "//apex_available:platform", Loading @@ -60,7 +58,7 @@ dnsresolver_aidl_interface_lateststable_version = "V8" cc_library_static { cc_library_static { name: "dnsresolver_aidl_interface-lateststable-ndk_platform", name: "dnsresolver_aidl_interface-lateststable-ndk_platform", whole_static_libs: [ whole_static_libs: [ "dnsresolver_aidl_interface-ndk_platform", "dnsresolver_aidl_interface-" + dnsresolver_aidl_interface_lateststable_version + "-ndk_platform", ], ], apex_available: [ apex_available: [ "com.android.resolv", "com.android.resolv", Loading @@ -85,10 +83,11 @@ aidl_interface { backend: { backend: { java: { java: { apex_available: [ apex_available: [ "//apex_available:platform", "com.android.bluetooth.updatable", "com.android.bluetooth.updatable", "com.android.tethering", "com.android.wifi", "com.android.wifi", ], ], min_sdk_version: "30", }, }, ndk: { ndk: { gen_log: true, gen_log: true, Loading Loading @@ -123,6 +122,8 @@ cc_defaults { "libbase", "libbase", "liblog", "liblog", ], ], // This field is required to make test compatible with Q devices. min_sdk_version: "29", } } cc_defaults { cc_defaults { Loading Loading @@ -315,81 +316,57 @@ filegroup { ], ], } } // rust_ffi_static { rust_ffi_static { // name: "libdoh_ffi", name: "libdoh_ffi", // enabled: support_rust_toolchain, crate_name: "doh", // crate_name: "doh", srcs: ["doh.rs"], // srcs: ["doh.rs"], edition: "2018", // edition: "2018", // rlibs: [ rlibs: [ // "libandroid_logger", "libandroid_logger", // "libanyhow", "libanyhow", // "liblazy_static", "liblazy_static", // "liblibc", "liblibc", // "liblog_rust", "liblog_rust", // "libquiche", "libquiche", // "libring", "libring", // "libtokio", "libtokio", // "liburl", "liburl", // ], ], // prefer_rlib: true, prefer_rlib: true, // shared_libs: [ // "libcrypto", // "libssl", // ], // apex_available: [ shared_libs: [ // "//apex_available:platform", // Needed by doh_ffi_test "libcrypto", // "com.android.resolv" "libssl", // ], ], // min_sdk_version: "29", // } // cc_test { apex_available: [ // name: "doh_ffi_test", "//apex_available:platform", // Needed by doh_ffi_test // enabled: support_rust_toolchain, "com.android.resolv" // test_suites: [ ], // "general-tests", min_sdk_version: "29", // ], } // defaults: ["netd_defaults"], // srcs: ["doh_ffi_test.cpp"], // static_libs: [ // "libdoh_ffi", // "libgmock", // "liblog", // "libring-core", // ], // // These are not carried over from libdoh_ffi. // shared_libs: [ // "libcrypto", // "libssl", // ], // min_sdk_version: "29", // } // rust_test { rust_test { // name: "doh_unit_test", name: "doh_unit_test", // enabled: support_rust_toolchain, crate_name: "doh", // crate_name: "doh", srcs: ["doh.rs"], // srcs: ["doh.rs"], edition: "2018", // edition: "2018", test_suites: ["general-tests"], // test_suites: ["general-tests"], auto_gen_config: true, // auto_gen_config: true, // Used to enable root permission for the test. // // Used to enable root permission for the test. // TODO: remove after 'require_root' is supported in rust_test. // // TODO: remove after 'require_root' is supported in rust_test. test_config_template: ":resolv_rust_test_config_template", // test_config_template: ":resolv_rust_test_config_template", rustlibs: [ // rustlibs: [ "libandroid_logger", // "libandroid_logger", "libanyhow", // "libanyhow", "liblazy_static", // "liblazy_static", "liblibc", // "liblibc", "liblog_rust", // "liblog_rust", "libquiche_static", // "libquiche", "libring", // "libring", "libtokio", // "libtokio", "liburl", // "liburl", ], // ], min_sdk_version: "29", // min_sdk_version: "29", } // } DnsStats.cpp +14 −0 Original line number Original line Diff line number Diff line Loading @@ -239,6 +239,20 @@ std::vector<IPSockAddr> DnsStats::getSortedServers(Protocol protocol) const { return ret; return ret; } } std::optional<microseconds> DnsStats::getAverageLatencyUs(Protocol protocol) const { const auto stats = getStats(protocol); int count = 0; microseconds sum; for (const auto& v : stats) { count += v.total; sum += v.latencyUs; } if (count == 0) return std::nullopt; return sum / count; } std::vector<StatsData> DnsStats::getStats(Protocol protocol) const { std::vector<StatsData> DnsStats::getStats(Protocol protocol) const { std::vector<StatsData> ret; std::vector<StatsData> ret; Loading DnsStats.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -121,9 +121,11 @@ class DnsStats { std::vector<netdutils::IPSockAddr> getSortedServers(Protocol protocol) const; std::vector<netdutils::IPSockAddr> getSortedServers(Protocol protocol) const; // Returns the average query latency in microseconds. std::optional<std::chrono::microseconds> getAverageLatencyUs(Protocol protocol) const; void dump(netdutils::DumpWriter& dw); void dump(netdutils::DumpWriter& dw); // For testing. std::vector<StatsData> getStats(Protocol protocol) const; std::vector<StatsData> getStats(Protocol protocol) const; // TODO: Compatible support for getResolverInfo(). // TODO: Compatible support for getResolverInfo(). Loading DnsStatsTest.cpp +56 −27 Original line number Original line Diff line number Diff line Loading @@ -26,12 +26,24 @@ namespace android::net { using namespace std::chrono_literals; using namespace std::chrono_literals; using android::netdutils::IPSockAddr; using android::netdutils::IPSockAddr; using std::chrono::microseconds; using std::chrono::milliseconds; using std::chrono::milliseconds; using ::testing::IsEmpty; using ::testing::IsEmpty; using ::testing::UnorderedElementsAreArray; using ::testing::UnorderedElementsAreArray; namespace { namespace { constexpr auto NO_AVERAGE_LATENCY = std::nullopt; // A helper which can propagate the failure to outside of the stmt to know which line // of stmt fails. The expectation fails only for the first failed stmt. #define EXPECT_NO_FAILURE(stmt) \ do { \ bool alreadyFailed = HasFailure(); \ stmt; \ if (!alreadyFailed && HasFailure()) EXPECT_FALSE(HasFailure()); \ } while (0) DnsQueryEvent makeDnsQueryEvent(const Protocol protocol, const NsRcode rcode, DnsQueryEvent makeDnsQueryEvent(const Protocol protocol, const NsRcode rcode, const milliseconds& latency) { const milliseconds& latency) { DnsQueryEvent event; DnsQueryEvent event; Loading @@ -41,11 +53,11 @@ DnsQueryEvent makeDnsQueryEvent(const Protocol protocol, const NsRcode rcode, return event; return event; } } StatsData makeStatsData(const IPSockAddr& server, const int total, const milliseconds& latencyMs, StatsData makeStatsData(const IPSockAddr& server, const int total, const microseconds& latencyUs, const std::map<int, int>& rcodeCounts) { const std::map<int, int>& rcodeCounts) { StatsData ret(server); StatsData ret(server); ret.total = total; ret.total = total; ret.latencyUs = latencyMs; ret.latencyUs = latencyUs; ret.rcodeCounts = rcodeCounts; ret.rcodeCounts = rcodeCounts; return ret; return ret; } } Loading Loading @@ -143,6 +155,17 @@ class DnsStatsTest : public ::testing::Test { EXPECT_EQ(dumpString, "\n"); EXPECT_EQ(dumpString, "\n"); } } void verifyDnsStatsContent(Protocol protocol, const std::vector<StatsData>& expectedStats, const std::optional<microseconds>& expectedAvgLatency) { if (expectedStats.empty()) { EXPECT_THAT(mDnsStats.getStats(protocol), IsEmpty()); } else { EXPECT_THAT(mDnsStats.getStats(protocol), UnorderedElementsAreArray(expectedStats)); } EXPECT_EQ(mDnsStats.getAverageLatencyUs(protocol), expectedAvgLatency); } DnsStats mDnsStats; DnsStats mDnsStats; }; }; Loading Loading @@ -200,9 +223,9 @@ TEST_F(DnsStatsTest, SetServers) { expectedStats.push_back(makeStatsData(IPSockAddr::toIPSockAddr(exp, 53), 0, 0ms, {})); expectedStats.push_back(makeStatsData(IPSockAddr::toIPSockAddr(exp, 53), 0, 0ms, {})); } } EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY)); } } verifyDumpOutput({}, {}, {}); verifyDumpOutput({}, {}, {}); Loading @@ -221,9 +244,9 @@ TEST_F(DnsStatsTest, SetServersDifferentPorts) { EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_UDP)); EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_UDP)); EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_DOT)); EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_DOT)); EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY)); verifyDumpOutput({}, {}, {}); verifyDumpOutput({}, {}, {}); EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP)); EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP)); Loading @@ -236,9 +259,9 @@ TEST_F(DnsStatsTest, SetServersDifferentPorts) { makeStatsData(servers[6], 0, 0ms, {}), makeStatsData(servers[7], 0, 0ms, {}), makeStatsData(servers[6], 0, 0ms, {}), makeStatsData(servers[7], 0, 0ms, {}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY)); verifyDumpOutput(expectedStats, expectedStats, expectedStats); verifyDumpOutput(expectedStats, expectedStats, expectedStats); } } Loading Loading @@ -269,18 +292,18 @@ TEST_F(DnsStatsTest, AddStatsAndClear) { makeStatsData(servers[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}), makeStatsData(servers[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStatsForTcp)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStatsForTcp, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStatsForUdp)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStatsForUdp, 10ms)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY)); verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {}); verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {}); // Clear stats. // Clear stats. EXPECT_TRUE(mDnsStats.setServers({}, PROTO_TCP)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_TCP)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_UDP)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_UDP)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_DOT)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_DOT)); EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY)); verifyDumpOutput({}, {}, {}); verifyDumpOutput({}, {}, {}); } } Loading Loading @@ -308,6 +331,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) { makeStatsData(servers[1], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}), makeStatsData(servers[1], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms)); verifyDumpOutput({}, expectedStats, {}); verifyDumpOutput({}, expectedStats, {}); // Update the server list, the stats of 127.0.0.2 will remain. // Update the server list, the stats of 127.0.0.2 will remain. Loading @@ -323,6 +347,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) { makeStatsData(servers[2], 0, 0ms, {}), makeStatsData(servers[2], 0, 0ms, {}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 130ms)); verifyDumpOutput({}, expectedStats, {}); verifyDumpOutput({}, expectedStats, {}); // Let's add a record to 127.0.0.2 again. // Let's add a record to 127.0.0.2 again. Loading @@ -333,6 +358,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) { makeStatsData(servers[2], 0, 0ms, {}), makeStatsData(servers[2], 0, 0ms, {}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms)); verifyDumpOutput({}, expectedStats, {}); verifyDumpOutput({}, expectedStats, {}); } } Loading Loading @@ -363,9 +389,9 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) { for (size_t i = 0; i < operations; i++) { for (size_t i = 0; i < operations; i++) { const NsRcode rcode = static_cast<NsRcode>(rcodes[i % rcodeNum]); const NsRcode rcode = static_cast<NsRcode>(rcodes[i % rcodeNum]); const auto eventTcp = makeDnsQueryEvent(PROTO_TCP, rcode, 10ms); const auto eventTcp = makeDnsQueryEvent(PROTO_TCP, rcode, milliseconds(i)); const auto eventUdp = makeDnsQueryEvent(PROTO_UDP, rcode, 10ms); const auto eventUdp = makeDnsQueryEvent(PROTO_UDP, rcode, milliseconds(i)); const auto eventDot = makeDnsQueryEvent(PROTO_DOT, rcode, 10ms); const auto eventDot = makeDnsQueryEvent(PROTO_DOT, rcode, milliseconds(i)); for (const auto& server : servers) { for (const auto& server : servers) { SCOPED_TRACE(server.toString() + "-" + std::to_string(i)); SCOPED_TRACE(server.toString() + "-" + std::to_string(i)); ASSERT_TRUE(mDnsStats.addStats(server, eventTcp)); ASSERT_TRUE(mDnsStats.addStats(server, eventTcp)); Loading @@ -378,16 +404,19 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) { for (const auto& rcode : rcodes) { for (const auto& rcode : rcodes) { expectedRcodeCounts.try_emplace(rcode, 32); expectedRcodeCounts.try_emplace(rcode, 32); } } // The average latency 99935.5 ms is derived from (99872ms + 99873ms + ... + 99999ms) / logSize, // where logSize is 128. const std::vector<StatsData> expectedStats = { const std::vector<StatsData> expectedStats = { makeStatsData(servers[0], logSize, logSize * 10ms, expectedRcodeCounts), makeStatsData(servers[0], logSize, logSize * 99935500us, expectedRcodeCounts), makeStatsData(servers[1], logSize, logSize * 10ms, expectedRcodeCounts), makeStatsData(servers[1], logSize, logSize * 99935500us, expectedRcodeCounts), makeStatsData(servers[2], logSize, logSize * 10ms, expectedRcodeCounts), makeStatsData(servers[2], logSize, logSize * 99935500us, expectedRcodeCounts), makeStatsData(servers[3], logSize, logSize * 10ms, expectedRcodeCounts), makeStatsData(servers[3], logSize, logSize * 99935500us, expectedRcodeCounts), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, 99935500us)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 99935500us)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, 99935500us)); verifyDumpOutput(expectedStats, expectedStats, expectedStats); verifyDumpOutput(expectedStats, expectedStats, expectedStats); } } Loading DnsTlsDispatcher.cpp +21 −4 Original line number Original line Diff line number Diff line Loading @@ -172,7 +172,7 @@ DnsTlsTransport::Response DnsTlsDispatcher::query(const DnsTlsServer& server, un { { std::lock_guard guard(sLock); std::lock_guard guard(sLock); if (xport = getTransport(key); xport == nullptr) { if (xport = getTransport(key); xport == nullptr) { xport = addTransport(server, mark); xport = addTransport(server, mark, netId); } } ++xport->useCount; ++xport->useCount; } } Loading Loading @@ -226,6 +226,11 @@ DnsTlsTransport::Response DnsTlsDispatcher::query(const DnsTlsServer& server, un return code; return code; } } void DnsTlsDispatcher::forceCleanup(unsigned netId) { std::lock_guard guard(sLock); forceCleanupLocked(netId); } DnsTlsTransport::Result DnsTlsDispatcher::queryInternal(Transport& xport, DnsTlsTransport::Result DnsTlsDispatcher::queryInternal(Transport& xport, const netdutils::Slice query) { const netdutils::Slice query) { LOG(DEBUG) << "Sending query of length " << query.size(); LOG(DEBUG) << "Sending query of length " << query.size(); Loading Loading @@ -272,8 +277,20 @@ void DnsTlsDispatcher::cleanup(std::chrono::time_point<std::chrono::steady_clock mLastCleanup = now; mLastCleanup = now; } } // TODO: unify forceCleanupLocked() and cleanup(). void DnsTlsDispatcher::forceCleanupLocked(unsigned netId) { for (auto it = mStore.begin(); it != mStore.end();) { auto& s = it->second; if (s->useCount == 0 && s->mNetId == netId) { it = mStore.erase(it); } else { ++it; } } } DnsTlsDispatcher::Transport* DnsTlsDispatcher::addTransport(const DnsTlsServer& server, DnsTlsDispatcher::Transport* DnsTlsDispatcher::addTransport(const DnsTlsServer& server, unsigned mark) { unsigned mark, unsigned netId) { const Key key = std::make_pair(mark, server); const Key key = std::make_pair(mark, server); Transport* ret = getTransport(key); Transport* ret = getTransport(key); if (ret != nullptr) return ret; if (ret != nullptr) return ret; Loading @@ -300,8 +317,8 @@ DnsTlsDispatcher::Transport* DnsTlsDispatcher::addTransport(const DnsTlsServer& queryTimeout = 1000; queryTimeout = 1000; } } ret = new Transport(server, mark, mFactory.get(), revalidationEnabled, triggerThr, unusableThr, ret = new Transport(server, mark, netId, mFactory.get(), revalidationEnabled, triggerThr, queryTimeout); unusableThr, queryTimeout); LOG(DEBUG) << "Transport is initialized with { " << triggerThr << ", " << unusableThr << ", " LOG(DEBUG) << "Transport is initialized with { " << triggerThr << ", " << unusableThr << ", " << queryTimeout << "ms }" << queryTimeout << "ms }" << " for server { " << server.toIpString() << "/" << server.name << " }"; << " for server { " << server.toIpString() << "/" << server.name << " }"; Loading Loading
Android.bp +57 −80 Original line number Original line Diff line number Diff line Loading @@ -30,10 +30,6 @@ license { ], ], } } // Whether to enable the targets in this file that require rust toolchain. // Set to false in branches like mainline-prod where rust toolchain isn't supported. support_rust_toolchain = false cc_library_headers { cc_library_headers { name: "libnetd_resolv_headers", name: "libnetd_resolv_headers", export_include_dirs: ["include"], export_include_dirs: ["include"], Loading @@ -48,6 +44,8 @@ cc_library_headers { cc_library_headers { cc_library_headers { name: "dnsproxyd_protocol_headers", name: "dnsproxyd_protocol_headers", sdk_version: "29", min_sdk_version: "29", export_include_dirs: ["include/dnsproxyd_protocol"], export_include_dirs: ["include/dnsproxyd_protocol"], apex_available: [ apex_available: [ "//apex_available:platform", "//apex_available:platform", Loading @@ -60,7 +58,7 @@ dnsresolver_aidl_interface_lateststable_version = "V8" cc_library_static { cc_library_static { name: "dnsresolver_aidl_interface-lateststable-ndk_platform", name: "dnsresolver_aidl_interface-lateststable-ndk_platform", whole_static_libs: [ whole_static_libs: [ "dnsresolver_aidl_interface-ndk_platform", "dnsresolver_aidl_interface-" + dnsresolver_aidl_interface_lateststable_version + "-ndk_platform", ], ], apex_available: [ apex_available: [ "com.android.resolv", "com.android.resolv", Loading @@ -85,10 +83,11 @@ aidl_interface { backend: { backend: { java: { java: { apex_available: [ apex_available: [ "//apex_available:platform", "com.android.bluetooth.updatable", "com.android.bluetooth.updatable", "com.android.tethering", "com.android.wifi", "com.android.wifi", ], ], min_sdk_version: "30", }, }, ndk: { ndk: { gen_log: true, gen_log: true, Loading Loading @@ -123,6 +122,8 @@ cc_defaults { "libbase", "libbase", "liblog", "liblog", ], ], // This field is required to make test compatible with Q devices. min_sdk_version: "29", } } cc_defaults { cc_defaults { Loading Loading @@ -315,81 +316,57 @@ filegroup { ], ], } } // rust_ffi_static { rust_ffi_static { // name: "libdoh_ffi", name: "libdoh_ffi", // enabled: support_rust_toolchain, crate_name: "doh", // crate_name: "doh", srcs: ["doh.rs"], // srcs: ["doh.rs"], edition: "2018", // edition: "2018", // rlibs: [ rlibs: [ // "libandroid_logger", "libandroid_logger", // "libanyhow", "libanyhow", // "liblazy_static", "liblazy_static", // "liblibc", "liblibc", // "liblog_rust", "liblog_rust", // "libquiche", "libquiche", // "libring", "libring", // "libtokio", "libtokio", // "liburl", "liburl", // ], ], // prefer_rlib: true, prefer_rlib: true, // shared_libs: [ // "libcrypto", // "libssl", // ], // apex_available: [ shared_libs: [ // "//apex_available:platform", // Needed by doh_ffi_test "libcrypto", // "com.android.resolv" "libssl", // ], ], // min_sdk_version: "29", // } // cc_test { apex_available: [ // name: "doh_ffi_test", "//apex_available:platform", // Needed by doh_ffi_test // enabled: support_rust_toolchain, "com.android.resolv" // test_suites: [ ], // "general-tests", min_sdk_version: "29", // ], } // defaults: ["netd_defaults"], // srcs: ["doh_ffi_test.cpp"], // static_libs: [ // "libdoh_ffi", // "libgmock", // "liblog", // "libring-core", // ], // // These are not carried over from libdoh_ffi. // shared_libs: [ // "libcrypto", // "libssl", // ], // min_sdk_version: "29", // } // rust_test { rust_test { // name: "doh_unit_test", name: "doh_unit_test", // enabled: support_rust_toolchain, crate_name: "doh", // crate_name: "doh", srcs: ["doh.rs"], // srcs: ["doh.rs"], edition: "2018", // edition: "2018", test_suites: ["general-tests"], // test_suites: ["general-tests"], auto_gen_config: true, // auto_gen_config: true, // Used to enable root permission for the test. // // Used to enable root permission for the test. // TODO: remove after 'require_root' is supported in rust_test. // // TODO: remove after 'require_root' is supported in rust_test. test_config_template: ":resolv_rust_test_config_template", // test_config_template: ":resolv_rust_test_config_template", rustlibs: [ // rustlibs: [ "libandroid_logger", // "libandroid_logger", "libanyhow", // "libanyhow", "liblazy_static", // "liblazy_static", "liblibc", // "liblibc", "liblog_rust", // "liblog_rust", "libquiche_static", // "libquiche", "libring", // "libring", "libtokio", // "libtokio", "liburl", // "liburl", ], // ], min_sdk_version: "29", // min_sdk_version: "29", } // }
DnsStats.cpp +14 −0 Original line number Original line Diff line number Diff line Loading @@ -239,6 +239,20 @@ std::vector<IPSockAddr> DnsStats::getSortedServers(Protocol protocol) const { return ret; return ret; } } std::optional<microseconds> DnsStats::getAverageLatencyUs(Protocol protocol) const { const auto stats = getStats(protocol); int count = 0; microseconds sum; for (const auto& v : stats) { count += v.total; sum += v.latencyUs; } if (count == 0) return std::nullopt; return sum / count; } std::vector<StatsData> DnsStats::getStats(Protocol protocol) const { std::vector<StatsData> DnsStats::getStats(Protocol protocol) const { std::vector<StatsData> ret; std::vector<StatsData> ret; Loading
DnsStats.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -121,9 +121,11 @@ class DnsStats { std::vector<netdutils::IPSockAddr> getSortedServers(Protocol protocol) const; std::vector<netdutils::IPSockAddr> getSortedServers(Protocol protocol) const; // Returns the average query latency in microseconds. std::optional<std::chrono::microseconds> getAverageLatencyUs(Protocol protocol) const; void dump(netdutils::DumpWriter& dw); void dump(netdutils::DumpWriter& dw); // For testing. std::vector<StatsData> getStats(Protocol protocol) const; std::vector<StatsData> getStats(Protocol protocol) const; // TODO: Compatible support for getResolverInfo(). // TODO: Compatible support for getResolverInfo(). Loading
DnsStatsTest.cpp +56 −27 Original line number Original line Diff line number Diff line Loading @@ -26,12 +26,24 @@ namespace android::net { using namespace std::chrono_literals; using namespace std::chrono_literals; using android::netdutils::IPSockAddr; using android::netdutils::IPSockAddr; using std::chrono::microseconds; using std::chrono::milliseconds; using std::chrono::milliseconds; using ::testing::IsEmpty; using ::testing::IsEmpty; using ::testing::UnorderedElementsAreArray; using ::testing::UnorderedElementsAreArray; namespace { namespace { constexpr auto NO_AVERAGE_LATENCY = std::nullopt; // A helper which can propagate the failure to outside of the stmt to know which line // of stmt fails. The expectation fails only for the first failed stmt. #define EXPECT_NO_FAILURE(stmt) \ do { \ bool alreadyFailed = HasFailure(); \ stmt; \ if (!alreadyFailed && HasFailure()) EXPECT_FALSE(HasFailure()); \ } while (0) DnsQueryEvent makeDnsQueryEvent(const Protocol protocol, const NsRcode rcode, DnsQueryEvent makeDnsQueryEvent(const Protocol protocol, const NsRcode rcode, const milliseconds& latency) { const milliseconds& latency) { DnsQueryEvent event; DnsQueryEvent event; Loading @@ -41,11 +53,11 @@ DnsQueryEvent makeDnsQueryEvent(const Protocol protocol, const NsRcode rcode, return event; return event; } } StatsData makeStatsData(const IPSockAddr& server, const int total, const milliseconds& latencyMs, StatsData makeStatsData(const IPSockAddr& server, const int total, const microseconds& latencyUs, const std::map<int, int>& rcodeCounts) { const std::map<int, int>& rcodeCounts) { StatsData ret(server); StatsData ret(server); ret.total = total; ret.total = total; ret.latencyUs = latencyMs; ret.latencyUs = latencyUs; ret.rcodeCounts = rcodeCounts; ret.rcodeCounts = rcodeCounts; return ret; return ret; } } Loading Loading @@ -143,6 +155,17 @@ class DnsStatsTest : public ::testing::Test { EXPECT_EQ(dumpString, "\n"); EXPECT_EQ(dumpString, "\n"); } } void verifyDnsStatsContent(Protocol protocol, const std::vector<StatsData>& expectedStats, const std::optional<microseconds>& expectedAvgLatency) { if (expectedStats.empty()) { EXPECT_THAT(mDnsStats.getStats(protocol), IsEmpty()); } else { EXPECT_THAT(mDnsStats.getStats(protocol), UnorderedElementsAreArray(expectedStats)); } EXPECT_EQ(mDnsStats.getAverageLatencyUs(protocol), expectedAvgLatency); } DnsStats mDnsStats; DnsStats mDnsStats; }; }; Loading Loading @@ -200,9 +223,9 @@ TEST_F(DnsStatsTest, SetServers) { expectedStats.push_back(makeStatsData(IPSockAddr::toIPSockAddr(exp, 53), 0, 0ms, {})); expectedStats.push_back(makeStatsData(IPSockAddr::toIPSockAddr(exp, 53), 0, 0ms, {})); } } EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY)); } } verifyDumpOutput({}, {}, {}); verifyDumpOutput({}, {}, {}); Loading @@ -221,9 +244,9 @@ TEST_F(DnsStatsTest, SetServersDifferentPorts) { EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_UDP)); EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_UDP)); EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_DOT)); EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_DOT)); EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY)); verifyDumpOutput({}, {}, {}); verifyDumpOutput({}, {}, {}); EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP)); EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP)); Loading @@ -236,9 +259,9 @@ TEST_F(DnsStatsTest, SetServersDifferentPorts) { makeStatsData(servers[6], 0, 0ms, {}), makeStatsData(servers[7], 0, 0ms, {}), makeStatsData(servers[6], 0, 0ms, {}), makeStatsData(servers[7], 0, 0ms, {}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY)); verifyDumpOutput(expectedStats, expectedStats, expectedStats); verifyDumpOutput(expectedStats, expectedStats, expectedStats); } } Loading Loading @@ -269,18 +292,18 @@ TEST_F(DnsStatsTest, AddStatsAndClear) { makeStatsData(servers[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}), makeStatsData(servers[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStatsForTcp)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStatsForTcp, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStatsForUdp)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStatsForUdp, 10ms)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY)); verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {}); verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {}); // Clear stats. // Clear stats. EXPECT_TRUE(mDnsStats.setServers({}, PROTO_TCP)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_TCP)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_UDP)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_UDP)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_DOT)); EXPECT_TRUE(mDnsStats.setServers({}, PROTO_DOT)); EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), IsEmpty()); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY)); verifyDumpOutput({}, {}, {}); verifyDumpOutput({}, {}, {}); } } Loading Loading @@ -308,6 +331,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) { makeStatsData(servers[1], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}), makeStatsData(servers[1], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms)); verifyDumpOutput({}, expectedStats, {}); verifyDumpOutput({}, expectedStats, {}); // Update the server list, the stats of 127.0.0.2 will remain. // Update the server list, the stats of 127.0.0.2 will remain. Loading @@ -323,6 +347,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) { makeStatsData(servers[2], 0, 0ms, {}), makeStatsData(servers[2], 0, 0ms, {}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 130ms)); verifyDumpOutput({}, expectedStats, {}); verifyDumpOutput({}, expectedStats, {}); // Let's add a record to 127.0.0.2 again. // Let's add a record to 127.0.0.2 again. Loading @@ -333,6 +358,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) { makeStatsData(servers[2], 0, 0ms, {}), makeStatsData(servers[2], 0, 0ms, {}), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms)); verifyDumpOutput({}, expectedStats, {}); verifyDumpOutput({}, expectedStats, {}); } } Loading Loading @@ -363,9 +389,9 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) { for (size_t i = 0; i < operations; i++) { for (size_t i = 0; i < operations; i++) { const NsRcode rcode = static_cast<NsRcode>(rcodes[i % rcodeNum]); const NsRcode rcode = static_cast<NsRcode>(rcodes[i % rcodeNum]); const auto eventTcp = makeDnsQueryEvent(PROTO_TCP, rcode, 10ms); const auto eventTcp = makeDnsQueryEvent(PROTO_TCP, rcode, milliseconds(i)); const auto eventUdp = makeDnsQueryEvent(PROTO_UDP, rcode, 10ms); const auto eventUdp = makeDnsQueryEvent(PROTO_UDP, rcode, milliseconds(i)); const auto eventDot = makeDnsQueryEvent(PROTO_DOT, rcode, 10ms); const auto eventDot = makeDnsQueryEvent(PROTO_DOT, rcode, milliseconds(i)); for (const auto& server : servers) { for (const auto& server : servers) { SCOPED_TRACE(server.toString() + "-" + std::to_string(i)); SCOPED_TRACE(server.toString() + "-" + std::to_string(i)); ASSERT_TRUE(mDnsStats.addStats(server, eventTcp)); ASSERT_TRUE(mDnsStats.addStats(server, eventTcp)); Loading @@ -378,16 +404,19 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) { for (const auto& rcode : rcodes) { for (const auto& rcode : rcodes) { expectedRcodeCounts.try_emplace(rcode, 32); expectedRcodeCounts.try_emplace(rcode, 32); } } // The average latency 99935.5 ms is derived from (99872ms + 99873ms + ... + 99999ms) / logSize, // where logSize is 128. const std::vector<StatsData> expectedStats = { const std::vector<StatsData> expectedStats = { makeStatsData(servers[0], logSize, logSize * 10ms, expectedRcodeCounts), makeStatsData(servers[0], logSize, logSize * 99935500us, expectedRcodeCounts), makeStatsData(servers[1], logSize, logSize * 10ms, expectedRcodeCounts), makeStatsData(servers[1], logSize, logSize * 99935500us, expectedRcodeCounts), makeStatsData(servers[2], logSize, logSize * 10ms, expectedRcodeCounts), makeStatsData(servers[2], logSize, logSize * 99935500us, expectedRcodeCounts), makeStatsData(servers[3], logSize, logSize * 10ms, expectedRcodeCounts), makeStatsData(servers[3], logSize, logSize * 99935500us, expectedRcodeCounts), }; }; EXPECT_THAT(mDnsStats.getStats(PROTO_TCP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, 99935500us)); EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 99935500us)); EXPECT_THAT(mDnsStats.getStats(PROTO_DOT), UnorderedElementsAreArray(expectedStats)); EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, 99935500us)); verifyDumpOutput(expectedStats, expectedStats, expectedStats); verifyDumpOutput(expectedStats, expectedStats, expectedStats); } } Loading
DnsTlsDispatcher.cpp +21 −4 Original line number Original line Diff line number Diff line Loading @@ -172,7 +172,7 @@ DnsTlsTransport::Response DnsTlsDispatcher::query(const DnsTlsServer& server, un { { std::lock_guard guard(sLock); std::lock_guard guard(sLock); if (xport = getTransport(key); xport == nullptr) { if (xport = getTransport(key); xport == nullptr) { xport = addTransport(server, mark); xport = addTransport(server, mark, netId); } } ++xport->useCount; ++xport->useCount; } } Loading Loading @@ -226,6 +226,11 @@ DnsTlsTransport::Response DnsTlsDispatcher::query(const DnsTlsServer& server, un return code; return code; } } void DnsTlsDispatcher::forceCleanup(unsigned netId) { std::lock_guard guard(sLock); forceCleanupLocked(netId); } DnsTlsTransport::Result DnsTlsDispatcher::queryInternal(Transport& xport, DnsTlsTransport::Result DnsTlsDispatcher::queryInternal(Transport& xport, const netdutils::Slice query) { const netdutils::Slice query) { LOG(DEBUG) << "Sending query of length " << query.size(); LOG(DEBUG) << "Sending query of length " << query.size(); Loading Loading @@ -272,8 +277,20 @@ void DnsTlsDispatcher::cleanup(std::chrono::time_point<std::chrono::steady_clock mLastCleanup = now; mLastCleanup = now; } } // TODO: unify forceCleanupLocked() and cleanup(). void DnsTlsDispatcher::forceCleanupLocked(unsigned netId) { for (auto it = mStore.begin(); it != mStore.end();) { auto& s = it->second; if (s->useCount == 0 && s->mNetId == netId) { it = mStore.erase(it); } else { ++it; } } } DnsTlsDispatcher::Transport* DnsTlsDispatcher::addTransport(const DnsTlsServer& server, DnsTlsDispatcher::Transport* DnsTlsDispatcher::addTransport(const DnsTlsServer& server, unsigned mark) { unsigned mark, unsigned netId) { const Key key = std::make_pair(mark, server); const Key key = std::make_pair(mark, server); Transport* ret = getTransport(key); Transport* ret = getTransport(key); if (ret != nullptr) return ret; if (ret != nullptr) return ret; Loading @@ -300,8 +317,8 @@ DnsTlsDispatcher::Transport* DnsTlsDispatcher::addTransport(const DnsTlsServer& queryTimeout = 1000; queryTimeout = 1000; } } ret = new Transport(server, mark, mFactory.get(), revalidationEnabled, triggerThr, unusableThr, ret = new Transport(server, mark, netId, mFactory.get(), revalidationEnabled, triggerThr, queryTimeout); unusableThr, queryTimeout); LOG(DEBUG) << "Transport is initialized with { " << triggerThr << ", " << unusableThr << ", " LOG(DEBUG) << "Transport is initialized with { " << triggerThr << ", " << unusableThr << ", " << queryTimeout << "ms }" << queryTimeout << "ms }" << " for server { " << server.toIpString() << "/" << server.name << " }"; << " for server { " << server.toIpString() << "/" << server.name << " }"; Loading