__mtk_ppe_check_skb() clears entry->hash for flows bound to other hardware slots in the same software hash bucket. This makes mtk_flow_offload_stats() skip their hardware counter updates. In the regular flow branch, clear entry->hash only when it matches the slot being checked. Fixes: c4f033d9e03e ("net: ethernet: mtk_eth_soc: rework hardware flow table management") Link: https://github.com/openwrt/openwrt/pull/26107 Assisted-by: LLM Signed-off-by: Alexander Goodkind --- The MediaTek Ethernet driver stores forwarding rules for active connections in hardware slots. For a bound flow entry, entry->hash stores the hardware slot index. Flow entries for different hardware slots can share the same software hash bucket. OpenWrt's driver maintains cumulative packet and byte totals. During each statistics update, mtk_flow_offload_stats() subtracts the previous reading from the current total to calculate newly transferred traffic. Losing a hardware slot association lowers the current total used in that calculation and causes unsigned underflow. Conversion to 32 bits produces a false increase of about 4 GiB. Subsequent calls to mtk_foe_entry_get_stats() return only the unchanged prev_packets and prev_bytes values, and mtk_flow_offload_stats() subtracts identical readings and reports zero increments while traffic continues. Two UDP trials reproduced this failure on a GL-MT3000 with MT7981 running OpenWrt 25.12.5 and Linux 6.12.94. ARM64 allmodconfig and allyesconfig builds passed on net ffdf678dd166 with GCC 14.2.0, W=1 and CONFIG_WERROR=n. Patched builds did not add warnings. Existing -Woverride-init warnings fail the unmodified build with CONFIG_WERROR=y. Codex assisted with investigating the counters and preparing the patch. drivers/net/ethernet/mediatek/mtk_ppe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c @@ -764,7 +764,7 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash) } if (found || !mtk_flow_entry_match(ppe->eth, entry, hwe)) { - if (entry->hash != 0xffff) + if (entry->hash == hash) entry->hash = 0xffff; continue; } base-commit: ffdf678dd16610e3f006dac904bd37c09684673c