Skip to content

Commit 0159837

Browse files
feat(quic): added more quic transport config parameters
1 parent b3d3167 commit 0159837

File tree

6 files changed

+241
-10
lines changed

6 files changed

+241
-10
lines changed

Cargo.lock

Lines changed: 14 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ libp2p-perf = { version = "0.4.0", path = "protocols/perf" }
9696
libp2p-ping = { version = "0.47.0", path = "protocols/ping" }
9797
libp2p-plaintext = { version = "0.43.0", path = "transports/plaintext" }
9898
libp2p-pnet = { version = "0.26.0", path = "transports/pnet" }
99-
libp2p-quic = { version = "0.13.0", path = "transports/quic" }
99+
libp2p-quic = { version = "0.14.0", path = "transports/quic" }
100100
libp2p-relay = { version = "0.21.1", path = "protocols/relay" }
101101
libp2p-rendezvous = { version = "0.17.0", path = "protocols/rendezvous" }
102102
libp2p-request-response = { version = "0.29.0", path = "protocols/request-response" }

transports/quic/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.14.0
2+
3+
- Added more QUIC transport config parameters.
4+
See [PR 6182](https://github.com/libp2p/rust-libp2p/pull/6182)
5+
16
## 0.13.0
27

38
- Remove `async-std` support.

transports/quic/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "libp2p-quic"
3-
version = "0.13.0"
3+
version = "0.14.0"
44
authors = ["Parity Technologies <[email protected]>"]
55
edition.workspace = true
66
rust-version = { workspace = true }
@@ -15,7 +15,8 @@ if-watch = { workspace = true }
1515
libp2p-core = { workspace = true }
1616
libp2p-tls = { workspace = true }
1717
libp2p-identity = { workspace = true }
18-
quinn = { version = "0.11.6", default-features = false, features = ["rustls", "futures-io"] }
18+
quinn = { version = "0.11.9", default-features = false, features = ["rustls", "futures-io"] }
19+
quinn-proto = { version = "0.11.13", default-features = false }
1920
rand = "0.8.5"
2021
rustls = { version = "0.23.9", default-features = false }
2122
thiserror = { workspace = true }

transports/quic/src/config.rs

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

transports/quic/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ mod transport;
6868

6969
use std::net::SocketAddr;
7070

71-
pub use config::Config;
71+
pub use config::{Config, CongestionController};
7272
pub use connection::{Connecting, Connection, Stream};
7373
#[cfg(feature = "tokio")]
7474
pub use provider::tokio;

0 commit comments

Comments
 (0)