From 998593f2435d65db21aa1c6d7dddfa5e985d041b Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Wed, 8 Jul 2026 16:00:26 +0300 Subject: [PATCH] stats: add statistics() to bridge, bond, and tun devices Bridge: statistics() aggregates rx/tx bytes+packets from all member ports. arp_stats() delegates to each port, showing per-port breakdown. Bond: statistics() aggregates from all slaves (active+standby). arp_stats() delegates to each slave. TUN: statistics() now returns live counters tracked during send()/recv(). rx_bytes, rx_packets, tx_bytes, tx_packets increment per-packet. Previously these devices returned Stats::default() (all zeros). Now netcfg /ifaces/*/stats shows real data for bridge, bond, tun. --- netstack/src/link/bond.rs | 25 +++++++++++++++++++++++++ netstack/src/link/bridge.rs | 24 ++++++++++++++++++++++++ netstack/src/link/tun.rs | 11 +++++++++++ 3 files changed, 60 insertions(+) diff --git a/netstack/src/link/bond.rs b/netstack/src/link/bond.rs index 434b5cd0f3..da806b23e6 100644 --- a/netstack/src/link/bond.rs +++ b/netstack/src/link/bond.rs @@ -18,6 +18,7 @@ use smoltcp::time::Instant; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use super::LinkDevice; +use super::Stats; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum BondMode { @@ -166,4 +167,28 @@ impl LinkDevice for BondDevice { } out } + + fn statistics(&self) -> Stats { + let mut total = Stats::default(); + for s in self.slaves.borrow().iter() { + let stats = s.dev.statistics(); + total.rx_bytes += stats.rx_bytes; + total.rx_packets += stats.rx_packets; + total.tx_bytes += stats.tx_bytes; + total.tx_packets += stats.tx_packets; + } + total + } + + fn arp_stats(&self) -> String { + let mut out = String::new(); + let slaves = self.slaves.borrow(); + for (i, s) in slaves.iter().enumerate() { + let stats = s.dev.arp_stats(); + if !stats.is_empty() { + out.push_str(&format!("slave{}: {}", i, stats)); + } + } + out + } } \ No newline at end of file diff --git a/netstack/src/link/bridge.rs b/netstack/src/link/bridge.rs index 5fa41375a0..7127970596 100644 --- a/netstack/src/link/bridge.rs +++ b/netstack/src/link/bridge.rs @@ -23,6 +23,7 @@ use smoltcp::wire::{ use super::stp::{self, BPDU_MAC, PortState, StpState}; use super::LinkDevice; +use super::Stats; const MAC_AGE_TIMEOUT: Duration = Duration::from_secs(300); @@ -235,4 +236,27 @@ impl LinkDevice for BridgeDevice { fn link_state(&self) -> &'static str { if self.ports.borrow().is_empty() { "down" } else { "up" } } + + fn statistics(&self) -> Stats { + let mut total = Stats::default(); + for port in self.ports.borrow().iter() { + let s = port.statistics(); + total.rx_bytes += s.rx_bytes; + total.rx_packets += s.rx_packets; + total.tx_bytes += s.tx_bytes; + total.tx_packets += s.tx_packets; + } + total + } + + fn arp_stats(&self) -> String { + let mut out = String::new(); + for (i, port) in self.ports.borrow().iter().enumerate() { + let s = port.arp_stats(); + if !s.is_empty() { + out.push_str(&format!("port{}: {}", i, s)); + } + } + out + } } \ No newline at end of file diff --git a/netstack/src/link/tun.rs b/netstack/src/link/tun.rs index d9781ad9bb..5849243b81 100644 --- a/netstack/src/link/tun.rs +++ b/netstack/src/link/tun.rs @@ -16,6 +16,7 @@ use smoltcp::time::Instant; use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr}; use super::LinkDevice; +use super::Stats; pub type PacketQueue = Rc>>>; @@ -25,6 +26,7 @@ pub struct TunDevice { tx_queue: PacketQueue, recv_buffer: Vec, ip_address: Option, + stats: Stats, } impl TunDevice { @@ -35,17 +37,22 @@ impl TunDevice { tx_queue: tx, recv_buffer: Vec::new(), ip_address: None, + stats: Stats::default(), } } } impl LinkDevice for TunDevice { fn send(&mut self, _next_hop: IpAddress, packet: &[u8], _now: Instant) { + self.stats.tx_bytes += packet.len() as u64; + self.stats.tx_packets += 1; self.tx_queue.borrow_mut().push_back(packet.to_vec()); } fn recv(&mut self, _now: Instant) -> Option<&[u8]> { self.recv_buffer = self.rx_queue.borrow_mut().pop_front()?; + self.stats.rx_bytes += self.recv_buffer.len() as u64; + self.stats.rx_packets += 1; Some(&self.recv_buffer) } @@ -70,4 +77,8 @@ impl LinkDevice for TunDevice { fn set_ip_address(&mut self, addr: IpCidr) { self.ip_address = Some(addr); } + + fn statistics(&self) -> Stats { + self.stats + } } \ No newline at end of file