(10) feat(match-action): MatchKey trait + derive + bolero generators#1574
(10) feat(match-action): MatchKey trait + derive + bolero generators#1574daniel-noland wants to merge 2 commits into
Conversation
Lands the match-action key vocabulary plus its derive. Backends in downstream PRs consume the result via a structural FIELD_SPECS view and a byte-packing as_key_into(); the bolero property-test generators land next as their own feature gate. match-action/src/: - lib.rs publishes the FieldKind enum (Prefix / Mask / Range / Exact), the FieldSpec layout record (name / kind / size / offset), and the MatchKey trait (N, KEY_SIZE, field_specs(), as_key_into()). Trait methods take slices rather than Self::N-sized arrays because Self::N in a trait fn needs unstable generic_const_exprs; the derive emits sized inherent helpers on concrete types instead. - field.rs is a thin re-export of FixedSize from the fixed-size crate, so consumers can refer to it via match_action::FixedSize. - predicate.rs holds the type-erased FieldPredicate form (Prefix, Mask, Range, Exact variants over FieldBytes) plus the Erased backend marker used by the reference oracle. - rule.rs defines the four kind-typed *Spec wrappers (PrefixSpec, MaskSpec, RangeSpec, ExactSpec), the Backend / Accepts / IntoBackendField / IsUniversal traits, and the RuleField envelope carrying name / spec. match-action-derive (proc-macro crate) emits, from a struct annotated with #[prefix] / #[mask] / #[range] / #[exact]: - the MatchKey impl, - a parallel <Name>Rule struct holding the typed *Spec data, - an inherent FIELD_SPECS const for compile-time inspection by downstream backends, and - (for non-generic structs) an inherent as_key() -> [u8; KEY_SIZE] for ergonomic byte packing. tests/derive_roundtrip.rs exercises a 5-tuple-shaped key covering all four predicate kinds: asserts N, KEY_SIZE, the field_specs() content, and that as_key_into / as_key produce the expected big-endian byte layout (with declared field ordering preserved). just fmt; cargo check --workspace --all-targets passes.
Adds property-test generators over the rule wrappers, behind a new `bolero` feature gate so the bolero dep stays out of the default build graph. Downstream consumers (acl property tests, future cascade Upsert-laws harnesses) enable the feature in their dev-deps and draw random matching / non-matching packets for any single rule. match-action/src/generator.rs: - FieldHit / FieldMiss TypeGenerators yielding bytes that satisfy / violate a given field predicate. Cover all four predicate kinds: Prefix (any address sharing the rule's high-order bits / one with flipped bits in that prefix), Mask (value bits match / a flipped in-mask bit), Range (uniform draw in [min, max] / outside the bounds), Exact (the value / a different value). - Miss generators skip universal predicates (range covering all values, mask of all zeros, prefix length zero, etc.); the derive-emitted IsUniversal check on <Name>Rule lets callers detect whole rules that have an empty miss set. match-action/src/lib.rs picks up #[cfg(feature = "bolero")] gates on the generator mod + its FieldHit / FieldMiss re-exports. match-action/Cargo.toml grows the bolero optional dep and the `bolero` feature, which also turns on the matching forwarded feature on match-action-derive (a no-op today, kept for future emit changes in the derive). match-action-derive/Cargo.toml mirrors the `bolero` feature declaration so cargo can forward through. just fmt; cargo check --workspace --all-targets and cargo check -p dataplane-match-action --features bolero pass.
There was a problem hiding this comment.
Pull request overview
Adds the match-action core crate and derive macro, providing typed field/rule specs, erased predicates, MatchKey derivation, and bolero-based field generators for future ACL and cascade layers.
Changes:
- Introduces
dataplane-match-actionwithMatchKey, field specs, predicates, rule specs, and generator support. - Adds
dataplane-match-action-deriveproc macro for deriving key layout and companion rule structs. - Adds workspace registration, lockfile entries, and derive/generator roundtrip tests.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
Cargo.toml |
Registers match-action crates and package metadata. |
Cargo.lock |
Adds lock entries for the new crates. |
match-action/Cargo.toml |
Defines crate dependencies and feature flags. |
match-action/src/lib.rs |
Exposes public match-action API types and traits. |
match-action/src/field.rs |
Re-exports FixedSize. |
match-action/src/rule.rs |
Adds rule field specs and universal checks. |
match-action/src/predicate.rs |
Adds erased predicate matching and conversions. |
match-action/src/generator.rs |
Adds bolero hit/miss generators for field predicates. |
match-action/tests/derive_roundtrip.rs |
Tests derive layout, packing, rules, and generics. |
match-action-derive/Cargo.toml |
Defines proc-macro crate dependencies/features. |
match-action-derive/src/lib.rs |
Implements #[derive(MatchKey)]. |
|
|
||
| #[test] | ||
| fn ipv6_prefix_hits_on_high_chunk() { | ||
| let spec = PrefixSpec::new("2001:db8::".parse::<Ipv6Addr>().unwrap(), 32); |
| impl_specs_for!(u32, u32, high_mask_u32); | ||
| impl_specs_for!(u64, u64, high_mask_u64); | ||
| impl_specs_for!(Ipv4Addr, u32, high_mask_u32); | ||
| impl_specs_for!(Ipv6Addr, u128, high_mask_u128); |
| let lo = be_to_u32(min); | ||
| let hi = be_to_u32(max); | ||
| let v = (lo..=hi).generate(d)?; | ||
| Some(u32_to_be(v, min.len())) |
mvachhar
left a comment
There was a problem hiding this comment.
I love the use of the macro, I hate the definition since it is really hard to understand, but that is the nature of these macros I suppose.
Copilot has some things that should be addressed.
Also, your FiveTuple doc example should be ThreeTuple or expanded to an actual FiveTuple.
I also feel like the macro testing is light, but that might be ok if we are mainly just using a single data type for most of dataplane. We can fix bugs later as we add more data types, assuming bugs crop up.
| //! | ||
| //! ```ignore | ||
| //! #[derive(MatchKey)] | ||
| //! struct FiveTuple { |
There was a problem hiding this comment.
Why is this a FiveTuple, it is a ThreeTuple match.
Stack (10). Base:
pr/daniel-noland/fixed-size-lookup.The match-action core: the trait + derive macro that everything keys off, plus
its property-test generators.
feat(match-action):MatchKeytrait +#[derive(MatchKey)]proc-macro.feat(match-action): boleroFieldHit/FieldMissgenerators.Review focus: derive semantics and generator coverage, in isolation from ACL.
Review stack (merge bottom -> top):