1 /** 2 * Copyright (c) 2023, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <perfetto/base/task_runner.h> 20 #include <perfetto/tracing.h> 21 22 #include <string> 23 #include <unordered_map> 24 25 #include "netdbpf/NetworkTracePoller.h" 26 27 // For PacketTrace struct definition 28 #include "netd.h" 29 30 namespace android { 31 namespace bpf { 32 33 // BundleKeys are PacketTraces where timestamp and length are ignored. 34 using BundleKey = PacketTrace; 35 36 // BundleKeys are hashed using all fields except timestamp/length. 37 struct BundleHash { 38 std::size_t operator()(const BundleKey& a) const; 39 }; 40 41 // BundleKeys are equal if all fields except timestamp/length are equal. 42 struct BundleEq { 43 bool operator()(const BundleKey& a, const BundleKey& b) const; 44 }; 45 46 // Track the bundles we've interned and their corresponding intern id (iid). We 47 // use IncrementalState (rather than state in the Handler) so that we stay in 48 // sync with Perfetto's periodic state clearing (which helps recover from packet 49 // loss). When state is cleared, the state object is replaced with a new default 50 // constructed instance. 51 struct NetworkTraceState { 52 bool cleared = true; 53 std::unordered_map<BundleKey, uint64_t, BundleHash, BundleEq> iids; 54 }; 55 56 // Inject our custom incremental state type using type traits. 57 struct NetworkTraceTraits : public perfetto::DefaultDataSourceTraits { 58 using IncrementalStateType = NetworkTraceState; 59 }; 60 61 // NetworkTraceHandler implements the android.network_packets data source. This 62 // class is registered with Perfetto and is instantiated when tracing starts and 63 // destroyed when tracing ends. There is one instance per trace session. 64 class NetworkTraceHandler 65 : public perfetto::DataSource<NetworkTraceHandler, NetworkTraceTraits> { 66 public: 67 // Registers this DataSource. 68 static void RegisterDataSource(); 69 70 // Connects to the system Perfetto daemon and registers the trace handler. 71 static void InitPerfettoTracing(); 72 73 // When isTest is true, skip non-hermetic code. mIsTest(isTest)74 NetworkTraceHandler(bool isTest = false) : mIsTest(isTest) {} 75 76 // perfetto::DataSource overrides: 77 void OnSetup(const SetupArgs& args) override; 78 void OnStart(const StartArgs&) override; 79 void OnStop(const StopArgs&) override; 80 81 // Writes the packets as Perfetto TracePackets, creating packets as needed 82 // using the provided callback (which allows easy testing). 83 void Write(const std::vector<PacketTrace>& packets, 84 NetworkTraceHandler::TraceContext& ctx); 85 86 private: 87 // Convert a PacketTrace into a Perfetto trace packet. 88 void Fill(const PacketTrace& src, 89 ::perfetto::protos::pbzero::NetworkPacketEvent* event); 90 91 // Fills in contextual information either inline or via interning. 92 ::perfetto::protos::pbzero::NetworkPacketBundle* FillWithInterning( 93 NetworkTraceState* state, const BundleKey& key, 94 ::perfetto::protos::pbzero::TracePacket* dst); 95 96 static internal::NetworkTracePoller sPoller; 97 bool mStarted; 98 bool mIsTest; 99 100 // Values from config, see proto for details. 101 uint32_t mPollMs; 102 uint32_t mInternLimit; 103 uint32_t mAggregationThreshold; 104 bool mDropLocalPort; 105 bool mDropRemotePort; 106 bool mDropTcpFlags; 107 }; 108 109 } // namespace bpf 110 } // namespace android 111