Add Perfetto part of NetworkTraceHandler am: a603ce5b8e
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/2381737
Change-Id: I99ff22dd4d1770f06fa03949e0c4f6a51771f56d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/service-t/native/libs/libnetworkstats/Android.bp b/service-t/native/libs/libnetworkstats/Android.bp
index 5cb27e6..aa1ee41 100644
--- a/service-t/native/libs/libnetworkstats/Android.bp
+++ b/service-t/native/libs/libnetworkstats/Android.bp
@@ -31,6 +31,12 @@
"libbase",
"liblog",
],
+ static_libs: [
+ "libperfetto_client_experimental",
+ ],
+ export_static_lib_headers: [
+ "libperfetto_client_experimental",
+ ],
export_include_dirs: ["include"],
cflags: [
"-Wall",
@@ -66,6 +72,7 @@
static_libs: [
"libgmock",
"libnetworkstats",
+ "libperfetto_client_experimental",
],
shared_libs: [
"libbase",
diff --git a/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp b/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
index c679357..a57dba3 100644
--- a/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
+++ b/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
@@ -18,11 +18,90 @@
#include "netdbpf/NetworkTraceHandler.h"
+#include <arpa/inet.h>
#include <bpf/BpfUtils.h>
#include <log/log.h>
+#include <perfetto/config/android/network_trace_config.pbzero.h>
+#include <perfetto/trace/android/network_trace.pbzero.h>
+#include <perfetto/trace/profiling/profile_packet.pbzero.h>
+#include <perfetto/tracing/platform.h>
+
+// Note: this is initializing state for a templated Perfetto type that resides
+// in the `perfetto` namespace. This must be defined in the global scope.
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::bpf::NetworkTraceHandler);
namespace android {
namespace bpf {
+using ::perfetto::protos::pbzero::NetworkPacketEvent;
+using ::perfetto::protos::pbzero::NetworkPacketTraceConfig;
+using ::perfetto::protos::pbzero::TracePacket;
+using ::perfetto::protos::pbzero::TrafficDirection;
+
+// static
+void NetworkTraceHandler::RegisterDataSource() {
+ ALOGD("Registering Perfetto data source");
+ perfetto::DataSourceDescriptor dsd;
+ dsd.set_name("android.network_packets");
+ NetworkTraceHandler::Register(dsd);
+}
+
+NetworkTraceHandler::NetworkTraceHandler()
+ : NetworkTraceHandler([this](const PacketTrace& pkt) {
+ NetworkTraceHandler::Trace(
+ [this, pkt](NetworkTraceHandler::TraceContext ctx) {
+ Fill(pkt, *ctx.NewTracePacket());
+ });
+ }) {}
+
+void NetworkTraceHandler::OnSetup(const SetupArgs& args) {
+ const std::string& raw = args.config->network_packet_trace_config_raw();
+ NetworkPacketTraceConfig::Decoder config(raw);
+
+ mPollMs = config.poll_ms();
+ if (mPollMs < 100) {
+ ALOGI("poll_ms is missing or below the 100ms minimum. Increasing to 100ms");
+ mPollMs = 100;
+ }
+}
+
+void NetworkTraceHandler::OnStart(const StartArgs&) {
+ if (!Start()) return;
+ mTaskRunner = perfetto::Platform::GetDefaultPlatform()->CreateTaskRunner({});
+ Loop();
+}
+
+void NetworkTraceHandler::OnStop(const StopArgs&) {
+ Stop();
+ mTaskRunner.reset();
+}
+
+void NetworkTraceHandler::Loop() {
+ mTaskRunner->PostDelayedTask([this]() { Loop(); }, mPollMs);
+ ConsumeAll();
+}
+
+void NetworkTraceHandler::Fill(const PacketTrace& src, TracePacket& dst) {
+ dst.set_timestamp(src.timestampNs);
+ auto* event = dst.set_network_packet();
+ event->set_direction(src.egress ? TrafficDirection::DIR_EGRESS
+ : TrafficDirection::DIR_INGRESS);
+ event->set_length(src.length);
+ event->set_uid(src.uid);
+ event->set_tag(src.tag);
+
+ event->set_local_port(src.egress ? ntohs(src.sport) : ntohs(src.dport));
+ event->set_remote_port(src.egress ? ntohs(src.dport) : ntohs(src.sport));
+
+ event->set_ip_proto(src.ipProto);
+ event->set_tcp_flags(src.tcpFlags);
+
+ char ifname[IF_NAMESIZE] = {};
+ if (if_indextoname(src.ifindex, ifname) == ifname) {
+ event->set_interface(std::string(ifname));
+ } else {
+ event->set_interface("error");
+ }
+}
bool NetworkTraceHandler::Start() {
ALOGD("Starting datasource");
diff --git a/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h
index 67fcf41..d7c9432 100644
--- a/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h
+++ b/service-t/native/libs/libnetworkstats/include/netdbpf/NetworkTraceHandler.h
@@ -16,6 +16,9 @@
#pragma once
+#include <perfetto/base/task_runner.h>
+#include <perfetto/tracing.h>
+
#include <string>
#include <unordered_map>
@@ -28,18 +31,38 @@
namespace android {
namespace bpf {
-class NetworkTraceHandler {
+class NetworkTraceHandler : public perfetto::DataSource<NetworkTraceHandler> {
public:
- // Initialize with a callback capable of intercepting data.
+ // Registers this DataSource.
+ static void RegisterDataSource();
+
+ // Initialize with the default Perfetto callback.
+ NetworkTraceHandler();
+
+ // Testonly: initialize with a callback capable of intercepting data.
NetworkTraceHandler(std::function<void(const PacketTrace&)> callback)
: mCallback(std::move(callback)) {}
- // Standalone functions without perfetto dependency.
+ // Testonly: standalone functions without perfetto dependency.
bool Start();
bool Stop();
bool ConsumeAll();
+ // perfetto::DataSource overrides:
+ void OnSetup(const SetupArgs&) override;
+ void OnStart(const StartArgs&) override;
+ void OnStop(const StopArgs&) override;
+
+ // Convert a PacketTrace into a Perfetto trace packet.
+ void Fill(const PacketTrace& src,
+ ::perfetto::protos::pbzero::TracePacket& dst);
+
private:
+ void Loop();
+
+ // How often to poll the ring buffer, defined by the trace config.
+ uint32_t mPollMs;
+
// The function to process PacketTrace, typically a Perfetto sink.
std::function<void(const PacketTrace&)> mCallback;
@@ -48,6 +71,10 @@
// The packet tracing config map (really a 1-element array).
BpfMap<uint32_t, bool> mConfigurationMap;
+
+ // This must be the last member, causing it to be the first deleted. If it is
+ // not, members required for callbacks can be deleted before it's stopped.
+ std::unique_ptr<perfetto::base::TaskRunner> mTaskRunner;
};
} // namespace bpf