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