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 // Since we cannot garbage collect the stats map since device boot, we need to make these maps as 73 // large as possible. The maximum size of number of map entries we can have is depend on the rlimit 74 // of MEM_LOCK granted to netd. The memory space needed by each map can be calculated by the 75 // following fomula: 76 // elem_size = 40 + roundup(key_size, 8) + roundup(value_size, 8) 77 // cost = roundup_pow_of_two(max_entries) * 16 + elem_size * max_entries + 78 // elem_size * number_of_CPU 79 // And the cost of each map currently used is(assume the device have 8 CPUs): 80 // cookie_tag_map: key: 8 bytes, value: 8 bytes, cost: 822592 bytes = 823Kbytes 81 // uid_counter_set_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 82 // app_uid_stats_map: key: 4 bytes, value: 32 bytes, cost: 1062784 bytes = 1063Kbytes 83 // uid_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes 84 // tag_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes 85 // iface_index_name_map:key: 4 bytes, value: 16 bytes, cost: 80896 bytes = 81Kbytes 86 // iface_stats_map: key: 4 bytes, value: 32 bytes, cost: 97024 bytes = 97Kbytes 87 // dozable_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 88 // standby_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 89 // powersave_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 90 // total: 4930Kbytes 91 // It takes maximum 4.9MB kernel memory space if all maps are full, which requires any devices 92 // running this module to have a memlock rlimit to be larger then 5MB. In the old qtaguid module, 93 // we don't have a total limit for data entries but only have limitation of tags each uid can have. 94 // (default is 1024 in kernel); 95 96 // 'static' - otherwise these constants end up in .rodata in the resulting .o post compilation 97 static const int COOKIE_UID_MAP_SIZE = 10000; 98 static const int UID_COUNTERSET_MAP_SIZE = 2000; 99 static const int APP_STATS_MAP_SIZE = 10000; 100 static const int STATS_MAP_SIZE = 5000; 101 static const int IFACE_INDEX_NAME_MAP_SIZE = 1000; 102 static const int IFACE_STATS_MAP_SIZE = 1000; 103 static const int CONFIGURATION_MAP_SIZE = 2; 104 static const int UID_OWNER_MAP_SIZE = 2000; 105 106 #ifdef __cplusplus 107 108 #define BPF_NETD_PATH "/sys/fs/bpf/netd_shared/" 109 110 #define BPF_EGRESS_PROG_PATH BPF_NETD_PATH "prog_netd_cgroupskb_egress_stats" 111 #define BPF_INGRESS_PROG_PATH BPF_NETD_PATH "prog_netd_cgroupskb_ingress_stats" 112 113 #define ASSERT_STRING_EQUAL(s1, s2) \ 114 static_assert(std::string_view(s1) == std::string_view(s2), "mismatch vs Android T netd") 115 116 /* -=-=-=-=- WARNING -=-=-=-=- 117 * 118 * These 4 xt_bpf program paths are actually defined by: 119 * //system/netd/include/mainline/XtBpfProgLocations.h 120 * which is intentionally a non-automerged location. 121 * 122 * They are *UNCHANGEABLE* due to being hard coded in Android T's netd binary 123 * as such we have compile time asserts that things match. 124 * (which will be validated during build on mainline-prod branch against old system/netd) 125 * 126 * If you break this, netd on T will fail to start with your tethering mainline module. 127 */ 128 ASSERT_STRING_EQUAL(XT_BPF_INGRESS_PROG_PATH, BPF_NETD_PATH "prog_netd_skfilter_ingress_xtbpf"); 129 ASSERT_STRING_EQUAL(XT_BPF_EGRESS_PROG_PATH, BPF_NETD_PATH "prog_netd_skfilter_egress_xtbpf"); 130 ASSERT_STRING_EQUAL(XT_BPF_ALLOWLIST_PROG_PATH, BPF_NETD_PATH "prog_netd_skfilter_allowlist_xtbpf"); 131 ASSERT_STRING_EQUAL(XT_BPF_DENYLIST_PROG_PATH, BPF_NETD_PATH "prog_netd_skfilter_denylist_xtbpf"); 132 133 #define CGROUP_SOCKET_PROG_PATH BPF_NETD_PATH "prog_netd_cgroupsock_inet_create" 134 135 #define TC_BPF_INGRESS_ACCOUNT_PROG_NAME "prog_netd_schedact_ingress_account" 136 #define TC_BPF_INGRESS_ACCOUNT_PROG_PATH BPF_NETD_PATH TC_BPF_INGRESS_ACCOUNT_PROG_NAME 137 138 #define COOKIE_TAG_MAP_PATH BPF_NETD_PATH "map_netd_cookie_tag_map" 139 #define UID_COUNTERSET_MAP_PATH BPF_NETD_PATH "map_netd_uid_counterset_map" 140 #define APP_UID_STATS_MAP_PATH BPF_NETD_PATH "map_netd_app_uid_stats_map" 141 #define STATS_MAP_A_PATH BPF_NETD_PATH "map_netd_stats_map_A" 142 #define STATS_MAP_B_PATH BPF_NETD_PATH "map_netd_stats_map_B" 143 #define IFACE_INDEX_NAME_MAP_PATH BPF_NETD_PATH "map_netd_iface_index_name_map" 144 #define IFACE_STATS_MAP_PATH BPF_NETD_PATH "map_netd_iface_stats_map" 145 #define CONFIGURATION_MAP_PATH BPF_NETD_PATH "map_netd_configuration_map" 146 #define UID_OWNER_MAP_PATH BPF_NETD_PATH "map_netd_uid_owner_map" 147 #define UID_PERMISSION_MAP_PATH BPF_NETD_PATH "map_netd_uid_permission_map" 148 149 #endif // __cplusplus 150 151 enum UidOwnerMatchType { 152 NO_MATCH = 0, 153 HAPPY_BOX_MATCH = (1 << 0), 154 PENALTY_BOX_MATCH = (1 << 1), 155 DOZABLE_MATCH = (1 << 2), 156 STANDBY_MATCH = (1 << 3), 157 POWERSAVE_MATCH = (1 << 4), 158 RESTRICTED_MATCH = (1 << 5), 159 LOW_POWER_STANDBY_MATCH = (1 << 6), 160 IIF_MATCH = (1 << 7), 161 LOCKDOWN_VPN_MATCH = (1 << 8), 162 OEM_DENY_1_MATCH = (1 << 9), 163 OEM_DENY_2_MATCH = (1 << 10), 164 OEM_DENY_3_MATCH = (1 << 11), 165 }; 166 167 enum BpfPermissionMatch { 168 BPF_PERMISSION_INTERNET = 1 << 2, 169 BPF_PERMISSION_UPDATE_DEVICE_STATS = 1 << 3, 170 }; 171 // In production we use two identical stats maps to record per uid stats and 172 // do swap and clean based on the configuration specified here. The statsMapType 173 // value in configuration map specified which map is currently in use. 174 enum StatsMapType { 175 SELECT_MAP_A, 176 SELECT_MAP_B, 177 }; 178 179 // TODO: change the configuration object from a bitmask to an object with clearer 180 // semantics, like a struct. 181 typedef uint32_t BpfConfig; 182 static const BpfConfig DEFAULT_CONFIG = 0; 183 184 typedef struct { 185 // Allowed interface index. Only applicable if IIF_MATCH is set in the rule bitmask above. 186 uint32_t iif; 187 // A bitmask of enum values in UidOwnerMatchType. 188 uint32_t rule; 189 } UidOwnerValue; 190 STRUCT_SIZE(UidOwnerValue, 2 * 4); // 8 191 192 // Entry in the configuration map that stores which UID rules are enabled. 193 #define UID_RULES_CONFIGURATION_KEY 0 194 // Entry in the configuration map that stores which stats map is currently in use. 195 #define CURRENT_STATS_MAP_CONFIGURATION_KEY 1 196 197 typedef struct { 198 uint32_t iif; // The input interface index 199 struct in6_addr pfx96; // The source /96 nat64 prefix, bottom 32 bits must be 0 200 struct in6_addr local6; // The full 128-bits of the destination IPv6 address 201 } ClatIngress6Key; 202 STRUCT_SIZE(ClatIngress6Key, 4 + 2 * 16); // 36 203 204 typedef struct { 205 uint32_t oif; // The output interface to redirect to (0 means don't redirect) 206 struct in_addr local4; // The destination IPv4 address 207 } ClatIngress6Value; 208 STRUCT_SIZE(ClatIngress6Value, 4 + 4); // 8 209 210 typedef struct { 211 uint32_t iif; // The input interface index 212 struct in_addr local4; // The source IPv4 address 213 } ClatEgress4Key; 214 STRUCT_SIZE(ClatEgress4Key, 4 + 4); // 8 215 216 typedef struct { 217 uint32_t oif; // The output interface to redirect to 218 struct in6_addr local6; // The full 128-bits of the source IPv6 address 219 struct in6_addr pfx96; // The destination /96 nat64 prefix, bottom 32 bits must be 0 220 bool oifIsEthernet; // Whether the output interface requires ethernet header 221 uint8_t pad[3]; 222 } ClatEgress4Value; 223 STRUCT_SIZE(ClatEgress4Value, 4 + 2 * 16 + 1 + 3); // 40 224 225 #undef STRUCT_SIZE 226