From ecc0ef33dea6da9ce338c4623488bfe662b5ad5a Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Wed, 8 Jul 2026 19:41:05 +0300 Subject: [PATCH] =?UTF-8?q?netfilter:=20add=20counters/reset=20path=20?= =?UTF-8?q?=E2=80=94=20preserves=20rules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously '/reset' replaced the entire FilterTable (destructive). Added '/counters/reset' that clears: - chain_counters (per-chain packets/bytes) - rule.match_count (per-rule match counts) WITHOUT removing rules or resetting policies. FilterTable gains reset_counters() method. Usage: echo > /scheme/netfilter/reset # wipe everything echo > /scheme/netfilter/counters/reset # clear metrics only Mirrors Linux 'iptables -Z' (zero counters) vs full flush. --- netstack/src/filter/table.rs | 12 ++++++++++++ netstack/src/scheme/netfilter.rs | 3 +++ 2 files changed, 15 insertions(+) diff --git a/netstack/src/filter/table.rs b/netstack/src/filter/table.rs index 9f707a5a48..a85aec85de 100644 --- a/netstack/src/filter/table.rs +++ b/netstack/src/filter/table.rs @@ -180,6 +180,18 @@ impl FilterTable { pub fn set_default_policy(&mut self, hook: Hook, verdict: Verdict) { self.default_policy.insert(hook, verdict); } + + /// Clear per-chain counters and per-rule match counts. + /// Rules themselves are preserved. Use this to restart metrics + /// without losing configuration. + pub fn reset_counters(&mut self) { + for counter in self.chain_counters.values_mut() { + *counter = (0, 0); + } + for rule in &mut self.rules { + rule.match_count = 0; + } + } } fn format_rule(rule: &FilterRule) -> String { diff --git a/netstack/src/scheme/netfilter.rs b/netstack/src/scheme/netfilter.rs index 893d78e311..f0b0b45a7e 100644 --- a/netstack/src/scheme/netfilter.rs +++ b/netstack/src/scheme/netfilter.rs @@ -282,6 +282,9 @@ impl NetFilterFile { } else if path == "/reset" { *table = FilterTable::new(); log::info!("netfilter: table reset to defaults"); + } else if path == "/counters/reset" { + table.reset_counters(); + log::info!("netfilter: counters reset (rules preserved)"); } else if let Some(rest) = path.strip_prefix("/policy/") { let hook = parse_hook_name(rest).ok_or(SyscallError::new(syscall::EINVAL))?; let verdict = match line.to_uppercase().as_str() {