Skip to content
Snippets Groups Projects
Commit 46152e48 authored by Martin Teichmann's avatar Martin Teichmann
Browse files

add support for mmaped ArrayMaps

this is still rough
parent 1118f0d3
Branches mmap
No related tags found
No related merge requests found
...@@ -16,10 +16,11 @@ ...@@ -16,10 +16,11 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from itertools import chain from itertools import chain
from mmap import mmap
from struct import pack_into, unpack_from, calcsize from struct import pack_into, unpack_from, calcsize
from .ebpf import FuncId, Map, MemoryDesc from .ebpf import FuncId, Map, MemoryDesc
from .bpf import create_map, lookup_elem, MapType, update_elem from .bpf import create_map, lookup_elem, MapType, MapFlags, update_elem
class ArrayGlobalVarDesc(MemoryDesc): class ArrayGlobalVarDesc(MemoryDesc):
...@@ -63,22 +64,21 @@ class ArrayGlobalVarDesc(MemoryDesc): ...@@ -63,22 +64,21 @@ class ArrayGlobalVarDesc(MemoryDesc):
class ArrayMapAccess: class ArrayMapAccess:
"""This is the array map proper""" """This is the array map proper"""
def __init__(self, fd, write_size, size): def __init__(self, data, size):
self.fd = fd self.data = data
self.write_size = write_size
self.size = size self.size = size
self.data = bytearray(size) #self.data = bytearray(size)
def read(self): def read(self):
"""read all variables in the map from EBPF to user space""" """read all variables in the map from EBPF to user space"""
self.data = lookup_elem(self.fd, b"\0\0\0\0", self.size) #self.data = lookup_elem(self.fd, b"\0\0\0\0", self.size)
def write(self): def write(self):
"""write all variables in the map from user space to EBPF """write all variables in the map from user space to EBPF
*all* variables are written, even those not marked ``write=True`` *all* variables are written, even those not marked ``write=True``
""" """
update_elem(self.fd, b"\0\0\0\0", self.data, 0) #update_elem(self.fd, b"\0\0\0\0", self.data, 0)
def readwrite(self): def readwrite(self):
"""read variables from EBPF and write them out immediately """read variables from EBPF and write them out immediately
...@@ -95,6 +95,7 @@ class ArrayMapAccess: ...@@ -95,6 +95,7 @@ class ArrayMapAccess:
will have the value from the EBPF program in user space, and will have the value from the EBPF program in user space, and
vice-versa. vice-versa.
""" """
return
write = self.data[:self.write_size] write = self.data[:self.write_size]
data = lookup_elem(self.fd, b"\0\0\0\0", self.size) data = lookup_elem(self.fd, b"\0\0\0\0", self.size)
self.data[:] = data self.data[:] = data
...@@ -137,8 +138,9 @@ class ArrayMap(Map): ...@@ -137,8 +138,9 @@ class ArrayMap(Map):
write_size, size = self.collect(ebpf) write_size, size = self.collect(ebpf)
if not size: # nobody is actually using the map if not size: # nobody is actually using the map
return return
fd = create_map(MapType.ARRAY, 4, size, 1) fd = create_map(MapType.ARRAY, 4, size, 1, MapFlags.MMAPABLE)
setattr(ebpf, self.name, ArrayMapAccess(fd, write_size, size)) data = mmap(fd, size)
setattr(ebpf, self.name, ArrayMapAccess(data, size))
with ebpf.save_registers(list(range(6))), ebpf.get_stack(4) as stack: with ebpf.save_registers(list(range(6))), ebpf.get_stack(4) as stack:
ebpf.mI[ebpf.r10 + stack] = 0 ebpf.mI[ebpf.r10 + stack] = 0
ebpf.r1 = ebpf.get_fd(fd) ebpf.r1 = ebpf.get_fd(fd)
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
A module that wraps the `bpf` system call in Python, using `ctypes`. A module that wraps the `bpf` system call in Python, using `ctypes`.
""" """
from ctypes import CDLL, c_int, get_errno, cast, c_void_p, create_string_buffer, c_char_p, addressof, c_char from ctypes import CDLL, c_int, get_errno, cast, c_void_p, create_string_buffer, c_char_p, addressof, c_char
from enum import Enum from enum import Enum, Flag
from struct import pack, unpack from struct import pack, unpack
from platform import machine from platform import machine
...@@ -60,6 +60,10 @@ class MapType(Enum): ...@@ -60,6 +60,10 @@ class MapType(Enum):
SOCKHASH = 18 SOCKHASH = 18
class MapFlags(Flag):
MMAPABLE = 1 << 10
class ProgType(Enum): class ProgType(Enum):
UNSPEC = 0 UNSPEC = 0
SOCKET_FILTER = 1 SOCKET_FILTER = 1
...@@ -96,9 +100,12 @@ def bpf(cmd, fmt, *args): ...@@ -96,9 +100,12 @@ def bpf(cmd, fmt, *args):
raise OSError(get_errno(), strerror(get_errno())) raise OSError(get_errno(), strerror(get_errno()))
return ret, unpack(fmt, attr.raw) return ret, unpack(fmt, attr.raw)
def create_map(map_type, key_size, value_size, max_entries): def create_map(map_type, key_size, value_size, max_entries,
attributes=MapFlags(0)):
assert isinstance(map_type, MapType) assert isinstance(map_type, MapType)
return bpf(0, "IIII", map_type.value, key_size, value_size, max_entries)[0] assert isinstance(attributes, MapFlags)
return bpf(0, "IIIII", map_type.value, key_size, value_size, max_entries,
attributes.value)[0]
def lookup_elem(fd, key, size): def lookup_elem(fd, key, size):
value = bytearray(size) value = bytearray(size)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment