• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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