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

Commit b226923e authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge changes Iec0657d4,I38befe45 am: 9069e6dc

Original change: https://android-review.googlesource.com/c/platform/packages/modules/DnsResolver/+/1749202

Change-Id: I1054a9388ba7b600ff64ef1c5789fe840386f2cc
parents 2523ab05 9069e6dc
Loading
Loading
Loading
Loading
+25 −22
Original line number Diff line number Diff line
@@ -59,10 +59,10 @@ std::string rcodeToName(int rcode) {
    // clang-format on
}

bool ensureNoInvalidIp(const std::vector<IPSockAddr>& servers) {
    for (const auto& server : servers) {
        if (server.ip() == INVALID_IPADDRESS || server.port() == 0) {
            LOG(WARNING) << "Invalid server: " << server;
bool ensureNoInvalidIp(const std::vector<IPSockAddr>& addrs) {
    for (const auto& addr : addrs) {
        if (addr.ip() == INVALID_IPADDRESS || addr.port() == 0) {
            LOG(WARNING) << "Invalid addr: " << addr;
            return false;
        }
    }
@@ -73,8 +73,8 @@ bool ensureNoInvalidIp(const std::vector<IPSockAddr>& servers) {

// The comparison ignores the last update time.
bool StatsData::operator==(const StatsData& o) const {
    return std::tie(serverSockAddr, total, rcodeCounts, latencyUs) ==
           std::tie(o.serverSockAddr, o.total, o.rcodeCounts, o.latencyUs);
    return std::tie(sockAddr, total, rcodeCounts, latencyUs) ==
           std::tie(o.sockAddr, o.total, o.rcodeCounts, o.latencyUs);
}

int StatsData::averageLatencyMs() const {
@@ -82,7 +82,7 @@ int StatsData::averageLatencyMs() const {
}

std::string StatsData::toString() const {
    if (total == 0) return StringPrintf("%s <no data>", serverSockAddr.ip().toString().c_str());
    if (total == 0) return StringPrintf("%s <no data>", sockAddr.ip().toString().c_str());

    const auto now = std::chrono::steady_clock::now();
    const int lastUpdateSec = duration_cast<seconds>(now - lastUpdate).count();
@@ -92,7 +92,7 @@ std::string StatsData::toString() const {
            buf += StringPrintf("%s:%d ", rcodeToName(rcode).c_str(), counts);
        }
    }
    return StringPrintf("%s (%d, %dms, [%s], %ds)", serverSockAddr.ip().toString().c_str(), total,
    return StringPrintf("%s (%d, %dms, [%s], %ds)", sockAddr.ip().toString().c_str(), total,
                        averageLatencyMs(), buf.c_str(), lastUpdateSec);
}

@@ -171,20 +171,20 @@ void StatsRecords::incrementSkippedCount() {
    mSkippedCount = std::min(mSkippedCount + 1, kMaxQuality);
}

bool DnsStats::setServers(const std::vector<netdutils::IPSockAddr>& servers, Protocol protocol) {
    if (!ensureNoInvalidIp(servers)) return false;
bool DnsStats::setAddrs(const std::vector<netdutils::IPSockAddr>& addrs, Protocol protocol) {
    if (!ensureNoInvalidIp(addrs)) return false;

    ServerStatsMap& statsMap = mStats[protocol];
    for (const auto& server : servers) {
        statsMap.try_emplace(server, StatsRecords(server, kLogSize));
    StatsMap& statsMap = mStats[protocol];
    for (const auto& addr : addrs) {
        statsMap.try_emplace(addr, StatsRecords(addr, kLogSize));
    }

    // Clean up the map to eliminate the nodes not belonging to the given list of servers.
    const auto cleanup = [&](ServerStatsMap* statsMap) {
        ServerStatsMap tmp;
        for (const auto& server : servers) {
            if (statsMap->find(server) != statsMap->end()) {
                tmp.insert(statsMap->extract(server));
    const auto cleanup = [&](StatsMap* statsMap) {
        StatsMap tmp;
        for (const auto& addr : addrs) {
            if (statsMap->find(addr) != statsMap->end()) {
                tmp.insert(statsMap->extract(addr));
            }
        }
        statsMap->swap(tmp);
@@ -199,8 +199,8 @@ bool DnsStats::addStats(const IPSockAddr& ipSockAddr, const DnsQueryEvent& recor
    if (ipSockAddr.ip() == INVALID_IPADDRESS) return false;

    bool added = false;
    for (auto& [serverSockAddr, statsRecords] : mStats[record.protocol()]) {
        if (serverSockAddr == ipSockAddr) {
    for (auto& [sockAddr, statsRecords] : mStats[record.protocol()]) {
        if (sockAddr == ipSockAddr) {
            const StatsRecords::Record rec = {
                    .rcode = record.rcode(),
                    .linux_errno = record.linux_errno(),
@@ -265,10 +265,10 @@ std::vector<StatsData> DnsStats::getStats(Protocol protocol) const {
}

void DnsStats::dump(DumpWriter& dw) {
    const auto dumpStatsMap = [&](ServerStatsMap& statsMap) {
    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
+8 −8
Original line number Diff line number Diff line
@@ -33,12 +33,12 @@ namespace android::net {

// The overall information of a StatsRecords.
struct StatsData {
    StatsData(const netdutils::IPSockAddr& ipSockAddr) : serverSockAddr(ipSockAddr) {
    StatsData(const netdutils::IPSockAddr& ipSockAddr) : sockAddr(ipSockAddr) {
        lastUpdate = std::chrono::steady_clock::now();
    };

    // Server socket address.
    netdutils::IPSockAddr serverSockAddr;
    // Socket address.
    netdutils::IPSockAddr sockAddr;

    // The most recent number of records being accumulated.
    int total = 0;
@@ -106,15 +106,15 @@ 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:
    using ServerStatsMap = std::map<netdutils::IPSockAddr, StatsRecords>;
    using StatsMap = std::map<netdutils::IPSockAddr, StatsRecords>;

    // Add |servers| to the map, and remove no-longer-used servers.
    // Add |addrs| to the map, and remove no-longer-used addresses.
    // Return true if they are successfully added; otherwise, return false.
    bool setServers(const std::vector<netdutils::IPSockAddr>& servers, Protocol protocol);
    bool setAddrs(const std::vector<netdutils::IPSockAddr>& addrs, Protocol protocol);

    // Return true if |record| is successfully added into |server|'s stats; otherwise, return false.
    bool addStats(const netdutils::IPSockAddr& server, const DnsQueryEvent& record);
@@ -133,7 +133,7 @@ class DnsStats {
    static constexpr size_t kLogSize = 128;

  private:
    std::map<Protocol, ServerStatsMap> mStats;
    std::map<Protocol, StatsMap> mStats;
};

}  // namespace android::net
+75 −41
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;
@@ -140,7 +141,7 @@ class DnsStatsTest : public ::testing::Test {

            for (const auto& stats : statsData) {
                ASSERT_TRUE(std::regex_search(*dumpString, sm, pattern));
                EXPECT_EQ(sm[1], stats.serverSockAddr.ip().toString());
                EXPECT_EQ(sm[1], stats.sockAddr.ip().toString());
                EXPECT_FALSE(sm[2].str().empty());
                EXPECT_FALSE(sm[3].str().empty());
                *dumpString = sm.suffix();
@@ -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");
@@ -169,9 +171,9 @@ class DnsStatsTest : public ::testing::Test {
    DnsStats mDnsStats;
};

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

    static const struct {
        std::vector<std::string> servers;
@@ -213,9 +215,9 @@ TEST_F(DnsStatsTest, SetServers) {
            ipSockAddrs.push_back(IPSockAddr::toIPSockAddr(server, 53));
        }

        EXPECT_TRUE(mDnsStats.setServers(ipSockAddrs, PROTO_TCP) == isSuccess);
        EXPECT_TRUE(mDnsStats.setServers(ipSockAddrs, PROTO_UDP) == isSuccess);
        EXPECT_TRUE(mDnsStats.setServers(ipSockAddrs, PROTO_DOT) == isSuccess);
        EXPECT_TRUE(mDnsStats.setAddrs(ipSockAddrs, PROTO_TCP) == isSuccess);
        EXPECT_TRUE(mDnsStats.setAddrs(ipSockAddrs, PROTO_UDP) == isSuccess);
        EXPECT_TRUE(mDnsStats.setAddrs(ipSockAddrs, PROTO_DOT) == isSuccess);

        std::vector<StatsData> expectedStats;
        expectedStats.reserve(expectation.size());
@@ -228,7 +230,7 @@ TEST_F(DnsStatsTest, SetServers) {
        EXPECT_NO_FAILURE(verifyDnsStatsContent(PROTO_DOT, expectedStats, NO_AVERAGE_LATENCY));
    }

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

TEST_F(DnsStatsTest, SetServersDifferentPorts) {
@@ -240,18 +242,18 @@ TEST_F(DnsStatsTest, SetServersDifferentPorts) {
    };

    // Servers setup fails due to port unset.
    EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_TCP));
    EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_UDP));
    EXPECT_FALSE(mDnsStats.setServers(servers, PROTO_DOT));
    EXPECT_FALSE(mDnsStats.setAddrs(servers, PROTO_TCP));
    EXPECT_FALSE(mDnsStats.setAddrs(servers, PROTO_UDP));
    EXPECT_FALSE(mDnsStats.setAddrs(servers, PROTO_DOT));

    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.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setServers(std::vector(servers.begin() + 2, servers.end()), PROTO_DOT));
    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));
    EXPECT_TRUE(mDnsStats.setAddrs(std::vector(servers.begin() + 2, servers.end()), PROTO_DOT));

    const std::vector<StatsData> expectedStats = {
            makeStatsData(servers[2], 0, 0ms, {}), makeStatsData(servers[3], 0, 0ms, {}),
@@ -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.setServers(servers, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
    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.setServers({}, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setServers({}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setServers({}, PROTO_DOT));
    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) {
@@ -315,7 +333,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
    const DnsQueryEvent recordNoError = makeDnsQueryEvent(PROTO_UDP, NS_R_NO_ERROR, 10ms);
    const DnsQueryEvent recordTimeout = makeDnsQueryEvent(PROTO_UDP, NS_R_TIMEOUT, 250ms);

    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));

    // Add a record to 127.0.0.1.
    EXPECT_TRUE(mDnsStats.addStats(servers[0], recordNoError));
@@ -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 = {
@@ -340,7 +358,7 @@ TEST_F(DnsStatsTest, StatsRemainsInExistentServer) {
            IPSockAddr::toIPSockAddr("127.0.0.3", 53),
            IPSockAddr::toIPSockAddr("127.0.0.4", 53),
    };
    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs(servers, PROTO_UDP));
    expectedStats = {
            makeStatsData(servers[0], 4, 520ms, {{NS_R_NO_ERROR, 2}, {NS_R_TIMEOUT, 2}}),
            makeStatsData(servers[1], 0, 0ms, {}),
@@ -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
@@ -383,9 +406,10 @@ TEST_F(DnsStatsTest, AddStatsRecords_100000) {
            NS_R_INTERNAL_ERROR,  // INTERNAL_ERROR
    };

    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_TCP));
    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setServers(servers, PROTO_DOT));
    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) {
@@ -430,8 +464,8 @@ TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
    EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP), IsEmpty());

    // Before there's any stats, the list of the sorted servers is the same as the setup's one.
    EXPECT_TRUE(mDnsStats.setServers({server1, server2, server3, server4}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setServers({server1, server2, server3, server4}, PROTO_DOT));
    EXPECT_TRUE(mDnsStats.setAddrs({server1, server2, server3, server4}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs({server1, server2, server3, server4}, PROTO_DOT));
    EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
                testing::ElementsAreArray({server1, server2, server3, server4}));

@@ -473,7 +507,7 @@ TEST_F(DnsStatsTest, GetServers_SortingByLatency) {
                testing::ElementsAreArray({server2, server3, server1, server4}));

    // The list of the DNS servers changed.
    EXPECT_TRUE(mDnsStats.setServers({server2, server4}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs({server2, server4}, PROTO_UDP));
    EXPECT_THAT(mDnsStats.getSortedServers(PROTO_UDP),
                testing::ElementsAreArray({server2, server4}));

@@ -490,7 +524,7 @@ TEST_F(DnsStatsTest, GetServers_DeprioritizingBadServers) {
    const IPSockAddr server3 = IPSockAddr::toIPSockAddr("127.0.0.3", 53);
    const IPSockAddr server4 = IPSockAddr::toIPSockAddr("127.0.0.4", 53);

    EXPECT_TRUE(mDnsStats.setServers({server1, server2, server3, server4}, PROTO_UDP));
    EXPECT_TRUE(mDnsStats.setAddrs({server1, server2, server3, server4}, PROTO_UDP));

    int server1Counts = 0;
    int server2Counts = 0;
@@ -521,15 +555,15 @@ TEST_F(DnsStatsTest, GetServers_DeprioritizingBadServers) {
    const std::vector<StatsData> allStatsData = mDnsStats.getStats(PROTO_UDP);
    for (const auto& data : allStatsData) {
        EXPECT_EQ(data.rcodeCounts.size(), 1U);
        if (data.serverSockAddr == server1 || data.serverSockAddr == server2) {
        if (data.sockAddr == server1 || data.sockAddr == server2) {
            const auto it = data.rcodeCounts.find(NS_R_NO_ERROR);
            ASSERT_NE(it, data.rcodeCounts.end());
            EXPECT_GT(server2Counts, 2 * server1Counts);  // At least twice larger.
        } else if (data.serverSockAddr == server3) {
        } else if (data.sockAddr == server3) {
            const auto it = data.rcodeCounts.find(NS_R_TIMEOUT);
            ASSERT_NE(it, data.rcodeCounts.end());
            EXPECT_LT(it->second, 10);
        } else if (data.serverSockAddr == server4) {
        } else if (data.sockAddr == server4) {
            const auto it = data.rcodeCounts.find(NS_R_INTERNAL_ERROR);
            ASSERT_NE(it, data.rcodeCounts.end());
            EXPECT_LT(it->second, 10);
+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;
    }

+32 −9
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;
}

@@ -1649,8 +1653,8 @@ int resolv_set_nameservers(unsigned netid, const std::vector<std::string>& serve
    netconfig->search_domains = filter_domains(domains);

    // Setup stats for cleartext dns servers.
    if (!netconfig->dnsStats.setServers(netconfig->nameserverSockAddrs, PROTO_TCP) ||
        !netconfig->dnsStats.setServers(netconfig->nameserverSockAddrs, PROTO_UDP)) {
    if (!netconfig->dnsStats.setAddrs(netconfig->nameserverSockAddrs, PROTO_TCP) ||
        !netconfig->dnsStats.setAddrs(netconfig->nameserverSockAddrs, PROTO_UDP)) {
        LOG(WARNING) << __func__ << ": netid = " << netid << ", failed to set dns stats";
        return -EINVAL;
    }
@@ -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.setServers(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