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.

XDP program example

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

Module configuration

Before an XDP

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:

  # 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
  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

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.
Clone this wiki locally