use std::time::Duration;
use super::state::{BbrState, ProbeBwPhase};
#[derive(Debug, Clone)]
pub struct BbrStats {
pub state: BbrState,
pub probe_bw_phase: ProbeBwPhase,
pub cwnd: usize,
pub flightsize: usize,
pub pacing_rate: u64,
pub max_bw: u64,
pub min_rtt: Option<Duration>,
pub bdp: usize,
pub delivered: u64,
pub lost: u64,
pub round_count: u64,
pub full_bw_count: u32,
pub full_bw: u64,
pub probe_rtt_rounds: u64,
pub timeouts: u64,
pub max_bdp_seen: usize,
pub is_app_limited: bool,
pub pacing_gain: f64,
pub cwnd_gain: f64,
}
impl Default for BbrStats {
fn default() -> Self {
Self {
state: BbrState::Startup,
probe_bw_phase: ProbeBwPhase::Cruise,
cwnd: 0,
flightsize: 0,
pacing_rate: 0,
max_bw: 0,
min_rtt: None,
bdp: 0,
delivered: 0,
lost: 0,
round_count: 0,
full_bw_count: 0,
full_bw: 0,
probe_rtt_rounds: 0,
timeouts: 0,
max_bdp_seen: 0,
is_app_limited: false,
pacing_gain: 1.0,
cwnd_gain: 1.0,
}
}
}
impl std::fmt::Display for BbrStats {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"BBR[{:?}] cwnd={} flight={} rate={}/s bw={}/s rtt={:?} bdp={}",
self.state,
format_bytes(self.cwnd),
format_bytes(self.flightsize),
format_bytes(self.pacing_rate as usize),
format_bytes(self.max_bw as usize),
self.min_rtt,
format_bytes(self.bdp),
)
}
}
fn format_bytes(bytes: usize) -> String {
if bytes >= 1_000_000 {
format!("{:.1}MB", bytes as f64 / 1_000_000.0)
} else if bytes >= 1_000 {
format!("{:.1}KB", bytes as f64 / 1_000.0)
} else {
format!("{}B", bytes)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stats_display() {
let stats = BbrStats {
state: BbrState::ProbeBW,
cwnd: 150_000,
flightsize: 100_000,
pacing_rate: 10_000_000,
max_bw: 10_000_000,
min_rtt: Some(Duration::from_millis(50)),
bdp: 500_000,
..Default::default()
};
let display = format!("{}", stats);
assert!(display.contains("ProbeBW"));
assert!(display.contains("150.0KB"));
}
#[test]
fn test_format_bytes() {
assert_eq!(format_bytes(500), "500B");
assert_eq!(format_bytes(1500), "1.5KB");
assert_eq!(format_bytes(1_500_000), "1.5MB");
}
}