1 /* 2 * Copyright (C) 2018 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 <linux/if.h> 20 #include <linux/if_ether.h> 21 #include <linux/in.h> 22 #include <linux/in6.h> 23 24 #ifdef __cplusplus 25 #include <string_view> 26 #include "XtBpfProgLocations.h" 27 #endif 28 29 // This header file is shared by eBPF kernel programs (C) and netd (C++) and 30 // some of the maps are also accessed directly from Java mainline module code. 31 // 32 // Hence: explicitly pad all relevant structures and assert that their size 33 // is the sum of the sizes of their fields. 34 #define STRUCT_SIZE(name, size) _Static_assert(sizeof(name) == (size), "Incorrect struct size.") 35 36 typedef struct { 37 uint32_t uid; 38 uint32_t tag; 39 } UidTagValue; 40 STRUCT_SIZE(UidTagValue, 2 * 4); // 8 41 42 typedef struct { 43 uint32_t uid; 44 uint32_t tag; 45 uint32_t counterSet; 46 uint32_t ifaceIndex; 47 } StatsKey; 48 STRUCT_SIZE(StatsKey, 4 * 4); // 16 49 50 typedef struct { 51 uint64_t rxPackets; 52 uint64_t rxBytes; 53 uint64_t txPackets; 54 uint64_t txBytes; 55 } StatsValue; 56 STRUCT_SIZE(StatsValue, 4 * 8); // 32 57 58 typedef struct { 59 char name[IFNAMSIZ]; 60 } IfaceValue; 61 STRUCT_SIZE(IfaceValue, 16); 62 63 typedef struct { 64 uint64_t rxBytes; 65 uint64_t rxPackets; 66 uint64_t txBytes; 67 uint64_t txPackets; 68 uint64_t tcpRxPackets; 69 uint64_t tcpTxPackets; 70 } Stats; 71 72 typedef struct { 73 uint64_t timestampNs; 74 uint32_t ifindex; 75 uint32_t length; 76 77 uint32_t uid; 78 uint32_t tag; 79 80 __be16 sport; 81 __be16 dport; 82 83 bool egress; 84 uint8_t ipProto; 85 uint8_t tcpFlags; 86 uint8_t ipVersion; // 4=IPv4, 6=IPv6, 0=unknown 87 } PacketTrace; 88 STRUCT_SIZE(PacketTrace, 8+4+4 + 4+4 + 2+2 + 1+1+1+1); 89 90 // Since we cannot garbage collect the stats map since device boot, we need to make these maps as 91 // large as possible. The maximum size of number of map entries we can have is depend on the rlimit 92 // of MEM_LOCK granted to netd. The memory space needed by each map can be calculated by the 93 // following fomula: 94 // elem_size = 40 + roundup(key_size, 8) + roundup(value_size, 8) 95 // cost = roundup_pow_of_two(max_entries) * 16 + elem_size * max_entries + 96 // elem_size * number_of_CPU 97 // And the cost of each map currently used is(assume the device have 8 CPUs): 98 // cookie_tag_map: key: 8 bytes, value: 8 bytes, cost: 822592 bytes = 823Kbytes 99 // uid_counter_set_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 100 // app_uid_stats_map: key: 4 bytes, value: 32 bytes, cost: 1062784 bytes = 1063Kbytes 101 // uid_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes 102 // tag_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes 103 // iface_index_name_map:key: 4 bytes, value: 16 bytes, cost: 80896 bytes = 81Kbytes 104 // iface_stats_map: key: 4 bytes, value: 32 bytes, cost: 97024 bytes = 97Kbytes 105 // dozable_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 106 // standby_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 107 // powersave_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 108 // packet_trace_ringbuf:key: 0 bytes, value: 24 bytes, cost: 32768 bytes = 32Kbytes 109 // total: 4962Kbytes 110 // It takes maximum 4.9MB kernel memory space if all maps are full, which requires any devices 111 // running this module to have a memlock rlimit to be larger then 5MB. In the old qtaguid module, 112 // we don't have a total limit for data entries but only have limitation of tags each uid can have. 113 // (default is 1024 in kernel); 114 115 // 'static' - otherwise these constants end up in .rodata in the resulting .o post compilation 116 static const int COOKIE_UID_MAP_SIZE = 10000; 117 static const int UID_COUNTERSET_MAP_SIZE = 4000; 118 static const int APP_STATS_MAP_SIZE = 10000; 119 static const int STATS_MAP_SIZE = 5000; 120 static const int IFACE_INDEX_NAME_MAP_SIZE = 1000; 121 static const int IFACE_STATS_MAP_SIZE = 1000; 122 static const int CONFIGURATION_MAP_SIZE = 2; 123 static const int UID_OWNER_MAP_SIZE = 4000; 124 static const int PACKET_TRACE_BUF_SIZE = 32 * 1024; 125 126 #ifdef __cplusplus 127 128 #define BPF_NETD_PATH "/sys/fs/bpf/netd_shared/" 129 130 #define BPF_EGRESS_PROG_PATH BPF_NETD_PATH "prog_netd_cgroupskb_egress_stats" 131 #define BPF_INGRESS_PROG_PATH BPF_NETD_PATH "prog_netd_cgroupskb_ingress_stats" 132 133 #define ASSERT_STRING_EQUAL(s1, s2) \ 134 static_assert(std::string_view(s1) == std::string_view(s2), "mismatch vs Android T netd") 135 136 /* -=-=-=-=- WARNING -=-=-=-=- 137 * 138 * These 4 xt_bpf program paths are actually defined by: 139 * //system/netd/include/mainline/XtBpfProgLocations.h 140 * which is intentionally a non-automerged location. 141 * 142 * They are *UNCHANGEABLE* due to being hard coded in Android T's netd binary 143 * as such we have compile time asserts that things match. 144 * (which will be validated during build on mainline-prod branch against old system/netd) 145 * 146 * If you break this, netd on T will fail to start with your tethering mainline module. 147 */ 148 ASSERT_STRING_EQUAL(XT_BPF_INGRESS_PROG_PATH, BPF_NETD_PATH "prog_netd_skfilter_ingress_xtbpf"); 149 ASSERT_STRING_EQUAL(XT_BPF_EGRESS_PROG_PATH, BPF_NETD_PATH "prog_netd_skfilter_egress_xtbpf"); 150 ASSERT_STRING_EQUAL(XT_BPF_ALLOWLIST_PROG_PATH, BPF_NETD_PATH "prog_netd_skfilter_allowlist_xtbpf"); 151 ASSERT_STRING_EQUAL(XT_BPF_DENYLIST_PROG_PATH, BPF_NETD_PATH "prog_netd_skfilter_denylist_xtbpf"); 152 153 #define CGROUP_SOCKET_PROG_PATH BPF_NETD_PATH "prog_netd_cgroupsock_inet_create" 154 155 #define TC_BPF_INGRESS_ACCOUNT_PROG_NAME "prog_netd_schedact_ingress_account" 156 #define TC_BPF_INGRESS_ACCOUNT_PROG_PATH BPF_NETD_PATH TC_BPF_INGRESS_ACCOUNT_PROG_NAME 157 158 #define COOKIE_TAG_MAP_PATH BPF_NETD_PATH "map_netd_cookie_tag_map" 159 #define UID_COUNTERSET_MAP_PATH BPF_NETD_PATH "map_netd_uid_counterset_map" 160 #define APP_UID_STATS_MAP_PATH BPF_NETD_PATH "map_netd_app_uid_stats_map" 161 #define STATS_MAP_A_PATH BPF_NETD_PATH "map_netd_stats_map_A" 162 #define STATS_MAP_B_PATH BPF_NETD_PATH "map_netd_stats_map_B" 163 #define IFACE_INDEX_NAME_MAP_PATH BPF_NETD_PATH "map_netd_iface_index_name_map" 164 #define IFACE_STATS_MAP_PATH BPF_NETD_PATH "map_netd_iface_stats_map" 165 #define CONFIGURATION_MAP_PATH BPF_NETD_PATH "map_netd_configuration_map" 166 #define UID_OWNER_MAP_PATH BPF_NETD_PATH "map_netd_uid_owner_map" 167 #define UID_PERMISSION_MAP_PATH BPF_NETD_PATH "map_netd_uid_permission_map" 168 #define PACKET_TRACE_RINGBUF_PATH BPF_NETD_PATH "map_netd_packet_trace_ringbuf" 169 #define PACKET_TRACE_ENABLED_MAP_PATH BPF_NETD_PATH "map_netd_packet_trace_enabled_map" 170 171 #endif // __cplusplus 172 173 // LINT.IfChange(match_type) 174 enum UidOwnerMatchType { 175 NO_MATCH = 0, 176 HAPPY_BOX_MATCH = (1 << 0), 177 PENALTY_BOX_MATCH = (1 << 1), 178 DOZABLE_MATCH = (1 << 2), 179 STANDBY_MATCH = (1 << 3), 180 POWERSAVE_MATCH = (1 << 4), 181 RESTRICTED_MATCH = (1 << 5), 182 LOW_POWER_STANDBY_MATCH = (1 << 6), 183 IIF_MATCH = (1 << 7), 184 LOCKDOWN_VPN_MATCH = (1 << 8), 185 OEM_DENY_1_MATCH = (1 << 9), 186 OEM_DENY_2_MATCH = (1 << 10), 187 OEM_DENY_3_MATCH = (1 << 11), 188 }; 189 // LINT.ThenChange(packages/modules/Connectivity/service/src/com/android/server/BpfNetMaps.java) 190 191 enum BpfPermissionMatch { 192 BPF_PERMISSION_INTERNET = 1 << 2, 193 BPF_PERMISSION_UPDATE_DEVICE_STATS = 1 << 3, 194 }; 195 // In production we use two identical stats maps to record per uid stats and 196 // do swap and clean based on the configuration specified here. The statsMapType 197 // value in configuration map specified which map is currently in use. 198 enum StatsMapType { 199 SELECT_MAP_A, 200 SELECT_MAP_B, 201 }; 202 203 // TODO: change the configuration object from a bitmask to an object with clearer 204 // semantics, like a struct. 205 typedef uint32_t BpfConfig; 206 static const BpfConfig DEFAULT_CONFIG = 0; 207 208 typedef struct { 209 // Allowed interface index. Only applicable if IIF_MATCH is set in the rule bitmask above. 210 uint32_t iif; 211 // A bitmask of enum values in UidOwnerMatchType. 212 uint32_t rule; 213 } UidOwnerValue; 214 STRUCT_SIZE(UidOwnerValue, 2 * 4); // 8 215 216 // Entry in the configuration map that stores which UID rules are enabled. 217 #define UID_RULES_CONFIGURATION_KEY 0 218 // Entry in the configuration map that stores which stats map is currently in use. 219 #define CURRENT_STATS_MAP_CONFIGURATION_KEY 1 220 221 #undef STRUCT_SIZE 222