From f5fc2e34033f367f7869a2217ac689d156d86159 Mon Sep 17 00:00:00 2001 From: Ryan Zuklie <rzuklie@google.com> Date: Tue, 24 Oct 2023 16:03:12 -0700 Subject: [PATCH] Report sparse per-iface stats using atrace. This reports the total bytes sent and received per interface using atrace. The totals are taken from the interface counters, rather than the ringbuffer, since the ring buffer can run out of space. Interfaces are only reported for interfaces which have packets sent on them as identified by Nettrace. This helps reduce the cost significantly for idle periods and on devices with a large number of interfaces accumulated in the iface stats maps. Test: TreeHugger Change-Id: I0e6a3b11de0d1e153b9f8ebb97c338f425381a9c --- .../libnetworkstats/NetworkTracePoller.cpp | 29 +++++++++++++++++++ .../include/netdbpf/NetworkTracePoller.h | 5 ++++ 2 files changed, 34 insertions(+) diff --git a/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp b/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp index 80c315a837..450f380644 100644 --- a/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp +++ b/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp @@ -25,9 +25,15 @@ #include <perfetto/tracing/platform.h> #include <perfetto/tracing/tracing.h> +#include <unordered_map> +#include <unordered_set> + +#include "netdbpf/BpfNetworkStats.h" + namespace android { namespace bpf { namespace internal { +using ::android::base::StringPrintf; void NetworkTracePoller::PollAndSchedule(perfetto::base::TaskRunner* runner, uint32_t poll_ms) { @@ -116,6 +122,28 @@ bool NetworkTracePoller::Stop() { return res.ok(); } +void NetworkTracePoller::TraceIfaces(const std::vector<PacketTrace>& packets) { + if (packets.empty()) return; + + std::unordered_set<uint32_t> uniqueIfindex; + for (const PacketTrace& pkt : packets) { + uniqueIfindex.insert(pkt.ifindex); + } + + for (uint32_t ifindex : uniqueIfindex) { + char ifname[IF_NAMESIZE] = {}; + if (if_indextoname(ifindex, ifname) != ifname) continue; + + StatsValue stats = {}; + if (bpfGetIfIndexStats(ifindex, &stats) != 0) continue; + + std::string rxTrack = StringPrintf("%s [%d] Rx Bytes", ifname, ifindex); + std::string txTrack = StringPrintf("%s [%d] Tx Bytes", ifname, ifindex); + ATRACE_INT64(rxTrack.c_str(), stats.rxBytes); + ATRACE_INT64(txTrack.c_str(), stats.txBytes); + } +} + bool NetworkTracePoller::ConsumeAll() { std::scoped_lock<std::mutex> lock(mMutex); return ConsumeAllLocked(); @@ -137,6 +165,7 @@ bool NetworkTracePoller::ConsumeAllLocked() { ATRACE_INT("NetworkTracePackets", packets.size()); + TraceIfaces(packets); mCallback(packets); return true; diff --git a/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTracePoller.h b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTracePoller.h index 8433934db7..092ab64575 100644 --- a/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTracePoller.h +++ b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTracePoller.h @@ -61,6 +61,11 @@ class NetworkTracePoller { void PollAndSchedule(perfetto::base::TaskRunner* runner, uint32_t poll_ms); bool ConsumeAllLocked() REQUIRES(mMutex); + // Record sparse iface stats via atrace. This queries the per-iface stats maps + // for any iface present in the vector of packets. This is inexact, but should + // have sufficient coverage given these are cumulative counters. + void TraceIfaces(const std::vector<PacketTrace>& packets) REQUIRES(mMutex); + std::mutex mMutex; // Records the number of successfully started active sessions so that only the -- GitLab