From 1bac0e0f0e6efa52876d0c5e9c0eec4e1003e2ad Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 19 Jul 2024 19:28:44 +1000 Subject: [PATCH] test(connlib): ensure portal `init` doesn't interrupt data plane (#5899) The connection to the portal could be interrupted at any point, most notably when it is being re-deployed. Doing so results in a new `init` message being pushed to all clients and gateways. This must not interrupt the data plane. To ensure this, we add a new `ReconnectPortal` transition to `tunnel_test` where we simulate receiving a new `init` message with the same values as we already have locally, i.e. same set of relays and resources. This resolves an existing TODO where the logic of performing non-destructive updates to resources in `set_resources` wasn't tested. --- rust/connlib/tunnel/src/tests/reference.rs | 5 +++++ rust/connlib/tunnel/src/tests/sut.rs | 19 +++++++++++++++++++ rust/connlib/tunnel/src/tests/transition.rs | 3 +++ 3 files changed, 27 insertions(+) diff --git a/rust/connlib/tunnel/src/tests/reference.rs b/rust/connlib/tunnel/src/tests/reference.rs index 6bd0b4b21..784092ceb 100644 --- a/rust/connlib/tunnel/src/tests/reference.rs +++ b/rust/connlib/tunnel/src/tests/reference.rs @@ -156,6 +156,7 @@ impl ReferenceStateMachine for ReferenceState { question_mark_wildcard_dns_resource(sample::select(state.portal.all_sites())), ], ) + .with(1, Just(Transition::ReconnectPortal)) .with_if_not_empty( 10, state.client.inner().ipv4_cidr_resource_dsts(), @@ -372,6 +373,9 @@ impl ReferenceStateMachine for ReferenceState { .client .exec_mut(|client| client.connected_dns_resources.clear()); } + Transition::ReconnectPortal => { + // Reconnecting to the portal should have no noticeable impact on the data plane. + } }; state @@ -557,6 +561,7 @@ impl ReferenceStateMachine for ReferenceState { !is_assigned_ip4 && !is_assigned_ip6 && !is_previous_port } + Transition::ReconnectPortal => true, } } } diff --git a/rust/connlib/tunnel/src/tests/sut.rs b/rust/connlib/tunnel/src/tests/sut.rs index 98d3eabd8..4dd66b6ad 100644 --- a/rust/connlib/tunnel/src/tests/sut.rs +++ b/rust/connlib/tunnel/src/tests/sut.rs @@ -256,6 +256,25 @@ impl StateMachineTest for TunnelTest { .set_resources(ref_state.client.inner().all_resources()); }); } + Transition::ReconnectPortal => { + let ipv4 = state.client.inner().sut.tunnel_ip4().unwrap(); + let ipv6 = state.client.inner().sut.tunnel_ip6().unwrap(); + let upstream_dns = ref_state.client.inner().upstream_dns_resolvers.clone(); + let relays = HashSet::from_iter(map_explode(state.relays.iter(), "client")); + let all_resources = ref_state.client.inner().all_resources(); + + // Simulate receiving `init`. + state.client.exec_mut(|c| { + let _ = c.sut.update_interface_config(Interface { + ipv4, + ipv6, + upstream_dns, + }); + c.sut + .update_relays(HashSet::default(), relays, ref_state.now); + c.sut.set_resources(all_resources); + }); + } }; state.advance(ref_state, &mut buffered_transmits); assert!(buffered_transmits.is_empty()); // Sanity check to ensure we handled all packets. diff --git a/rust/connlib/tunnel/src/tests/transition.rs b/rust/connlib/tunnel/src/tests/transition.rs index 2c068dc18..ba47e3ddb 100644 --- a/rust/connlib/tunnel/src/tests/transition.rs +++ b/rust/connlib/tunnel/src/tests/transition.rs @@ -83,6 +83,9 @@ pub(crate) enum Transition { ip6: Option, port: u16, }, + + /// Reconnect to the portal. + ReconnectPortal, } pub(crate) fn ping_random_ip(