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

Commit 2cc79562 authored by Frank Li's avatar Frank Li Committed by Luke Huang
Browse files

Fill in each dns stats value in message NetworkDnsEventReported

Result dump
metric_id: 1111
event_metrics {
  data {
    elapsed_timestamp_nanos: 166844290056
    atom {
      network_dns_event_reported {
        event_type: EVENT_GETADDRINFO
        return_code: RC_EAI_NO_ERROR
        latency_micros: 78961
        hints_ai_flags: 1024
        res_nsend_flags: -1
        network_type: NT_UNKNOWN
        private_dns_modes: PDM_STRICT
        dns_query_events {
          dns_query_event {
            rcode: NS_R_NO_ERROR
            type: NS_T_A
            ip_version: IV_IPV4
            protocol: PROTO_DOT
            dns_server_index: 0
            latency_micros: 77843
          }
        }
      }
    }
  }

Bug: 119862317
Test: ./out/host/linux-x86/bin/statsd_testdrive 116

Merged-In: I07fc15388b3bbc4e8a9aaaa68470cc3d8a187b8e
Merged-In: Ic06e6eb30afd62e5da08d478e68d4418949c4116
(cherry picked from commit 35ff7888951031efe52e2de940e268e0aa5395f9)

Change-Id: I25eca88dd3881b666135a1dd9d0941fcb697a719
parent 39db9e1f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -216,6 +216,8 @@ cc_test {
        "libnetd_resolv",
        "libnetd_test_dnsresponder",
        "libnetdutils",
        "libprotobuf-cpp-lite",
        "server_configurable_flags",
        "stats_proto",
    ],
}
+5 −2
Original line number Diff line number Diff line
@@ -33,9 +33,11 @@
#include "netdutils/BackoffSequence.h"
#include "netdutils/DumpWriter.h"
#include "netid_client.h"
#include "stats.pb.h"

