Skip to content

Commit 23b07e4

Browse files
feat(s2n-quic): allow disabling active connection migration support (#2182)
* feat(s2n-quic): allow disabling active connection migration support * change comment * typo * combine tests * more comments * more comments * putting default back * format * update nightly * fix test due to new s2n-tls version * remove unused snapshot * Update tests.rs Co-authored-by: toidiu <[email protected]> --------- Co-authored-by: toidiu <[email protected]>
1 parent 5f88e54 commit 23b07e4

File tree

11 files changed

+185
-29
lines changed

11 files changed

+185
-29
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ env:
1515
RUST_BACKTRACE: 1
1616
# Pin the nightly toolchain to prevent breakage.
1717
# This should be occasionally updated.
18-
RUST_NIGHTLY_TOOLCHAIN: nightly-2024-03-21
18+
RUST_NIGHTLY_TOOLCHAIN: nightly-2024-04-16
1919
CDN: https://dnglbrstg7yg.cloudfront.net
2020
# enable unstable features for testing
2121
S2N_UNSTABLE_CRYPTO_OPT_TX: 100

quic/s2n-quic-core/src/connection/limits.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
AckDelayExponent, ActiveConnectionIdLimit, InitialFlowControlLimits, InitialMaxData,
1010
InitialMaxStreamDataBidiLocal, InitialMaxStreamDataBidiRemote, InitialMaxStreamDataUni,
1111
InitialMaxStreamsBidi, InitialMaxStreamsUni, InitialStreamLimits, MaxAckDelay,
12-
MaxDatagramFrameSize, MaxIdleTimeout, TransportParameters,
12+
MaxDatagramFrameSize, MaxIdleTimeout, MigrationSupport, TransportParameters,
1313
},
1414
};
1515
use core::time::Duration;
@@ -66,6 +66,7 @@ pub struct Limits {
6666
pub(crate) max_keep_alive_period: Duration,
6767
pub(crate) max_datagram_frame_size: MaxDatagramFrameSize,
6868
pub(crate) initial_round_trip_time: Duration,
69+
pub(crate) migration_support: MigrationSupport,
6970
}
7071

7172
impl Default for Limits {
@@ -110,6 +111,7 @@ impl Limits {
110111
max_keep_alive_period: MAX_KEEP_ALIVE_PERIOD_DEFAULT,
111112
max_datagram_frame_size: MaxDatagramFrameSize::DEFAULT,
112113
initial_round_trip_time: recovery::DEFAULT_INITIAL_RTT,
114+
migration_support: MigrationSupport::RECOMMENDED,
113115
}
114116
}
115117

@@ -236,6 +238,21 @@ impl Limits {
236238
Duration
237239
);
238240
setter!(with_max_keep_alive_period, max_keep_alive_period, Duration);
241+
/// Sets whether active connection migration is supported for a server endpoint (default: true)
242+
///
243+
/// If set to false, the `disable_active_migration` transport parameter will be sent to the
244+
/// peer, and any attempt by the peer to perform an active connection migration will be ignored.
245+
pub fn with_active_connection_migration(
246+
mut self,
247+
enabled: bool,
248+
) -> Result<Self, ValidationError> {
249+
if enabled {
250+
self.migration_support = MigrationSupport::Enabled
251+
} else {
252+
self.migration_support = MigrationSupport::Disabled
253+
}
254+
Ok(self)
255+
}
239256

240257
/// Sets the initial round trip time (RTT) for use in recovery mechanisms prior to
241258
/// measuring an actual RTT sample.
@@ -335,6 +352,12 @@ impl Limits {
335352
pub fn initial_round_trip_time(&self) -> Duration {
336353
self.initial_round_trip_time
337354
}
355+
356+
#[doc(hidden)]
357+
#[inline]
358+
pub fn active_migration_enabled(&self) -> bool {
359+
matches!(self.migration_support, MigrationSupport::Enabled)
360+
}
338361
}
339362

340363
/// Creates limits for a given connection

quic/s2n-quic-core/src/transport/parameters/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,10 @@ pub enum MigrationSupport {
860860
Disabled,
861861
}
862862

863+
impl MigrationSupport {
864+
pub const RECOMMENDED: Self = Self::Enabled;
865+
}
866+
863867
impl TransportParameter for MigrationSupport {
864868
type CodecValue = ();
865869

@@ -878,7 +882,7 @@ impl TransportParameter for MigrationSupport {
878882
}
879883

880884
fn default_value() -> Self {
881-
MigrationSupport::Enabled
885+
Self::default()
882886
}
883887
}
884888

@@ -1462,5 +1466,6 @@ impl<
14621466
load!(ack_delay_exponent, ack_delay_exponent);
14631467
load!(max_active_connection_ids, active_connection_id_limit);
14641468
load!(max_datagram_frame_size, max_datagram_frame_size);
1469+
load!(migration_support, migration_support);
14651470
}
14661471
}

quic/s2n-quic-tls/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ fn s2n_client_no_client_auth_s2n_server_requires_client_auth_test() {
403403
// but the client does not support it.
404404
assert!(test_result.is_err());
405405
let e = test_result.unwrap_err();
406-
assert_eq!(e.description().unwrap(), "UNEXPECTED_MESSAGE");
406+
assert_eq!(e.description().unwrap(), "CERTIFICATE_REQUIRED");
407407
}
408408

409409
#[test]

quic/s2n-quic-transport/src/connection/connection_impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ impl<Config: endpoint::Config> connection::Trait for ConnectionImpl<Config> {
11541154
congestion_controller_endpoint,
11551155
path_migration,
11561156
mtu_config,
1157-
self.limits.initial_round_trip_time(),
1157+
&self.limits,
11581158
&mut publisher,
11591159
)?;
11601160

