From 107e3b6851e7e7760e60b8c412c74ee2e1a58aa1 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Wed, 8 Jul 2026 14:53:08 +0300 Subject: [PATCH] stp: enforce blocking on unicast send + enhanced stats display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BridgeDevice STP hardening: - send(): check STP blocking before unicast forwarding (host-originated) - recv(): check STP blocking before unicast forwarding (switched frames) - Previously only flood() checked STP; unicast forwarding bypassed it. A blocked port must never forward any traffic — STP semantics now correct. netcfg stats enhancement: - Per-interface stats now include mtu= and link= fields alongside counters - Applies to both eth0 and loopback - Enables bandwidth monitoring tools to self-discover MTU/link state --- netstack/src/link/bridge.rs | 7 ++++++- netstack/src/scheme/netcfg/mod.rs | 10 ++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/netstack/src/link/bridge.rs b/netstack/src/link/bridge.rs index 95fa2d323c..5fa41375a0 100644 --- a/netstack/src/link/bridge.rs +++ b/netstack/src/link/bridge.rs @@ -117,6 +117,9 @@ impl LinkDevice for BridgeDevice { if repr.dst_addr.is_broadcast() || repr.dst_addr.is_multicast() { self.flood(packet, now, None); } else if let Some(port_idx) = self.lookup(dst_mac) { + if self.stp.borrow().as_ref().is_some_and(|s| s.is_blocked(port_idx)) { + return; + } if let Some(port) = self.ports.borrow_mut().get_mut(port_idx) { port.send(IpAddress::Ipv4(smoltcp::wire::Ipv4Address::UNSPECIFIED), packet, now); } @@ -179,7 +182,9 @@ impl LinkDevice for BridgeDevice { self.flood(&self.recv_buffer, now, Some(port_idx)); return Some(&self.recv_buffer); } else if let Some(dst_port_idx) = self.lookup(dst_mac) { - if dst_port_idx != port_idx { + if dst_port_idx != port_idx + && !self.stp.borrow().as_ref().is_some_and(|s| s.is_blocked(dst_port_idx)) + { let mut ports = self.ports.borrow_mut(); if let Some(target) = ports.get_mut(dst_port_idx) { target.send(IpAddress::Ipv4(smoltcp::wire::Ipv4Address::UNSPECIFIED), &packet, now); diff --git a/netstack/src/scheme/netcfg/mod.rs b/netstack/src/scheme/netcfg/mod.rs index fedfb0a678..038da7e625 100644 --- a/netstack/src/scheme/netcfg/mod.rs +++ b/netstack/src/scheme/netcfg/mod.rs @@ -351,8 +351,9 @@ fn mk_root_node( match devices.borrow().get("eth0") { Some(dev) => { let s = dev.statistics(); - format!("rx_bytes={} rx_packets={} tx_bytes={} tx_packets={}\n", - s.rx_bytes, s.rx_packets, s.tx_bytes, s.tx_packets) + format!("rx_bytes={} rx_packets={} tx_bytes={} tx_packets={} mtu={} link={}\n", + s.rx_bytes, s.rx_packets, s.tx_bytes, s.tx_packets, + dev.mtu(), dev.link_state()) } None => "Device not found\n".into(), } @@ -394,8 +395,9 @@ fn mk_root_node( match devices.borrow().get("loopback") { Some(dev) => { let s = dev.statistics(); - format!("rx_bytes={} rx_packets={} tx_bytes={} tx_packets={}\n", - s.rx_bytes, s.rx_packets, s.tx_bytes, s.tx_packets) + format!("rx_bytes={} rx_packets={} tx_bytes={} tx_packets={} mtu={} link={}\n", + s.rx_bytes, s.rx_packets, s.tx_bytes, s.tx_packets, + dev.mtu(), dev.link_state()) } None => "Device not found\n".into(), }