namespace android {

using android::net::NetworkDnsEventReported;
using netdutils::DumpWriter;
using netdutils::IPAddress;
using netdutils::IPPrefix;
@@ -152,8 +154,9 @@ bool Dns64Configuration::doRfc7050PrefixDiscovery(const android_net_context& net
    // ourselves, which means we also bypass all the special netcontext flag
    // handling and the resolver event logging.
    struct addrinfo* res = nullptr;
    const int status =
            android_getaddrinfofornetcontext(kIPv4OnlyHost, nullptr, &hints, &netcontext, &res);
    NetworkDnsEventReported event;
    const int status = android_getaddrinfofornetcontext(kIPv4OnlyHost, nullptr, &hints, &netcontext,
                                                        &res, &event);
    ScopedAddrinfo result(res);
    if (status != 0) {
        ALOGW("(%u, %u) plat_prefix/dns(%s) status = %d/%s", cfg->netId, cfg->discoveryId,
+65 −38
Original line number Diff line number Diff line
@@ -299,17 +299,23 @@ bool parseQuery(const uint8_t* msg, size_t msgLen, uint16_t* query_id, int* rr_t
    return true;
}

void initDnsEvent(NetworkDnsEventReported* event) {
    // The value 0 has the special meaning of unset/unknown in Westworld atoms.
    event->set_hints_ai_flags(-1);
    event->set_res_nsend_flags(-1);
}

void reportDnsEvent(int eventType, const android_net_context& netContext, int latencyUs,
                    int returnCode, const NetworkDnsEventReported& dnsEvent,
                    const std::string& query_name, const std::vector<std::string>& ip_addrs = {},
                    int total_ip_addr_count = 0) {
    std::string dnsQueryStats = dnsEvent.dns_query_events().SerializeAsString();
    char const* dnsQueryStatsBytes = dnsQueryStats.c_str();
    stats::BytesField dnsQueryBytesField{dnsQueryStatsBytes, dnsQueryStats.size()};
    android::net::stats::stats_write(android::net::stats::NETWORK_DNS_EVENT_REPORTED, eventType,
                                     returnCode, latencyUs, dnsEvent.hints_ai_flags(),
                                     dnsEvent.res_nsend_flags(), dnsEvent.network_type(),
                                     dnsEvent.private_dns_modes(), dnsQueryBytesField);
                    int returnCode, NetworkDnsEventReported& event, const std::string& query_name,
                    const std::vector<std::string>& ip_addrs = {}, int total_ip_addr_count = 0) {
    const std::string& dnsQueryStats = event.dns_query_events().SerializeAsString();
    stats::BytesField dnsQueryBytesField{dnsQueryStats.c_str(), dnsQueryStats.size()};
    event.set_return_code(static_cast<ReturnCode>(returnCode));
    android::net::stats::stats_write(android::net::stats::NETWORK_DNS_EVENT_REPORTED,
                                     event.event_type(), event.return_code(),
                                     event.latency_micros(), event.hints_ai_flags(),
                                     event.res_nsend_flags(), event.network_type(),
                                     event.private_dns_modes(), dnsQueryBytesField);

    const auto& listeners = ResolverEventReporter::getInstance().getListeners();
    if (listeners.size() == 0) {
@@ -590,7 +596,8 @@ static bool sendaddrinfo(SocketClient* c, addrinfo* ai) {
    return true;
}

void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinfo** res) {
void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinfo** res,
                                                            NetworkDnsEventReported* event) {
    if (mHost == nullptr) return;

    const bool ipv6WantedButNoData = (mHints && mHints->ai_family == AF_INET6 && *rv == EAI_NODATA);
@@ -613,7 +620,8 @@ void DnsProxyListener::GetAddrInfoHandler::doDns64Synthesis(int32_t* rv, addrinf
            mHints->ai_family = AF_INET;
            // Don't need to do freeaddrinfo(res) before starting new DNS lookup because previous
            // DNS lookup is failed with error EAI_NODATA.
            *rv = android_getaddrinfofornetcontext(mHost, mService, mHints, &mNetContext, res);
            *rv = android_getaddrinfofornetcontext(mHost, mService, mHints, &mNetContext, res,
                                                   event);
            queryLimiter.finish(uid);
            if (*rv) {
                *rv = EAI_NODATA;  // return original error code
@@ -648,9 +656,11 @@ void DnsProxyListener::GetAddrInfoHandler::run() {
    maybeFixupNetContext(&mNetContext);
    const uid_t uid = mClient->getUid();
    int32_t rv = 0;
    NetworkDnsEventReported dnsEvent;
    NetworkDnsEventReported event;
    initDnsEvent(&event);
    if (queryLimiter.start(uid)) {
        rv = android_getaddrinfofornetcontext(mHost, mService, mHints, &mNetContext, &result);
        rv = android_getaddrinfofornetcontext(mHost, mService, mHints, &mNetContext, &result,
                                              &event);
        queryLimiter.finish(uid);
    } else {
        // Note that this error code is currently not passed down to the client.
@@ -660,8 +670,11 @@ void DnsProxyListener::GetAddrInfoHandler::run() {
                   << ", max concurrent queries reached";
    }

    doDns64Synthesis(&rv, &result);
    const int latencyUs = int(s.timeTakenUs());
    doDns64Synthesis(&rv, &result, &event);
    const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
    event.set_latency_micros(latencyUs);
    event.set_event_type(EVENT_GETADDRINFO);
    event.set_hints_ai_flags((mHints ? mHints->ai_flags : 0));

    if (rv) {
        // getaddrinfo failed
@@ -680,8 +693,8 @@ void DnsProxyListener::GetAddrInfoHandler::run() {
    }
    std::vector<std::string> ip_addrs;
    const int total_ip_addr_count = extractGetAddrInfoAnswers(result, &ip_addrs);
    reportDnsEvent(INetdEventListener::EVENT_GETADDRINFO, mNetContext, latencyUs, rv, dnsEvent,
                   mHost, ip_addrs, total_ip_addr_count);
    reportDnsEvent(INetdEventListener::EVENT_GETADDRINFO, mNetContext, latencyUs, rv, event, mHost,
                   ip_addrs, total_ip_addr_count);
    freeaddrinfo(result);
    mClient->decRef();
}
@@ -854,10 +867,11 @@ void DnsProxyListener::ResNSendHandler::run() {
    // Send DNS query
    std::vector<uint8_t> ansBuf(MAXPACKET, 0);
    int arcode, nsendAns = -1;
    NetworkDnsEventReported dnsEvent;
    NetworkDnsEventReported event;
    initDnsEvent(&event);
    if (queryLimiter.start(uid)) {
        nsendAns = resolv_res_nsend(&mNetContext, msg.data(), msgLen, ansBuf.data(), MAXPACKET,
                                    &arcode, static_cast<ResNsendFlags>(mFlags));
                                    &arcode, static_cast<ResNsendFlags>(mFlags), &event);
        queryLimiter.finish(uid);
    } else {
        LOG(WARNING) << "ResNSendHandler::run: resnsend: from UID " << uid
@@ -865,14 +879,17 @@ void DnsProxyListener::ResNSendHandler::run() {
        nsendAns = -EBUSY;
    }

    const int latencyUs = int(s.timeTakenUs());
    const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
    event.set_latency_micros(latencyUs);
    event.set_event_type(EVENT_RES_NSEND);
    event.set_res_nsend_flags(static_cast<ResNsendFlags>(mFlags));

    // Fail, send -errno
    if (nsendAns < 0) {
        sendBE32(mClient, nsendAns);
        if (rr_type == ns_t_a || rr_type == ns_t_aaaa) {
            reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs,
                           resNSendToAiError(nsendAns, arcode), dnsEvent, rr_name);
                           resNSendToAiError(nsendAns, arcode), event, rr_name);
        }
        return;
    }
@@ -895,7 +912,7 @@ void DnsProxyListener::ResNSendHandler::run() {
        const int total_ip_addr_count =
                extractResNsendAnswers((uint8_t*) ansBuf.data(), nsendAns, rr_type, &ip_addrs);
        reportDnsEvent(INetdEventListener::EVENT_RES_NSEND, mNetContext, latencyUs,
                       resNSendToAiError(nsendAns, arcode), dnsEvent, rr_name, ip_addrs,
                       resNSendToAiError(nsendAns, arcode), event, rr_name, ip_addrs,
                       total_ip_addr_count);
    }
}
@@ -994,7 +1011,8 @@ DnsProxyListener::GetHostByNameHandler::~GetHostByNameHandler() {
    free(mName);
}

void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, struct hostent** hpp) {
void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, struct hostent** hpp,
                                                              NetworkDnsEventReported* event) {
    // Don't have to consider family AF_UNSPEC case because gethostbyname{, 2} only supports
    // family AF_INET or AF_INET6.
    const bool ipv6WantedButNoData = (mAf == AF_INET6 && *rv == EAI_NODATA);
@@ -1011,7 +1029,7 @@ void DnsProxyListener::GetHostByNameHandler::doDns64Synthesis(int32_t* rv, struc
    // If caller wants IPv6 answers but no data, try to query IPv4 answers for synthesis
    const uid_t uid = mClient->getUid();
    if (queryLimiter.start(uid)) {
        *rv = android_gethostbynamefornetcontext(mName, AF_INET, &mNetContext, hpp);
        *rv = android_gethostbynamefornetcontext(mName, AF_INET, &mNetContext, hpp, event);
        queryLimiter.finish(uid);
        if (*rv) {
            *rv = EAI_NODATA;  // return original error code
@@ -1035,9 +1053,10 @@ void DnsProxyListener::GetHostByNameHandler::run() {
    const uid_t uid = mClient->getUid();
    hostent* hp = nullptr;
    int32_t rv = 0;
    NetworkDnsEventReported dnsEvent;
    NetworkDnsEventReported event;
    initDnsEvent(&event);
    if (queryLimiter.start(uid)) {
        rv = android_gethostbynamefornetcontext(mName, mAf, &mNetContext, &hp);
        rv = android_gethostbynamefornetcontext(mName, mAf, &mNetContext, &hp, &event);
        queryLimiter.finish(uid);
    } else {
        rv = EAI_MEMORY;
@@ -1045,8 +1064,11 @@ void DnsProxyListener::GetHostByNameHandler::run() {
                   << ", max concurrent queries reached";
    }

    doDns64Synthesis(&rv, &hp);
    const int latencyUs = lround(s.timeTakenUs());
    doDns64Synthesis(&rv, &hp, &event);
    const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
    event.set_latency_micros(latencyUs);
    event.set_event_type(EVENT_GETHOSTBYNAME);

    LOG(DEBUG) << "GetHostByNameHandler::run: errno: " << (hp ? "success" : strerror(errno));

    bool success = true;
@@ -1064,7 +1086,7 @@ void DnsProxyListener::GetHostByNameHandler::run() {

    std::vector<std::string> ip_addrs;
    const int total_ip_addr_count = extractGetHostByNameAnswers(hp, &ip_addrs);
    reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYNAME, mNetContext, latencyUs, rv, dnsEvent,
    reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYNAME, mNetContext, latencyUs, rv, event,
                   mName, ip_addrs, total_ip_addr_count);
    mClient->decRef();
}
@@ -1134,7 +1156,8 @@ DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() {
    free(mAddress);
}

void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(struct hostent** hpp) {
void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(struct hostent** hpp,
                                                                  NetworkDnsEventReported* event) {
    if (*hpp != nullptr || mAddressFamily != AF_INET6 || !mAddress) {
        return;
    }
@@ -1162,7 +1185,8 @@ void DnsProxyListener::GetHostByAddrHandler::doDns64ReverseLookup(struct hostent
    if (queryLimiter.start(uid)) {
        // Remove NAT64 prefix and do reverse DNS query
        struct in_addr v4addr = {.s_addr = v6addr.s6_addr32[3]};
        android_gethostbyaddrfornetcontext(&v4addr, sizeof(v4addr), AF_INET, &mNetContext, hpp);
        android_gethostbyaddrfornetcontext(&v4addr, sizeof(v4addr), AF_INET, &mNetContext, hpp,
                                           event);
        queryLimiter.finish(uid);
        if (*hpp) {
            // Replace IPv4 address with original queried IPv6 address in place. The space has
@@ -1184,10 +1208,11 @@ void DnsProxyListener::GetHostByAddrHandler::run() {
    const uid_t uid = mClient->getUid();
    hostent* hp = nullptr;
    int32_t rv = 0;
    NetworkDnsEventReported dnsEvent;
    NetworkDnsEventReported event;
    initDnsEvent(&event);
    if (queryLimiter.start(uid)) {
        rv = android_gethostbyaddrfornetcontext(mAddress, mAddressLen, mAddressFamily,
                                                &mNetContext, &hp);
        rv = android_gethostbyaddrfornetcontext(mAddress, mAddressLen, mAddressFamily, &mNetContext,
                                                &hp, &event);
        queryLimiter.finish(uid);
    } else {
        rv = EAI_MEMORY;
@@ -1195,8 +1220,10 @@ void DnsProxyListener::GetHostByAddrHandler::run() {
                   << ", max concurrent queries reached";
    }

    doDns64ReverseLookup(&hp);
    const int latencyUs = int(s.timeTakenUs());
    doDns64ReverseLookup(&hp, &event);
    const int32_t latencyUs = saturate_cast<int32_t>(s.timeTakenUs());
    event.set_latency_micros(latencyUs);
    event.set_event_type(EVENT_GETHOSTBYADDR);

    LOG(DEBUG) << "GetHostByAddrHandler::run: result: " << (hp ? "success" : gai_strerror(rv));

@@ -1212,7 +1239,7 @@ void DnsProxyListener::GetHostByAddrHandler::run() {
        LOG(WARNING) << "GetHostByAddrHandler::run: Error writing DNS result to client";
    }

    reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYADDR, mNetContext, latencyUs, rv, dnsEvent,
    reportDnsEvent(INetdEventListener::EVENT_GETHOSTBYADDR, mNetContext, latencyUs, rv, event,
                   (hp && hp->h_name) ? hp->h_name : "null", {}, 0);
    mClient->decRef();
}
+5 −3
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ struct hostent;
namespace android {
namespace net {

class NetworkDnsEventReported;

class DnsProxyListener : public FrameworkListener {
  public:
    DnsProxyListener();
@@ -54,7 +56,7 @@ class DnsProxyListener : public FrameworkListener {
        void run();

      private:
        void doDns64Synthesis(int32_t* rv, addrinfo** res);
        void doDns64Synthesis(int32_t* rv, addrinfo** res, NetworkDnsEventReported* event);

        SocketClient* mClient;  // ref counted
        char* mHost;            // owned. TODO: convert to std::string.
@@ -80,7 +82,7 @@ class DnsProxyListener : public FrameworkListener {
        void run();

      private:
        void doDns64Synthesis(int32_t* rv, hostent** hpp);
        void doDns64Synthesis(int32_t* rv, hostent** hpp, NetworkDnsEventReported* event);

        SocketClient* mClient;  // ref counted
        char* mName;            // owned. TODO: convert to std::string.
@@ -105,7 +107,7 @@ class DnsProxyListener : public FrameworkListener {
        void run();

      private:
        void doDns64ReverseLookup(hostent** hpp);
        void doDns64ReverseLookup(hostent** hpp, NetworkDnsEventReported* event);

        SocketClient* mClient;  // ref counted
        void* mAddress;         // address to lookup; owned
+27 −7
Original line number Diff line number Diff line
@@ -18,13 +18,17 @@
//#define LOG_NDEBUG 0

#include "DnsTlsDispatcher.h"
#include <netdutils/Stopwatch.h>
#include "DnsTlsSocketFactory.h"
#include "resolv_private.h"
#include "stats.pb.h"

#include "log/log.h"

namespace android {
namespace net {

using android::netdutils::Stopwatch;
using netdutils::Slice;

// static
@@ -82,29 +86,45 @@ std::list<DnsTlsServer> DnsTlsDispatcher::getOrderedServerList(
    return out;
}

DnsTlsTransport::Response DnsTlsDispatcher::query(
        const std::list<DnsTlsServer> &tlsServers, unsigned mark,
        const Slice query, const Slice ans, int *resplen) {
    const std::list<DnsTlsServer> orderedServers(getOrderedServerList(tlsServers, mark));
DnsTlsTransport::Response DnsTlsDispatcher::query(const std::list<DnsTlsServer>& tlsServers,
                                                  res_state statp, const Slice query,
                                                  const Slice ans, int* resplen) {
    const std::list<DnsTlsServer> orderedServers(getOrderedServerList(tlsServers, statp->_mark));

    if (orderedServers.empty()) ALOGW("Empty DnsTlsServer list");

    DnsTlsTransport::Response code = DnsTlsTransport::Response::internal_error;
    int serverCount = 0;
    for (const auto& server : orderedServers) {
        code = this->query(server, mark, query, ans, resplen);
        DnsQueryEvent* dnsQueryEvent =
                statp->event->mutable_dns_query_events()->add_dns_query_event();
        dnsQueryEvent->set_rcode(NS_R_INTERNAL_ERROR);
        Stopwatch query_stopwatch;
        code = this->query(server, statp->_mark, query, ans, resplen);

        dnsQueryEvent->set_latency_micros(saturate_cast<int32_t>(query_stopwatch.timeTakenUs()));
        dnsQueryEvent->set_dns_server_index(serverCount++);
        dnsQueryEvent->set_ip_version(ipFamilyToIPVersion(server.ss.ss_family));
        dnsQueryEvent->set_protocol(PROTO_DOT);
        dnsQueryEvent->set_type(getQueryType(query.base(), query.size()));

        switch (code) {
            // These response codes are valid responses and not expected to
            // change if another server is queried.
            case DnsTlsTransport::Response::success:
                dnsQueryEvent->set_rcode(
                        static_cast<NsRcode>(reinterpret_cast<HEADER*>(ans.base())->rcode));
                [[fallthrough]];
            case DnsTlsTransport::Response::limit_error:
                return code;
                break;
            // These response codes might differ when trying other servers, so
            // keep iterating to see if we can get a different (better) result.
            case DnsTlsTransport::Response::network_error:
                // Sync from res_tls_send in res_send.cpp
                dnsQueryEvent->set_rcode(NS_R_TIMEOUT);
                [[fallthrough]];
            case DnsTlsTransport::Response::internal_error:
                continue;
                break;
            // No "default" statement.
        }
    }
Loading