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.
This commit is contained in:
Red Bear OS
2026-07-08 16:00:26 +03:00
parent 5cfbe23b5c
commit 998593f243
3 changed files with 60 additions and 0 deletions
+25
View File
@@ -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
}
}
+24
View File
@@ -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
}
}
+11
View File
@@ -16,6 +16,7 @@ use smoltcp::time::Instant;
use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
use super::LinkDevice;
use super::Stats;
pub type PacketQueue = Rc<RefCell<VecDeque<Vec<u8>>>>;
@@ -25,6 +26,7 @@ pub struct TunDevice {
tx_queue: PacketQueue,
recv_buffer: Vec<u8>,
ip_address: Option<IpCidr>,
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
}
}