Report per-peer byte counters, not just packets
The overlay peer report carried packet counts only, so the GUI could show packets/s but no byte throughput. Adds tx_bytes/rx_bytes to OverlayPeerReport and fills them from each data plane: - the wg and wg-quic plugins already counted plaintext bytes per peer; the CLI now maps them into the report; - the generic tunnel (tcp-tls) gains tx_bytes/rx_bytes on its peer state and report, incremented by the plaintext length at the same points it counts packets. The local control protocol version is bumped (TSN 15 -> 16) since the report shape changed; a client and agent on different builds already detect and report the mismatch. Checks: fmt, clippy --workspace --all-targets -D warnings, and the tsunagi lib, tsunagi-cli and wg-quic local_control tests pass on macOS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
2cda56e1f8
commit
0a344c1b4f
3 files changed
+31
-1
No files matched your search
@@ -4078,6 +4078,8 @@ async fn build_report(
|
||||
handshake_secs_ago: tunnel.health.since_handshake.map(|s| s.as_secs()),
|
||||
tx_packets: tunnel.stats.tx_packets,
|
||||
rx_packets: tunnel.stats.rx_packets,
|
||||
tx_bytes: tunnel.stats.tx_bytes,
|
||||
rx_bytes: tunnel.stats.rx_bytes,
|
||||
dropped: tunnel.stats.dropped_wrong_source
|
||||
+ tunnel.stats.dropped_oversize,
|
||||
protocol_errors: tunnel.stats.protocol_errors,
|
||||
@@ -4096,6 +4098,8 @@ async fn build_report(
|
||||
handshake_secs_ago: Some(tcp_tls.uptime_secs),
|
||||
tx_packets: tcp_tls.tx_packets,
|
||||
rx_packets: tcp_tls.rx_packets,
|
||||
tx_bytes: tcp_tls.tx_bytes,
|
||||
rx_bytes: tcp_tls.rx_bytes,
|
||||
dropped: tcp_tls.dropped,
|
||||
protocol_errors: 0,
|
||||
path: tcp_tls.path.clone(),
|
||||
@@ -4114,6 +4118,8 @@ async fn build_report(
|
||||
handshake_secs_ago: tunnel.health.since_handshake.map(|s| s.as_secs()),
|
||||
tx_packets: tunnel.stats.tx_packets,
|
||||
rx_packets: tunnel.stats.rx_packets,
|
||||
tx_bytes: tunnel.stats.tx_bytes,
|
||||
rx_bytes: tunnel.stats.rx_bytes,
|
||||
dropped: tunnel.stats.dropped_wrong_source
|
||||
+ tunnel.stats.dropped_oversize,
|
||||
protocol_errors: tunnel.stats.protocol_errors,
|
||||
@@ -4131,6 +4137,8 @@ async fn build_report(
|
||||
handshake_secs_ago: None,
|
||||
tx_packets: 0,
|
||||
rx_packets: 0,
|
||||
tx_bytes: 0,
|
||||
rx_bytes: 0,
|
||||
dropped: 0,
|
||||
protocol_errors: 0,
|
||||
path: "no data link".into(),
|
||||
@@ -4147,6 +4155,8 @@ async fn build_report(
|
||||
handshake_secs_ago: None,
|
||||
tx_packets: 0,
|
||||
rx_packets: 0,
|
||||
tx_bytes: 0,
|
||||
rx_bytes: 0,
|
||||
dropped: 0,
|
||||
protocol_errors: 0,
|
||||
path: "no data link".into(),
|
||||
|
||||
@@ -83,6 +83,8 @@ struct TunnelPeerState {
|
||||
link: SharedLink,
|
||||
tx_packets: AtomicU64,
|
||||
rx_packets: AtomicU64,
|
||||
tx_bytes: AtomicU64,
|
||||
rx_bytes: AtomicU64,
|
||||
dropped: AtomicU64,
|
||||
established_at: std::time::Instant,
|
||||
}
|
||||
@@ -100,6 +102,10 @@ pub struct TunnelPeerReport {
|
||||
pub tx_packets: u64,
|
||||
/// Packets successfully received and decrypted.
|
||||
pub rx_packets: u64,
|
||||
/// Plaintext bytes successfully encrypted and sent.
|
||||
pub tx_bytes: u64,
|
||||
/// Plaintext bytes successfully received and decrypted.
|
||||
pub rx_bytes: u64,
|
||||
/// Packets dropped due to encryption/decryption/send failures.
|
||||
pub dropped: u64,
|
||||
/// Uptime in seconds since the data link was established.
|
||||
@@ -145,6 +151,8 @@ impl<C: TunnelCodec> GenericTunnelPlugin<C> {
|
||||
path: state.link.path_description(),
|
||||
tx_packets: state.tx_packets.load(Ordering::Relaxed),
|
||||
rx_packets: state.rx_packets.load(Ordering::Relaxed),
|
||||
tx_bytes: state.tx_bytes.load(Ordering::Relaxed),
|
||||
rx_bytes: state.rx_bytes.load(Ordering::Relaxed),
|
||||
dropped: state.dropped.load(Ordering::Relaxed),
|
||||
uptime_secs: state.established_at.elapsed().as_secs(),
|
||||
})
|
||||
@@ -223,6 +231,9 @@ impl<C: TunnelCodec> IpPlugin for GenericTunnelPlugin<C> {
|
||||
Ok(ciphertext) => {
|
||||
if state.link.send(ciphertext).is_ok() {
|
||||
state.tx_packets.fetch_add(1, Ordering::Relaxed);
|
||||
state
|
||||
.tx_bytes
|
||||
.fetch_add(packet.len() as u64, Ordering::Relaxed);
|
||||
true
|
||||
} else {
|
||||
state.dropped.fetch_add(1, Ordering::Relaxed);
|
||||
@@ -242,6 +253,8 @@ impl<C: TunnelCodec> IpPlugin for GenericTunnelPlugin<C> {
|
||||
link: Arc::clone(&link),
|
||||
tx_packets: AtomicU64::new(0),
|
||||
rx_packets: AtomicU64::new(0),
|
||||
tx_bytes: AtomicU64::new(0),
|
||||
rx_bytes: AtomicU64::new(0),
|
||||
dropped: AtomicU64::new(0),
|
||||
established_at: std::time::Instant::now(),
|
||||
});
|
||||
@@ -268,6 +281,9 @@ impl<C: TunnelCodec> IpPlugin for GenericTunnelPlugin<C> {
|
||||
match codec.decrypt(network, peer, &payload) {
|
||||
Ok(packet) => {
|
||||
rx_state.rx_packets.fetch_add(1, Ordering::Relaxed);
|
||||
rx_state
|
||||
.rx_bytes
|
||||
.fetch_add(packet.len() as u64, Ordering::Relaxed);
|
||||
if let Some(ref sink) = sink {
|
||||
sink.deliver(network, peer, packet).await;
|
||||
}
|
||||
|
||||
@@ -472,6 +472,10 @@ pub struct OverlayPeerReport {
|
||||
pub tx_packets: u64,
|
||||
/// Packets decrypted from this peer.
|
||||
pub rx_packets: u64,
|
||||
/// Plaintext bytes encrypted and sent to this peer.
|
||||
pub tx_bytes: u64,
|
||||
/// Plaintext bytes decrypted from this peer.
|
||||
pub rx_bytes: u64,
|
||||
/// Data packets dropped: wrong source address, or too large for the path.
|
||||
pub dropped: u64,
|
||||
/// WireGuard protocol errors.
|
||||
@@ -605,7 +609,7 @@ pub const EXCHANGE_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
///
|
||||
/// Bump it whenever [`Request`], [`Response`] or anything they contain
|
||||
/// changes shape.
|
||||
pub const CONTROL_PROTOCOL: u32 = u32::from_be_bytes([b'T', b'S', b'N', 15]);
|
||||
pub const CONTROL_PROTOCOL: u32 = u32::from_be_bytes([b'T', b'S', b'N', 16]);
|
||||
|
||||
/// Reads one request off an accepted stream, answers it, writes the response.
|
||||
///
|
||||
|
||||
Reference in new issue
Block a user