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 (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
| Property | Value |
|---|---|
| Minimum kernel | 5.15 (baseline minimum, not a special requirement) |
| Detection | test $(KERNEL_MAJOR) -gt 5 -o \( $(KERNEL_MAJOR) -eq 5 -a $(KERNEL_MINOR) -ge 15 \) |
| What it gates | XDP SYN-cookie challenge/validate stage (synproxy_mode) |
| Compiles to | the syncookie stage (kernel helpers bpf_tcp_raw_*_syncookie_*, 5.10+) |
| Below threshold | Compiles 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.
// 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
| Property | Value |
|---|---|
| Minimum kernel | 6.10 |
| Detection | test $(KERNEL_MAJOR) -gt 6 -o \( $(KERNEL_MAJOR) -eq 6 -a $(KERNEL_MINOR) -ge 10 \) |
| What it gates | SYN/FIN ratio detection + entropy spoofing detection |
| Compiles to | check_global_detection() function call |
| Below threshold | No-op — global detection stage skipped |
#ifdef OPENSHIELD_GLOBAL_DETECT
check_global_detection(cfg, now);
#endifWhy 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
| Property | Value |
|---|---|
| Minimum kernel | 6.10 |
| Detection | Same combined check as OPENSHIELD_GLOBAL_DETECT |
| What it gates | Per-packet entropy bucket updates |
| Compiles to | update_entropy_bucket() function call |
| Below threshold | No-op |
#ifdef OPENSHIELD_ENTROPY
update_entropy_bucket(&info);
#endifWhy 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 Gate | Kernel | Feature |
|---|---|---|
| (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_SYNPROXY | 5.15+ | Scalar, rate-based SYN gate (no cookies, no helpers) |
OPENSHIELD_GLOBAL_DETECT | 6.10+ | SYN/FIN ratio + entropy spoofing detection |
OPENSHIELD_ENTROPY | 6.10+ | Per-packet entropy bucket tracking |
Verification
Check enabled features at build time
make ebpf
# Output:
# ==> Compiling eBPF program (kernel 6.8.0)
# Features: -DOPENSHIELD_SYNPROXYThe Makefile prints which feature flags were detected and passed to the compiler.
Check available features at runtime
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
- Upgrade the kernel package (e.g.,
apt install linux-image-6.10-...) - Reboot into the new kernel
- Rebuild OpenShield-XDP:bash
cd /opt/openshield/src make clean && make all - 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_HASHper-CPU pre-allocation improvementsbpf_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.
