diff --git a/Cargo.toml b/Cargo.toml index c6a7759..6e896a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ authors = ["Akshay Narayan "] [dependencies] clap = "2.29" fnv = "1" -portus = "^0.4.1" +portus = { path = "/home/frank/portus" } +portus_export = { path = "/home/frank/portus/portus_export" } slog = "2" slog-async = "2" slog-term = "2" diff --git a/src/bin/bbr.rs b/src/bin/bbr.rs index 99a20b2..1e6ad06 100644 --- a/src/bin/bbr.rs +++ b/src/bin/bbr.rs @@ -56,7 +56,7 @@ fn main() { .map_err(|e| warn!(log, "bad argument"; "err" => ?e)) .unwrap(); - info!(log, "configured BBR"; + info!(log, "configured BBR"; "ipc" => ipc.clone(), "probe_rtt_interval" => ?cfg.probe_rtt_interval, ); diff --git a/src/lib.rs b/src/lib.rs index c3aab3b..10ca719 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,13 +45,15 @@ extern crate slog; extern crate fnv; extern crate portus; +extern crate portus_export; extern crate time; +extern crate clap; use portus::ipc::Ipc; use portus::lang::Scope; -use portus::{CongAlg, Datapath, DatapathInfo, DatapathTrait, Report}; +use portus::{CongAlg, CongAlgBuilder, Datapath, DatapathInfo, DatapathTrait, Report}; -use fnv::FnvHashMap; +use std::collections::HashMap; pub struct Bbr { control_channel: Datapath, @@ -75,6 +77,7 @@ enum BbrMode { pub const PROBE_RTT_INTERVAL_SECONDS: i64 = 10; +#[portus_export::register_ccp_alg] #[derive(Clone)] pub struct BbrConfig { pub logger: Option, @@ -169,6 +172,45 @@ impl Bbr { } } +use clap::Arg; +impl<'a,'b> CongAlgBuilder<'a,'b> for BbrConfig { + fn args() -> clap::App<'a,'b> { + clap::App::new("CCP BBR") + .version("0.2.1") + .author("CCP Project ") + .about("Implementation of BBR Congestion Control") + .arg(Arg::with_name("probe_rtt_interval") + .long("probe_rtt_interval") + .help("Sets the BBR probe RTT interval in seconds, after which BBR drops its congestion window to potentially observe a new minimum RTT.") + .default_value("10")) + .arg(Arg::with_name("verbose") + .short("v") + .help("If provided, log internal BBR state")) + } + fn with_arg_matches(args: &clap::ArgMatches, logger: Option) -> Result { + let probe_rtt_interval = time::Duration::seconds( + i64::from_str_radix(args.value_of("probe_rtt_interval").unwrap(), 10) + .map_err(|e| format!("{:?}", e)) + .and_then(|probe_rtt_interval_arg| { + if probe_rtt_interval_arg <= 0 { + Err(format!( + "probe_rtt_interval must be positive: {}", + probe_rtt_interval_arg + )) + } else { + Ok(probe_rtt_interval_arg) + } + }).map_err(|e| portus::Error(e))?, + ); + Ok( + Self { + logger: logger, + probe_rtt_interval + } + ) + } +} + impl CongAlg for BbrConfig { type Flow = Bbr; @@ -176,7 +218,7 @@ impl CongAlg for BbrConfig { "bbr" } - fn datapath_programs(&self) -> FnvHashMap<&'static str, String> { + fn datapath_programs(&self) -> HashMap<&'static str, String> { vec![ ("init_program", String::from(" (def @@ -199,16 +241,23 @@ impl CongAlg for BbrConfig { ) ")), ("probe_rtt", String::from(" - (def - (Report (volatile minrtt +infinity)) - ) - (when true - (:= Report.minrtt (min Report.minrtt Flow.rtt_sample_us)) - (fallthrough) - ) - (when (&& (> Micros 200000) (|| (< Flow.packets_in_flight 4) (== Flow.packets_in_flight 4))) - (report) - ) + (def + (Report (volatile minrtt +infinity)) + (target_inflight_reached false) + ) + (when true + (:= Report.minrtt (min Report.minrtt Flow.rtt_sample_us)) + (fallthrough) + ) + (when (&& (== target_inflight_reached false) + (|| (< Flow.packets_in_flight 4) (== Flow.packets_in_flight 4))) + (:= target_inflight_reached true) + (:= Micros 0) + ) + (when (&& (== target_inflight_reached true) + (&& (> Micros Flow.rtt_sample_us) (> Micros 200000)) + (report) + ) ")), ("probe_bw", String::from(" (def