diff --git a/dc/s2n-quic-dc/src/fixed_map.rs b/dc/s2n-quic-dc/src/fixed_map.rs index cffb4d1cbe..576abeba5e 100644 --- a/dc/s2n-quic-dc/src/fixed_map.rs +++ b/dc/s2n-quic-dc/src/fixed_map.rs @@ -25,8 +25,9 @@ where S: BuildHasher, { pub fn with_capacity(entries: usize, hasher: S) -> Self { + let slots = std::cmp::max(1, (entries + SLOT_CAPACITY) / SLOT_CAPACITY).next_power_of_two(); let map = Map { - slots: (0..std::cmp::min(1, (entries + SLOT_CAPACITY) / SLOT_CAPACITY)) + slots: (0..slots) .map(|_| Slot::new()) .collect::>() .into_boxed_slice(), diff --git a/dc/s2n-quic-dc/src/fixed_map/test.rs b/dc/s2n-quic-dc/src/fixed_map/test.rs index 2d4e62d44a..7268691373 100644 --- a/dc/s2n-quic-dc/src/fixed_map/test.rs +++ b/dc/s2n-quic-dc/src/fixed_map/test.rs @@ -31,3 +31,12 @@ fn slot_clear() { assert_eq!(slot.len(), 0); } + +#[test] +fn capacity_size() { + let map: Map = Map::with_capacity(500_000, Default::default()); + for idx in 0..500_000 { + map.insert(idx, ()); + } + assert!(map.len() >= 400_000, "{}", map.len()); +} diff --git a/dc/s2n-quic-dc/src/path/secret/map/test.rs b/dc/s2n-quic-dc/src/path/secret/map/test.rs index c0fad24f6b..f295c6e80b 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/test.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/test.rs @@ -317,7 +317,9 @@ fn check_invariants_no_overflow() { fn no_memory_growth() { let signer = stateless_reset::Signer::new(b"secret"); let map = Map::new(signer); - for idx in 0..500_000_000 { + map.state.cleaner.stop(); + for idx in 0..500_000 { + // FIXME: this ends up 2**16 peers in the `peers` map map.insert(fake_entry(idx as u16)); } } @@ -327,6 +329,6 @@ fn no_memory_growth() { fn entry_size() { // This gates to running only on specific GHA to reduce false positives. if std::env::var("S2N_QUIC_RUN_VERSION_SPECIFIC_TESTS").is_ok() { - assert_eq!(fake_entry(0).size(), 270); + assert_eq!(fake_entry(0).size(), 238); } } diff --git a/dc/s2n-quic-dc/src/stream/recv/state.rs b/dc/s2n-quic-dc/src/stream/recv/state.rs index a0b0e35bd0..77454e954a 100644 --- a/dc/s2n-quic-dc/src/stream/recv/state.rs +++ b/dc/s2n-quic-dc/src/stream/recv/state.rs @@ -70,7 +70,7 @@ impl State { recovery_ack: Default::default(), state: Default::default(), idle_timer: Default::default(), - idle_timeout: params.max_idle_timeout.unwrap_or(DEFAULT_IDLE_TIMEOUT), + idle_timeout: params.max_idle_timeout().unwrap_or(DEFAULT_IDLE_TIMEOUT), tick_timer: Default::default(), _should_transmit: false, max_data: initial_max_data, diff --git a/dc/s2n-quic-dc/src/stream/send/state.rs b/dc/s2n-quic-dc/src/stream/send/state.rs index 166a10af19..7a7a5b1d75 100644 --- a/dc/s2n-quic-dc/src/stream/send/state.rs +++ b/dc/s2n-quic-dc/src/stream/send/state.rs @@ -151,7 +151,7 @@ impl State { pto_backoff: INITIAL_PTO_BACKOFF, inflight_timer: Default::default(), idle_timer: Default::default(), - idle_timeout: params.max_idle_timeout.unwrap_or(DEFAULT_IDLE_TIMEOUT), + idle_timeout: params.max_idle_timeout().unwrap_or(DEFAULT_IDLE_TIMEOUT), error: None, unacked_ranges, max_sent_offset, diff --git a/quic/s2n-quic-core/src/dc.rs b/quic/s2n-quic-core/src/dc.rs index 14a88c5884..be0a5c8d38 100644 --- a/quic/s2n-quic-core/src/dc.rs +++ b/quic/s2n-quic-core/src/dc.rs @@ -11,7 +11,7 @@ use crate::{ transport::parameters::{DcSupportedVersions, InitialFlowControlLimits}, varint::VarInt, }; -use core::time::Duration; +use core::{num::NonZeroU32, time::Duration}; mod disabled; mod traits; @@ -98,8 +98,8 @@ pub struct ApplicationParams { pub remote_max_data: VarInt, pub local_send_max_data: VarInt, pub local_recv_max_data: VarInt, - pub max_idle_timeout: Option, - pub max_ack_delay: Duration, + // Actually a Duration, stored as milliseconds to shrink this struct + pub max_idle_timeout: Option, } impl ApplicationParams { @@ -113,8 +113,15 @@ impl ApplicationParams { remote_max_data: peer_flow_control_limits.max_data, local_send_max_data: limits.initial_stream_limits().max_data_bidi_local, local_recv_max_data: limits.initial_stream_limits().max_data_bidi_remote, - max_idle_timeout: limits.max_idle_timeout(), - max_ack_delay: limits.max_ack_delay.into(), + max_idle_timeout: limits + .max_idle_timeout() + // If > u32::MAX, treat as not having an idle timeout, that's ~50 days. + .and_then(|v| v.as_millis().try_into().ok()) + .and_then(NonZeroU32::new), } } + + pub fn max_idle_timeout(&self) -> Option { + Some(Duration::from_millis(self.max_idle_timeout?.get() as u64)) + } } diff --git a/quic/s2n-quic-core/src/dc/testing.rs b/quic/s2n-quic-core/src/dc/testing.rs index 2fea792b56..06faef4e70 100644 --- a/quic/s2n-quic-core/src/dc/testing.rs +++ b/quic/s2n-quic-core/src/dc/testing.rs @@ -8,7 +8,7 @@ use crate::{ stateless_reset, transport, varint::VarInt, }; -use core::time::Duration; +use core::{num::NonZeroU32, time::Duration}; use std::sync::{ atomic::{AtomicU8, Ordering}, Arc, @@ -83,8 +83,7 @@ pub const TEST_APPLICATION_PARAMS: ApplicationParams = ApplicationParams { remote_max_data: VarInt::from_u32(1u32 << 25), local_send_max_data: VarInt::from_u32(1u32 << 25), local_recv_max_data: VarInt::from_u32(1u32 << 25), - max_idle_timeout: Some(Duration::from_secs(30)), - max_ack_delay: Duration::from_millis(25), + max_idle_timeout: NonZeroU32::new(Duration::from_secs(30).as_millis() as _), }; pub const TEST_REHANDSHAKE_PERIOD: Duration = Duration::from_secs(3600 * 12); diff --git a/tools/xdp/s2n-quic-xdp/src/ring.rs b/tools/xdp/s2n-quic-xdp/src/ring.rs index 1780e504c5..4197a4ee39 100644 --- a/tools/xdp/s2n-quic-xdp/src/ring.rs +++ b/tools/xdp/s2n-quic-xdp/src/ring.rs @@ -15,7 +15,7 @@ use std::{io, os::unix::io::AsRawFd}; struct Ring { cursor: Cursor, flags: NonNull, - // make the area clonable in test mode + // make the area cloneable in test mode #[cfg(test)] area: std::sync::Arc, #[cfg(not(test))]