1 /* 2 * Copyright (C) 2017 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 #ifndef BPF_BPFUTILS_H 18 #define BPF_BPFUTILS_H 19 20 #include <linux/bpf.h> 21 #include <linux/if_ether.h> 22 #include <linux/in.h> 23 #include <linux/unistd.h> 24 #include <net/if.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <sys/socket.h> 28 29 #include "android-base/unique_fd.h" 30 #include "netdutils/Slice.h" 31 #include "netdutils/StatusOr.h" 32 33 #define BPF_PASS 1 34 #define BPF_DROP 0 35 36 namespace android { 37 namespace bpf { 38 39 struct UidTag { 40 uint32_t uid; 41 uint32_t tag; 42 }; 43 44 struct StatsKey { 45 uint32_t uid; 46 uint32_t tag; 47 uint32_t counterSet; 48 uint32_t ifaceIndex; 49 }; 50 51 struct StatsValue { 52 uint64_t rxPackets; 53 uint64_t rxBytes; 54 uint64_t txPackets; 55 uint64_t txBytes; 56 }; 57 58 struct Stats { 59 uint64_t rxBytes; 60 uint64_t rxPackets; 61 uint64_t txBytes; 62 uint64_t txPackets; 63 uint64_t tcpRxPackets; 64 uint64_t tcpTxPackets; 65 }; 66 67 struct IfaceValue { 68 char name[IFNAMSIZ]; 69 }; 70 71 #ifndef DEFAULT_OVERFLOWUID 72 #define DEFAULT_OVERFLOWUID 65534 73 #endif 74 75 #define BPF_PATH "/sys/fs/bpf" 76 77 // Since we cannot garbage collect the stats map since device boot, we need to make these maps as 78 // large as possible. The maximum size of number of map entries we can have is depend on the rlimit 79 // of MEM_LOCK granted to netd. The memory space needed by each map can be calculated by the 80 // following fomula: 81 // elem_size = 40 + roundup(key_size, 8) + roundup(value_size, 8) 82 // cost = roundup_pow_of_two(max_entries) * 16 + elem_size * max_entries + 83 // elem_size * number_of_CPU 84 // And the cost of each map currently used is(assume the device have 8 CPUs): 85 // cookie_tag_map: key: 8 bytes, value: 8 bytes, cost: 822592 bytes = 823Kbytes 86 // uid_counter_set_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 87 // app_uid_stats_map: key: 4 bytes, value: 32 bytes, cost: 1062784 bytes = 1063Kbytes 88 // uid_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes 89 // tag_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes 90 // iface_index_name_map:key: 4 bytes, value: 16 bytes, cost: 80896 bytes = 81Kbytes 91 // iface_stats_map: key: 4 bytes, value: 32 bytes, cost: 97024 bytes = 97Kbytes 92 // dozable_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 93 // standby_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 94 // powersave_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes 95 // total: 4930Kbytes 96 // It takes maximum 4.9MB kernel memory space if all maps are full, which requires any devices 97 // running this module to have a memlock rlimit to be larger then 5MB. In the old qtaguid module, 98 // we don't have a total limit for data entries but only have limitation of tags each uid can have. 99 // (default is 1024 in kernel); 100 101 constexpr const int COOKIE_UID_MAP_SIZE = 10000; 102 constexpr const int UID_COUNTERSET_MAP_SIZE = 2000; 103 constexpr const int UID_STATS_MAP_SIZE = 10000; 104 constexpr const int TAG_STATS_MAP_SIZE = 10000; 105 constexpr const int IFACE_INDEX_NAME_MAP_SIZE = 1000; 106 constexpr const int IFACE_STATS_MAP_SIZE = 1000; 107 constexpr const int UID_OWNER_MAP_SIZE = 2000; 108 109 constexpr const char* BPF_EGRESS_PROG_PATH = BPF_PATH "/egress_prog"; 110 constexpr const char* BPF_INGRESS_PROG_PATH = BPF_PATH "/ingress_prog"; 111 constexpr const char* XT_BPF_INGRESS_PROG_PATH = BPF_PATH "/xt_bpf_ingress_prog"; 112 constexpr const char* XT_BPF_EGRESS_PROG_PATH = BPF_PATH "/xt_bpf_egress_prog"; 113 114 constexpr const char* CGROUP_ROOT_PATH = "/dev/cg2_bpf"; 115 116 constexpr const char* COOKIE_TAG_MAP_PATH = BPF_PATH "/traffic_cookie_tag_map"; 117 constexpr const char* UID_COUNTERSET_MAP_PATH = BPF_PATH "/traffic_uid_counterSet_map"; 118 constexpr const char* APP_UID_STATS_MAP_PATH = BPF_PATH "/traffic_app_uid_stats_map"; 119 constexpr const char* UID_STATS_MAP_PATH = BPF_PATH "/traffic_uid_stats_map"; 120 constexpr const char* TAG_STATS_MAP_PATH = BPF_PATH "/traffic_tag_stats_map"; 121 constexpr const char* IFACE_INDEX_NAME_MAP_PATH = BPF_PATH "/traffic_iface_index_name_map"; 122 constexpr const char* IFACE_STATS_MAP_PATH = BPF_PATH "/traffic_iface_stats_map"; 123 constexpr const char* DOZABLE_UID_MAP_PATH = BPF_PATH "/traffic_dozable_uid_map"; 124 constexpr const char* STANDBY_UID_MAP_PATH = BPF_PATH "/traffic_standby_uid_map"; 125 constexpr const char* POWERSAVE_UID_MAP_PATH = BPF_PATH "/traffic_powersave_uid_map"; 126 127 constexpr const int OVERFLOW_COUNTERSET = 2; 128 129 constexpr const uint64_t NONEXISTENT_COOKIE = 0; 130 131 constexpr const int MINIMUM_API_REQUIRED = 28; 132 133 int createMap(bpf_map_type map_type, uint32_t key_size, uint32_t value_size, 134 uint32_t max_entries, uint32_t map_flags); 135 int writeToMapEntry(const base::unique_fd& map_fd, void* key, void* value, uint64_t flags); 136 int findMapEntry(const base::unique_fd& map_fd, void* key, void* value); 137 int deleteMapEntry(const base::unique_fd& map_fd, void* key); 138 int getNextMapKey(const base::unique_fd& map_fd, void* key, void* next_key); 139 int getFirstMapKey(const base::unique_fd& map_fd, void* firstKey); 140 int bpfProgLoad(bpf_prog_type prog_type, netdutils::Slice bpf_insns, const char* license, 141 uint32_t kern_version, netdutils::Slice bpf_log); 142 int mapPin(const base::unique_fd& map_fd, const char* pathname); 143 int mapRetrieve(const char* pathname, uint32_t flags); 144 int attachProgram(bpf_attach_type type, uint32_t prog_fd, uint32_t cg_fd); 145 int detachProgram(bpf_attach_type type, uint32_t cg_fd); 146 uint64_t getSocketCookie(int sockFd); 147 bool hasBpfSupport(); 148 149 #define SKIP_IF_BPF_NOT_SUPPORTED \ 150 do { \ 151 if (!hasBpfSupport()) return; \ 152 } while (0) 153 154 constexpr int BPF_CONTINUE = 0; 155 constexpr int BPF_DELETED = 1; 156 157 bool operator==(const StatsValue& lhs, const StatsValue& rhs); 158 bool operator==(const UidTag& lhs, const UidTag& rhs); 159 bool operator==(const StatsKey& lhs, const StatsKey& rhs); 160 } // namespace bpf 161 } // namespace android 162 163 #endif 164