diff --git a/transports/quic/CHANGELOG.md b/transports/quic/CHANGELOG.md index d73e32ce992..0899ec4aea7 100644 --- a/transports/quic/CHANGELOG.md +++ b/transports/quic/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.13.0 +- Add `Config::max_connection_send_data` to configure the connection-level + send window independently from `max_connection_data`. + This enables tuning for high BDP while preserving Quinn's default send window when unset. + - Remove `async-std` support. See [PR 5954](https://github.com/libp2p/rust-libp2p/pull/5954) diff --git a/transports/quic/src/config.rs b/transports/quic/src/config.rs index 85b89cf35e3..7d28339e8fe 100644 --- a/transports/quic/src/config.rs +++ b/transports/quic/src/config.rs @@ -26,6 +26,16 @@ use quinn::{ }; /// Config for the transport. +/// +/// Performance or resource requirements can be improved in some cases by tuning these values for +/// the particular application and/or network configuration. +/// +/// Flow-control window sizes should reflect expected round-trip time, link capacity, and available +/// memory. Larger windows improve headroom for high-bandwidth, high-latency links, but increase +/// worst-case memory usage. +/// +/// Defaults follow Quinn and are tuned for roughly 100 Mbit/s at 100 ms RTT. For details see: +/// https://github.com/quinn-rs/quinn/blob/f853e5e0826a00f4b80551986eba0ca251ae1b45/quinn-proto/src/config/transport.rs #[derive(Clone)] pub struct Config { /// Timeout for the initial handshake when establishing a connection. @@ -44,13 +54,20 @@ pub struct Config { /// concurrently by the remote peer. pub max_concurrent_stream_limit: u32, - /// Max unacknowledged data in bytes that may be sent on a single stream. + /// Maximum amount of stream data in bytes that may be received on a single stream + /// before the peer is blocked. pub max_stream_data: u32, - /// Max unacknowledged data in bytes that may be sent in total on all streams - /// of a connection. + /// Maximum amount of stream data in bytes that may be received in total across all + /// streams of a connection before the peer is blocked. pub max_connection_data: u32, + /// Optional override for the maximum amount of stream data in bytes for sending on + /// a connection. + /// + /// If unset, Quinn's default [`quinn::TransportConfig::send_window`] is used. + pub max_connection_send_data: Option, + /// Support QUIC version draft-29 for dialing and listening. /// /// Per default only QUIC Version 1 / [`libp2p_core::multiaddr::Protocol::QuicV1`] @@ -93,6 +110,7 @@ impl Config { max_concurrent_stream_limit: 256, keep_alive_interval: Duration::from_secs(5), max_connection_data: 15_000_000, + max_connection_send_data: None, // Ensure that one stream is not consuming the whole connection. max_stream_data: 10_000_000, @@ -114,6 +132,14 @@ impl Config { self.mtu_discovery_config = None; self } + + /// Override the connection-level send window. + /// + /// If not set, Quinn's default send window is used. + pub fn max_connection_send_data(mut self, value: u32) -> Self { + self.max_connection_send_data = Some(value); + self + } } /// Represents the inner configuration for [`quinn`]. @@ -134,6 +160,7 @@ impl From for QuinnConfig { max_concurrent_stream_limit, keep_alive_interval, max_connection_data, + max_connection_send_data, max_stream_data, support_draft_29, handshake_timeout: _, @@ -152,6 +179,10 @@ impl From for QuinnConfig { transport.stream_receive_window(max_stream_data.into()); transport.receive_window(max_connection_data.into()); transport.mtu_discovery_config(mtu_discovery_config); + if let Some(max_connection_send_data) = max_connection_send_data { + transport.send_window(max_connection_send_data.into()); + } + let transport = Arc::new(transport); let mut server_config = quinn::ServerConfig::with_crypto(server_tls_config);