@@ -24,6 +24,36 @@ use quinn::{
2424 crypto:: rustls:: { QuicClientConfig , QuicServerConfig } ,
2525 MtuDiscoveryConfig , VarInt ,
2626} ;
27+ use quinn_proto:: congestion;
28+
29+ /// Congestion controller algorithm selection with algorithm-specific parameters
30+ #[ derive( Debug , Clone , PartialEq ) ]
31+ pub enum CongestionController {
32+ /// CUBIC congestion control algorithm (default)
33+ Cubic {
34+ /// Initial congestion window in bytes.
35+ /// Default: None, which uses Quinn's default (~14720 bytes).
36+ initial_window : Option < u64 > ,
37+ } ,
38+ /// NewReno congestion control algorithm
39+ NewReno {
40+ /// Initial congestion window in bytes.
41+ /// Default: None, which uses Quinn's default (~14720 bytes).
42+ initial_window : Option < u64 > ,
43+ /// Reduction in congestion window when a new loss event is detected.
44+ /// Value should be between 0.0 and 1.0.
45+ /// Default: None, which uses Quinn's default (0.5).
46+ loss_reduction_factor : Option < f32 > ,
47+ } ,
48+ /// BBR (Bottleneck Bandwidth and Round-trip propagation time) congestion control.
49+ /// Experimental! Aims for reduced buffer bloat and improved performance over
50+ /// high bandwidth-delay product networks.
51+ Bbr {
52+ /// Initial congestion window in bytes.
53+ /// Default: None, which uses Quinn's default (~14720 bytes).
54+ initial_window : Option < u64 > ,
55+ } ,
56+ }
2757
2858/// Config for the transport.
2959#[ derive( Clone ) ]
@@ -51,6 +81,49 @@ pub struct Config {
5181 /// of a connection.
5282 pub max_connection_data : u32 ,
5383
84+ /// Initial round-trip time (RTT) estimate for new connections.
85+ /// This is used before the actual RTT is measured.
86+ /// Default is None, which uses Quinn's default (333ms).
87+ pub initial_rtt : Option < Duration > ,
88+
89+ /// Maximum amount of data the peer may send without acknowledgement on
90+ /// any single stream before becoming blocked.
91+ /// Default is None, which uses the value of max_stream_data.
92+ pub send_window : Option < u64 > ,
93+
94+ /// Whether to enable send stream fairness. When true, streams with the same priority
95+ /// share bandwidth fairly. When false, a single stream can monopolize the connection.
96+ /// Default is None, which uses Quinn's default (true).
97+ pub send_fairness : Option < bool > ,
98+
99+ /// Packet threshold for triggering fast retransmit.
100+ /// Default is None, which uses Quinn's default (3).
101+ pub packet_threshold : Option < u32 > ,
102+
103+ /// Time threshold for triggering fast retransmit, as a fraction of RTT.
104+ /// Default is None, which uses Quinn's default (9/8).
105+ pub time_threshold : Option < f32 > ,
106+
107+ /// Minimum MTU size guaranteed to be supported by the network.
108+ /// Must be at least 1200 bytes (QUIC minimum).
109+ /// Default is None, which uses Quinn's default (1200).
110+ pub min_mtu : Option < u16 > ,
111+
112+ /// Number of consecutive PTOs after which the network is considered to be experiencing
113+ /// persistent congestion.
114+ /// Default is None, which uses Quinn's default (3).
115+ pub persistent_congestion_threshold : Option < u32 > ,
116+
117+ /// Whether to enable Generic Segmentation Offload (GSO) for improved performance.
118+ /// GSO can reduce CPU usage when sending large amounts of data by offloading
119+ /// segmentation to the NIC.
120+ /// Default is None, which uses Quinn's default (true on supported platforms).
121+ pub enable_segmentation_offload : Option < bool > ,
122+
123+ /// Congestion controller algorithm to use with its specific parameters.
124+ /// Default is None, which uses CUBIC with default settings.
125+ pub congestion_controller : Option < CongestionController > ,
126+
54127 /// Support QUIC version draft-29 for dialing and listening.
55128 ///
56129 /// Per default only QUIC Version 1 / [`libp2p_core::multiaddr::Protocol::QuicV1`]
@@ -98,6 +171,17 @@ impl Config {
98171 max_stream_data : 10_000_000 ,
99172 keypair : keypair. clone ( ) ,
100173 mtu_discovery_config : Some ( Default :: default ( ) ) ,
174+
175+ // Quinn defaults
176+ initial_rtt : None ,
177+ send_window : None ,
178+ send_fairness : None ,
179+ packet_threshold : None ,
180+ time_threshold : None ,
181+ min_mtu : None ,
182+ persistent_congestion_threshold : None ,
183+ enable_segmentation_offload : None ,
184+ congestion_controller : None ,
101185 }
102186 }
103187
@@ -114,6 +198,61 @@ impl Config {
114198 self . mtu_discovery_config = None ;
115199 self
116200 }
201+
202+ /// Set the initial RTT estimate for new connections.
203+ pub fn initial_rtt ( mut self , value : Duration ) -> Self {
204+ self . initial_rtt = Some ( value) ;
205+ self
206+ }
207+
208+ /// Set the maximum amount of data the peer may send without acknowledgement on any single
209+ /// stream.
210+ pub fn send_window ( mut self , value : u64 ) -> Self {
211+ self . send_window = Some ( value) ;
212+ self
213+ }
214+
215+ /// Enable or disable send stream fairness.
216+ pub fn send_fairness ( mut self , value : bool ) -> Self {
217+ self . send_fairness = Some ( value) ;
218+ self
219+ }
220+
221+ /// Set the packet threshold for triggering fast retransmit.
222+ pub fn packet_threshold ( mut self , value : u32 ) -> Self {
223+ self . packet_threshold = Some ( value) ;
224+ self
225+ }
226+
227+ /// Set the time threshold for triggering fast retransmit, as a fraction of RTT.
228+ pub fn time_threshold ( mut self , value : f32 ) -> Self {
229+ self . time_threshold = Some ( value) ;
230+ self
231+ }
232+
233+ /// Set the minimum MTU size. Must be at least 1200 bytes.
234+ pub fn min_mtu ( mut self , value : u16 ) -> Self {
235+ self . min_mtu = Some ( value) ;
236+ self
237+ }
238+
239+ /// Set the persistent congestion threshold (number of consecutive PTOs).
240+ pub fn persistent_congestion_threshold ( mut self , value : u32 ) -> Self {
241+ self . persistent_congestion_threshold = Some ( value) ;
242+ self
243+ }
244+
245+ /// Enable or disable Generic Segmentation Offload (GSO).
246+ pub fn enable_segmentation_offload ( mut self , value : bool ) -> Self {
247+ self . enable_segmentation_offload = Some ( value) ;
248+ self
249+ }
250+
251+ /// Set the congestion controller algorithm with its parameters.
252+ pub fn congestion_controller ( mut self , value : CongestionController ) -> Self {
253+ self . congestion_controller = Some ( value) ;
254+ self
255+ }
117256}
118257
119258/// Represents the inner configuration for [`quinn`].
@@ -139,6 +278,15 @@ impl From<Config> for QuinnConfig {
139278 handshake_timeout : _,
140279 keypair,
141280 mtu_discovery_config,
281+ initial_rtt,
282+ send_window,
283+ send_fairness,
284+ packet_threshold,
285+ time_threshold,
286+ min_mtu,
287+ persistent_congestion_threshold,
288+ enable_segmentation_offload,
289+ congestion_controller,
142290 } = config;
143291 let mut transport = quinn:: TransportConfig :: default ( ) ;
144292 // Disable uni-directional streams.
@@ -152,6 +300,75 @@ impl From<Config> for QuinnConfig {
152300 transport. stream_receive_window ( max_stream_data. into ( ) ) ;
153301 transport. receive_window ( max_connection_data. into ( ) ) ;
154302 transport. mtu_discovery_config ( mtu_discovery_config) ;
303+
304+ // Apply additional transport configurations
305+ if let Some ( initial_rtt) = initial_rtt {
306+ transport. initial_rtt ( initial_rtt) ;
307+ }
308+
309+ if let Some ( send_window) = send_window {
310+ transport. send_window ( send_window) ;
311+ }
312+
313+ if let Some ( send_fairness) = send_fairness {
314+ transport. send_fairness ( send_fairness) ;
315+ }
316+
317+ if let Some ( packet_threshold) = packet_threshold {
318+ transport. packet_threshold ( packet_threshold) ;
319+ }
320+
321+ if let Some ( time_threshold) = time_threshold {
322+ transport. time_threshold ( time_threshold) ;
323+ }
324+
325+ if let Some ( min_mtu) = min_mtu {
326+ transport. min_mtu ( min_mtu) ;
327+ }
328+
329+ if let Some ( persistent_congestion_threshold) = persistent_congestion_threshold {
330+ transport. persistent_congestion_threshold ( persistent_congestion_threshold) ;
331+ }
332+
333+ if let Some ( enable_segmentation_offload) = enable_segmentation_offload {
334+ transport. enable_segmentation_offload ( enable_segmentation_offload) ;
335+ }
336+
337+ // Configure congestion controller if specified
338+ if let Some ( congestion_controller) = congestion_controller {
339+ let controller: Arc < dyn congestion:: ControllerFactory + Send + Sync > =
340+ match congestion_controller {
341+ CongestionController :: Cubic { initial_window } => {
342+ let mut cubic_config = congestion:: CubicConfig :: default ( ) ;
343+ if let Some ( window) = initial_window {
344+ cubic_config. initial_window ( window) ;
345+ }
346+ Arc :: new ( cubic_config)
347+ }
348+ CongestionController :: NewReno {
349+ initial_window,
350+ loss_reduction_factor,
351+ } => {
352+ let mut new_reno_config = congestion:: NewRenoConfig :: default ( ) ;
353+ if let Some ( window) = initial_window {
354+ new_reno_config. initial_window ( window) ;
355+ }
356+ if let Some ( factor) = loss_reduction_factor {
357+ new_reno_config. loss_reduction_factor ( factor) ;
358+ }
359+ Arc :: new ( new_reno_config)
360+ }
361+ CongestionController :: Bbr { initial_window } => {
362+ let mut bbr_config = congestion:: BbrConfig :: default ( ) ;
363+ if let Some ( window) = initial_window {
364+ bbr_config. initial_window ( window) ;
365+ }
366+ Arc :: new ( bbr_config)
367+ }
368+ } ;
369+ transport. congestion_controller_factory ( controller) ;
370+ }
371+
155372 let transport = Arc :: new ( transport) ;
156373
157374 let mut server_config = quinn:: ServerConfig :: with_crypto ( server_tls_config) ;
0 commit comments