Skip to content

Pr/daniel noland/user acls dpdk rework#1639

Closed
daniel-noland wants to merge 15 commits into
pr/qmonnet/user-aclsfrom
pr/daniel-noland/user-acls-dpdk-rework
Closed

Pr/daniel noland/user acls dpdk rework#1639
daniel-noland wants to merge 15 commits into
pr/qmonnet/user-aclsfrom
pr/daniel-noland/user-acls-dpdk-rework

Conversation

@daniel-noland

Copy link
Copy Markdown
Collaborator

No description provided.

qmonnet and others added 10 commits July 16, 2026 10:09
This is so we can use one protocol, or "any protocol" (by ranging on all
existing values) in ACL tables to apply filtering rules to packets.

Signed-off-by: Quentin Monnet <qmo@qmon.net>
No need to clone the enum variants.

Signed-off-by: Quentin Monnet <qmo@qmon.net>
Add a way to return the ValidatedAcl object attached to a
ValidatedPeering, if any. We'll use it to process the ACL rules in a
future commit.

Signed-off-by: Quentin Monnet <qmo@qmon.net>
There's no point in allowing an empty list in the first place: remove
the ACL list (to allow all), or the peering altogether (to deny all).
This will also avoid the corner case of an empty list when building the
context for the ACLs.

Signed-off-by: Quentin Monnet <qmo@qmon.net>
ICMP doesn't really deserve any specific treatment internally, as we can
trivially implement it with AclProtoMatch::Other(1).

Signed-off-by: Quentin Monnet <qmo@qmon.net>
User can specify manual protocol values in the CRD. When they specify 6
or 17, this means TCP or UDP, respectively; but we have dedicated
AclProtoMatch enum variants for these protocols. Convert the relevant
numerical value into the TCP/UDP variants.

Signed-off-by: Quentin Monnet <qmo@qmon.net>
Add a new crate containing the implementation for the user ACLs: list of
access control rules that allow or deny specific packets or flow. We
recently introduced support for parsing and validating user ACL objects;
The new pipeline stage builds up context tables from validated ACLs, and
then apply the rules on coming packets.

With the "scope: flow" option, reply traffic for authorized flows is
automatically allowed as well (unless another explicit rule denies it).
This mode should be extended to all NAT modes (including no-NAT) in the
future, but is only supported with masquerade and port forwarding at
this time.

Signed-off-by: Quentin Monnet <qmo@qmon.net>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Quentin Monnet <qmo@qmon.net>
Add unit tests to validate the behaviour of the new ACL filter pipeline
stage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Quentin Monnet <qmo@qmon.net>
Add a pipeline stage with the recently-added ACL filter to the main
pipeline, so that users can enforce ACLs on the traffic.

Signed-off-by: Quentin Monnet <qmo@qmon.net>
@daniel-noland
daniel-noland changed the base branch from main to pr/qmonnet/user-acls July 17, 2026 08:11
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9d7378c0-2c25-4a2f-8f43-252948c67a59

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@daniel-noland daniel-noland self-assigned this Jul 17, 2026
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/user-acls-dpdk-rework branch from 435cfeb to 36c41f7 Compare July 17, 2026 10:02
daniel-noland and others added 4 commits July 17, 2026 04:20
…Lookup

Add a non-default `reference` cargo feature and gate the linear-scan reference backend behind it, so production builds
link only the rte_acl backend. Share `DpdkAclLookup` via `Arc<dyn DynClassifier>` and derive `Clone` so a built
classifier can be cheaply shared across pipeline workers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Daniel Noland <daniel@githedgehog.com>
The ACL filter builds rte_acl classifiers when configuration is applied,
which needs the EAL memory subsystem up. Initialize a minimal EAL (no
hugepages / no PCI) early in `dataplane::main`, before `run_mgmt` applies
the first config; the guard is held for the process. The real DPDK datapath
driver must eventually take over EAL ownership (there is one `rte_eal_init`
per process). The mgmt config-processor test starts the EAL for the same
reason.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Daniel Noland <daniel@githedgehog.com>
…e per IP version

rte_acl requires the first key field to be a single byte, but the tuple keys led
with a u32 VNI. Restructure to a single `AclKey<I>` per IP version whose first
field is a `#[mask]` protocol byte: it satisfies the one-byte-first-field rule and
carries the protocol match in the key (exact via mask 0xff, any via mask 0x00).

This collapses the six per-protocol tables (tcp/udp/other x v4/v6) into two
(v4/v6) and removes the duplication of every `Any` rule across protocols. All
rules for an IP version now live in one ordered table, so first-match precedence
holds across protocol kinds, not just within a protocol's table. Config
validation forbids ports on non-TCP/UDP protocols, so those rules always carry a
wildcard port range.

