Gap
The eBPF dataplane implements two-rate three-color (RFC 2698, POLICER_MODE_TWO_RATE) and single-rate three-color (RFC 2697, POLICER_MODE_SR3C) policers in xpf_helpers.h:1487+. The userspace dataplane has only single-rate two-color policers. Configs with firewall three-color-policer ... are explicitly rejected by the userspace capability gate.
eBPF implementation (source of truth)
bpf/headers/xpf_common.h:830-851 — struct policer_config with committed_rate, peak_rate, committed_burst, peak_burst for two-rate three-color
bpf/headers/xpf_helpers.h:1531 — Two-rate three-color (RFC 2698) evaluation
bpf/headers/xpf_helpers.h:1557 — Single-rate three-color (RFC 2697): CIR fills C, C overflow fills E
pkg/dataplane/compiler_filter.go:57-87 — compiles ThreeColorPolicers from config into BPF maps
pkg/dataplane/types.go:851-852 — PolicerModeTwoRate, PolicerModeSR3C constants
pkg/dataplane/userspace/manager.go:767-768 — capability gate: if len(cfg.Firewall.ThreeColorPolicers) > 0 { addReason(...) }
Userspace-dp gap
Searched: grep -rn 'three.color\\|three_color\\|ThreeColor' userspace-dp/src/ — zero matches.
userspace-dp/src/filter/ implements only flat rate + burst (single-rate two-color via token_bucket.rs).
Recommended fix
In userspace-dp/src/filter/:
- Extend
PolicerConfig (or add ThreeColorPolicerConfig) with peak_rate / peak_burst / excess_burst fields
- Implement RFC 2697 srTCM: C/E buckets with CIR fill, C overflow into E
- Implement RFC 2698 trTCM: C/P buckets, both filled independently at CIR/PIR
- Plumb three-color action (green/yellow/red) to DSCP-rewrite + discard decision
- Surface three-color policer snapshots through
pkg/dataplane/userspace/protocol.go and policer_state in Rust
- Remove the
cfg.Firewall.ThreeColorPolicers gate in pkg/dataplane/userspace/manager.go:767
Blocker for #1373
This must land before Phase 4 (BPF source removal) of #1373 (retire eBPF dataplane). Currently the userspace capability gate falls back to the eBPF dataplane when this config is set.
Refined contract (added 2026-05-17 after triple-review of #1384)
See docs/pr/1373-retire-ebpf-dataplane/plan-1375-three-color-policers.md for the full implementation contract refined through 4 rounds of Claude+Codex+Gemini Pro 3 review. New since the original issue body:
- Risks called out: token overflow/math (refill mul stays in u128 or saturates before packet-size conversion), atomicity (per-policer sharded state must avoid cross-worker false sharing while keeping one logical bucket per identity), color semantics (color-aware mode must never promote yellow/red — one wrong branch turns security into bandwidth grant), counter attribution (green/yellow/red/drop counters survive snapshot rebuilds by stable identity).
- Required test added: Go
deriveUserspaceCapabilities() admits three-color policer configs only after userspace snapshot + Rust runtime support are wired, and rejects them before that point.
Gap
The eBPF dataplane implements two-rate three-color (RFC 2698,
POLICER_MODE_TWO_RATE) and single-rate three-color (RFC 2697,POLICER_MODE_SR3C) policers inxpf_helpers.h:1487+. The userspace dataplane has only single-rate two-color policers. Configs withfirewall three-color-policer ...are explicitly rejected by the userspace capability gate.eBPF implementation (source of truth)
bpf/headers/xpf_common.h:830-851—struct policer_configwithcommitted_rate,peak_rate,committed_burst,peak_burstfor two-rate three-colorbpf/headers/xpf_helpers.h:1531—Two-rate three-color (RFC 2698)evaluationbpf/headers/xpf_helpers.h:1557—Single-rate three-color (RFC 2697): CIR fills C, C overflow fills Epkg/dataplane/compiler_filter.go:57-87— compiles ThreeColorPolicers from config into BPF mapspkg/dataplane/types.go:851-852—PolicerModeTwoRate,PolicerModeSR3Cconstantspkg/dataplane/userspace/manager.go:767-768— capability gate:if len(cfg.Firewall.ThreeColorPolicers) > 0 { addReason(...) }Userspace-dp gap
Searched:
grep -rn 'three.color\\|three_color\\|ThreeColor' userspace-dp/src/— zero matches.userspace-dp/src/filter/implements only flat rate + burst (single-rate two-color viatoken_bucket.rs).Recommended fix
In
userspace-dp/src/filter/:PolicerConfig(or addThreeColorPolicerConfig) with peak_rate / peak_burst / excess_burst fieldspkg/dataplane/userspace/protocol.goandpolicer_statein Rustcfg.Firewall.ThreeColorPolicersgate inpkg/dataplane/userspace/manager.go:767Blocker for #1373
This must land before Phase 4 (BPF source removal) of #1373 (retire eBPF dataplane). Currently the userspace capability gate falls back to the eBPF dataplane when this config is set.
Refined contract (added 2026-05-17 after triple-review of #1384)
See
docs/pr/1373-retire-ebpf-dataplane/plan-1375-three-color-policers.mdfor the full implementation contract refined through 4 rounds of Claude+Codex+Gemini Pro 3 review. New since the original issue body:deriveUserspaceCapabilities()admits three-color policer configs only after userspace snapshot + Rust runtime support are wired, and rejects them before that point.