diff --git a/crates/irtt-app/src/cmd/client/output.rs b/crates/irtt-app/src/cmd/client/output.rs index 2801a8a..a89746c 100644 --- a/crates/irtt-app/src/cmd/client/output.rs +++ b/crates/irtt-app/src/cmd/client/output.rs @@ -541,7 +541,7 @@ columns! { SendDelay("sd", ["send_delay"], 9, right, "human-readable client-to-server delay"); SendDelayUs("sd_us", ["send_delay_us"], 10, right, "client-to-server delay in signed microseconds"); Ipdv("ipdv", [], 9, right, "human-readable round-trip IPDV for adjacent samples"); - IpdvUs("ipdv_us", [], 10, right, "round-trip IPDV in microseconds"); + IpdvUs("ipdv_us", [], 10, right, "round-trip IPDV in signed microseconds"); ServerProcessing("proc", ["server_processing"], 9, right, "human-readable server processing time"); ServerProcessingUs("server_processing_us", [], 20, right, "server processing time in microseconds"); Bytes("bytes", [], 10, right, "packet bytes for packet events"); @@ -820,11 +820,15 @@ fn cell_for(row: &OutputRow, column: Column, context: RenderContext<'_>) -> Opti Column::Ipdv => row .seq() .and_then(|seq| ipdv_pair(context.stats, seq)) - .map(|pair| CellValue::text(format_duration(pair.rtt_ipdv))), + .map(|pair| { + CellValue::text(format_signed_duration(SignedDuration::from_nanos( + pair.rtt_ipdv_ns, + ))) + }), Column::IpdvUs => row .seq() .and_then(|seq| ipdv_pair(context.stats, seq)) - .map(|pair| CellValue::Unsigned(duration_us(pair.rtt_ipdv))), + .map(|pair| CellValue::Integer(pair.rtt_ipdv_ns / 1_000)), Column::ServerProcessing => row .reply() .and_then(|reply| reply.server_timing.and_then(|timing| timing.processing)) diff --git a/crates/irtt-stats/src/core.rs b/crates/irtt-stats/src/core.rs index c812ec9..3178f58 100644 --- a/crates/irtt-stats/src/core.rs +++ b/crates/irtt-stats/src/core.rs @@ -175,29 +175,31 @@ impl CoreStats { let mut updates = Vec::new(); for pair in self.ipdv_tracker.insert(sample) { - let Some(rtt_ipdv) = duration_from_non_negative_i128_ns(pair.rtt_ipdv_ns) else { + let rtt_magnitude_ns = pair.rtt_ipdv_ns.saturating_abs(); + let send_magnitude_ns = pair.send_ipdv_ns.map(i128::saturating_abs); + let receive_magnitude_ns = pair.receive_ipdv_ns.map(i128::saturating_abs); + let Some(rtt_ipdv) = duration_from_non_negative_i128_ns(rtt_magnitude_ns) else { continue; }; - let send_ipdv = pair - .send_ipdv_ns - .and_then(duration_from_non_negative_i128_ns); - let receive_ipdv = pair - .receive_ipdv_ns - .and_then(duration_from_non_negative_i128_ns); + let send_ipdv = send_magnitude_ns.and_then(duration_from_non_negative_i128_ns); + let receive_ipdv = receive_magnitude_ns.and_then(duration_from_non_negative_i128_ns); - self.ipdv_round_trip.push_ns(pair.rtt_ipdv_ns); + self.ipdv_round_trip.push_ns(rtt_magnitude_ns); - if let Some(value) = pair.send_ipdv_ns { + if let Some(value) = send_magnitude_ns { self.ipdv_send.push_ns(value); } - if let Some(value) = pair.receive_ipdv_ns { + if let Some(value) = receive_magnitude_ns { self.ipdv_receive.push_ns(value); } updates.push(IpdvPairUpdate { previous_seq: pair.previous_seq, current_seq: pair.current_seq, + rtt_ipdv_ns: pair.rtt_ipdv_ns, + send_ipdv_ns: pair.send_ipdv_ns, + receive_ipdv_ns: pair.receive_ipdv_ns, rtt_ipdv, send_ipdv, receive_ipdv, diff --git a/crates/irtt-stats/src/ipdv.rs b/crates/irtt-stats/src/ipdv.rs index 606e465..f5ec069 100644 --- a/crates/irtt-stats/src/ipdv.rs +++ b/crates/irtt-stats/src/ipdv.rs @@ -89,9 +89,9 @@ impl IpdvTracker { Some(CompletedIpdvPair { previous_seq, current_seq, - rtt_ipdv_ns: abs_i128_ns(current.rtt_primary_ns - previous.rtt_primary_ns), - send_ipdv_ns: send_ipdv_ns(previous, current).map(abs_i128_ns), - receive_ipdv_ns: receive_ipdv_ns(previous, current).map(abs_i128_ns), + rtt_ipdv_ns: current.rtt_primary_ns - previous.rtt_primary_ns, + send_ipdv_ns: send_ipdv_ns(previous, current), + receive_ipdv_ns: receive_ipdv_ns(previous, current), }) } } @@ -161,10 +161,6 @@ fn duration_ns_i128(duration: Duration) -> i128 { i128::try_from(duration.as_nanos()).unwrap_or(i128::MAX) } -fn abs_i128_ns(value: i128) -> i128 { - value.saturating_abs() -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/irtt-stats/src/lib.rs b/crates/irtt-stats/src/lib.rs index 6c566ae..b5a6742 100644 --- a/crates/irtt-stats/src/lib.rs +++ b/crates/irtt-stats/src/lib.rs @@ -520,6 +520,12 @@ pub struct IpdvPairUpdate { pub previous_seq: u32, /// Sequence number of the later reply in the adjacent pair. pub current_seq: u32, + /// Signed round-trip delay change (current minus previous) in nanoseconds. + pub rtt_ipdv_ns: i128, + /// Signed send-side delay change in nanoseconds, when available for both replies. + pub send_ipdv_ns: Option, + /// Signed receive-side delay change in nanoseconds, when available for both replies. + pub receive_ipdv_ns: Option, /// Absolute round-trip IPDV between the adjacent replies. pub rtt_ipdv: Duration, /// Absolute send-side IPDV when send one-way delay is available for both replies.