From c1cfee3beaa33818e636f3fd49cfeed88cd2fe50 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Wed, 8 Jul 2026 17:50:31 +0300 Subject: [PATCH] qdisc: expose traffic shaping info via netcfg and LinkDevice trait MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LinkDevice gains qdisc_info() → String defaulting to 'none'. EthernetLink reports current qdisc configuration: none / token_bucket rate=N burst=N tokens=N / priority_queue len=N max=N TokenBucket and PriorityQueue gain public accessor methods: rate(), burst(), tokens() / max_len() netcfg exposes at /scheme/netcfg/ifaces/eth0/qdisc: cat /scheme/netcfg/ifaces/eth0/qdisc → 'none' (default) Enables monitoring tools to discover current traffic shaping. Future: wo node for configuring qdisc type + parameters. --- netstack/src/link/ethernet.rs | 12 ++++++++++++ netstack/src/link/mod.rs | 4 ++++ netstack/src/link/qdisc.rs | 18 ++++++------------ netstack/src/scheme/netcfg/mod.rs | 8 ++++++++ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/netstack/src/link/ethernet.rs b/netstack/src/link/ethernet.rs index 89d1ea5361..b9a4c45d35 100644 --- a/netstack/src/link/ethernet.rs +++ b/netstack/src/link/ethernet.rs @@ -882,5 +882,17 @@ impl LinkDevice for EthernetLink { fn link_state(&self) -> &'static str { if self.hardware_address.is_some() { "up" } else { "down" } } + + fn qdisc_info(&self) -> String { + match &self.qdisc_config { + QdiscConfig::None => "none\n".to_string(), + QdiscConfig::TokenBucket(tb) => { + format!("token_bucket rate={} burst={} tokens={}\n", tb.rate(), tb.burst(), tb.tokens()) + } + QdiscConfig::PriorityQueue(pq) => { + format!("priority_queue len={} max={}\n", pq.len(), pq.max_len()) + } + } + } } diff --git a/netstack/src/link/mod.rs b/netstack/src/link/mod.rs index fdff2467f2..b73401434c 100644 --- a/netstack/src/link/mod.rs +++ b/netstack/src/link/mod.rs @@ -49,6 +49,10 @@ pub trait LinkDevice { String::new() } + fn qdisc_info(&self) -> String { + "none\n".to_string() + } + fn mtu(&self) -> usize { 1500 } diff --git a/netstack/src/link/qdisc.rs b/netstack/src/link/qdisc.rs index 4c190fc05f..edc78d0b82 100644 --- a/netstack/src/link/qdisc.rs +++ b/netstack/src/link/qdisc.rs @@ -25,13 +25,11 @@ pub struct TokenBucket { impl TokenBucket { pub fn new(rate_bps: u64, burst_bytes: u64) -> Self { - Self { - rate: rate_bps, - burst: burst_bytes.max(1500), - tokens: burst_bytes.max(1500), - last_update: Instant::from_millis(0), - } + Self { rate: rate_bps, burst: burst_bytes.max(1500), tokens: burst_bytes.max(1500), last_update: Instant::from_millis(0) } } + pub fn rate(&self) -> u64 { self.rate } + pub fn burst(&self) -> u64 { self.burst } + pub fn tokens(&self) -> u64 { self.tokens } pub fn set_rate(&mut self, rate_bps: u64) { self.rate = rate_bps; @@ -67,12 +65,8 @@ pub struct PriorityQueue { } impl PriorityQueue { - pub fn new(max_len: usize) -> Self { - Self { - bands: [VecDeque::new(), VecDeque::new(), VecDeque::new()], - max_len, - } - } + pub fn new(max_len: usize) -> Self { Self { bands: [VecDeque::new(), VecDeque::new(), VecDeque::new()], max_len } } + pub fn max_len(&self) -> usize { self.max_len } fn classify(packet: &[u8]) -> usize { if packet.len() < 2 || packet[0] >> 4 != 4 { diff --git a/netstack/src/scheme/netcfg/mod.rs b/netstack/src/scheme/netcfg/mod.rs index 2cdd36f6ba..78763bebbc 100644 --- a/netstack/src/scheme/netcfg/mod.rs +++ b/netstack/src/scheme/netcfg/mod.rs @@ -458,6 +458,14 @@ fn mk_root_node( None => "Device not found\n".into(), } } + }, + "qdisc" => { + ro [devices] || { + match devices.borrow().get("eth0") { + Some(dev) => dev.qdisc_info(), + None => "Device not found\n".into(), + } + } } }, "lo" => {