blob: f0df97baf266e3d96f94626bbe0af4b49717bf83 [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
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 TC_BPF_INGRESS_ACCOUNT_PROG_NAME "prog_netd_schedact_ingress_account"
112#define TC_BPF_INGRESS_ACCOUNT_PROG_PATH BPF_PATH TC_BPF_INGRESS_ACCOUNT_PROG_NAME
113
114#define COOKIE_TAG_MAP_PATH BPF_PATH "map_netd_cookie_tag_map"
115#define UID_COUNTERSET_MAP_PATH BPF_PATH "map_netd_uid_counterset_map"
116#define APP_UID_STATS_MAP_PATH BPF_PATH "map_netd_app_uid_stats_map"
117#define STATS_MAP_A_PATH BPF_PATH "map_netd_stats_map_A"
118#define STATS_MAP_B_PATH BPF_PATH "map_netd_stats_map_B"
119#define IFACE_INDEX_NAME_MAP_PATH BPF_PATH "map_netd_iface_index_name_map"
120#define IFACE_STATS_MAP_PATH BPF_PATH "map_netd_iface_stats_map"
121#define CONFIGURATION_MAP_PATH BPF_PATH "map_netd_configuration_map"
122#define UID_OWNER_MAP_PATH BPF_PATH "map_netd_uid_owner_map"
123#define UID_PERMISSION_MAP_PATH BPF_PATH "map_netd_uid_permission_map"
124
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),
133 IIF_MATCH = (1 << 6),
134};
135
136enum BpfPermissionMatch {
137 BPF_PERMISSION_INTERNET = 1 << 2,
138 BPF_PERMISSION_UPDATE_DEVICE_STATS = 1 << 3,
139};
140// In production we use two identical stats maps to record per uid stats and
141// do swap and clean based on the configuration specified here. The statsMapType
142// value in configuration map specified which map is currently in use.
143enum StatsMapType {
144 SELECT_MAP_A,
145 SELECT_MAP_B,
146};
147
148// TODO: change the configuration object from an 8-bit bitmask to an object with clearer
149// semantics, like a struct.
150typedef uint8_t BpfConfig;
151static const BpfConfig DEFAULT_CONFIG = 0;
152
153typedef struct {
154 // Allowed interface index. Only applicable if IIF_MATCH is set in the rule bitmask above.
155 uint32_t iif;
156 // A bitmask of enum values in UidOwnerMatchType.
157 uint32_t rule;
158} UidOwnerValue;
159STRUCT_SIZE(UidOwnerValue, 2 * 4); // 8
160
161#define UID_RULES_CONFIGURATION_KEY 1
162#define CURRENT_STATS_MAP_CONFIGURATION_KEY 2
163
164#define CLAT_INGRESS6_PROG_RAWIP_NAME "prog_clatd_schedcls_ingress6_clat_rawip"
165#define CLAT_INGRESS6_PROG_ETHER_NAME "prog_clatd_schedcls_ingress6_clat_ether"
166
167#define CLAT_INGRESS6_PROG_RAWIP_PATH BPF_PATH CLAT_INGRESS6_PROG_RAWIP_NAME
168#define CLAT_INGRESS6_PROG_ETHER_PATH BPF_PATH CLAT_INGRESS6_PROG_ETHER_NAME
169
170#define CLAT_INGRESS6_MAP_PATH BPF_PATH "map_clatd_clat_ingress6_map"
171
172typedef struct {
173 uint32_t iif; // The input interface index
174 struct in6_addr pfx96; // The source /96 nat64 prefix, bottom 32 bits must be 0
175 struct in6_addr local6; // The full 128-bits of the destination IPv6 address
176} ClatIngress6Key;
177STRUCT_SIZE(ClatIngress6Key, 4 + 2 * 16); // 36
178
179typedef struct {
180 uint32_t oif; // The output interface to redirect to (0 means don't redirect)
181 struct in_addr local4; // The destination IPv4 address
182} ClatIngress6Value;
183STRUCT_SIZE(ClatIngress6Value, 4 + 4); // 8
184
185#define CLAT_EGRESS4_PROG_RAWIP_NAME "prog_clatd_schedcls_egress4_clat_rawip"
186#define CLAT_EGRESS4_PROG_ETHER_NAME "prog_clatd_schedcls_egress4_clat_ether"
187
188#define CLAT_EGRESS4_PROG_RAWIP_PATH BPF_PATH CLAT_EGRESS4_PROG_RAWIP_NAME
189#define CLAT_EGRESS4_PROG_ETHER_PATH BPF_PATH CLAT_EGRESS4_PROG_ETHER_NAME
190
191#define CLAT_EGRESS4_MAP_PATH BPF_PATH "map_clatd_clat_egress4_map"
192
193typedef struct {
194 uint32_t iif; // The input interface index
195 struct in_addr local4; // The source IPv4 address
196} ClatEgress4Key;
197STRUCT_SIZE(ClatEgress4Key, 4 + 4); // 8
198
199typedef struct {
200 uint32_t oif; // The output interface to redirect to
201 struct in6_addr local6; // The full 128-bits of the source IPv6 address
202 struct in6_addr pfx96; // The destination /96 nat64 prefix, bottom 32 bits must be 0
203 bool oifIsEthernet; // Whether the output interface requires ethernet header
204 uint8_t pad[3];
205} ClatEgress4Value;
206STRUCT_SIZE(ClatEgress4Value, 4 + 2 * 16 + 1 + 3); // 40
207
208#undef STRUCT_SIZE