blob: 634fbf4106c3de09b9d648b24b4ebf91fb7db2d5 [file] [log] [blame]
Ken Chen335c0d42021-10-23 11:35:26 +08001/*
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>
Ken Chen335c0d42021-10-23 11:35:26 +080023
24// This header file is shared by eBPF kernel programs (C) and netd (C++) and
25// some of the maps are also accessed directly from Java mainline module code.
26//
27// Hence: explicitly pad all relevant structures and assert that their size
28// is the sum of the sizes of their fields.
29#define STRUCT_SIZE(name, size) _Static_assert(sizeof(name) == (size), "Incorrect struct size.")
30
31typedef struct {
32 uint32_t uid;
33 uint32_t tag;
34} UidTagValue;
35STRUCT_SIZE(UidTagValue, 2 * 4); // 8
36
37typedef struct {
38 uint32_t uid;
39 uint32_t tag;
40 uint32_t counterSet;
41 uint32_t ifaceIndex;
42} StatsKey;
43STRUCT_SIZE(StatsKey, 4 * 4); // 16
44
45typedef struct {
46 uint64_t rxPackets;
47 uint64_t rxBytes;
48 uint64_t txPackets;
49 uint64_t txBytes;
50} StatsValue;
51STRUCT_SIZE(StatsValue, 4 * 8); // 32
52
53typedef struct {
54 char name[IFNAMSIZ];
55} IfaceValue;
56STRUCT_SIZE(IfaceValue, 16);
57
58typedef struct {
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} Stats;
66
67// Since we cannot garbage collect the stats map since device boot, we need to make these maps as
68// large as possible. The maximum size of number of map entries we can have is depend on the rlimit
69// of MEM_LOCK granted to netd. The memory space needed by each map can be calculated by the
70// following fomula:
71// elem_size = 40 + roundup(key_size, 8) + roundup(value_size, 8)
72// cost = roundup_pow_of_two(max_entries) * 16 + elem_size * max_entries +
73// elem_size * number_of_CPU
74// And the cost of each map currently used is(assume the device have 8 CPUs):
75// cookie_tag_map: key: 8 bytes, value: 8 bytes, cost: 822592 bytes = 823Kbytes
76// uid_counter_set_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes
77// app_uid_stats_map: key: 4 bytes, value: 32 bytes, cost: 1062784 bytes = 1063Kbytes
78// uid_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes
79// tag_stats_map: key: 16 bytes, value: 32 bytes, cost: 1142848 bytes = 1143Kbytes
80// iface_index_name_map:key: 4 bytes, value: 16 bytes, cost: 80896 bytes = 81Kbytes
81// iface_stats_map: key: 4 bytes, value: 32 bytes, cost: 97024 bytes = 97Kbytes
82// dozable_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes
83// standby_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes
84// powersave_uid_map: key: 4 bytes, value: 1 bytes, cost: 145216 bytes = 145Kbytes
85// total: 4930Kbytes
86// It takes maximum 4.9MB kernel memory space if all maps are full, which requires any devices
87// running this module to have a memlock rlimit to be larger then 5MB. In the old qtaguid module,
88// we don't have a total limit for data entries but only have limitation of tags each uid can have.
89// (default is 1024 in kernel);
90
91// 'static' - otherwise these constants end up in .rodata in the resulting .o post compilation
92static const int COOKIE_UID_MAP_SIZE = 10000;
93static const int UID_COUNTERSET_MAP_SIZE = 2000;
94static const int APP_STATS_MAP_SIZE = 10000;
95static const int STATS_MAP_SIZE = 5000;
96static const int IFACE_INDEX_NAME_MAP_SIZE = 1000;
97static const int IFACE_STATS_MAP_SIZE = 1000;
98static const int CONFIGURATION_MAP_SIZE = 2;
99static const int UID_OWNER_MAP_SIZE = 2000;
100
Maciej Żenczykowskia52aca72022-05-16 13:59:12 -0700101#define BPF_NETD_PATH "/sys/fs/bpf/netd_shared/"
Ken Chen335c0d42021-10-23 11:35:26 +0800102
Maciej Żenczykowskia52aca72022-05-16 13:59:12 -0700103#define BPF_EGRESS_PROG_PATH BPF_NETD_PATH "prog_netd_cgroupskb_egress_stats"
104#define BPF_INGRESS_PROG_PATH BPF_NETD_PATH "prog_netd_cgroupskb_ingress_stats"
105#define XT_BPF_INGRESS_PROG_PATH BPF_NETD_PATH "prog_netd_skfilter_ingress_xtbpf"
106#define XT_BPF_EGRESS_PROG_PATH BPF_NETD_PATH "prog_netd_skfilter_egress_xtbpf"
107#define XT_BPF_ALLOWLIST_PROG_PATH BPF_NETD_PATH "prog_netd_skfilter_allowlist_xtbpf"
108#define XT_BPF_DENYLIST_PROG_PATH BPF_NETD_PATH "prog_netd_skfilter_denylist_xtbpf"
109#define CGROUP_SOCKET_PROG_PATH BPF_NETD_PATH "prog_netd_cgroupsock_inet_create"
Ken Chen335c0d42021-10-23 11:35:26 +0800110
111#define TC_BPF_INGRESS_ACCOUNT_PROG_NAME "prog_netd_schedact_ingress_account"
Maciej Żenczykowskia52aca72022-05-16 13:59:12 -0700112#define TC_BPF_INGRESS_ACCOUNT_PROG_PATH BPF_NETD_PATH TC_BPF_INGRESS_ACCOUNT_PROG_NAME
Ken Chen335c0d42021-10-23 11:35:26 +0800113
Maciej Żenczykowskia52aca72022-05-16 13:59:12 -0700114#define COOKIE_TAG_MAP_PATH BPF_NETD_PATH "map_netd_cookie_tag_map"
115#define UID_COUNTERSET_MAP_PATH BPF_NETD_PATH "map_netd_uid_counterset_map"
116#define APP_UID_STATS_MAP_PATH BPF_NETD_PATH "map_netd_app_uid_stats_map"
117#define STATS_MAP_A_PATH BPF_NETD_PATH "map_netd_stats_map_A"
118#define STATS_MAP_B_PATH BPF_NETD_PATH "map_netd_stats_map_B"
119#define IFACE_INDEX_NAME_MAP_PATH BPF_NETD_PATH "map_netd_iface_index_name_map"
120#define IFACE_STATS_MAP_PATH BPF_NETD_PATH "map_netd_iface_stats_map"
121#define CONFIGURATION_MAP_PATH BPF_NETD_PATH "map_netd_configuration_map"
122#define UID_OWNER_MAP_PATH BPF_NETD_PATH "map_netd_uid_owner_map"
123#define UID_PERMISSION_MAP_PATH BPF_NETD_PATH "map_netd_uid_permission_map"
Ken Chen335c0d42021-10-23 11:35:26 +0800124
125enum UidOwnerMatchType {
126 NO_MATCH = 0,
127 HAPPY_BOX_MATCH = (1 << 0),
128 PENALTY_BOX_MATCH = (1 << 1),
129 DOZABLE_MATCH = (1 << 2),
130 STANDBY_MATCH = (1 << 3),
131 POWERSAVE_MATCH = (1 << 4),
132 RESTRICTED_MATCH = (1 << 5),
Robert Horvath54423022022-01-27 19:53:27 +0100133 LOW_POWER_STANDBY_MATCH = (1 << 6),
134 IIF_MATCH = (1 << 7),
Motomu Utsumi966ff7f2022-05-11 05:56:26 +0000135 LOCKDOWN_VPN_MATCH = (1 << 8),
Ken Chen335c0d42021-10-23 11:35:26 +0800136};
137
138enum BpfPermissionMatch {
139 BPF_PERMISSION_INTERNET = 1 << 2,
140 BPF_PERMISSION_UPDATE_DEVICE_STATS = 1 << 3,
141};
142// In production we use two identical stats maps to record per uid stats and
143// do swap and clean based on the configuration specified here. The statsMapType
144// value in configuration map specified which map is currently in use.
145enum StatsMapType {
146 SELECT_MAP_A,
147 SELECT_MAP_B,
148};
149
Lorenzo Colitti90c0c3f2022-03-03 17:49:01 +0900150// TODO: change the configuration object from a bitmask to an object with clearer
Ken Chen335c0d42021-10-23 11:35:26 +0800151// semantics, like a struct.
Lorenzo Colitti90c0c3f2022-03-03 17:49:01 +0900152typedef uint32_t BpfConfig;
Ken Chen335c0d42021-10-23 11:35:26 +0800153static const BpfConfig DEFAULT_CONFIG = 0;
154
155typedef struct {
156 // Allowed interface index. Only applicable if IIF_MATCH is set in the rule bitmask above.
157 uint32_t iif;
158 // A bitmask of enum values in UidOwnerMatchType.
159 uint32_t rule;
160} UidOwnerValue;
161STRUCT_SIZE(UidOwnerValue, 2 * 4); // 8
162
Lorenzo Colitti90c0c3f2022-03-03 17:49:01 +0900163// Entry in the configuration map that stores which UID rules are enabled.
Ken Chen335c0d42021-10-23 11:35:26 +0800164#define UID_RULES_CONFIGURATION_KEY 1
Lorenzo Colitti90c0c3f2022-03-03 17:49:01 +0900165// Entry in the configuration map that stores which stats map is currently in use.
Ken Chen335c0d42021-10-23 11:35:26 +0800166#define CURRENT_STATS_MAP_CONFIGURATION_KEY 2
167
Maciej Żenczykowskia52aca72022-05-16 13:59:12 -0700168#define BPF_CLATD_PATH "/sys/fs/bpf/net_shared/"
169
Ken Chen335c0d42021-10-23 11:35:26 +0800170#define CLAT_INGRESS6_PROG_RAWIP_NAME "prog_clatd_schedcls_ingress6_clat_rawip"
171#define CLAT_INGRESS6_PROG_ETHER_NAME "prog_clatd_schedcls_ingress6_clat_ether"
172
Maciej Żenczykowskia52aca72022-05-16 13:59:12 -0700173#define CLAT_INGRESS6_PROG_RAWIP_PATH BPF_CLATD_PATH CLAT_INGRESS6_PROG_RAWIP_NAME
174#define CLAT_INGRESS6_PROG_ETHER_PATH BPF_CLATD_PATH CLAT_INGRESS6_PROG_ETHER_NAME
Ken Chen335c0d42021-10-23 11:35:26 +0800175
Maciej Żenczykowskia52aca72022-05-16 13:59:12 -0700176#define CLAT_INGRESS6_MAP_PATH BPF_CLATD_PATH "map_clatd_clat_ingress6_map"
Ken Chen335c0d42021-10-23 11:35:26 +0800177
178typedef struct {
179 uint32_t iif; // The input interface index
180 struct in6_addr pfx96; // The source /96 nat64 prefix, bottom 32 bits must be 0
181 struct in6_addr local6; // The full 128-bits of the destination IPv6 address
182} ClatIngress6Key;
183STRUCT_SIZE(ClatIngress6Key, 4 + 2 * 16); // 36
184
185typedef struct {
186 uint32_t oif; // The output interface to redirect to (0 means don't redirect)
187 struct in_addr local4; // The destination IPv4 address
188} ClatIngress6Value;
189STRUCT_SIZE(ClatIngress6Value, 4 + 4); // 8
190
191#define CLAT_EGRESS4_PROG_RAWIP_NAME "prog_clatd_schedcls_egress4_clat_rawip"
192#define CLAT_EGRESS4_PROG_ETHER_NAME "prog_clatd_schedcls_egress4_clat_ether"
193
Maciej Żenczykowskia52aca72022-05-16 13:59:12 -0700194#define CLAT_EGRESS4_PROG_RAWIP_PATH BPF_CLATD_PATH CLAT_EGRESS4_PROG_RAWIP_NAME
195#define CLAT_EGRESS4_PROG_ETHER_PATH BPF_CLATD_PATH CLAT_EGRESS4_PROG_ETHER_NAME
Ken Chen335c0d42021-10-23 11:35:26 +0800196
Maciej Żenczykowskia52aca72022-05-16 13:59:12 -0700197#define CLAT_EGRESS4_MAP_PATH BPF_CLATD_PATH "map_clatd_clat_egress4_map"
Ken Chen335c0d42021-10-23 11:35:26 +0800198
199typedef struct {
200 uint32_t iif; // The input interface index
201 struct in_addr local4; // The source IPv4 address
202} ClatEgress4Key;
203STRUCT_SIZE(ClatEgress4Key, 4 + 4); // 8
204
205typedef struct {
206 uint32_t oif; // The output interface to redirect to
207 struct in6_addr local6; // The full 128-bits of the source IPv6 address
208 struct in6_addr pfx96; // The destination /96 nat64 prefix, bottom 32 bits must be 0
209 bool oifIsEthernet; // Whether the output interface requires ethernet header
210 uint8_t pad[3];
211} ClatEgress4Value;
212STRUCT_SIZE(ClatEgress4Value, 4 + 2 * 16 + 1 + 3); // 40
213
214#undef STRUCT_SIZE