Skip to content

Commit

Permalink
feat: option to select congestion control algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
crazyscot committed Oct 25, 2024
1 parent cf91b96 commit da105d6
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 16 deletions.
19 changes: 10 additions & 9 deletions src/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,19 @@ pub(crate) struct CliArgs {
)]
pub rtt: u16,

/// Selects use of the experimental Bbr congestion control algorithm.
/// (default: use Cubic, which is the algorithm TCP uses).
/// Use with caution!
#[arg(long, action, help_heading("Network tuning"), display_order(50))]
pub bbr: bool,

/// (Network wizards only! Setting this too high will cause a reduction in throughput.)
/// The initial value for the sending congestion control window.
/// qcp uses the CUBIC congestion control algorithm. The window grows by the number of bytes acknowledged each time,
/// The default is specified by the selected congestion control algorithm.
/// The window grows as the remote endpoint acknowledges receipt of packets,
/// until encountering saturation or congestion.
#[arg(
hide(true),
long,
help_heading("Network tuning"),
default_value("14720"),
value_name = "bytes"
)]
pub initial_congestion_window: u64,
#[arg(hide(true), long, help_heading("Network tuning"), value_name = "bytes")]
pub initial_congestion_window: Option<u64>,

// POSITIONAL ARGUMENTS ================================================================
/// The source file. This may be a local filename, or remote specified as HOST:FILE.
Expand Down
10 changes: 10 additions & 0 deletions src/client/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ pub struct Parameters {
remote_rx_bw_bytes: u64,
rtt_ms: u16,
timeout: Duration,
bbr: bool,
iwind: Option<u64>,
}

impl TryFrom<&CliArgs> for Parameters {
Expand All @@ -36,6 +38,8 @@ impl TryFrom<&CliArgs> for Parameters {
remote_tx_bw_bytes: args.bandwidth.size(),
rtt_ms: args.rtt,
timeout: args.timeout,
bbr: args.bbr,
iwind: args.initial_congestion_window,
})
}
}
Expand Down Expand Up @@ -103,6 +107,12 @@ impl ControlChannel {
if args.remote_debug {
let _ = server.arg("--debug");
}
if args.bbr {
let _ = server.arg("--bbr");
}
if let Some(w) = args.iwind {
let _ = server.args(["--initial-congestion-window", &w.to_string()]);
}
let _ = server
.stdin(Stdio::piped())
.stdout(Stdio::piped())
Expand Down
50 changes: 43 additions & 7 deletions src/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use std::{fmt::Display, sync::Arc, time::Duration};

use anyhow::Result;
use human_repr::{HumanCount, HumanDuration as _};
use quinn::{congestion::CubicConfig, TransportConfig};
use quinn::{
congestion::{BbrConfig, CubicConfig},
TransportConfig,
};
use tracing::{debug, info};

use crate::cli::CliArgs;
Expand All @@ -25,6 +28,15 @@ pub enum ThroughputMode {
Both,
}

/// Selects the congestion control algorithm to use
#[derive(Copy, Clone, Debug)]
pub enum CongestionControllerType {
/// The CUBIC algorithm (this is the congestion algorithm TCP uses)
Cubic,
/// The BBR algorithm (experimental!)
Bbr,
}

/// Parameters needed to set up transport configuration
#[derive(Copy, Clone, Debug)]
pub struct BandwidthParams {
Expand All @@ -35,20 +47,26 @@ pub struct BandwidthParams {
/// Expected round trip time to the remote
rtt: Duration,
/// Initial congestion window (network wizards only!)
initial_window: u64,
initial_window: Option<u64>,
/// Congestion controller selection
congestion: CongestionControllerType,
}

impl Display for BandwidthParams {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let iwind = match self.initial_window {
None => "<default>".to_string(),
Some(s) => s.human_count_bytes().to_string(),
};
write!(
f,
"tx {tx} ({txbits}), rx {rx} ({rxbits}), rtt {rtt}, initial window {iwind}",
"tx {tx} ({txbits}), rx {rx} ({rxbits}), rtt {rtt}, congestion algorithm {congestion:?} with initial window {iwind}",
tx = self.tx.human_count_bytes(),
txbits = (self.tx * 8).human_count("bit"),
rx = self.rx.human_count_bytes(),
rxbits = (self.rx * 8).human_count("bit"),
rtt = self.rtt.human_duration(),
iwind = self.initial_window.human_count_bytes()
congestion = self.congestion,
)
}
}
Expand All @@ -60,6 +78,11 @@ impl From<&CliArgs> for BandwidthParams {
tx: args.bandwidth_outbound.unwrap_or(args.bandwidth).size(),
rtt: Duration::from_millis(u64::from(args.rtt)),
initial_window: args.initial_congestion_window,
congestion: if args.bbr {
CongestionControllerType::Bbr
} else {
CongestionControllerType::Cubic
},
}
}
}
Expand Down Expand Up @@ -168,9 +191,22 @@ pub fn create_config(
ThroughputMode::Tx => (),
}

let mut cubic = CubicConfig::default();
let _ = cubic.initial_window(params.initial_window);
let _ = config.congestion_controller_factory(Arc::new(cubic));
match params.congestion {
CongestionControllerType::Cubic => {
let mut cubic = CubicConfig::default();
if let Some(w) = params.initial_window {
let _ = cubic.initial_window(w);
}
let _ = config.congestion_controller_factory(Arc::new(cubic));
}
CongestionControllerType::Bbr => {
let mut bbr = BbrConfig::default();
if let Some(w) = params.initial_window {
let _ = bbr.initial_window(w);
}
let _ = config.congestion_controller_factory(Arc::new(bbr));
}
}

info!("Network configuration: {params}");
debug!("Buffer configuration: {bcfg}",);
Expand Down

0 comments on commit da105d6

Please sign in to comment.