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

Commit edec3e16 authored by chenbruce's avatar chenbruce
Browse files

Add Mdns statistics log

When developers run "dumpsys dnsresolver", Mdns statistics
will show the information in the log if the Mdns queries
happened.

Bug: 140857615
Test: cd packages/modules/DnsResolver && atest
Change-Id: Iec0657d417ddf329590f1fc0a599497aaf45639b
parent 72a646c2
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -268,7 +268,7 @@ void DnsStats::dump(DumpWriter& dw) {
    const auto dumpStatsMap = [&](StatsMap& statsMap) {
        ScopedIndent indentLog(dw);
        if (statsMap.size() == 0) {
            dw.println("<no server>");
            dw.println("<no data>");
            return;
        }
        for (const auto& [_, statsRecords] : statsMap) {
@@ -290,6 +290,9 @@ void DnsStats::dump(DumpWriter& dw) {

    dw.println("over TCP");
    dumpStatsMap(mStats[PROTO_TCP]);

    dw.println("over MDNS");
    dumpStatsMap(mStats[PROTO_MDNS]);
}

}  // namespace android::net
+1 −1
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ class StatsRecords {
    static constexpr int kMaxQuality = 10000;
};

// DnsStats class manages the statistics of DNS servers per netId.
// DnsStats class manages the statistics of DNS servers or MDNS multicast addresses per netId.
// The class itself is not thread-safe.
class DnsStats {
  public:
+47 −13
Original line number Diff line number Diff line
@@ -116,7 +116,8 @@ class DnsStatsTest : public ::testing::Test {
    // Get the output string from dump() and check the content.
    void verifyDumpOutput(const std::vector<StatsData>& tcpData,
                          const std::vector<StatsData>& udpData,
                          const std::vector<StatsData>& dotData) {
                          const std::vector<StatsData>& dotData,
                          const std::vector<StatsData>& mdnsData) {
        // 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*))");
@@ -128,11 +129,11 @@ class DnsStatsTest : public ::testing::Test {
            ASSERT_NE(dumpString->find(protocol), std::string::npos);
            std::smatch sm;

            // Expect to show something even if none of servers is set.
            // Expect to show something even if none of servers or mdns multicast addresses is set.
            if (statsData.empty()) {
                ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
                EXPECT_TRUE(sm[1].str().empty());
                EXPECT_EQ(sm[2], "<no server>");
                EXPECT_EQ(sm[2], "<no data>");
                EXPECT_TRUE(sm[3].str().empty());
                *dumpString = sm.suffix();
                return;
@@ -150,6 +151,7 @@ class DnsStatsTest : public ::testing::Test {
        check(udpData, "UDP", &dumpString);
        check(dotData, "TLS", &dumpString);
        check(tcpData, "TCP", &dumpString);
        check(mdnsData, "MDNS", &dumpString);

        // Ensure the whole string has been checked.
        EXPECT_EQ(dumpString, "\n");
@@ -171,7 +173,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;
@@ -228,7 +230,7 @@ TEST_F(DnsStatsTest, SetAddrs) {
        EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
    }

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

TEST_F(DnsStatsTest, SetServersDifferentPorts) {
@@ -247,7 +249,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));
@@ -262,7 +264,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) {
@@ -270,10 +272,16 @@ TEST_F(DnsStatsTest, AddStatsAndClear) {
            IPSockAddr::toIPSockAddr("127.0.0.1", 53),
            IPSockAddr::toIPSockAddr("127.0.0.2", 53),
    };
    const std::vector<IPSockAddr> mdnsaddrs = {
            IPSockAddr::toIPSockAddr("ff02::fb", 5353),
            IPSockAddr::toIPSockAddr("224.0.0.251", 5353),
    };
    const DnsQueryEvent record = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
    const DnsQueryEvent mdnsrecord = makeDnsQueryEvent(PROTO_MDNS, NS_R_NO_ERROR, 10ms);

    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(mdnsaddrs, PROTO_MDNS));

    // Fail to add stats because of incorrect arguments.
    EXPECT_FALSE(mDnsStats.addStats(IPSockAddr::toIPSockAddr("127.0.0.4", 53), record));
@@ -282,6 +290,8 @@ TEST_F(DnsStatsTest, AddStatsAndClear) {
    EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
    EXPECT_TRUE(mDnsStats.addStats(servers[0], record));
    EXPECT_TRUE(mDnsStats.addStats(servers[1], record));
    EXPECT_TRUE(mDnsStats.addStats(mdnsaddrs[0], mdnsrecord));
    EXPECT_TRUE(mDnsStats.addStats(mdnsaddrs[1], mdnsrecord));

    const std::vector<StatsData> expectedStatsForTcp = {
            makeStatsData(servers[0], 0, 0ms, {}),
@@ -292,19 +302,27 @@ TEST_F(DnsStatsTest, AddStatsAndClear) {
            makeStatsData(servers[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
    };

    const std::vector<StatsData> expectedStatsForMdns = {
            makeStatsData(mdnsaddrs[1], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
            makeStatsData(mdnsaddrs[0], 1, 10ms, {{NS_R_NO_ERROR, 1}}),
    };

    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStatsForTcp, NO_AVERAGE_LATENCY));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStatsForUdp, 10ms));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, {}, NO_AVERAGE_LATENCY));
    verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {});
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, expectedStatsForMdns, 10ms));
    verifyDumpOutput(expectedStatsForTcp, expectedStatsForUdp, {}, expectedStatsForMdns);

    // Clear stats.
    EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_DOT));
    EXPECT_TRUE(mDnsStats.setAddrs({}, PROTO_MDNS));
    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({}, {}, {});
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, {}, NO_AVERAGE_LATENCY));
    verifyDumpOutput({}, {}, {}, {});
}

TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
@@ -332,7 +350,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 = {
@@ -348,7 +366,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));
@@ -359,7 +377,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) {
@@ -375,6 +393,11 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
            IPSockAddr::toIPSockAddr("127.0.0.4", 53),
    };

    const std::vector<IPSockAddr> mdnsaddrs = {
            IPSockAddr::toIPSockAddr("ff02::fb", 5353),
            IPSockAddr::toIPSockAddr("224.0.0.251", 5353),
    };

    // To test unknown rcode in rcodeToName(), store the elements as type int.
    const std::array<int, rcodeNum> rcodes = {
            NS_R_NO_ERROR,        // NOERROR
@@ -386,6 +409,7 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_DOT));
    EXPECT_TRUE(mDnsStats.setAddrs(mdnsaddrs, PROTO_MDNS));

    for (size_t i = 0; i < operations; i++) {
        const NsRcode rcode = static_cast<NsRcode>(rcodes[i % rcodeNum]);
@@ -398,6 +422,11 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
            ASSERT_TRUE(mDnsStats.addStats(server, eventUdp));
            ASSERT_TRUE(mDnsStats.addStats(server, eventDot));
        }
        const auto eventMdns = makeDnsQueryEvent(PROTO_MDNS, rcode, milliseconds(i));
        for (const auto& mdnsaddr : mdnsaddrs) {
            SCOPED_TRACE(mdnsaddr.toString() + "-" + std::to_string(i));
            ASSERT_TRUE(mDnsStats.addStats(mdnsaddr, eventMdns));
        }
    }

    std::map<int, int> expectedRcodeCounts;
@@ -414,10 +443,15 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
            makeStatsData(servers[3], logSize, logSize * 99935500us, expectedRcodeCounts),
    };

    const std::vector<StatsData> expectedMdnsStats = {
            makeStatsData(mdnsaddrs[1], logSize, logSize * 99935500us, expectedRcodeCounts),
            makeStatsData(mdnsaddrs[0], logSize, logSize * 99935500us, expectedRcodeCounts),
    };
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_TCP, expectedStats, 99935500us));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_UDP, expectedStats, 99935500us));
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, 99935500us));
    verifyDumpOutput(expectedStats, expectedStats, expectedStats);
    EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_MDNS, expectedMdnsStats, 99935500us));
    verifyDumpOutput(expectedStats, expectedStats, expectedStats, expectedMdnsStats);
}

TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
+10 −1
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@
using aidl::android::net::ResolverParamsParcel;
using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener;
using aidl::android::net::resolv::aidl::Nat64PrefixEventParcel;
using android::net::PROTO_DOT;
using android::net::PROTO_MDNS;

namespace android {

@@ -212,7 +214,14 @@ int ResolverController::setResolverConfiguration(const ResolverParamsParcel& res
        return err;
    }

    if (int err = resolv_stats_set_servers_for_dot(resolverParams.netId, tlsServers); err != 0) {
    if (int 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);
        err != 0) {
        return err;
    }

+30 −7
Original line number Diff line number Diff line
@@ -71,9 +71,12 @@ using android::base::StringAppendF;
using android::net::DnsQueryEvent;
using android::net::DnsStats;
using android::net::Experiments;
using android::net::PROTO_DOH;
using android::net::PROTO_DOT;
using android::net::PROTO_MDNS;
using android::net::PROTO_TCP;
using android::net::PROTO_UDP;
using android::net::Protocol;
using android::netdutils::DumpWriter;
using android::netdutils::IPSockAddr;

@@ -1476,6 +1479,7 @@ int resolv_create_cache_for_net(unsigned netid) {
    }

    sNetConfigMap[netid] = std::make_unique<NetConfig>(netid);

    return 0;
}

@@ -1898,20 +1902,39 @@ int resolv_cache_get_expiration(unsigned netid, const std::vector<char>& query,
    return 0;
}

int resolv_stats_set_servers_for_dot(unsigned netid, const std::vector<std::string>& servers) {
static const char* protocol_to_str(const Protocol proto) {
    switch (proto) {
        case PROTO_UDP:
            return "UDP";
        case PROTO_TCP:
            return "TCP";
        case PROTO_DOT:
            return "DOT";
        case PROTO_DOH:
            return "DOH";
        case PROTO_MDNS:
            return "MDNS";
        default:
            return "UNKNOWN";
    }
}

int resolv_stats_set_addrs(unsigned netid, Protocol proto, const std::vector<std::string>& addrs,
                           int port) {
    std::lock_guard guard(cache_mutex);
    const auto info = find_netconfig_locked(netid);

    if (info == nullptr) return -ENONET;

    std::vector<IPSockAddr> serverSockAddrs;
    serverSockAddrs.reserve(servers.size());
    for (const auto& server : servers) {
        serverSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 853));
    std::vector<IPSockAddr> sockAddrs;
    sockAddrs.reserve(addrs.size());
    for (const auto& addr : addrs) {
        sockAddrs.push_back(IPSockAddr::toIPSockAddr(addr, port));
    }

    if (!info->dnsStats.setAddrs(serverSockAddrs, android::net::PROTO_DOT)) {
        LOG(WARNING) << __func__ << ": netid = " << netid << ", failed to set dns stats";
    if (!info->dnsStats.setAddrs(sockAddrs, proto)) {
        LOG(WARNING) << __func__ << ": netid = " << netid << ", failed to set "
                     << protocol_to_str(proto) << " stats";
        return -EINVAL;
    }

Loading