xref: /aosp_15_r20/kernel/tests/net/test/bpf.py (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
1*2f2c4c7aSAndroid Build Coastguard Worker#!/usr/bin/python3
2*2f2c4c7aSAndroid Build Coastguard Worker#
3*2f2c4c7aSAndroid Build Coastguard Worker# Copyright 2016 The Android Open Source Project
4*2f2c4c7aSAndroid Build Coastguard Worker#
5*2f2c4c7aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*2f2c4c7aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*2f2c4c7aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*2f2c4c7aSAndroid Build Coastguard Worker#
9*2f2c4c7aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0
10*2f2c4c7aSAndroid Build Coastguard Worker#
11*2f2c4c7aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*2f2c4c7aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*2f2c4c7aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*2f2c4c7aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*2f2c4c7aSAndroid Build Coastguard Worker# limitations under the License.
16*2f2c4c7aSAndroid Build Coastguard Worker
17*2f2c4c7aSAndroid Build Coastguard Worker"""kernel net test library for bpf testing."""
18*2f2c4c7aSAndroid Build Coastguard Worker
19*2f2c4c7aSAndroid Build Coastguard Workerimport ctypes
20*2f2c4c7aSAndroid Build Coastguard Workerimport errno
21*2f2c4c7aSAndroid Build Coastguard Workerimport os
22*2f2c4c7aSAndroid Build Coastguard Workerimport resource
23*2f2c4c7aSAndroid Build Coastguard Workerimport socket
24*2f2c4c7aSAndroid Build Coastguard Workerimport sys
25*2f2c4c7aSAndroid Build Coastguard Worker
26*2f2c4c7aSAndroid Build Coastguard Workerimport csocket
27*2f2c4c7aSAndroid Build Coastguard Workerimport cstruct
28*2f2c4c7aSAndroid Build Coastguard Workerimport net_test
29*2f2c4c7aSAndroid Build Coastguard Worker
30*2f2c4c7aSAndroid Build Coastguard Worker# __NR_bpf syscall numbers for various architectures.
31*2f2c4c7aSAndroid Build Coastguard Worker# NOTE: If python inherited COMPAT_UTS_MACHINE, uname's 'machine' field will
32*2f2c4c7aSAndroid Build Coastguard Worker# return the 32-bit architecture name, even if python itself is 64-bit. To work
33*2f2c4c7aSAndroid Build Coastguard Worker# around this problem and pick the right syscall nr, we can additionally check
34*2f2c4c7aSAndroid Build Coastguard Worker# the bitness of the python interpreter. Assume that the 64-bit architectures
35*2f2c4c7aSAndroid Build Coastguard Worker# are not running with COMPAT_UTS_MACHINE and must be 64-bit at all times.
36*2f2c4c7aSAndroid Build Coastguard Worker__NR_bpf = {  # pylint: disable=invalid-name
37*2f2c4c7aSAndroid Build Coastguard Worker    "aarch64-32bit": 386,
38*2f2c4c7aSAndroid Build Coastguard Worker    "aarch64-64bit": 280,
39*2f2c4c7aSAndroid Build Coastguard Worker    "armv7l-32bit": 386,
40*2f2c4c7aSAndroid Build Coastguard Worker    "armv8l-32bit": 386,
41*2f2c4c7aSAndroid Build Coastguard Worker    "armv8l-64bit": 280,
42*2f2c4c7aSAndroid Build Coastguard Worker    "i686-32bit": 357,
43*2f2c4c7aSAndroid Build Coastguard Worker    "i686-64bit": 321,
44*2f2c4c7aSAndroid Build Coastguard Worker    "x86_64-32bit": 357,
45*2f2c4c7aSAndroid Build Coastguard Worker    "x86_64-64bit": 321,
46*2f2c4c7aSAndroid Build Coastguard Worker    "riscv64-64bit": 280,
47*2f2c4c7aSAndroid Build Coastguard Worker}[os.uname()[4] + "-" + ("64" if sys.maxsize > 0x7FFFFFFF else "32") + "bit"]
48*2f2c4c7aSAndroid Build Coastguard Worker
49*2f2c4c7aSAndroid Build Coastguard Worker# After ACK merge of 5.10.168 is when support for this was backported from
50*2f2c4c7aSAndroid Build Coastguard Worker# upstream Linux 5.14 and was merged into ACK android{12,13}-5.10 branches.
51*2f2c4c7aSAndroid Build Coastguard Worker# Require support to be backported to any 5.10+ kernel.
52*2f2c4c7aSAndroid Build Coastguard WorkerHAVE_SO_NETNS_COOKIE = net_test.LINUX_VERSION >= (5, 10, 0)
53*2f2c4c7aSAndroid Build Coastguard Worker
54*2f2c4c7aSAndroid Build Coastguard Worker# Note: This is *not* correct for parisc & sparc architectures
55*2f2c4c7aSAndroid Build Coastguard WorkerSO_NETNS_COOKIE = 71
56*2f2c4c7aSAndroid Build Coastguard Worker
57*2f2c4c7aSAndroid Build Coastguard WorkerLOG_LEVEL = 1
58*2f2c4c7aSAndroid Build Coastguard WorkerLOG_SIZE = 65536
59*2f2c4c7aSAndroid Build Coastguard Worker
60*2f2c4c7aSAndroid Build Coastguard Worker# BPF syscall commands constants.
61*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_CREATE = 0
62*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_LOOKUP_ELEM = 1
63*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_UPDATE_ELEM = 2
64*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_DELETE_ELEM = 3
65*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_GET_NEXT_KEY = 4
66*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_LOAD = 5
67*2f2c4c7aSAndroid Build Coastguard WorkerBPF_OBJ_PIN = 6
68*2f2c4c7aSAndroid Build Coastguard WorkerBPF_OBJ_GET = 7
69*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_ATTACH = 8
70*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_DETACH = 9
71*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TEST_RUN = 10
72*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_GET_NEXT_ID = 11
73*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_GET_NEXT_ID = 12
74*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_GET_FD_BY_ID = 13
75*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_GET_FD_BY_ID = 14
76*2f2c4c7aSAndroid Build Coastguard WorkerBPF_OBJ_GET_INFO_BY_FD = 15
77*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_QUERY = 16
78*2f2c4c7aSAndroid Build Coastguard Worker
79*2f2c4c7aSAndroid Build Coastguard Worker# setsockopt SOL_SOCKET constants
80*2f2c4c7aSAndroid Build Coastguard WorkerSO_ATTACH_BPF = 50
81*2f2c4c7aSAndroid Build Coastguard Worker
82*2f2c4c7aSAndroid Build Coastguard Worker# BPF map type constant.
83*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_TYPE_UNSPEC = 0
84*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_TYPE_HASH = 1
85*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_TYPE_ARRAY = 2
86*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_TYPE_PROG_ARRAY = 3
87*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MAP_TYPE_PERF_EVENT_ARRAY = 4
88*2f2c4c7aSAndroid Build Coastguard Worker
89*2f2c4c7aSAndroid Build Coastguard Worker# BPF program type constant.
90*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_UNSPEC = 0
91*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_SOCKET_FILTER = 1
92*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_KPROBE = 2
93*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_SCHED_CLS = 3
94*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_SCHED_ACT = 4
95*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_TRACEPOINT = 5
96*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_XDP = 6
97*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_PERF_EVENT = 7
98*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_CGROUP_SKB = 8
99*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PROG_TYPE_CGROUP_SOCK = 9
100*2f2c4c7aSAndroid Build Coastguard Worker
101*2f2c4c7aSAndroid Build Coastguard Worker# BPF program attach type.
102*2f2c4c7aSAndroid Build Coastguard WorkerBPF_CGROUP_INET_INGRESS = 0
103*2f2c4c7aSAndroid Build Coastguard WorkerBPF_CGROUP_INET_EGRESS = 1
104*2f2c4c7aSAndroid Build Coastguard WorkerBPF_CGROUP_INET_SOCK_CREATE = 2
105*2f2c4c7aSAndroid Build Coastguard Worker
106*2f2c4c7aSAndroid Build Coastguard Worker# BPF register constant
107*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_0 = 0
108*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_1 = 1
109*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_2 = 2
110*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_3 = 3
111*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_4 = 4
112*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_5 = 5
113*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_6 = 6
114*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_7 = 7
115*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_8 = 8
116*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_9 = 9
117*2f2c4c7aSAndroid Build Coastguard WorkerBPF_REG_10 = 10
118*2f2c4c7aSAndroid Build Coastguard Worker
119*2f2c4c7aSAndroid Build Coastguard Worker# BPF instruction constants
120*2f2c4c7aSAndroid Build Coastguard WorkerBPF_PSEUDO_MAP_FD = 1
121*2f2c4c7aSAndroid Build Coastguard WorkerBPF_LD = 0x00
122*2f2c4c7aSAndroid Build Coastguard WorkerBPF_LDX = 0x01
123*2f2c4c7aSAndroid Build Coastguard WorkerBPF_ST = 0x02
124*2f2c4c7aSAndroid Build Coastguard WorkerBPF_STX = 0x03
125*2f2c4c7aSAndroid Build Coastguard WorkerBPF_ALU = 0x04
126*2f2c4c7aSAndroid Build Coastguard WorkerBPF_JMP = 0x05
127*2f2c4c7aSAndroid Build Coastguard WorkerBPF_RET = 0x06
128*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MISC = 0x07
129*2f2c4c7aSAndroid Build Coastguard WorkerBPF_W = 0x00
130*2f2c4c7aSAndroid Build Coastguard WorkerBPF_H = 0x08
131*2f2c4c7aSAndroid Build Coastguard WorkerBPF_B = 0x10
132*2f2c4c7aSAndroid Build Coastguard WorkerBPF_IMM = 0x00
133*2f2c4c7aSAndroid Build Coastguard WorkerBPF_ABS = 0x20
134*2f2c4c7aSAndroid Build Coastguard WorkerBPF_IND = 0x40
135*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MEM = 0x60
136*2f2c4c7aSAndroid Build Coastguard WorkerBPF_LEN = 0x80
137*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MSH = 0xa0
138*2f2c4c7aSAndroid Build Coastguard WorkerBPF_ADD = 0x00
139*2f2c4c7aSAndroid Build Coastguard WorkerBPF_SUB = 0x10
140*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MUL = 0x20
141*2f2c4c7aSAndroid Build Coastguard WorkerBPF_DIV = 0x30
142*2f2c4c7aSAndroid Build Coastguard WorkerBPF_OR = 0x40
143*2f2c4c7aSAndroid Build Coastguard WorkerBPF_AND = 0x50
144*2f2c4c7aSAndroid Build Coastguard WorkerBPF_LSH = 0x60
145*2f2c4c7aSAndroid Build Coastguard WorkerBPF_RSH = 0x70
146*2f2c4c7aSAndroid Build Coastguard WorkerBPF_NEG = 0x80
147*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MOD = 0x90
148*2f2c4c7aSAndroid Build Coastguard WorkerBPF_XOR = 0xa0
149*2f2c4c7aSAndroid Build Coastguard WorkerBPF_JA = 0x00
150*2f2c4c7aSAndroid Build Coastguard WorkerBPF_JEQ = 0x10
151*2f2c4c7aSAndroid Build Coastguard WorkerBPF_JGT = 0x20
152*2f2c4c7aSAndroid Build Coastguard WorkerBPF_JGE = 0x30
153*2f2c4c7aSAndroid Build Coastguard WorkerBPF_JSET = 0x40
154*2f2c4c7aSAndroid Build Coastguard WorkerBPF_K = 0x00
155*2f2c4c7aSAndroid Build Coastguard WorkerBPF_X = 0x08
156*2f2c4c7aSAndroid Build Coastguard WorkerBPF_ALU64 = 0x07
157*2f2c4c7aSAndroid Build Coastguard WorkerBPF_DW = 0x18
158*2f2c4c7aSAndroid Build Coastguard WorkerBPF_XADD = 0xc0
159*2f2c4c7aSAndroid Build Coastguard WorkerBPF_MOV = 0xb0
160*2f2c4c7aSAndroid Build Coastguard Worker
161*2f2c4c7aSAndroid Build Coastguard WorkerBPF_ARSH = 0xc0
162*2f2c4c7aSAndroid Build Coastguard WorkerBPF_END = 0xd0
163*2f2c4c7aSAndroid Build Coastguard WorkerBPF_TO_LE = 0x00
164*2f2c4c7aSAndroid Build Coastguard WorkerBPF_TO_BE = 0x08
165*2f2c4c7aSAndroid Build Coastguard Worker
166*2f2c4c7aSAndroid Build Coastguard WorkerBPF_JNE = 0x50
167*2f2c4c7aSAndroid Build Coastguard WorkerBPF_JSGT = 0x60
168*2f2c4c7aSAndroid Build Coastguard Worker
169*2f2c4c7aSAndroid Build Coastguard WorkerBPF_JSGE = 0x70
170*2f2c4c7aSAndroid Build Coastguard WorkerBPF_CALL = 0x80
171*2f2c4c7aSAndroid Build Coastguard WorkerBPF_EXIT = 0x90
172*2f2c4c7aSAndroid Build Coastguard Worker
173*2f2c4c7aSAndroid Build Coastguard Worker# BPF helper function constants
174*2f2c4c7aSAndroid Build Coastguard Worker# pylint: disable=invalid-name
175*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_unspec = 0
176*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_map_lookup_elem = 1
177*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_map_update_elem = 2
178*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_map_delete_elem = 3
179*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_ktime_get_ns = 5
180*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_get_current_uid_gid = 15
181*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_skb_change_head = 43
182*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_get_socket_cookie = 46
183*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_get_socket_uid = 47
184*2f2c4c7aSAndroid Build Coastguard WorkerBPF_FUNC_ktime_get_boot_ns = 125
185*2f2c4c7aSAndroid Build Coastguard Worker# pylint: enable=invalid-name
186*2f2c4c7aSAndroid Build Coastguard Worker
187*2f2c4c7aSAndroid Build Coastguard WorkerBPF_F_RDONLY = 1 << 3
188*2f2c4c7aSAndroid Build Coastguard WorkerBPF_F_WRONLY = 1 << 4
189*2f2c4c7aSAndroid Build Coastguard Worker
190*2f2c4c7aSAndroid Build Coastguard Worker#  These object below belongs to the same kernel union and the types below
191*2f2c4c7aSAndroid Build Coastguard Worker#  (e.g., bpf_attr_create) aren't kernel struct names but just different
192*2f2c4c7aSAndroid Build Coastguard Worker#  variants of the union.
193*2f2c4c7aSAndroid Build Coastguard Worker# pylint: disable=invalid-name
194*2f2c4c7aSAndroid Build Coastguard WorkerBpfAttrCreate = cstruct.Struct(
195*2f2c4c7aSAndroid Build Coastguard Worker    "bpf_attr_create", "=IIIII",
196*2f2c4c7aSAndroid Build Coastguard Worker    "map_type key_size value_size max_entries, map_flags")
197*2f2c4c7aSAndroid Build Coastguard WorkerBpfAttrOps = cstruct.Struct(
198*2f2c4c7aSAndroid Build Coastguard Worker    "bpf_attr_ops", "=QQQQ",
199*2f2c4c7aSAndroid Build Coastguard Worker    "map_fd key_ptr value_ptr flags")
200*2f2c4c7aSAndroid Build Coastguard WorkerBpfAttrProgLoad = cstruct.Struct(
201*2f2c4c7aSAndroid Build Coastguard Worker    "bpf_attr_prog_load", "=IIQQIIQI", "prog_type insn_cnt insns"
202*2f2c4c7aSAndroid Build Coastguard Worker    " license log_level log_size log_buf kern_version")
203*2f2c4c7aSAndroid Build Coastguard WorkerBpfAttrProgAttach = cstruct.Struct(
204*2f2c4c7aSAndroid Build Coastguard Worker    "bpf_attr_prog_attach", "=III", "target_fd attach_bpf_fd attach_type")
205*2f2c4c7aSAndroid Build Coastguard WorkerBpfAttrGetFdById = cstruct.Struct(
206*2f2c4c7aSAndroid Build Coastguard Worker    "bpf_attr_get_fd_by_id", "=III", "id next_id open_flags")
207*2f2c4c7aSAndroid Build Coastguard WorkerBpfAttrProgQuery = cstruct.Struct(
208*2f2c4c7aSAndroid Build Coastguard Worker    "bpf_attr_prog_query", "=IIIIQIQ", "target_fd attach_type query_flags attach_flags prog_ids_ptr prog_cnt prog_attach_flags")
209*2f2c4c7aSAndroid Build Coastguard WorkerBpfInsn = cstruct.Struct("bpf_insn", "=BBhi", "code dst_src_reg off imm")
210*2f2c4c7aSAndroid Build Coastguard Worker# pylint: enable=invalid-name
211*2f2c4c7aSAndroid Build Coastguard Worker
212*2f2c4c7aSAndroid Build Coastguard Workerlibc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
213*2f2c4c7aSAndroid Build Coastguard Worker
214*2f2c4c7aSAndroid Build Coastguard Worker# set memlock resource 1 GiB
215*2f2c4c7aSAndroid Build Coastguard Workerresource.setrlimit(resource.RLIMIT_MEMLOCK, (1073741824, 1073741824))
216*2f2c4c7aSAndroid Build Coastguard Worker
217*2f2c4c7aSAndroid Build Coastguard Worker
218*2f2c4c7aSAndroid Build Coastguard Worker# BPF program syscalls
219*2f2c4c7aSAndroid Build Coastguard Workerdef BpfSyscall(op, attr):
220*2f2c4c7aSAndroid Build Coastguard Worker  ret = libc.syscall(__NR_bpf, op, csocket.VoidPointer(attr), len(attr))
221*2f2c4c7aSAndroid Build Coastguard Worker  csocket.MaybeRaiseSocketError(ret)
222*2f2c4c7aSAndroid Build Coastguard Worker  return ret
223*2f2c4c7aSAndroid Build Coastguard Worker
224*2f2c4c7aSAndroid Build Coastguard Worker
225*2f2c4c7aSAndroid Build Coastguard Workerdef CreateMap(map_type, key_size, value_size, max_entries, map_flags=0):
226*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrCreate((map_type, key_size, value_size, max_entries, map_flags))
227*2f2c4c7aSAndroid Build Coastguard Worker  return BpfSyscall(BPF_MAP_CREATE, attr)
228*2f2c4c7aSAndroid Build Coastguard Worker
229*2f2c4c7aSAndroid Build Coastguard Worker
230*2f2c4c7aSAndroid Build Coastguard Workerdef UpdateMap(map_fd, key, value, flags=0):
231*2f2c4c7aSAndroid Build Coastguard Worker  c_value = ctypes.c_uint32(value)
232*2f2c4c7aSAndroid Build Coastguard Worker  c_key = ctypes.c_uint32(key)
233*2f2c4c7aSAndroid Build Coastguard Worker  value_ptr = ctypes.addressof(c_value)
234*2f2c4c7aSAndroid Build Coastguard Worker  key_ptr = ctypes.addressof(c_key)
235*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrOps((map_fd, key_ptr, value_ptr, flags))
236*2f2c4c7aSAndroid Build Coastguard Worker  BpfSyscall(BPF_MAP_UPDATE_ELEM, attr)
237*2f2c4c7aSAndroid Build Coastguard Worker
238*2f2c4c7aSAndroid Build Coastguard Worker
239*2f2c4c7aSAndroid Build Coastguard Workerdef LookupMap(map_fd, key):
240*2f2c4c7aSAndroid Build Coastguard Worker  c_value = ctypes.c_uint32(0)
241*2f2c4c7aSAndroid Build Coastguard Worker  c_key = ctypes.c_uint32(key)
242*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrOps(
243*2f2c4c7aSAndroid Build Coastguard Worker      (map_fd, ctypes.addressof(c_key), ctypes.addressof(c_value), 0))
244*2f2c4c7aSAndroid Build Coastguard Worker  BpfSyscall(BPF_MAP_LOOKUP_ELEM, attr)
245*2f2c4c7aSAndroid Build Coastguard Worker  return c_value
246*2f2c4c7aSAndroid Build Coastguard Worker
247*2f2c4c7aSAndroid Build Coastguard Worker
248*2f2c4c7aSAndroid Build Coastguard Workerdef GetNextKey(map_fd, key):
249*2f2c4c7aSAndroid Build Coastguard Worker  """Get the next key in the map after the specified key."""
250*2f2c4c7aSAndroid Build Coastguard Worker  if key is not None:
251*2f2c4c7aSAndroid Build Coastguard Worker    c_key = ctypes.c_uint32(key)
252*2f2c4c7aSAndroid Build Coastguard Worker    c_next_key = ctypes.c_uint32(0)
253*2f2c4c7aSAndroid Build Coastguard Worker    key_ptr = ctypes.addressof(c_key)
254*2f2c4c7aSAndroid Build Coastguard Worker  else:
255*2f2c4c7aSAndroid Build Coastguard Worker    key_ptr = 0
256*2f2c4c7aSAndroid Build Coastguard Worker  c_next_key = ctypes.c_uint32(0)
257*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrOps(
258*2f2c4c7aSAndroid Build Coastguard Worker      (map_fd, key_ptr, ctypes.addressof(c_next_key), 0))
259*2f2c4c7aSAndroid Build Coastguard Worker  BpfSyscall(BPF_MAP_GET_NEXT_KEY, attr)
260*2f2c4c7aSAndroid Build Coastguard Worker  return c_next_key
261*2f2c4c7aSAndroid Build Coastguard Worker
262*2f2c4c7aSAndroid Build Coastguard Worker
263*2f2c4c7aSAndroid Build Coastguard Workerdef GetFirstKey(map_fd):
264*2f2c4c7aSAndroid Build Coastguard Worker  return GetNextKey(map_fd, None)
265*2f2c4c7aSAndroid Build Coastguard Worker
266*2f2c4c7aSAndroid Build Coastguard Worker
267*2f2c4c7aSAndroid Build Coastguard Workerdef DeleteMap(map_fd, key):
268*2f2c4c7aSAndroid Build Coastguard Worker  c_key = ctypes.c_uint32(key)
269*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrOps((map_fd, ctypes.addressof(c_key), 0, 0))
270*2f2c4c7aSAndroid Build Coastguard Worker  BpfSyscall(BPF_MAP_DELETE_ELEM, attr)
271*2f2c4c7aSAndroid Build Coastguard Worker
272*2f2c4c7aSAndroid Build Coastguard Worker
273*2f2c4c7aSAndroid Build Coastguard Workerdef BpfProgLoad(prog_type, instructions, prog_license=b"GPL"):
274*2f2c4c7aSAndroid Build Coastguard Worker  bpf_prog = b"".join(instructions)
275*2f2c4c7aSAndroid Build Coastguard Worker  insn_buff = ctypes.create_string_buffer(bpf_prog)
276*2f2c4c7aSAndroid Build Coastguard Worker  gpl_license = ctypes.create_string_buffer(prog_license)
277*2f2c4c7aSAndroid Build Coastguard Worker  log_buf = ctypes.create_string_buffer(b"", LOG_SIZE)
278*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrProgLoad((prog_type, len(insn_buff) // len(BpfInsn),
279*2f2c4c7aSAndroid Build Coastguard Worker                          ctypes.addressof(insn_buff),
280*2f2c4c7aSAndroid Build Coastguard Worker                          ctypes.addressof(gpl_license), LOG_LEVEL,
281*2f2c4c7aSAndroid Build Coastguard Worker                          LOG_SIZE, ctypes.addressof(log_buf), 0))
282*2f2c4c7aSAndroid Build Coastguard Worker  return BpfSyscall(BPF_PROG_LOAD, attr)
283*2f2c4c7aSAndroid Build Coastguard Worker
284*2f2c4c7aSAndroid Build Coastguard Worker
285*2f2c4c7aSAndroid Build Coastguard Worker# Attach a socket eBPF filter to a target socket
286*2f2c4c7aSAndroid Build Coastguard Workerdef BpfProgAttachSocket(sock_fd, prog_fd):
287*2f2c4c7aSAndroid Build Coastguard Worker  uint_fd = ctypes.c_uint32(prog_fd)
288*2f2c4c7aSAndroid Build Coastguard Worker  ret = libc.setsockopt(sock_fd, socket.SOL_SOCKET, SO_ATTACH_BPF,
289*2f2c4c7aSAndroid Build Coastguard Worker                        ctypes.pointer(uint_fd), ctypes.sizeof(uint_fd))
290*2f2c4c7aSAndroid Build Coastguard Worker  csocket.MaybeRaiseSocketError(ret)
291*2f2c4c7aSAndroid Build Coastguard Worker
292*2f2c4c7aSAndroid Build Coastguard Worker
293*2f2c4c7aSAndroid Build Coastguard Worker# Attach a eBPF filter to a cgroup
294*2f2c4c7aSAndroid Build Coastguard Workerdef BpfProgAttach(prog_fd, target_fd, prog_type):
295*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrProgAttach((target_fd, prog_fd, prog_type))
296*2f2c4c7aSAndroid Build Coastguard Worker  return BpfSyscall(BPF_PROG_ATTACH, attr)
297*2f2c4c7aSAndroid Build Coastguard Worker
298*2f2c4c7aSAndroid Build Coastguard Worker
299*2f2c4c7aSAndroid Build Coastguard Worker# Detach a eBPF filter from a cgroup
300*2f2c4c7aSAndroid Build Coastguard Workerdef BpfProgDetach(target_fd, prog_type):
301*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrProgAttach((target_fd, 0, prog_type))
302*2f2c4c7aSAndroid Build Coastguard Worker  try:
303*2f2c4c7aSAndroid Build Coastguard Worker    return BpfSyscall(BPF_PROG_DETACH, attr)
304*2f2c4c7aSAndroid Build Coastguard Worker  except socket.error as e:
305*2f2c4c7aSAndroid Build Coastguard Worker    if e.errno != errno.ENOENT:
306*2f2c4c7aSAndroid Build Coastguard Worker      raise
307*2f2c4c7aSAndroid Build Coastguard Worker
308*2f2c4c7aSAndroid Build Coastguard Worker
309*2f2c4c7aSAndroid Build Coastguard Worker# Convert a BPF program ID into an open file descriptor
310*2f2c4c7aSAndroid Build Coastguard Workerdef BpfProgGetFdById(prog_id):
311*2f2c4c7aSAndroid Build Coastguard Worker  if prog_id is None:
312*2f2c4c7aSAndroid Build Coastguard Worker    return None
313*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrGetFdById((prog_id, 0, 0))
314*2f2c4c7aSAndroid Build Coastguard Worker  return BpfSyscall(BPF_PROG_GET_FD_BY_ID, attr)
315*2f2c4c7aSAndroid Build Coastguard Worker
316*2f2c4c7aSAndroid Build Coastguard Worker
317*2f2c4c7aSAndroid Build Coastguard Worker# Convert a BPF map ID into an open file descriptor
318*2f2c4c7aSAndroid Build Coastguard Workerdef BpfMapGetFdById(map_id):
319*2f2c4c7aSAndroid Build Coastguard Worker  if map_id is None:
320*2f2c4c7aSAndroid Build Coastguard Worker    return None
321*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrGetFdById((map_id, 0, 0))
322*2f2c4c7aSAndroid Build Coastguard Worker  return BpfSyscall(BPF_MAP_GET_FD_BY_ID, attr)
323*2f2c4c7aSAndroid Build Coastguard Worker
324*2f2c4c7aSAndroid Build Coastguard Worker
325*2f2c4c7aSAndroid Build Coastguard Worker# Return BPF program id attached to a given cgroup & attach point
326*2f2c4c7aSAndroid Build Coastguard Worker# Note: as written this only supports a *single* program per attach point
327*2f2c4c7aSAndroid Build Coastguard Workerdef BpfProgQuery(target_fd, attach_type, query_flags, attach_flags):
328*2f2c4c7aSAndroid Build Coastguard Worker  prog_id = ctypes.c_uint32(-1)
329*2f2c4c7aSAndroid Build Coastguard Worker  minus_one = prog_id.value   # but unsigned, so really 4294967295
330*2f2c4c7aSAndroid Build Coastguard Worker  attr = BpfAttrProgQuery((target_fd, attach_type, query_flags, attach_flags, ctypes.addressof(prog_id), 1, 0))
331*2f2c4c7aSAndroid Build Coastguard Worker  if BpfSyscall(BPF_PROG_QUERY, attr) == 0:
332*2f2c4c7aSAndroid Build Coastguard Worker    # to see kernel updates we have to convert back from the buffer that actually went to the kernel...
333*2f2c4c7aSAndroid Build Coastguard Worker    attr._Parse(attr._buffer)
334*2f2c4c7aSAndroid Build Coastguard Worker    assert attr.prog_cnt >= 0, "prog_cnt is %s" % attr.prog_cnt
335*2f2c4c7aSAndroid Build Coastguard Worker    assert attr.prog_cnt <= 1, "prog_cnt is %s" % attr.prog_cnt  # we don't support more atm
336*2f2c4c7aSAndroid Build Coastguard Worker    if attr.prog_cnt == 0:
337*2f2c4c7aSAndroid Build Coastguard Worker      assert prog_id.value == minus_one, "prog_id is %s" % prog_id
338*2f2c4c7aSAndroid Build Coastguard Worker      return None
339*2f2c4c7aSAndroid Build Coastguard Worker    else:
340*2f2c4c7aSAndroid Build Coastguard Worker      assert prog_id.value != minus_one, "prog_id is %s" % prog_id
341*2f2c4c7aSAndroid Build Coastguard Worker      return prog_id.value
342*2f2c4c7aSAndroid Build Coastguard Worker  else:
343*2f2c4c7aSAndroid Build Coastguard Worker    return None
344*2f2c4c7aSAndroid Build Coastguard Worker
345*2f2c4c7aSAndroid Build Coastguard Worker
346*2f2c4c7aSAndroid Build Coastguard Worker# BPF program command constructors
347*2f2c4c7aSAndroid Build Coastguard Workerdef BpfMov64Reg(dst, src):
348*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_ALU64 | BPF_MOV | BPF_X
349*2f2c4c7aSAndroid Build Coastguard Worker  dst_src = src << 4 | dst
350*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, dst_src, 0, 0))
351*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
352*2f2c4c7aSAndroid Build Coastguard Worker
353*2f2c4c7aSAndroid Build Coastguard Worker
354*2f2c4c7aSAndroid Build Coastguard Workerdef BpfLdxMem(size, dst, src, off):
355*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_LDX | (size & 0x18) | BPF_MEM
356*2f2c4c7aSAndroid Build Coastguard Worker  dst_src = src << 4 | dst
357*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, dst_src, off, 0))
358*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
359*2f2c4c7aSAndroid Build Coastguard Worker
360*2f2c4c7aSAndroid Build Coastguard Worker
361*2f2c4c7aSAndroid Build Coastguard Workerdef BpfStxMem(size, dst, src, off):
362*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_STX | (size & 0x18) | BPF_MEM
363*2f2c4c7aSAndroid Build Coastguard Worker  dst_src = src << 4 | dst
364*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, dst_src, off, 0))
365*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
366*2f2c4c7aSAndroid Build Coastguard Worker
367*2f2c4c7aSAndroid Build Coastguard Worker
368*2f2c4c7aSAndroid Build Coastguard Workerdef BpfStMem(size, dst, off, imm):
369*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_ST | (size & 0x18) | BPF_MEM
370*2f2c4c7aSAndroid Build Coastguard Worker  dst_src = dst
371*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, dst_src, off, imm))
372*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
373*2f2c4c7aSAndroid Build Coastguard Worker
374*2f2c4c7aSAndroid Build Coastguard Worker
375*2f2c4c7aSAndroid Build Coastguard Workerdef BpfAlu64Imm(op, dst, imm):
376*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_ALU64 | (op & 0xf0) | BPF_K
377*2f2c4c7aSAndroid Build Coastguard Worker  dst_src = dst
378*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, dst_src, 0, imm))
379*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
380*2f2c4c7aSAndroid Build Coastguard Worker
381*2f2c4c7aSAndroid Build Coastguard Worker
382*2f2c4c7aSAndroid Build Coastguard Workerdef BpfJumpImm(op, dst, imm, off):
383*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_JMP | (op & 0xf0) | BPF_K
384*2f2c4c7aSAndroid Build Coastguard Worker  dst_src = dst
385*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, dst_src, off, imm))
386*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
387*2f2c4c7aSAndroid Build Coastguard Worker
388*2f2c4c7aSAndroid Build Coastguard Worker
389*2f2c4c7aSAndroid Build Coastguard Workerdef BpfRawInsn(code, dst, src, off, imm):
390*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, (src << 4 | dst), off, imm))
391*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
392*2f2c4c7aSAndroid Build Coastguard Worker
393*2f2c4c7aSAndroid Build Coastguard Worker
394*2f2c4c7aSAndroid Build Coastguard Workerdef BpfMov64Imm(dst, imm):
395*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_ALU64 | BPF_MOV | BPF_K
396*2f2c4c7aSAndroid Build Coastguard Worker  dst_src = dst
397*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, dst_src, 0, imm))
398*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
399*2f2c4c7aSAndroid Build Coastguard Worker
400*2f2c4c7aSAndroid Build Coastguard Worker
401*2f2c4c7aSAndroid Build Coastguard Workerdef BpfExitInsn():
402*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_JMP | BPF_EXIT
403*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, 0, 0, 0))
404*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
405*2f2c4c7aSAndroid Build Coastguard Worker
406*2f2c4c7aSAndroid Build Coastguard Worker
407*2f2c4c7aSAndroid Build Coastguard Workerdef BpfLoadMapFd(map_fd, dst):
408*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_LD | BPF_DW | BPF_IMM
409*2f2c4c7aSAndroid Build Coastguard Worker  dst_src = BPF_PSEUDO_MAP_FD << 4 | dst
410*2f2c4c7aSAndroid Build Coastguard Worker  insn1 = BpfInsn((code, dst_src, 0, map_fd))
411*2f2c4c7aSAndroid Build Coastguard Worker  insn2 = BpfInsn((0, 0, 0, map_fd >> 32))
412*2f2c4c7aSAndroid Build Coastguard Worker  return insn1.Pack() + insn2.Pack()
413*2f2c4c7aSAndroid Build Coastguard Worker
414*2f2c4c7aSAndroid Build Coastguard Worker
415*2f2c4c7aSAndroid Build Coastguard Workerdef BpfFuncCall(func):
416*2f2c4c7aSAndroid Build Coastguard Worker  code = BPF_JMP | BPF_CALL
417*2f2c4c7aSAndroid Build Coastguard Worker  dst_src = 0
418*2f2c4c7aSAndroid Build Coastguard Worker  ret = BpfInsn((code, dst_src, 0, func))
419*2f2c4c7aSAndroid Build Coastguard Worker  return ret.Pack()
420