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 #include <netdutils/UidConstants.h> 24 25 // This header file is shared by eBPF kernel programs (C) and netd (C++) and 26 // some of the maps are also accessed directly from Java mainline module code. 27 // 28 // Hence: explicitly pad all relevant structures and assert that their size 29 // is the sum of the sizes of their fields. 30 #define STRUCT_SIZE(name, size) _Static_assert(sizeof(name) == (size), "Incorrect struct size.") 31 32 typedef struct { 33 uint32_t uid; 34 uint32_t tag; 35 } UidTagValue; 36 STRUCT_SIZE(UidTagValue, 2 * 4); // 8 37 38 typedef struct { 39 uint32_t uid; 40 uint32_t tag; 41 uint32_t counterSet; 42 uint32_t ifaceIndex; 43 } StatsKey; 44 STRUCT_SIZE(StatsKey, 4 * 4); // 16 45 46 typedef struct { 47 uint64_t rxPackets; 48 uint64_t rxBytes; 49 uint64_t txPackets; 50 uint64_t txBytes; 51 } StatsValue; 52 STRUCT_SIZE(StatsValue, 4 * 8); // 32 53 54 typedef struct { 55 char name[IFNAMSIZ]; 56 } IfaceValue; 57 STRUCT_SIZE(IfaceValue, 16); 58 59 typedef struct { 60 uint64_t rxBytes; 61 uint64_t rxPackets; 62 uint64_t txBytes; 63 uint64_t txPackets; 64 uint64_t tcpRxPackets; 65 uint64_t tcpTxPackets; 66 } Stats; 67 68 // Since we cannot garbage collect the stats map since device boot, we need to make these maps as 69 // large as possible. The maximum size of number of map entries we can have is depend on the rlimit 70 // of MEM_LOCK granted to netd. The memory space needed by each map can be calculated by the 71 // following fomula: 72 // elem_size = 40 + roundup(key_size, 8) + roundup(value_size, 8) 73 // cost = roundup_pow_of_two(max_entries) * 16 + elem_size * max_entries + 74 // elem_size * number_of_CPU 75 // And the cost of each map currently used is(assume the device have 8 CPUs): 76 // cookie_tag_map: key: 8 bytes, value: 8 bytes, cost: 822592 bytes = 823Kbytes 77 // uid_counter_set_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 78 // app_uid_stats_map: key: 4 bytes, value: 32 bytes, cost: 1062784 bytes = 1063Kbytes 79 // uid_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes 80 // tag_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes 81 // iface_index_name_map:key: 4 bytes, value: 16 bytes, cost: 80896 bytes = 81Kbytes 82 // iface_stats_map: key: 4 bytes, value: 32 bytes, cost: 97024 bytes = 97Kbytes 83 // dozable_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 84 // standby_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 85 // powersave_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 86 // total: 4930Kbytes 87 // It takes maximum 4.9MB kernel memory space if all maps are full, which requires any devices 88 // running this module to have a memlock rlimit to be larger then 5MB. In the old qtaguid module, 89 // we don't have a total limit for data entries but only have limitation of tags each uid can have. 90 // (default is 1024 in kernel); 91 92 const int COOKIE_UID_MAP_SIZE = 10000; 93 const int UID_COUNTERSET_MAP_SIZE = 2000; 94 const int APP_STATS_MAP_SIZE = 10000; 95 const int STATS_MAP_SIZE = 5000; 96 const int IFACE_INDEX_NAME_MAP_SIZE = 1000; 97 const int IFACE_STATS_MAP_SIZE = 1000; 98 const int CONFIGURATION_MAP_SIZE = 2; 99 const int UID_OWNER_MAP_SIZE = 2000; 100 101 #define BPF_PATH "/sys/fs/bpf/" 102 103 #define BPF_EGRESS_PROG_PATH BPF_PATH "prog_netd_cgroupskb_egress_stats" 104 #define BPF_INGRESS_PROG_PATH BPF_PATH "prog_netd_cgroupskb_ingress_stats" 105 #define XT_BPF_INGRESS_PROG_PATH BPF_PATH "prog_netd_skfilter_ingress_xtbpf" 106 #define XT_BPF_EGRESS_PROG_PATH BPF_PATH "prog_netd_skfilter_egress_xtbpf" 107 #define XT_BPF_ALLOWLIST_PROG_PATH BPF_PATH "prog_netd_skfilter_allowlist_xtbpf" 108 #define XT_BPF_DENYLIST_PROG_PATH BPF_PATH "prog_netd_skfilter_denylist_xtbpf" 109 #define CGROUP_SOCKET_PROG_PATH BPF_PATH "prog_netd_cgroupsock_inet_create" 110 111 #define COOKIE_TAG_MAP_PATH BPF_PATH "map_netd_cookie_tag_map" 112 #define UID_COUNTERSET_MAP_PATH BPF_PATH "map_netd_uid_counterset_map" 113 #define APP_UID_STATS_MAP_PATH BPF_PATH "map_netd_app_uid_stats_map" 114 #define STATS_MAP_A_PATH BPF_PATH "map_netd_stats_map_A" 115 #define STATS_MAP_B_PATH BPF_PATH "map_netd_stats_map_B" 116 #define IFACE_INDEX_NAME_MAP_PATH BPF_PATH "map_netd_iface_index_name_map" 117 #define IFACE_STATS_MAP_PATH BPF_PATH "map_netd_iface_stats_map" 118 #define CONFIGURATION_MAP_PATH BPF_PATH "map_netd_configuration_map" 119 #define UID_OWNER_MAP_PATH BPF_PATH "map_netd_uid_owner_map" 120 #define UID_PERMISSION_MAP_PATH BPF_PATH "map_netd_uid_permission_map" 121 122 enum UidOwnerMatchType { 123 NO_MATCH = 0, 124 HAPPY_BOX_MATCH = (1 << 0), 125 PENALTY_BOX_MATCH = (1 << 1), 126 DOZABLE_MATCH = (1 << 2), 127 STANDBY_MATCH = (1 << 3), 128 POWERSAVE_MATCH = (1 << 4), 129 RESTRICTED_MATCH = (1 << 5), 130 IIF_MATCH = (1 << 6), 131 }; 132 133 enum BpfPermissionMatch { 134 BPF_PERMISSION_INTERNET = 1 << 2, 135 BPF_PERMISSION_UPDATE_DEVICE_STATS = 1 << 3, 136 }; 137 // In production we use two identical stats maps to record per uid stats and 138 // do swap and clean based on the configuration specified here. The statsMapType 139 // value in configuration map specified which map is currently in use. 140 enum StatsMapType { 141 SELECT_MAP_A, 142 SELECT_MAP_B, 143 }; 144 145 // TODO: change the configuration object from an 8-bit bitmask to an object with clearer 146 // semantics, like a struct. 147 typedef uint8_t BpfConfig; 148 const BpfConfig DEFAULT_CONFIG = 0; 149 150 typedef struct { 151 // Allowed interface index. Only applicable if IIF_MATCH is set in the rule bitmask above. 152 uint32_t iif; 153 // A bitmask of enum values in UidOwnerMatchType. 154 uint32_t rule; 155 } UidOwnerValue; 156 STRUCT_SIZE(UidOwnerValue, 2 * 4); // 8 157 158 #define UID_RULES_CONFIGURATION_KEY 1 159 #define CURRENT_STATS_MAP_CONFIGURATION_KEY 2 160 161 #define CLAT_INGRESS6_PROG_RAWIP_NAME "prog_clatd_schedcls_ingress6_clat_rawip" 162 #define CLAT_INGRESS6_PROG_ETHER_NAME "prog_clatd_schedcls_ingress6_clat_ether" 163 164 #define CLAT_INGRESS6_PROG_RAWIP_PATH BPF_PATH CLAT_INGRESS6_PROG_RAWIP_NAME 165 #define CLAT_INGRESS6_PROG_ETHER_PATH BPF_PATH CLAT_INGRESS6_PROG_ETHER_NAME 166 167 #define CLAT_INGRESS6_MAP_PATH BPF_PATH "map_clatd_clat_ingress6_map" 168 169 typedef struct { 170 uint32_t iif; // The input interface index 171 struct in6_addr pfx96; // The source /96 nat64 prefix, bottom 32 bits must be 0 172 struct in6_addr local6; // The full 128-bits of the destination IPv6 address 173 } ClatIngress6Key; 174 STRUCT_SIZE(ClatIngress6Key, 4 + 2 * 16); // 36 175 176 typedef struct { 177 uint32_t oif; // The output interface to redirect to (0 means don't redirect) 178 struct in_addr local4; // The destination IPv4 address 179 } ClatIngress6Value; 180 STRUCT_SIZE(ClatIngress6Value, 4 + 4); // 8 181 182 #define CLAT_EGRESS4_PROG_RAWIP_NAME "prog_clatd_schedcls_egress4_clat_rawip" 183 #define CLAT_EGRESS4_PROG_ETHER_NAME "prog_clatd_schedcls_egress4_clat_ether" 184 185 #define CLAT_EGRESS4_PROG_RAWIP_PATH BPF_PATH CLAT_EGRESS4_PROG_RAWIP_NAME 186 #define CLAT_EGRESS4_PROG_ETHER_PATH BPF_PATH CLAT_EGRESS4_PROG_ETHER_NAME 187 188 #define CLAT_EGRESS4_MAP_PATH BPF_PATH "map_clatd_clat_egress4_map" 189 190 typedef struct { 191 uint32_t iif; // The input interface index 192 struct in_addr local4; // The source IPv4 address 193 } ClatEgress4Key; 194 STRUCT_SIZE(ClatEgress4Key, 4 + 4); // 8 195 196 typedef struct { 197 uint32_t oif; // The output interface to redirect to 198 struct in6_addr local6; // The full 128-bits of the source IPv6 address 199 struct in6_addr pfx96; // The destination /96 nat64 prefix, bottom 32 bits must be 0 200 bool oifIsEthernet; // Whether the output interface requires ethernet header 201 uint8_t pad[3]; 202 } ClatEgress4Value; 203 STRUCT_SIZE(ClatEgress4Value, 4 + 2 * 16 + 1 + 3); // 40 204 205 #undef STRUCT_SIZE 206