Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9aaf1d8
fix(flow-entry): Add an insertion that will not displace a live flow
daniel-noland Aug 7, 2026
0b0046f
feat(config): Generate port-forwarding exposes for property tests
daniel-noland Aug 7, 2026
5905bb1
feat(config): Generate masquerade exposes, and share the overlay arou…
daniel-noland Aug 7, 2026
7b6b416
feat(config): Generate static NAT exposes, and pin the mapping is a b…
daniel-noland Aug 7, 2026
06ce0dc
fix(config): Refuse a port-forwarding expose the dataplane cannot build
daniel-noland Aug 7, 2026
bc26967
test(mgmt): Property-test the configuration chain, and unblock its ge…
daniel-noland Aug 7, 2026
91c46a2
test(mgmt): Drive the config builder with generated NAT peerings
daniel-noland Aug 7, 2026
f33fc25
test(k8s-intf): Generate configurations that are valid by construction
daniel-noland Aug 7, 2026
fc3630e
test(k8s-intf): Generate peering ACLs
daniel-noland Aug 7, 2026
a9a2943
test(mgmt): Build every dataplane table a validated config implies
daniel-noland Aug 7, 2026
4001ca8
test(config): Hunt validator permissiveness with near-miss configurat…
daniel-noland Aug 8, 2026
229ad76
test(mgmt): Let a fuzzing engine drive the near-miss property
daniel-noland Aug 8, 2026
e2821d0
test(k8s-intf): Draw prefixes from slots so exposes cannot overlap
daniel-noland Aug 8, 2026
8d808c8
fix(k8s-intf): Give every vpc its own slots, and assert the control v…
daniel-noland Aug 8, 2026
fb6b57e
test(mgmt): Check that a validated configuration has only one meaning
daniel-noland Aug 8, 2026
79737d8
test(config): Assert the validator refuses what a mutation certainly …
daniel-noland Aug 8, 2026
7a5c096
test(nat): Catch a static NAT table that holds one of two rules asked…
daniel-noland Aug 8, 2026
a070796
fix(k8s-intf): Put the generated gateway in its own gateway groups
daniel-noland Aug 8, 2026
a3049ac
test(mgmt): Check that every expose leaves a trace
daniel-noland Aug 8, 2026
e240cc1
test(mgmt): Follow the genid out of MasqueradeConfig
daniel-noland Aug 17, 2026
a86fad9
fix(mgmt): Refuse an IPv6 peering by name instead of two ways by acci…
daniel-noland Aug 27, 2026
6c44388
fix(mgmt): Route both build sites through the same declared-limitatio…
daniel-noland Aug 27, 2026
440a6fa
fix(k8s-intf): Refuse a slot budget the scheme cannot separate
daniel-noland Aug 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ license.workspace = true
publish.workspace = true
version.workspace = true

[features]
bolero = ["dep:bolero", "lpm/bolero"]

[dependencies]
# internal
common = { workspace = true }
Expand All @@ -16,6 +19,7 @@ net = { workspace = true }

# external
arc-swap = { workspace = true }
bolero = { workspace = true, optional = true, default-features = false, features = ["alloc"] }
chrono = { workspace = true, features = ["alloc", "std"] }
derive_builder = { workspace = true, features = [] }
ipnet = { workspace = true }
Expand Down
6 changes: 5 additions & 1 deletion config/src/converters/k8s/config/expose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ mod test {
"10.0.4.0/24".parse::<Prefix>().unwrap(),
),
]);
let expose_gen = k8s_intf::bolero::expose::LegalValueExposeGenerator::new(&subnets);
let expose_gen = k8s_intf::bolero::expose::AnyExposeGenerator::new(0, &subnets);
bolero::check!()
.with_generator(expose_gen)
.for_each(|k8s_expose| {
Expand Down Expand Up @@ -549,6 +549,7 @@ mod test {
})
.unwrap_or(vec![]);
k8s_nots.sort();
k8s_nots.dedup();
let k8s_subnets = k8s_expose
.ips
.as_ref()
Expand All @@ -566,6 +567,7 @@ mod test {
.unwrap_or(vec![]);
k8s_ips.extend(k8s_subnets);
k8s_ips.sort();
k8s_ips.dedup();

let k8s_as = k8s_expose.r#as.as_ref().map(|r#as| {
let mut ret = r#as
Expand All @@ -574,6 +576,7 @@ mod test {
.map(|r#as| r#as.cidr.as_ref().unwrap().clone())
.collect::<Vec<_>>();
ret.sort();
ret.dedup();
ret
});

Expand All @@ -584,6 +587,7 @@ mod test {
.map(|r#as| r#as.not.as_ref().unwrap().clone())
.collect::<Vec<_>>();
ret.sort();
ret.dedup();
ret
});

Expand Down
11 changes: 9 additions & 2 deletions config/src/converters/k8s/config/peering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,17 @@ mod test {
use k8s_intf::bolero::peering::{
LegalValuePeeringsGenerator, LegalValuePeeringsPeeringGenerator,
};
use k8s_intf::bolero::{AddressFamily, NatFlavour};
use lpm::prefix::Prefix;

use crate::converters::k8s::config::{SubnetMap, VpcSubnetMap};

#[test]
fn test_vpc_manifest_conversion() {
let subnets = SubnetMap::new(); // Let this be empty since we are test subnet conversion elsewhere
let generator = LegalValuePeeringsPeeringGenerator::new(&subnets);
let flavours = NatFlavour::all();
let generator =
LegalValuePeeringsPeeringGenerator::new(&subnets, &flavours, AddressFamily::V4, 3, 0);
bolero::check!()
.with_generator(generator)
.for_each(|peering| {
Expand Down Expand Up @@ -169,7 +172,11 @@ mod test {
]),
),
]);
let generator = LegalValuePeeringsGenerator::new(&subnets).unwrap();
let flavours = NatFlavour::all();
let families = AddressFamily::all();
let groups = vec!["gwgroup-0".to_string()];
let generator =
LegalValuePeeringsGenerator::new(&subnets, &flavours, &families, 3, &groups).unwrap();
bolero::check!()
.with_generator(generator)
.for_each(|peering| {
Expand Down
17 changes: 16 additions & 1 deletion config/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub enum ConfigError {
FailureApply(String),
#[error("Forbidden: {0}")]
Forbidden(&'static str),
#[error("Not supported yet: {0}")]
Unsupported(&'static str),
#[error("Bad VPC Id")]
BadVpcId(String),
#[error("Bad VTEP local address {0}: {1}")]
Expand Down Expand Up @@ -75,8 +77,21 @@ pub enum ConfigError {
#[error("Invalid ACL configuration: {0}")]
InvalidAcl(String),
// NAT-specific
#[error("Mismatched prefixes sizes for static NAT: {0:?} and {1:?}")]
#[error(
"Mismatched sizes for static NAT: the exposed prefixes and the range they translate to \
must cover the same number of address-port pairs (they cover {0:?} and {1:?})"
)]
MismatchedPrefixSizes(PrefixWithPortsSize, PrefixWithPortsSize),
#[error(
"Mismatched prefix lengths for port forwarding: /{private} exposed and /{public} \
translated to; a rule maps addresses one for one, so the two must be the same length"
)]
MismatchedPrefixLengths { private: u8, public: u8 },
#[error(
"Mismatched port range sizes for port forwarding: {private} ports exposed and {public} \
translated to; a rule maps ports one for one, so the two must be the same size"
)]
MismatchedPortRangeSizes { private: usize, public: usize },
#[error("Peering {0} has manifests using incompatible NAT modes")]
IncompatibleNatModes(String),
#[error("Vpc {0} has a peering with no exposes")]
Expand Down
8 changes: 7 additions & 1 deletion config/src/external/overlay/validation_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,13 @@ mod test {
.unwrap();
let result = expose.validate();
assert!(
matches!(result, Err(ConfigError::MismatchedPrefixSizes(_, _))),
matches!(
result,
Err(ConfigError::MismatchedPrefixLengths {
private: 24,
public: 25
})
),
"{result:?}",
);
}
Expand Down
Loading
Loading