diff options
author | Maciej Żenczykowski <maze@google.com> | 2021-02-16 05:16:14 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-02-16 05:16:14 +0000 |
commit | 64f366c089fd64be77a4f07b0866bf390c9b7845 (patch) | |
tree | b317d4ed9c84ad40b0b5601d8e6cb1defe5f2144 | |
parent | a0d5f9edab93d01652ee1cdee1458d28b2aa15bf (diff) | |
parent | 90145477bc2182460121d03a79f6486f1b017173 (diff) | |
download | tests-64f366c089fd64be77a4f07b0866bf390c9b7845.tar.gz |
net-test: fix all gpylint2 errors in bpf.py and bpf_test.py am: 90145477bc
Original change: https://android-review.googlesource.com/c/kernel/tests/+/1589552
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: I2d2657e9c72ce52109f5cfe54030fa2b2335d132
-rwxr-xr-x | net/test/bpf.py | 43 | ||||
-rwxr-xr-x | net/test/bpf_test.py | 127 |
2 files changed, 127 insertions, 43 deletions
diff --git a/net/test/bpf.py b/net/test/bpf.py index 9e8f6c8..4e4f34f 100755 --- a/net/test/bpf.py +++ b/net/test/bpf.py @@ -14,15 +14,17 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""kernel net test library for bpf testing.""" + import ctypes import os +import platform +import resource +import socket import csocket import cstruct import net_test -import socket -import platform -import resource # __NR_bpf syscall numbers for various architectures. # NOTE: If python inherited COMPAT_UTS_MACHINE, uname's 'machine' field will @@ -30,8 +32,11 @@ import resource # around this problem and pick the right syscall nr, we can additionally check # the bitness of the python interpreter. Assume that the 64-bit architectures # are not running with COMPAT_UTS_MACHINE and must be 64-bit at all times. -# TODO: is there a better way of doing this? -__NR_bpf = { +# +# Is there a better way of doing this? +# Is it correct to use os.uname()[4] instead of platform.machine() ? +# Should we use 'sys.maxsize > 2**32' instead of platform.architecture()[0] ? +__NR_bpf = { # pylint: disable=invalid-name "aarch64-32bit": 386, "aarch64-64bit": 280, "armv7l-32bit": 386, @@ -151,6 +156,7 @@ BPF_CALL = 0x80 BPF_EXIT = 0x90 # BPF helper function constants +# pylint: disable=invalid-name BPF_FUNC_unspec = 0 BPF_FUNC_map_lookup_elem = 1 BPF_FUNC_map_update_elem = 2 @@ -158,6 +164,7 @@ BPF_FUNC_map_delete_elem = 3 BPF_FUNC_get_current_uid_gid = 15 BPF_FUNC_get_socket_cookie = 46 BPF_FUNC_get_socket_uid = 47 +# pylint: enable=invalid-name BPF_F_RDONLY = 1 << 3 BPF_F_WRONLY = 1 << 4 @@ -165,29 +172,39 @@ BPF_F_WRONLY = 1 << 4 # These object below belongs to the same kernel union and the types below # (e.g., bpf_attr_create) aren't kernel struct names but just different # variants of the union. -BpfAttrCreate = cstruct.Struct("bpf_attr_create", "=IIIII", - "map_type key_size value_size max_entries, map_flags") -BpfAttrOps = cstruct.Struct("bpf_attr_ops", "=QQQQ", - "map_fd key_ptr value_ptr flags") +# pylint: disable=invalid-name +BpfAttrCreate = cstruct.Struct( + "bpf_attr_create", "=IIIII", + "map_type key_size value_size max_entries, map_flags") +BpfAttrOps = cstruct.Struct( + "bpf_attr_ops", "=QQQQ", + "map_fd key_ptr value_ptr flags") BpfAttrProgLoad = cstruct.Struct( "bpf_attr_prog_load", "=IIQQIIQI", "prog_type insn_cnt insns" " license log_level log_size log_buf kern_version") BpfAttrProgAttach = cstruct.Struct( "bpf_attr_prog_attach", "=III", "target_fd attach_bpf_fd attach_type") BpfInsn = cstruct.Struct("bpf_insn", "=BBhi", "code dst_src_reg off imm") +# pylint: enable=invalid-name libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True) HAVE_EBPF_SUPPORT = net_test.LINUX_VERSION >= (4, 4, 0) +HAVE_EBPF_4_9 = net_test.LINUX_VERSION >= (4, 9, 0) +HAVE_EBPF_4_14 = net_test.LINUX_VERSION >= (4, 14, 0) +HAVE_EBPF_4_19 = net_test.LINUX_VERSION >= (4, 19, 0) +HAVE_EBPF_5_4 = net_test.LINUX_VERSION >= (5, 4, 0) # set memlock resource 1 GiB resource.setrlimit(resource.RLIMIT_MEMLOCK, (1073741824, 1073741824)) + # BPF program syscalls def BpfSyscall(op, attr): ret = libc.syscall(__NR_bpf, op, csocket.VoidPointer(attr), len(attr)) csocket.MaybeRaiseSocketError(ret) return ret + def CreateMap(map_type, key_size, value_size, max_entries, map_flags=0): attr = BpfAttrCreate((map_type, key_size, value_size, max_entries, map_flags)) return BpfSyscall(BPF_MAP_CREATE, attr) @@ -212,21 +229,24 @@ def LookupMap(map_fd, key): def GetNextKey(map_fd, key): + """Get the next key in the map after the specified key.""" if key is not None: c_key = ctypes.c_uint32(key) c_next_key = ctypes.c_uint32(0) key_ptr = ctypes.addressof(c_key) else: - key_ptr = 0; + key_ptr = 0 c_next_key = ctypes.c_uint32(0) attr = BpfAttrOps( (map_fd, key_ptr, ctypes.addressof(c_next_key), 0)) BpfSyscall(BPF_MAP_GET_NEXT_KEY, attr) return c_next_key + def GetFirstKey(map_fd): return GetNextKey(map_fd, None) + def DeleteMap(map_fd, key): c_key = ctypes.c_uint32(key) attr = BpfAttrOps((map_fd, ctypes.addressof(c_key), 0, 0)) @@ -244,6 +264,7 @@ def BpfProgLoad(prog_type, instructions): LOG_SIZE, ctypes.addressof(log_buf), 0)) return BpfSyscall(BPF_PROG_LOAD, attr) + # Attach a socket eBPF filter to a target socket def BpfProgAttachSocket(sock_fd, prog_fd): uint_fd = ctypes.c_uint32(prog_fd) @@ -251,11 +272,13 @@ def BpfProgAttachSocket(sock_fd, prog_fd): ctypes.pointer(uint_fd), ctypes.sizeof(uint_fd)) csocket.MaybeRaiseSocketError(ret) + # Attach a eBPF filter to a cgroup def BpfProgAttach(prog_fd, target_fd, prog_type): attr = BpfAttrProgAttach((target_fd, prog_fd, prog_type)) return BpfSyscall(BPF_PROG_ATTACH, attr) + # Detach a eBPF filter from a cgroup def BpfProgDetach(target_fd, prog_type): attr = BpfAttrProgAttach((target_fd, 0, prog_type)) diff --git a/net/test/bpf_test.py b/net/test/bpf_test.py index 30e8e49..33ad1da 100755 --- a/net/test/bpf_test.py +++ b/net/test/bpf_test.py @@ -18,19 +18,73 @@ import ctypes import errno import os import socket -import struct import subprocess import tempfile import unittest -from bpf import * # pylint: disable=wildcard-import +import bpf +from bpf import BPF_ADD +from bpf import BPF_AND +from bpf import BPF_CGROUP_INET_EGRESS +from bpf import BPF_CGROUP_INET_INGRESS +from bpf import BPF_CGROUP_INET_SOCK_CREATE +from bpf import BPF_DW +from bpf import BPF_F_RDONLY +from bpf import BPF_F_WRONLY +from bpf import BPF_FUNC_get_current_uid_gid +from bpf import BPF_FUNC_get_socket_cookie +from bpf import BPF_FUNC_get_socket_uid +from bpf import BPF_FUNC_ktime_get_boot_ns +from bpf import BPF_FUNC_ktime_get_ns +from bpf import BPF_FUNC_map_lookup_elem +from bpf import BPF_FUNC_map_update_elem +from bpf import BPF_JNE +from bpf import BPF_MAP_TYPE_HASH +from bpf import BPF_PROG_TYPE_CGROUP_SKB +from bpf import BPF_PROG_TYPE_CGROUP_SOCK +from bpf import BPF_PROG_TYPE_SCHED_CLS +from bpf import BPF_PROG_TYPE_SOCKET_FILTER +from bpf import BPF_REG_0 +from bpf import BPF_REG_1 +from bpf import BPF_REG_10 +from bpf import BPF_REG_2 +from bpf import BPF_REG_3 +from bpf import BPF_REG_4 +from bpf import BPF_REG_6 +from bpf import BPF_REG_7 +from bpf import BPF_STX +from bpf import BPF_W +from bpf import BPF_XADD +from bpf import BpfAlu64Imm +from bpf import BpfExitInsn +from bpf import BpfFuncCall +from bpf import BpfJumpImm +from bpf import BpfLdxMem +from bpf import BpfLoadMapFd +from bpf import BpfMov64Imm +from bpf import BpfMov64Reg +from bpf import BpfProgAttach +from bpf import BpfProgAttachSocket +from bpf import BpfProgDetach +from bpf import BpfProgLoad +from bpf import BpfRawInsn +from bpf import BpfStMem +from bpf import BpfStxMem +from bpf import CreateMap +from bpf import DeleteMap +from bpf import GetFirstKey +from bpf import GetNextKey +from bpf import LookupMap +from bpf import UpdateMap import csocket import net_test import sock_diag libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True) -HAVE_EBPF_ACCOUNTING = net_test.LINUX_VERSION >= (4, 9, 0) -HAVE_EBPF_SOCKET = net_test.LINUX_VERSION >= (4, 14, 0) + +HAVE_EBPF_ACCOUNTING = bpf.HAVE_EBPF_4_9 +HAVE_EBPF_SOCKET = bpf.HAVE_EBPF_4_14 + KEY_SIZE = 8 VALUE_SIZE = 4 TOTAL_ENTRIES = 20 @@ -41,18 +95,19 @@ key_offset = -8 # Offset to store the map value in stack register REG10 value_offset = -16 + # Debug usage only. def PrintMapInfo(map_fd): # A random key that the map does not contain. key = 10086 while 1: try: - nextKey = GetNextKey(map_fd, key).value - value = LookupMap(map_fd, nextKey) - print(repr(nextKey) + " : " + repr(value.value)) - key = nextKey - except: - print("no value") + next_key = GetNextKey(map_fd, key).value + value = LookupMap(map_fd, next_key) + print(repr(next_key) + " : " + repr(value.value)) # pylint: disable=superfluous-parens + key = next_key + except Exception: # pylint: disable=broad-except + print("no value") # pylint: disable=superfluous-parens break @@ -67,7 +122,7 @@ def SocketUDPLoopBack(packet_count, version, prog_fd): sock.bind((addr, 0)) addr = sock.getsockname() sockaddr = csocket.Sockaddr(addr) - for i in range(packet_count): + for _ in range(packet_count): sock.sendto("foo", addr) data, retaddr = csocket.Recvfrom(sock, 4096, 0) assert "foo" == data @@ -91,7 +146,7 @@ def SocketUDPLoopBack(packet_count, version, prog_fd): # the stack. def BpfFuncCountPacketInit(map_fd): key_pos = BPF_REG_7 - insPackCountStart = [ + return [ # Get a preloaded key from BPF_REG_0 and store it at BPF_REG_7 BpfMov64Reg(key_pos, BPF_REG_10), BpfAlu64Imm(BPF_ADD, key_pos, key_offset), @@ -111,7 +166,6 @@ def BpfFuncCountPacketInit(map_fd): BpfMov64Imm(BPF_REG_4, 0), BpfFuncCall(BPF_FUNC_map_update_elem) ] - return insPackCountStart INS_BPF_EXIT_BLOCK = [ @@ -148,11 +202,13 @@ INS_BPF_PARAM_STORE = [ BpfStxMem(BPF_DW, BPF_REG_10, BPF_REG_0, key_offset), ] + @unittest.skipUnless(HAVE_EBPF_ACCOUNTING, "BPF helper function is not fully supported") class BpfTest(net_test.NetworkTest): def setUp(self): + super(BpfTest, self).setUp() self.map_fd = -1 self.prog_fd = -1 self.sock = None @@ -164,6 +220,7 @@ class BpfTest(net_test.NetworkTest): os.close(self.map_fd) if self.sock: self.sock.close() + super(BpfTest, self).tearDown() def testCreateMap(self): key, value = 1, 1 @@ -174,11 +231,11 @@ class BpfTest(net_test.NetworkTest): DeleteMap(self.map_fd, key) self.assertRaisesErrno(errno.ENOENT, LookupMap, self.map_fd, key) - def CheckAllMapEntry(self, nonexistent_key, totalEntries, value): + def CheckAllMapEntry(self, nonexistent_key, total_entries, value): count = 0 key = nonexistent_key while True: - if count == totalEntries: + if count == total_entries: self.assertRaisesErrno(errno.ENOENT, GetNextKey, self.map_fd, key) break else: @@ -206,11 +263,10 @@ class BpfTest(net_test.NetworkTest): value = 1024 for key in range(0, TOTAL_ENTRIES): UpdateMap(self.map_fd, key, value) - firstKey = GetFirstKey(self.map_fd) - key = firstKey.value + first_key = GetFirstKey(self.map_fd) + key = first_key.value self.CheckAllMapEntry(key, TOTAL_ENTRIES - 1, value) - def testRdOnlyMap(self): self.map_fd = CreateMap(BPF_MAP_TYPE_HASH, KEY_SIZE, VALUE_SIZE, TOTAL_ENTRIES, map_flags=BPF_F_RDONLY) @@ -302,16 +358,18 @@ class BpfTest(net_test.NetworkTest): self.assertRaisesErrno(errno.ENOENT, LookupMap, self.map_fd, uid) SocketUDPLoopBack(packet_count, 4, self.prog_fd) self.assertEqual(packet_count, LookupMap(self.map_fd, uid).value) - DeleteMap(self.map_fd, uid); + DeleteMap(self.map_fd, uid) SocketUDPLoopBack(packet_count, 6, self.prog_fd) self.assertEqual(packet_count, LookupMap(self.map_fd, uid).value) + @unittest.skipUnless(HAVE_EBPF_ACCOUNTING, "Cgroup BPF is not fully supported") class BpfCgroupTest(net_test.NetworkTest): @classmethod def setUpClass(cls): + super(BpfCgroupTest, cls).setUpClass() cls._cg_dir = tempfile.mkdtemp(prefix="cg_bpf-") cmd = "mount -t cgroup2 cg_bpf %s" % cls._cg_dir try: @@ -326,10 +384,12 @@ class BpfCgroupTest(net_test.NetworkTest): @classmethod def tearDownClass(cls): os.close(cls._cg_fd) - subprocess.call(('umount %s' % cls._cg_dir).split()) + subprocess.call(("umount %s" % cls._cg_dir).split()) os.rmdir(cls._cg_dir) + super(BpfCgroupTest, cls).tearDownClass() def setUp(self): + super(BpfCgroupTest, self).setUp() self.prog_fd = -1 self.map_fd = -1 @@ -350,6 +410,7 @@ class BpfCgroupTest(net_test.NetworkTest): BpfProgDetach(self._cg_fd, BPF_CGROUP_INET_SOCK_CREATE) except socket.error: pass + super(BpfCgroupTest, self).tearDown() def testCgroupBpfAttach(self): self.prog_fd = BpfProgLoad(BPF_PROG_TYPE_CGROUP_SKB, INS_BPF_EXIT_BLOCK) @@ -371,8 +432,8 @@ class BpfCgroupTest(net_test.NetworkTest): self.assertRaisesErrno(errno.EPERM, SocketUDPLoopBack, 1, 4, None) self.assertRaisesErrno(errno.EPERM, SocketUDPLoopBack, 1, 6, None) BpfProgDetach(self._cg_fd, BPF_CGROUP_INET_EGRESS) - SocketUDPLoopBack( 1, 4, None) - SocketUDPLoopBack( 1, 6, None) + SocketUDPLoopBack(1, 4, None) + SocketUDPLoopBack(1, 6, None) def testCgroupBpfUid(self): self.map_fd = CreateMap(BPF_MAP_TYPE_HASH, KEY_SIZE, VALUE_SIZE, @@ -383,7 +444,8 @@ class BpfCgroupTest(net_test.NetworkTest): BpfFuncCall(BPF_FUNC_get_socket_uid) ] instructions += (INS_BPF_PARAM_STORE + BpfFuncCountPacketInit(self.map_fd) - + INS_CGROUP_ACCEPT + INS_PACK_COUNT_UPDATE + INS_CGROUP_ACCEPT) + + INS_CGROUP_ACCEPT + INS_PACK_COUNT_UPDATE + + INS_CGROUP_ACCEPT) self.prog_fd = BpfProgLoad(BPF_PROG_TYPE_CGROUP_SKB, instructions) BpfProgAttach(self.prog_fd, self._cg_fd, BPF_CGROUP_INET_INGRESS) packet_count = 20 @@ -405,31 +467,30 @@ class BpfCgroupTest(net_test.NetworkTest): if success: self.fail("Failed to create socket family=%d type=%d err=%s" % (family, socktype, os.strerror(e.errno))) - return; + return if not success: - self.fail("unexpected socket family=%d type=%d created, should be blocked" % - (family, socktype)) - + self.fail("unexpected socket family=%d type=%d created, should be blocked" + % (family, socktype)) def trySocketCreate(self, success): - for family in [socket.AF_INET, socket.AF_INET6]: - for socktype in [socket.SOCK_DGRAM, socket.SOCK_STREAM]: - self.checkSocketCreate(family, socktype, success) + for family in [socket.AF_INET, socket.AF_INET6]: + for socktype in [socket.SOCK_DGRAM, socket.SOCK_STREAM]: + self.checkSocketCreate(family, socktype, success) @unittest.skipUnless(HAVE_EBPF_SOCKET, - "Cgroup BPF socket is not supported") + "Cgroup BPF socket is not supported") def testCgroupSocketCreateBlock(self): instructions = [ BpfFuncCall(BPF_FUNC_get_current_uid_gid), BpfAlu64Imm(BPF_AND, BPF_REG_0, 0xfffffff), BpfJumpImm(BPF_JNE, BPF_REG_0, TEST_UID, 2), ] - instructions += INS_BPF_EXIT_BLOCK + INS_CGROUP_ACCEPT; + instructions += INS_BPF_EXIT_BLOCK + INS_CGROUP_ACCEPT self.prog_fd = BpfProgLoad(BPF_PROG_TYPE_CGROUP_SOCK, instructions) BpfProgAttach(self.prog_fd, self._cg_fd, BPF_CGROUP_INET_SOCK_CREATE) with net_test.RunAsUid(TEST_UID): # Socket creation with target uid should fail - self.trySocketCreate(False); + self.trySocketCreate(False) # Socket create with different uid should success self.trySocketCreate(True) BpfProgDetach(self._cg_fd, BPF_CGROUP_INET_SOCK_CREATE) |