Lower `AclProtoMatch` to `MaskSpec<u8>` (replacing the now-unused RangeSpec
conversion). Rules are still lowered via the backend-neutral `Erased` path; this
only changes the key shape so it is rte_acl-installable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Replace the reference (linear-scan) tables with rte_acl `DpdkAclLookup` tables in
production, keeping the reference backend as a cfg(test) differential oracle.

- Introduce `AnyTable { Empty, Dpdk, Reference }` per IP version: `Empty` avoids
  building a zero-rule rte_acl context, `Dpdk` is production, `Reference` is the
  test/opt-in oracle. Rules are lowered once to backend-neutral predicates and the
  selected `Backend` consumes them.
- Positional first-match: rte_acl returns the highest-priority match, so rules are
  installed with priority descending by insertion index (rule 0 wins). This
  reproduces the reference backend's first-match-on-insertion-order precedence.
- Fallible build threads through `ConfigError`; `TryFrom` uses the dpdk backend
  (EAL initialised early in dataplane::main), and `for_test`/`for_test_dpdk` select
  a backend for tests.
- Each rte_acl context gets a process-unique name (a hot-swap briefly keeps the old
  and new contexts alive).
- Display shows per-table rule counts in production (opaque classifier) and the
  full per-rule dump in test builds (reference backend retains the rules).

The semantic suite runs on the reference backend (fast, EAL-free); a new
`#[dpdk::with_eal]` differential test builds the same overlay on both backends and
asserts identical verdicts, proving the rte_acl path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Daniel Noland <daniel@githedgehog.com>
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/user-acls-dpdk-rework branch from 36c41f7 to b69b634 Compare July 17, 2026 10:20
@daniel-noland
daniel-noland marked this pull request as ready for review July 17, 2026 10:22
@daniel-noland
daniel-noland requested a review from a team as a code owner July 17, 2026 10:22
@daniel-noland
daniel-noland requested review from mvachhar and removed request for a team July 17, 2026 10:22
Under the loom backend, concurrency::sync::atomic::{AtomicU32,
AtomicU64}::new is not const: each instance registers with the loom
executor, so it cannot initialize a "static". This makes "cargo check
--features loom --workspace --tests --benches" fail with E0015 ("cannot
call non-const associated function ... in statics").

This is a consequence of a recent commit where we flipped acl's default
features from [] to ["dpdk"]. Every atomic static involved lives behind
'feature = "dpdk"' -- the integration tests and bench module, and the
lib's #[cfg(all(test, feature = "dpdk"))] modules. With dpdk off by
default they were compiled out and never seen by the loom backend;
turning dpdk on by default brings them into every build, including the
loom one.

Wrap each in LazyLock<Atomic..> so the initializer runs on first use
instead of at compile time. The value is still the backend atomic, so
"fetch_add" stays loom-instrumented; only the const requirement on
construction is removed. These are process-unique name/sequence counters
on cold paths, so the one-time lazy init is negligible, and on every
non-loom backend LazyLock merely wraps an otherwise-const atomic.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Quentin Monnet <qmo@qmon.net>
@qmonnet
qmonnet force-pushed the pr/daniel-noland/user-acls-dpdk-rework branch from 5a7b396 to fba60ac Compare July 17, 2026 11:48
@qmonnet

qmonnet commented Jul 17, 2026

Copy link
Copy Markdown
Member

This passes CI! 🎉 although dataplane-acl::property_predicate property_v6 for job sanitize/fuzz/thread seems to have become brittle, but I'll probably leave it for Daniel to fix.

I'll squash the acl-filter changes into my own commits, in the initial PR.

@qmonnet qmonnet added the dont-merge Do not merge this Pull Request label Jul 17, 2026
@qmonnet
qmonnet force-pushed the pr/qmonnet/user-acls branch from b63f9f3 to ee23168 Compare July 17, 2026 15:57
@qmonnet qmonnet removed the dont-merge Do not merge this Pull Request label Jul 17, 2026
@qmonnet
qmonnet force-pushed the pr/qmonnet/user-acls branch from 6f5a544 to 6bf22e6 Compare July 20, 2026 12:58
@qmonnet
qmonnet marked this pull request as draft July 20, 2026 16:33
@qmonnet

qmonnet commented Jul 20, 2026

Copy link
Copy Markdown
Member

Closing in favour of #1634

@qmonnet qmonnet closed this Jul 20, 2026
@qmonnet
qmonnet deleted the pr/daniel-noland/user-acls-dpdk-rework branch July 20, 2026 22:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants