Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 356e4c60 authored by waynema's avatar waynema
Browse files

DoH statistics is now available from DnsStats and is shown in dumpsys dnsresolver.

Example of output from dumpsys dnsresolver:

  Server statistics: (total, RTT avg, {rcode:counts}, last update)
    over UDP
      8.8.4.4 (3, 2503ms, [TIMEOUT:3 ], 465s) score{71.0}
      8.8.8.8 (4, 1880ms, [NOERROR:1 TIMEOUT:3 ], 468s) score{77.3}
      2001:4860:4860::8844 (9, 15ms, [NOERROR:9 ], 78s) score{99.8}
      2001:4860:4860::8888 <no data> score{100.0}
    over DOH
      2001:4860:4860::8888 (89, 30ms, [NOERROR:89 ], 127s) score{99.7}
    over TLS
      8.8.4.4 <no data> score{100.0}
      8.8.8.8 <no data> score{100.0}
      2001:4860:4860::8844 <no data> score{100.0}
      2001:4860:4860::8888 <no data> score{100.0}
    over TCP
      8.8.4.4 <no data> score{100.0}
      8.8.8.8 <no data> score{100.0}
      2001:4860:4860::8844 <no data> score{100.0}
      2001:4860:4860::8888 <no data> score{100.0}
    over MDNS
      224.0.0.251 <no data> score{100.0}
      ff02::fb <no data> score{100.0}
  TC mode: default
  TransportType: WIFI

Test steps:
a. Default enable strict mode.
b. Turn on WiFi.
c. Turn on Mobile data.
d. Check the output from dumpsys dnsresolver.
e. Expect to see two different statistics with the same DNS server on different NetId.

NetId: 101
    over DOH
      2001:4860:4860::8888 (90, 29ms, [NOERROR:90 ], 7s) score{99.7}
  TransportType: WIFI

NetId: 102
    over DOH
      2001:4860:4860::8888 (2, 33ms, [NOERROR:2 ], 74s) score{99.7}
  TransportType: CELLULAR

Bug: 195092631
Test: checked output in dumpsys dnsresolver
Change-Id: I65c69a850bce352839314833d44c9f165c7ca142
parent 67936ef2
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -284,6 +284,9 @@ void DnsStats::dump(DumpWriter& dw) {
    dw.println("over UDP");
    dumpStatsMap(mStats[PROTO_UDP]);

    dw.println("over DOH");
    dumpStatsMap(mStats[PROTO_DOH]);

    dw.println("over TLS");
    dumpStatsMap(mStats[PROTO_DOT]);

+13 −11
Original line number Diff line number Diff line
@@ -117,7 +117,8 @@ class DnsStatsTest : public ::testing::Test {
    void verifyDumpOutput(const std::vector<StatsData>& tcpData,
                          const std::vector<StatsData>& udpData,
                          const std::vector<StatsData>& dotData,
                          const std::vector<StatsData>& mdnsData) {
                          const std::vector<StatsData>& mdnsData,
                          const std::vector<StatsData>& dohData) {
        // A pattern to capture three matches:
        //     server address (empty allowed), the statistics, and the score.
        const std::regex pattern(R"(\s{4,}([0-9a-fA-F:\.]*)[ ]?([<(].*[>)])[ ]?(\S*))");
@@ -149,6 +150,7 @@ class DnsStatsTest : public ::testing::Test {
        };

        check(udpData, "UDP", &dumpString);
        check(dohData, "DOH", &dumpString);
        check(dotData, "TLS", &dumpString);
        check(tcpData, "TCP", &dumpString);
        check(mdnsData, "MDNS", &dumpString);
@@ -173,7 +175,7 @@ class DnsStatsTest : public ::testing::Test {

TEST_F(DnsStatsTest, SetAddrs) {
    // Check before any operation to mDnsStats.
    verifyDumpOutput({}, {}, {}, {});
    verifyDumpOutput({}, {}, {}, {}, {});

    static const struct {
        std::vector<std::string> servers;
@@ -230,7 +232,7 @@ TEST_F(DnsStatsTest, SetAddrs) {
        EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
    }

    verifyDumpOutput({}, {}, {}, {});
    verifyDumpOutput({}, {}, {}, {}, {});
}

TEST_F(DnsStatsTest, SetServersDifferentPorts) {
@@ -249,7 +251,7 @@ TEST_F(DnsStatsTest, SetServersDifferentPorts) {
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    verifyDumpOutput({}, {}, {}, {});
    verifyDumpOutput({}, {}, {}, {}, {});

    EXPECT_TRUE(mDnsStats.setAddrs(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setAddrs(std::vector(servers.begin() + 2, servers.end()), PROTO_UDP));
@@ -264,7 +266,7 @@ TEST_F(DnsStatsTest, SetServersDifferentPorts) {
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
    verifyDumpOutput(expectedStats, expectedStats, expectedStats, {});
    verifyDumpOutput(expectedStats, expectedStats, expectedStats, {}, {});
}

TEST_F(DnsStatsTest, AddStatsAndClear) {
@@ -311,7 +313,7 @@ TEST_F(DnsStatsTest, AddStatsAndClear) {
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStatsForUdp, 10ms));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, expectedStatsForMdns, 10ms));
    verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {}, expectedStatsForMdns);
    verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {}, expectedStatsForMdns, {});

    // Clear stats.
    EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_TCP));
@@ -322,7 +324,7 @@ TEST_F(DnsStatsTest, AddStatsAndClear) {
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, {}, NO_AVERAGE_LATENCY));
    verifyDumpOutput({}, {}, {}, {});
    verifyDumpOutput({}, {}, {}, {}, {});
}

TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
@@ -350,7 +352,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
    };
    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.
    servers = {
@@ -366,7 +368,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
    };
    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.
    EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
@@ -377,7 +379,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
    };
    EXPECT_THAT(mDnsStats.getStats(PROTO_UDP), UnorderedElementsAreArray(expectedStats));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 106ms));
    verifyDumpOutput({}, expectedStats, {}, {});
    verifyDumpOutput({}, expectedStats, {}, {}, {});
}

TEST_F(DnsStatsTest, AddStatsRecords_100000) {
@@ -451,7 +453,7 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 99935500us));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, 99935500us));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, expectedMdnsStats, 99935500us));
    verifyDumpOutput(expectedStats, expectedStats, expectedStats, expectedMdnsStats);
    verifyDumpOutput(expectedStats, expectedStats, expectedStats, expectedMdnsStats, {});
}

TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
+10 −0
Original line number Diff line number Diff line
@@ -383,6 +383,16 @@ void PrivateDnsConfiguration::setObserver(PrivateDnsValidationObserver* observer
    mObserver = observer;
}

base::Result<netdutils::IPSockAddr> PrivateDnsConfiguration::getDohServer(unsigned netId) const {
    std::lock_guard guard(mPrivateDnsLock);
    auto it = mDohTracker.find(netId);
    if (it != mDohTracker.end()) {
        return netdutils::IPSockAddr::toIPSockAddr(it->second.ipAddr, 443);
    }

    return Errorf("Failed to get DoH Server: netId {} not found", netId);
}

void PrivateDnsConfiguration::notifyValidationStateUpdate(const netdutils::IPSockAddr& sockaddr,
                                                          Validation validation,
                                                          uint32_t netId) const {
+3 −0
Original line number Diff line number Diff line
@@ -115,6 +115,9 @@ class PrivateDnsConfiguration {
    void onDohStatusUpdate(uint32_t netId, bool success, const char* ipAddr, const char* host)
            EXCLUDES(mPrivateDnsLock);

    base::Result<netdutils::IPSockAddr> getDohServer(unsigned netId) const
            EXCLUDES(mPrivateDnsLock);

  private:
    typedef std::map<ServerIdentity, std::unique_ptr<IPrivateDnsServer>> PrivateDnsTracker;

+22 −13
Original line number Diff line number Diff line
@@ -208,33 +208,42 @@ int ResolverController::setResolverConfiguration(const ResolverParamsParcel& res
    // through a different network. For example, on a VPN with no DNS servers (Do53), if the VPN
    // applies to UID 0, dns_mark is assigned for default network rathan the VPN. (note that it's
    // possible that a VPN doesn't have any DNS servers but DoT servers in DNS strict mode)
    int err = PrivateDnsConfiguration::getInstance().set(resolverParams.netId, netcontext.app_mark,
                                                         tlsServers, resolverParams.tlsName,
                                                         resolverParams.caCertificate);
    auto& privateDnsConfiguration = PrivateDnsConfiguration::getInstance();
    int err = privateDnsConfiguration.set(resolverParams.netId, netcontext.app_mark, tlsServers,
                                          resolverParams.tlsName, resolverParams.caCertificate);

    if (err != 0) {
        return err;
    }

    if (int err = resolv_stats_set_addrs(resolverParams.netId, PROTO_DOT, tlsServers, 853);
    if (err = resolv_stats_set_addrs(resolverParams.netId, PROTO_DOT, tlsServers, 853);
        err != 0) {
        return err;
    }

    if (int err = resolv_stats_set_addrs(resolverParams.netId, PROTO_MDNS,
                                         {"ff02::fb", "224.0.0.251"}, 5353);
    if (err = resolv_stats_set_addrs(resolverParams.netId, PROTO_MDNS, {"ff02::fb", "224.0.0.251"},
                                     5353);
        err != 0) {
        return err;
    }

    if (isDoHEnabled())
        err = PrivateDnsConfiguration::getInstance().setDoh(
                resolverParams.netId, netcontext.app_mark, tlsServers, resolverParams.tlsName,
    if (isDoHEnabled()) {
        if (err = privateDnsConfiguration.setDoh(resolverParams.netId, netcontext.app_mark,
                                                 tlsServers, resolverParams.tlsName,
                                                 resolverParams.caCertificate);

    if (err != 0) {
            err != 0) {
            return err;
        }
        auto result = privateDnsConfiguration.getDohServer(resolverParams.netId);
        if (result.ok()) {
            const netdutils::IPSockAddr sockAddr = result.value();
            if (err = resolv_stats_set_addrs(resolverParams.netId, PROTO_DOH,
                                             {sockAddr.ip().toString()}, sockAddr.port());
                err != 0) {
                return err;
            }
        }
    }

    res_params res_params = {};
    res_params.sample_validity = resolverParams.sampleValiditySeconds;
Loading