Skip to content

Kernel Feature Gates

OpenShield-XDP uses compile-time feature gates to enable or disable functionality based on the running kernel version. This allows a single codebase to support kernels from 5.15 through 6.10+ while leveraging newer BPF features when available.

How It Works

The top-level Makefile detects the running kernel version via uname -r and sets C preprocessor defines (-D flags) passed to both the eBPF compiler (clang) and the Go binding generator (bpf2go):

makefile
# Makefile (top-level)
KERNEL_VER := $(shell uname -r | cut -d. -f1,2)
KERNEL_MAJOR := $(word 1,$(subst ., ,$(KERNEL_VER)))
KERNEL_MINOR := $(word 2,$(subst ., ,$(KERNEL_VER)))

BPF_FEATURES := -D__TARGET_ARCH_x86 -D_GNU_SOURCE

# Feature-specific gates added conditionally...

Build-time only

Feature gates are evaluated at build time, not at runtime. If you upgrade your kernel, you must rebuild OpenShield-XDP to enable newly available features. Running uname -r during the build determines what gets compiled in.

Feature Gates

OPENSHIELD_SYNPROXY

PropertyValue
Minimum kernel5.15 (baseline minimum, not a special requirement)
Detectiontest $(KERNEL_MAJOR) -gt 5 -o \( $(KERNEL_MAJOR) -eq 5 -a $(KERNEL_MINOR) -ge 15 \)
What it gatesXDP SYN-cookie challenge/validate stage (synproxy_mode)
Compiles tothe syncookie stage (kernel helpers bpf_tcp_raw_*_syncookie_*, 5.10+)
Below thresholdCompiles out entirely — SYN handling falls back to the rate limiter (also the pre-6.9 base build's behavior)

Since v2.14 the stage generates and validates real SYN cookies using the kernel's own syncookie helpers — no version-specific helpers beyond the 5.15 floor and no per-connection state, so it verifies identically everywhere. Actual cookie scoring backup remains the per-IP syn_pps_threshold rate limiter, which runs in every mode.

L7 signatures — not gated (all 16 slots, every kernel)

The L7 signature matcher is not behind a kernel gate. It always compiles a single #pragma unroll loop over all 16 slots of l7_sig_map, and this verifies and loads on every supported kernel from 5.15. There is no "slot 0 only" mode.

c
// openshield.bpf.c — always compiled, all kernels
#pragma unroll
for (u32 i = 0; i < 16; i++) { /* check l7_sig_map[i] */ }

Note

Earlier builds shipped an OPENSHIELD_L7_MULTISLOT flag intended to gate slots 1-15 at kernel 6.10. The flag was never referenced by the BPF source (the loop was always 16 slots), so it has been removed to avoid a misleading, dead build gate. L7 protection is identical on every supported kernel.

OPENSHIELD_GLOBAL_DETECT

PropertyValue
Minimum kernel6.10
Detectiontest $(KERNEL_MAJOR) -gt 6 -o \( $(KERNEL_MAJOR) -eq 6 -a $(KERNEL_MINOR) -ge 10 \)
What it gatesSYN/FIN ratio detection + entropy spoofing detection
Compiles tocheck_global_detection() function call
Below thresholdNo-op — global detection stage skipped
c
#ifdef OPENSHIELD_GLOBAL_DETECT
    check_global_detection(cfg, now);
#endif

Why kernel ≥ 6.10? Global detection uses bpf_for_each_map_elem for iterating entropy buckets and SYN/FIN counters, which requires kernel 5.13+. The 6.10 gate is conservative — it also covers the combined verifier complexity of global detection + entropy together.

OPENSHIELD_ENTROPY

PropertyValue
Minimum kernel6.10
DetectionSame combined check as OPENSHIELD_GLOBAL_DETECT
What it gatesPer-packet entropy bucket updates
Compiles toupdate_entropy_bucket() function call
Below thresholdNo-op
c
#ifdef OPENSHIELD_ENTROPY
    update_entropy_bucket(&info);
#endif

Why kernel ≥ 6.10? Per-packet entropy tracking uses bpf_get_prandom_u32() for bucket selection and requires spinlock-free per-CPU hash bucket updates. The verifier in older kernels would reject the complexity.

Feature Gate Summary

Feature GateKernelFeature
(none required)5.15+Core pipeline: MAC filter, parse, panic breaker, whitelist, ban check, validation, L4, UDP amp, L7 (16 slots), IP stats, new-source flood, connection tracking, window reset, rate limiting
OPENSHIELD_SYNPROXY5.15+Scalar, rate-based SYN gate (no cookies, no helpers)
OPENSHIELD_GLOBAL_DETECT6.10+SYN/FIN ratio + entropy spoofing detection
OPENSHIELD_ENTROPY6.10+Per-packet entropy bucket tracking

Verification

Check enabled features at build time

bash
make ebpf
# Output:
# ==> Compiling eBPF program (kernel 6.8.0)
#     Features: -DOPENSHIELD_SYNPROXY

The Makefile prints which feature flags were detected and passed to the compiler.

Check available features at runtime

bash
openshield status --features
# Output:
#   Kernel: 6.8.0-45-generic
#   SYNPROXY: enabled
#   Global Detection: disabled (need kernel >= 6.10)
#   Entropy: disabled (need kernel >= 6.10)

The CLI reads the compiled-in feature set from the BPF program's BTF and reports which features are active.

Upgrading Your Kernel

  1. Upgrade the kernel package (e.g., apt install linux-image-6.10-...)
  2. Reboot into the new kernel
  3. Rebuild OpenShield-XDP:
    bash
    cd /opt/openshield/src
    make clean && make all
  4. Restart the loader:
    bash
    systemctl restart openshield-loader

The rebuilt binary will auto-detect the new kernel version and enable all compatible features.

Base Minimum

OpenShield-XDP requires kernel ≥ 5.15 as the absolute minimum. Below 5.15, several core BPF features are unavailable:

  • BPF_MAP_TYPE_LRU_HASH per-CPU pre-allocation improvements
  • bpf_ktime_get_boot_ns() precision
  • Various verifier improvements needed for the pipeline complexity

Attempting to build on a kernel below 5.15 will result in compilation errors.