netcfg: add summary node — at-a-glance network state

/scheme/netcfg/summary outputs:
  interfaces: eth0=up lo=up
  routes: 4
  sockets: 7 (tcp=3 udp=4 icmp=0 raw=0)
  ip_forward: 1
  eth0 stats: rx=1234/16 tx=5678/12 err=0/0 drop=0/2

Single read aggregates:
- Link state of eth0 and loopback
- Total route count
- Per-protocol socket counts (TCP/UDP/ICMP/Raw)
- ip_forward toggle state
- Full MIB-II stats for eth0

Useful for at-a-glance monitoring without reading 6+ separate nodes.
This commit is contained in:
Red Bear OS
2026-07-08 19:16:46 +03:00
parent 19199096c5
commit 1036881f03
+34
View File
@@ -106,6 +106,40 @@ fn mk_root_node(
observer: ObserverRef,
) -> CfgNodeRef {
cfg_node! {
"summary" => {
ro [devices, route_table, socket_set, ip_forward] || {
let mut out = String::new();
let devs = devices.borrow();
let eth0 = devs.get("eth0");
let lo = devs.get("loopback");
let eth_state = eth0.map(|d| d.link_state()).unwrap_or("missing");
let lo_state = lo.map(|d| d.link_state()).unwrap_or("missing");
out.push_str(&format!("interfaces: eth0={} lo={}\n", eth_state, lo_state));
out.push_str(&format!("routes: {}\n", route_table.borrow().len()));
let set = socket_set.borrow();
let mut tcp = 0u32; let mut udp = 0u32; let mut icmp = 0u32; let mut raw = 0u32;
for (_handle, socket) in set.iter() {
match socket {
smoltcp::socket::Socket::Tcp(_) => tcp += 1,
smoltcp::socket::Socket::Udp(_) => udp += 1,
smoltcp::socket::Socket::Icmp(_) => icmp += 1,
smoltcp::socket::Socket::Raw(_) => raw += 1,
_ => {}
}
}
out.push_str(&format!("sockets: {} (tcp={} udp={} icmp={} raw={})\n",
tcp + udp + icmp + raw, tcp, udp, icmp, raw));
out.push_str(&format!("ip_forward: {}\n",
if ip_forward.get() { "1" } else { "0" }));
if let Some(dev) = eth0 {
let s = dev.statistics();
out.push_str(&format!("eth0 stats: rx={}/{} tx={}/{} err={}/{} drop={}/{}\n",
s.rx_bytes, s.rx_packets, s.tx_bytes, s.tx_packets,
s.rx_errors, s.tx_errors, s.rx_dropped, s.tx_dropped));
}
out
}
},
"capture" => {
"enable" => {
wo [observer] (Option<()>, None)