Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
ebpfCAT
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Martin Teichmann
ebpfCAT
Commits
597b01ee
Commit
597b01ee
authored
2 years ago
by
Martin Teichmann
Browse files
Options
Downloads
Patches
Plain Diff
use mmap for ebpf arrays
parent
1118f0d3
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
ebpfcat/arraymap.py
+17
-57
17 additions, 57 deletions
ebpfcat/arraymap.py
ebpfcat/bpf.py
+10
-3
10 additions, 3 deletions
ebpfcat/bpf.py
ebpfcat/ebpfcat.py
+2
-2
2 additions, 2 deletions
ebpfcat/ebpfcat.py
with
29 additions
and
62 deletions
ebpfcat/arraymap.py
+
17
−
57
View file @
597b01ee
...
...
@@ -16,19 +16,19 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from
itertools
import
chain
from
mmap
import
mmap
from
struct
import
pack_into
,
unpack_from
,
calcsize
from
.ebpf
import
FuncId
,
Map
,
Memory
Desc
from
.bpf
import
create_map
,
lookup_elem
,
MapType
,
update_elem
from
.ebpf
import
FuncId
,
Map
,
Memory
,
MemoryDesc
,
Opcode
,
SubProgram
from
.bpf
import
create_map
,
lookup_elem
,
MapType
,
MapFlags
,
update_elem
class
ArrayGlobalVarDesc
(
MemoryDesc
):
base_register
=
0
def
__init__
(
self
,
map
,
fmt
,
write
=
False
):
def
__init__
(
self
,
map
,
fmt
):
self
.
map
=
map
self
.
fmt
=
fmt
self
.
write
=
write
def
fmt_addr
(
self
,
ebpf
):
return
self
.
fmt
,
ebpf
.
__dict__
[
self
.
name
]
...
...
@@ -63,49 +63,16 @@ class ArrayGlobalVarDesc(MemoryDesc):
class
ArrayMapAccess
:
"""
This is the array map proper
"""
def
__init__
(
self
,
fd
,
write_size
,
size
):
self
.
fd
=
fd
self
.
write_size
=
write_size
def
__init__
(
self
,
data
,
size
):
self
.
data
=
data
self
.
size
=
size
self
.
data
=
bytearray
(
size
)
def
read
(
self
):
"""
read all variables in the map from EBPF to user space
"""
self
.
data
=
lookup_elem
(
self
.
fd
,
b
"
\0\0\0\0
"
,
self
.
size
)
def
write
(
self
):
"""
write all variables in the map from user space to EBPF
*all* variables are written, even those not marked ``write=True``
"""
update_elem
(
self
.
fd
,
b
"
\0\0\0\0
"
,
self
.
data
,
0
)
def
readwrite
(
self
):
"""
read variables from EBPF and write them out immediately
This reads all variables, swaps in the user-modified values for
the ``write=True`` variables, and writes the out again
immediately.
This means that even the read-only variables will be overwritten
with the values we have just read. If the EBPF program changed
the value in the meantime, that may be a problem.
Note that after this method returns, all *write* variables
will have the value from the EBPF program in user space, and
vice-versa.
"""
write
=
self
.
data
[:
self
.
write_size
]
data
=
lookup_elem
(
self
.
fd
,
b
"
\0\0\0\0
"
,
self
.
size
)
self
.
data
[:]
=
data
data
[:
self
.
write_size
]
=
write
update_elem
(
self
.
fd
,
b
"
\0\0\0\0
"
,
data
,
0
)
class
ArrayMap
(
Map
):
"""
A descriptor for an array map
"""
def
globalVar
(
self
,
fmt
=
"
I
"
,
write
=
False
):
return
ArrayGlobalVarDesc
(
self
,
fmt
,
write
)
def
globalVar
(
self
,
fmt
=
"
I
"
):
return
ArrayGlobalVarDesc
(
self
,
fmt
)
def
collect
(
self
,
ebpf
):
collection
=
[]
...
...
@@ -113,32 +80,25 @@ class ArrayMap(Map):
for
prog
in
chain
([
ebpf
],
ebpf
.
subprograms
):
for
k
,
v
in
prog
.
__class__
.
__dict__
.
items
():
if
isinstance
(
v
,
ArrayGlobalVarDesc
):
collection
.
append
((
v
.
write
,
calcsize
(
v
.
fmt
),
prog
,
k
))
collection
.
sort
(
key
=
lambda
t
:
t
[
:
2
],
reverse
=
True
)
collection
.
append
((
calcsize
(
v
.
fmt
),
prog
,
k
))
collection
.
sort
(
key
=
lambda
t
:
t
[
0
],
reverse
=
True
)
position
=
0
last_write
=
write
=
True
for
write
,
size
,
prog
,
name
in
collection
:
if
last_write
!=
write
:
position
=
(
position
+
7
)
&
-
8
write_size
=
position
for
size
,
prog
,
name
in
collection
:
prog
.
__dict__
[
name
]
=
position
position
+=
size
last_write
=
write
if
write
:
# there are read variables
return
position
,
position
else
:
return
write_size
,
position
return
position
def
__set_name__
(
self
,
owner
,
name
):
self
.
name
=
name
def
init
(
self
,
ebpf
):
setattr
(
ebpf
,
self
.
name
,
0
)
write_size
,
size
=
self
.
collect
(
ebpf
)
size
=
self
.
collect
(
ebpf
)
if
not
size
:
# nobody is actually using the map
return
fd
=
create_map
(
MapType
.
ARRAY
,
4
,
size
,
1
)
setattr
(
ebpf
,
self
.
name
,
ArrayMapAccess
(
fd
,
write_size
,
size
))
fd
=
create_map
(
MapType
.
ARRAY
,
4
,
size
,
1
,
MapFlags
.
MMAPABLE
)
data
=
mmap
(
fd
,
size
)
setattr
(
ebpf
,
self
.
name
,
ArrayMapAccess
(
data
,
size
))
with
ebpf
.
save_registers
(
list
(
range
(
6
))),
ebpf
.
get_stack
(
4
)
as
stack
:
ebpf
.
mI
[
ebpf
.
r10
+
stack
]
=
0
ebpf
.
r1
=
ebpf
.
get_fd
(
fd
)
...
...
This diff is collapsed.
Click to expand it.
ebpfcat/bpf.py
+
10
−
3
View file @
597b01ee
...
...
@@ -19,7 +19,7 @@
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
enum
import
Enum
from
enum
import
Enum
,
Flag
from
struct
import
pack
,
unpack
from
platform
import
machine
...
...
@@ -60,6 +60,10 @@ class MapType(Enum):
SOCKHASH
=
18
class
MapFlags
(
Flag
):
MMAPABLE
=
1
<<
10
class
ProgType
(
Enum
):
UNSPEC
=
0
SOCKET_FILTER
=
1
...
...
@@ -96,9 +100,12 @@ def bpf(cmd, fmt, *args):
raise
OSError
(
get_errno
(),
strerror
(
get_errno
()))
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
)
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
):
value
=
bytearray
(
size
)
...
...
This diff is collapsed.
Click to expand it.
ebpfcat/ebpfcat.py
+
2
−
2
View file @
597b01ee
...
...
@@ -175,7 +175,8 @@ class TerminalVar:
class
DeviceVar
(
ArrayGlobalVarDesc
):
def
__init__
(
self
,
size
=
"
I
"
,
write
=
False
):
super
().
__init__
(
FastSyncGroup
.
properties
,
size
,
write
)
super
().
__init__
(
FastSyncGroup
.
properties
,
size
)
self
.
write
=
write
def
__get__
(
self
,
instance
,
owner
):
if
instance
is
None
:
...
...
@@ -316,7 +317,6 @@ class FastEtherCat(SimpleEtherCat):
lastcounts
=
[
0
]
*
64
while
True
:
t0
=
time
()
self
.
ebpf
.
variables
.
read
()
counts
=
self
.
ebpf
.
counters
for
i
,
sg
in
self
.
sync_groups
.
items
():
if
((
counts
[
i
]
^
lastcounts
[
i
])
&
0xffff
==
0
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment