Skip to content

Feature gap: three-color policers (RFC 2697/2698) implemented in eBPF, missing from userspace-dp #1375

@psaab

Description

@psaab

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-851struct policer_config with committed_rate, peak_rate, committed_burst, peak_burst for two-rate three-color
  • bpf/headers/xpf_helpers.h:1531Two-rate three-color (RFC 2698) evaluation
  • bpf/headers/xpf_helpers.h:1557Single-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-852PolicerModeTwoRate, 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/:

  1. Extend PolicerConfig (or add ThreeColorPolicerConfig) with peak_rate / peak_burst / excess_burst fields
  2. Implement RFC 2697 srTCM: C/E buckets with CIR fill, C overflow into E
  3. Implement RFC 2698 trTCM: C/P buckets, both filled independently at CIR/PIR
  4. Plumb three-color action (green/yellow/red) to DSCP-rewrite + discard decision
  5. Surface three-color policer snapshots through pkg/dataplane/userspace/protocol.go and policer_state in Rust
  6. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions