-
Notifications
You must be signed in to change notification settings - Fork 5
Using the linux rex module
To work with regular expressions in the eBPF, these three components are required:
- Patched Linux kernel
- Hyperscan userspace tools or library
- Hyperscan kernel module
See the Installation page for more details about kernel patches and installation steps.
When loaded, xdp_rex.ko
exposes two helpers to XDP programs:
#include "rex.h"
int bpf_scan_bytes(const void *buf, __u32 buf__sz,
struct rex_scan_attr *scan_attr);
int bpf_xdp_scan_bytes(struct xdp_md *xdp_md, __u32 offset, __u32 len,
struct rex_scan_attr *scan_attr);
The bpf_scan_bytes
receives any linear buffer to scan through the pointer.
Unfortunately, the eBPF verifier cannot prove the safety of variable-sized packet memory access.
To trick around this limitation, we provide a second helper, bpf_xdp_scan_bytes
, that takes XDP context and packet offsets.
Both forms take input/output attributes:
-
rex_scan_attr->database_id
: an identifier of a pattern compiled and loaded into the module usingconfigfs
. We will cover this below. -
rex_scan_attr->handler_flags
:match_callback
's behaviour flags. Currently, the only option isREX_SINGLE_SHOT
when the engine stops on the very first match.
Other struct rex_scan_attr
fields are filled with match results.
Return values:
-
-errno
in case of failures, -
0
if the whole buffer was scanned -
1
if scanning was terminated eagerly.
Note that programs linked with that helpers won't load without
xdp_rex
module.
#include "rex.h"
SEC("xdp")
int dummy(struct xdp_md *xdp)
{
struct rex_scan_attr attr = {};
attr.database_id = 1234;
__u32 len = xdp->data_end - xdp->data;
return bpf_xdp_scan_bytes(xdp, 0, len, &attr);
}
Before the XDP program can use regular expressions, they must be compiled and loaded to the module via the configfs
interface.
The resulting regex identifier must be passed to the eBPF program to use the compiled database.
To load a new database to the module, a user can create a new knob in the configfs directory - /sys/kernel/config/rex/<pattern_name>
.
The name of the knob may be any, but we recommend using meaningful names.
Every knob has entities:
- id (rw): the unique identifier of a regular expression. It may be set by a user or dynamically generated by the module (default).
- database (rw): a regular expression compiled by the Hyperscan tools
- epoch (ro): update the database counter. Zero after knob creation, non-zero after setting the database
- note (rw): an auxiliary text string. We recommend putting a text representation of the database (before compilation) to review, what is loaded.
Insert the module first.
modprobe xdp_rex.ko
Create a file that contains all the regular expressions that should be evaluated simultaneously for the same buffer.
echo '101:/foobar/' > patterns.txt
echo '201:/a{3,10}/' >> patterns.txt
Compile regular expressions:
rm -rf out/ && mkdir out
hscollider -e patterns.txt -ao out/ -n1
Load the patterns into the kernel module:
mkdir /sys/kernel/config/rex/foobar
dd if=$(echo out/``.db) of=/sys/kernel/config/rex/foobar/database
cat patterns.txt > /sys/kernel/config/rex/foobar/note
Optionally verify the loaded database:
cat /sys/kernel/config/rex/hello/epoch # -> 1
diff /sys/kernel/config/rex/hello/database out/``.db
cat /sys/kernel/config/rex/foobar/note
A user-defined identifier can be used for the regular expression.
cat 1234 > /sys/kernel/config/rex/hello/id
Verify the examples for the correctness of the loaded generation:
bpftool prog load dummy.o /sys/fs/bpf/dummy
echo 'xxx foobar yyy' > data.txt
bpftool prog run pinned /sys/fs/bpf/dummy data_in data.txt repeat 1
The following conditions must be met before the module can be unloaded:
- All the regular expression databases are removed, and the
/sys/kernel/config/rex
is empty, - No eBPF programs linked with helper left loaded.