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 // BundleKey encodes a PacketTrace minus timestamp and length. The key should 34 // match many packets over time for interning. For convenience, sport/dport 35 // are parsed here as either local/remote port or icmp type/code. 36 struct BundleKey { 37 explicit BundleKey(const PacketTrace& pkt); 38 39 uint32_t ifindex; 40 uint32_t uid; 41 uint32_t tag; 42 43 bool egress; 44 uint8_t ipProto; 45 uint8_t ipVersion; 46 47 std::optional<uint8_t> tcpFlags; 48 std::optional<uint16_t> localPort; 49 std::optional<uint16_t> remotePort; 50 std::optional<uint8_t> icmpType; 51 std::optional<uint8_t> icmpCode; 52 }; 53 54 // BundleKeys are hashed using a simple hash combine. 55 struct BundleHash { 56 std::size_t operator()(const BundleKey& a) const; 57 }; 58 59 // BundleKeys are equal if all fields are equal. 60 struct BundleEq { 61 bool operator()(const BundleKey& a, const BundleKey& b) const; 62 }; 63 64 // Track the bundles we've interned and their corresponding intern id (iid). We 65 // use IncrementalState (rather than state in the Handler) so that we stay in 66 // sync with Perfetto's periodic state clearing (which helps recover from packet 67 // loss). When state is cleared, the state object is replaced with a new default 68 // constructed instance. 69 struct NetworkTraceState { 70 bool cleared = true; 71 std::unordered_map<BundleKey, uint64_t, BundleHash, BundleEq> iids; 72 }; 73 74 // Inject our custom incremental state type using type traits. 75 struct NetworkTraceTraits : public perfetto::DefaultDataSourceTraits { 76 using IncrementalStateType = NetworkTraceState; 77 }; 78 79 // NetworkTraceHandler implements the android.network_packets data source. This 80 // class is registered with Perfetto and is instantiated when tracing starts and 81 // destroyed when tracing ends. There is one instance per trace session. 82 class NetworkTraceHandler 83 : public perfetto::DataSource<NetworkTraceHandler, NetworkTraceTraits> { 84 public: 85 // Registers this DataSource. 86 static void RegisterDataSource(); 87 88 // Connects to the system Perfetto daemon and registers the trace handler. 89 static void InitPerfettoTracing(); 90 91 // When isTest is true, skip non-hermetic code. mIsTest(isTest)92 NetworkTraceHandler(bool isTest = false) : mIsTest(isTest) {} 93 94 // perfetto::DataSource overrides: 95 void OnSetup(const SetupArgs& args) override; 96 void OnStart(const StartArgs&) override; 97 void OnStop(const StopArgs&) override; 98 99 // Writes the packets as Perfetto TracePackets, creating packets as needed 100 // using the provided callback (which allows easy testing). 101 void Write(const std::vector<PacketTrace>& packets, 102 NetworkTraceHandler::TraceContext& ctx); 103 104 private: 105 // Fills in contextual information from a bundle without interning. 106 void Fill(const BundleKey& src, 107 ::perfetto::protos::pbzero::NetworkPacketEvent* event); 108 109 // Fills in contextual information either inline or via interning. 110 ::perfetto::protos::pbzero::NetworkPacketBundle* FillWithInterning( 111 NetworkTraceState* state, const BundleKey& src, 112 ::perfetto::protos::pbzero::TracePacket* dst); 113 114 static internal::NetworkTracePoller sPoller; 115 bool mStarted; 116 bool mIsTest; 117 118 // Values from config, see proto for details. 119 uint32_t mPollMs; 120 uint32_t mInternLimit; 121 uint32_t mAggregationThreshold; 122 bool mDropLocalPort; 123 bool mDropRemotePort; 124 bool mDropTcpFlags; 125 }; 126 127 } // namespace bpf 128 } // namespace android 129