Skip to content

Using the linux rex module

Ivan Koveshnikov edited this page Oct 21, 2022 · 4 revisions

To work with regular expressions in the eBPF these 3 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.

eBPF API

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 eBPF verifier cannot prove 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 using configfs, we will cover this below.
  • rex_scan_attr->handler_flags: match_callback's behaviour flags. Currently the only option is REX_SINGLE_SHOT, when 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.

Module configuration

Configuration plane must compile and upload regular expressions beforehand and tell BPF program identifier taken from /sys/kernel/config/rex/<pattern_name>/id.

Example runbook

Configure sample database:

.. code-block:: bash

Insert module

insmod xdp_rex.ko

Compile pattern database

rm -rf out/ && mkdir out echo '101:/foobar/' > patterns.txt echo '201:/a{3,10}/' >> patterns.txt build/bin/hscollider -e patterns.txt -ao out/ -n1

Create database slot

mkdir /sys/kernel/config/rex/hello

Check the current DB version on the slot

cat /sys/kernel/config/rex/hello/epoch # -> 0

Upload compiled database into kernel

dd if=$(echo out/``.db) of=/sys/kernel/config/rex/hello/database

Check if database was accepted by the kernel

cat /sys/kernel/config/rex/hello/epoch # -> 1

Read database back and compare it with compiled one

diff /sys/kernel/config/rex/hello/database out/``.db

Assign our own ID to the database

cat 1234 > /sys/kernel/config/rex/hello/id

.. code-block:: c

#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); }

.. code-block:: bash

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

Unloading xdp_rex module

To unload module the following conditions must met:

  • /sys/kernel/config/rex is emtpy,
  • there are no bpf programs linked with helper left.

XDP example

Clone this wiki locally