quic/s2n-quic-transport/src/path/manager.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ use crate::{
99
path::{challenge, Path},
1010
transmission,
1111
};
12-
use core::time::Duration;
1312
use s2n_quic_core::{
1413
ack,
15-
connection::{self, PeerId},
14+
connection::{self, Limits, PeerId},
15+
ensure,
1616
event::{
1717
self,
1818
builder::{DatagramDropReason, MtuUpdatedCause},
@@ -245,7 +245,7 @@ impl<Config: endpoint::Config> Manager<Config> {
245245
congestion_controller_endpoint: &mut Config::CongestionControllerEndpoint,
246246
migration_validator: &mut Config::PathMigrationValidator,
247247
mtu_config: mtu::Config,
248-
initial_rtt: Duration,
248+
limits: &Limits,
249249
publisher: &mut Pub,
250250
) -> Result<(Id, AmplificationOutcome), DatagramDropReason> {
251251
let valid_initial_received = self.valid_initial_received();
@@ -308,7 +308,7 @@ impl<Config: endpoint::Config> Manager<Config> {
308308
congestion_controller_endpoint,
309309
migration_validator,
310310
mtu_config,
311-
initial_rtt,
311+
limits,
312312
publisher,
313313
)
314314
}
@@ -321,7 +321,7 @@ impl<Config: endpoint::Config> Manager<Config> {
321321
congestion_controller_endpoint: &mut Config::CongestionControllerEndpoint,
322322
migration_validator: &mut Config::PathMigrationValidator,
323323
mtu_config: mtu::Config,
324-
initial_rtt: Duration,
324+
limits: &Limits,
325325
publisher: &mut Pub,
326326
) -> Result<(Id, AmplificationOutcome), DatagramDropReason> {
327327
//= https://www.rfc-editor.org/rfc/rfc9000#section-9
@@ -332,6 +332,17 @@ impl<Config: endpoint::Config> Manager<Config> {
332332
let local_address = path_handle.local_address();
333333
let active_local_addr = self.active_path().local_address();
334334
let active_remote_addr = self.active_path().remote_address();
335+
// The peer has intentionally tried to migrate to a new path because they changed
336+
// their destination_connection_id. This is considered an "active" migration.
337+
let active_migration =
338+
self.active_path().local_connection_id != datagram.destination_connection_id;
339+
340+
if active_migration {
341+
ensure!(
342+
limits.active_migration_enabled(),
343+
Err(DatagramDropReason::RejectedConnectionMigration)
344+
)
345+
}
335346

336347
// TODO set alpn if available
337348
let attempt: migration::Attempt = migration::AttemptBuilder {
@@ -403,19 +414,21 @@ impl<Config: endpoint::Config> Manager<Config> {
403414
// estimator for the new path, and they are initialized with initial values,
404415
// we do not need to reset congestion controller and round-trip time estimator
405416
// again on confirming the peer's ownership of its new address.
406-
let rtt = self.active_path().rtt_estimator.for_new_path(initial_rtt);
417+
let rtt = self
418+
.active_path()
419+
.rtt_estimator
420+
.for_new_path(limits.initial_round_trip_time());
407421
let path_info =
408422
congestion_controller::PathInfo::new(mtu_config.initial_mtu, &remote_address);
409423
let cc = congestion_controller_endpoint.new_congestion_controller(path_info);
410424

411425
let peer_connection_id = {
412-
if self.active_path().local_connection_id != datagram.destination_connection_id {
426+
if active_migration {
413427
//= https://www.rfc-editor.org/rfc/rfc9000#section-9.5
414428
//# Similarly, an endpoint MUST NOT reuse a connection ID when sending to
415429
//# more than one destination address.
416430

417-
// Peer has intentionally tried to migrate to this new path because they changed
418-
// their destination_connection_id, so we will change our destination_connection_id as well.
431+
// Active connection migrations must use a new connection ID
419432
self.peer_id_registry
420433
.consume_new_id_for_new_path()
421434
.ok_or(DatagramDropReason::InsufficientConnectionIds)?

quic/s2n-quic-transport/src/path/manager/fuzz_target.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use s2n_quic_core::{
1515
inet::{DatagramInfo, ExplicitCongestionNotification},
1616
random,
1717
random::testing::Generator,
18-
recovery::DEFAULT_INITIAL_RTT,
1918
time::{testing::Clock, Clock as _},
2019
transport,
2120
};
@@ -178,7 +177,7 @@ impl Model {
178177
&mut Default::default(),
179178
&mut migration_validator,
180179
mtu::Config::default(),
181-
DEFAULT_INITIAL_RTT,
180+
&Limits::default(),
182181
&mut publisher,
183182
) {
184183
Ok(_) => {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
source: quic/s2n-quic-transport/src/path/manager/tests.rs
3+
expression: ""
4+
---
5+
ConnectionIdUpdated { path_id: 0, cid_consumer: Local, previous: 0x01, current: 0x69643032 }
6+
PathCreated { active: Path { local_addr: 0.0.0.0:0, local_cid: 0x4c6f63616c4900000000000000004c6f63616c49, remote_addr: 127.0.0.1:1, remote_cid: 0x69643032, id: 0, is_active: true }, new: Path { local_addr: 0.0.0.0:0, local_cid: 0x69643032, remote_addr: 127.0.0.2:1, remote_cid: 0x69643033, id: 1, is_active: false } }
7+
MtuUpdated { path_id: 1, mtu: 1200, cause: NewPath }
8+
PathCreated { active: Path { local_addr: 0.0.0.0:0, local_cid: 0x4c6f63616c4900000000000000004c6f63616c49, remote_addr: 127.0.0.1:1, remote_cid: 0x69643032, id: 0, is_active: true }, new: Path { local_addr: 0.0.0.0:0, local_cid: 0x4c6f63616c4900000000000000004c6f63616c49, remote_addr: 127.0.0.3:1, remote_cid: 0x69643032, id: 2, is_active: false } }
9+
MtuUpdated { path_id: 2, mtu: 1200, cause: NewPath }

0 commit comments

Comments
 (0)