From nobody Sat Jun 20 23:04:16 2026 Received: from pidgin.makrotopia.org (pidgin.makrotopia.org [185.142.180.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1EBAB3C6A39; Thu, 9 Apr 2026 13:07:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.142.180.65 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775740059; cv=none; b=EasXYTomy1U5NbXYWBvSK0VNi1Vhio5XzXbzjK3XEZv7nbF/6xi1+Tq93p+rmVj6VheY1HdOAMsICD0ozfYtPMZRC0s6CZQtmGjdUfgcehJmYW2+2G5rBwsVoKitpxuE4d/ORRUPr48GjH6tgqHk/dACMtWzl4n/JBuJLn4XsQ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775740059; c=relaxed/simple; bh=dls/Wpp1Eq0cIYONF2jW98TENqkjUWDdoHaOOiHpl34=; h=Date:From:To:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=DopUIG2jcoNO1jHz4dSMc2r9h8l51B6yDAn6YnYzINZBMjq3JojAfdHwmFFmBQ/J4b0Z1p3WvOixzjeXDD9+UfkhNL4wHSIf1BSt28NnYz0+ZSGMxfkjBtfI0h96evXmTActWWnG+gB/IqjUzvgf8gykZLvTbxWurGhvB/kL4xM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=makrotopia.org; spf=pass smtp.mailfrom=makrotopia.org; arc=none smtp.client-ip=185.142.180.65 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=makrotopia.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=makrotopia.org Received: from local by pidgin.makrotopia.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.99) (envelope-from ) id 1wAp6a-000000001k4-1gBy; Thu, 09 Apr 2026 13:07:32 +0000 Date: Thu, 9 Apr 2026 14:07:29 +0100 From: Daniel Golle To: Felix Fietkau , John Crispin , Lorenzo Bianconi , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Matthias Brugger , AngeloGioacchino Del Regno , Simon Horman , Pablo Neira Ayuso , Florian Westphal , Phil Sutter , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, netfilter-devel@vger.kernel.org, coreteam@netfilter.org Subject: [PATCH RFC net-next 1/4] net: flow_offload: let drivers report byte counter semantics Message-ID: <15636456e2bb94a565d139333e586ce5b63bc8c2.1775739840.git.daniel@makrotopia.org> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Hardware flow offload engines count bytes at different points -- some report ingress L2 frame bytes, others egress L2, others L3. Add an enum so drivers can declare what their counters represent. The framework can then convert to L3 as needed for conntrack. Default is FLOW_STATS_BYTES_L3 (zero), preserving existing behaviour for all current drivers. Signed-off-by: Daniel Golle --- include/net/flow_offload.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index 70a02ee143080..7f5ef29b3abce 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -541,12 +541,19 @@ static inline bool flow_rule_match_has_control_flags(= const struct flow_rule *rul return flow_rule_has_control_flags(match.mask->flags, extack); } =20 +enum flow_stats_byte_type { + FLOW_STATS_BYTES_L3 =3D 0, /* L3 (inner IP) bytes */ + FLOW_STATS_BYTES_INGRESS_L2, /* full ingress L2 frame bytes */ + FLOW_STATS_BYTES_EGRESS_L2, /* full egress L2 frame bytes */ +}; + struct flow_stats { u64 pkts; u64 bytes; u64 drops; u64 lastused; enum flow_action_hw_stats used_hw_stats; + enum flow_stats_byte_type byte_type; bool used_hw_stats_valid; }; =20 --=20 2.53.0 From nobody Sat Jun 20 23:04:16 2026 Received: from pidgin.makrotopia.org (pidgin.makrotopia.org [185.142.180.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CAAC43CF03E; Thu, 9 Apr 2026 13:07:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.142.180.65 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775740068; cv=none; b=Vl4D2+4jiVxH8c/o6GIcjAUszhlVddT6wIOo3miPcJRgyMiU9il+gYy1Zyb126WRuRiykVmi3wvQsjaEG4VbOj6YsqFbL8wwHvJtefk53bJFk+VzjfA2X3c+xa00UOJQXCMj+BYafWfwTDwPXnqWFFbrCVynzrQxREwJNmy9j90= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775740068; c=relaxed/simple; bh=V8yWgEIDw3Aej3VaRFD1FMwXyNe1Q8zT/fES3H1tciU=; h=Date:From:To:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=N/M7rrizYePDp/pOD2G1hLdYUEzd4vVqec4xn0nftZxFZjUTbvHjuOTD2a3/H1jUWRIlNQ506D28GoSpX35ZqoU7GfONV1r+SvQQ8KPzg4Qwi4SV8Yl2cwPD+Dl0b49UJI8A9v3208jKHfO5IYMQ0L7q83aCteMWbAtL2MahT6g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=makrotopia.org; spf=pass smtp.mailfrom=makrotopia.org; arc=none smtp.client-ip=185.142.180.65 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=makrotopia.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=makrotopia.org Received: from local by pidgin.makrotopia.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.99) (envelope-from ) id 1wAp6j-000000001kZ-0rCL; Thu, 09 Apr 2026 13:07:41 +0000 Date: Thu, 9 Apr 2026 14:07:38 +0100 From: Daniel Golle To: Felix Fietkau , John Crispin , Lorenzo Bianconi , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Matthias Brugger , AngeloGioacchino Del Regno , Simon Horman , Pablo Neira Ayuso , Florian Westphal , Phil Sutter , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, netfilter-devel@vger.kernel.org, coreteam@netfilter.org Subject: [PATCH RFC net-next 2/4] nf_flow_table: track sub-interface and bridge ifindex in flow tuple Message-ID: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Store the net_device ifindex alongside each encap entry and for bridge devices during path discovery so the flow offload stats path can later update sub-interface (VLAN, PPPoE, bridge) counters for hw-offloaded flows. The indices are placed below __hash so they do not affect flow tuple lookups. No functional change -- the indices are stored but not yet used. Signed-off-by: Daniel Golle --- include/net/netfilter/nf_flow_table.h | 5 +++++ net/netfilter/nf_flow_table_core.c | 2 ++ net/netfilter/nf_flow_table_path.c | 8 ++++++++ 3 files changed, 15 insertions(+) diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/= nf_flow_table.h index b09c11c048d51..ec1a18cfd9621 100644 --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h @@ -148,6 +148,9 @@ struct flow_offload_tuple { /* All members above are keys for lookups, see flow_offload_hash(). */ struct { } __hash; =20 + int encap_ifidx[NF_FLOW_TABLE_ENCAP_MAX]; + int bridge_ifidx; + u8 dir:2, xmit_type:3, encap_num:2, @@ -221,11 +224,13 @@ struct nf_flow_route { struct { u16 id; __be16 proto; + int ifindex; } encap[NF_FLOW_TABLE_ENCAP_MAX]; struct flow_offload_tunnel tun; u8 num_encaps:2, num_tuns:2, ingress_vlans:2; + int bridge_ifindex; } in; struct { u32 ifindex; diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_tab= le_core.c index 2c4140e6f53c5..9bc8be177b392 100644 --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c @@ -115,6 +115,7 @@ static int flow_offload_fill_route(struct flow_offload = *flow, for (i =3D route->tuple[dir].in.num_encaps - 1; i >=3D 0; i--) { flow_tuple->encap[j].id =3D route->tuple[dir].in.encap[i].id; flow_tuple->encap[j].proto =3D route->tuple[dir].in.encap[i].proto; + flow_tuple->encap_ifidx[j] =3D route->tuple[dir].in.encap[i].ifindex; if (route->tuple[dir].in.ingress_vlans & BIT(i)) flow_tuple->in_vlan_ingress |=3D BIT(j); j++; @@ -123,6 +124,7 @@ static int flow_offload_fill_route(struct flow_offload = *flow, flow_tuple->tun =3D route->tuple[dir].in.tun; flow_tuple->encap_num =3D route->tuple[dir].in.num_encaps; flow_tuple->tun_num =3D route->tuple[dir].in.num_tuns; + flow_tuple->bridge_ifidx =3D route->tuple[dir].in.bridge_ifindex; =20 switch (route->tuple[dir].xmit_type) { case FLOW_OFFLOAD_XMIT_DIRECT: diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_tab= le_path.c index 6bb9579dcc2ab..c5817cb96a9f6 100644 --- a/net/netfilter/nf_flow_table_path.c +++ b/net/netfilter/nf_flow_table_path.c @@ -79,8 +79,10 @@ struct nft_forward_info { struct id { __u16 id; __be16 proto; + int ifindex; } encap[NF_FLOW_TABLE_ENCAP_MAX]; u8 num_encaps; + int bridge_ifindex; struct flow_offload_tunnel tun; u8 num_tuns; u8 ingress_vlans; @@ -136,12 +138,15 @@ static void nft_dev_path_info(const struct net_device= _path_stack *stack, path->encap.id; info->encap[info->num_encaps].proto =3D path->encap.proto; + info->encap[info->num_encaps].ifindex =3D + path->dev->ifindex; info->num_encaps++; } if (path->type =3D=3D DEV_PATH_PPPOE) memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN); break; case DEV_PATH_BRIDGE: + info->bridge_ifindex =3D path->dev->ifindex; if (is_zero_ether_addr(info->h_source)) memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); =20 @@ -156,6 +161,7 @@ static void nft_dev_path_info(const struct net_device_p= ath_stack *stack, } info->encap[info->num_encaps].id =3D path->bridge.vlan_id; info->encap[info->num_encaps].proto =3D path->bridge.vlan_proto; + info->encap[info->num_encaps].ifindex =3D path->dev->ifindex; info->num_encaps++; break; case DEV_PATH_BR_VLAN_UNTAG: @@ -261,6 +267,7 @@ static void nft_dev_forward_path(const struct nft_pktin= fo *pkt, for (i =3D 0; i < info.num_encaps; i++) { route->tuple[!dir].in.encap[i].id =3D info.encap[i].id; route->tuple[!dir].in.encap[i].proto =3D info.encap[i].proto; + route->tuple[!dir].in.encap[i].ifindex =3D info.encap[i].ifindex; } =20 if (info.num_tuns && @@ -273,6 +280,7 @@ static void nft_dev_forward_path(const struct nft_pktin= fo *pkt, =20 route->tuple[!dir].in.num_encaps =3D info.num_encaps; route->tuple[!dir].in.ingress_vlans =3D info.ingress_vlans; + route->tuple[!dir].in.bridge_ifindex =3D info.bridge_ifindex; =20 if (info.xmit_type =3D=3D FLOW_OFFLOAD_XMIT_DIRECT) { memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); --=20 2.53.0 From nobody Sat Jun 20 23:04:16 2026 Received: from pidgin.makrotopia.org (pidgin.makrotopia.org [185.142.180.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5DA073CF03E; Thu, 9 Apr 2026 13:07:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.142.180.65 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775740074; cv=none; b=jFDZgv9jNEBO2aBGHI3/XQmOEQ38X4Ot400rBaFk6HtY99ZhG62uXLwdQD1OdJiuFLdF8GLxmAmn0AfciyfeF8orftXH0EUkMekkDFfBvLMNDFwXm2qDUNBliaZ7724JXQkFH8Vr9etVKMM6UU79h+LQsMS3zBkgPwzBt3ijrPE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775740074; c=relaxed/simple; bh=qgHyUF6g4crc16uF8ArziTxB513q2/NNff1YStmKGOY=; h=Date:From:To:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=gqG88ufibPn3bUWaF5sCWGSCDbJzjiFzB48ud6wQ5MAdufofo9le3/jplBPmdWGflKuAaGo+z5/y05gduNDKLCcn8u5pEhEZgVKyVqmZN1XwYCEABQ8LI6vjIQ29Qvhiaw468j08hL9bCL3EDYMXSY9HC3I6i63XC/6sLklhSTg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=makrotopia.org; spf=pass smtp.mailfrom=makrotopia.org; arc=none smtp.client-ip=185.142.180.65 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=makrotopia.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=makrotopia.org Received: from local by pidgin.makrotopia.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.99) (envelope-from ) id 1wAp6p-000000001km-2eEu; Thu, 09 Apr 2026 13:07:47 +0000 Date: Thu, 9 Apr 2026 14:07:44 +0100 From: Daniel Golle To: Felix Fietkau , John Crispin , Lorenzo Bianconi , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Matthias Brugger , AngeloGioacchino Del Regno , Simon Horman , Pablo Neira Ayuso , Florian Westphal , Phil Sutter , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, netfilter-devel@vger.kernel.org, coreteam@netfilter.org Subject: [PATCH RFC net-next 3/4] nf_flow_table: convert hw byte counts and update sub-interface stats Message-ID: <28eadbf14db58dd6e402325b62658a86d240e0f9.1775739840.git.daniel@makrotopia.org> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Hardware flow offload counters may report L2 frame bytes while conntrack expects L3 (IP) bytes. When a driver sets byte_type to INGRESS_L2 or EGRESS_L2, subtract the appropriate per-direction encap and tunnel overhead to derive L3 byte counts for conntrack. Additionally, propagate per-flow stats to bridge, VLAN and PPPoE sub-interfaces that are bypassed by hardware offloading. Each sub-interface gets the L3 byte count plus the overhead of any inner encap layers below it, matching what the software path would count. Both RX and TX directions are updated. Signed-off-by: Daniel Golle --- net/netfilter/nf_flow_table_offload.c | 174 +++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_= table_offload.c index 002ec15d988bd..67452da487c94 100644 --- a/net/netfilter/nf_flow_table_offload.c +++ b/net/netfilter/nf_flow_table_offload.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include #include @@ -1008,10 +1010,135 @@ static void flow_offload_tuple_stats(struct flow_o= ffload_work *offload, &offload->flowtable->flow_block.cb_list); } =20 +static int flow_offload_encap_hlen(const struct flow_offload_tuple *tuple, + int idx) +{ + switch (tuple->encap[idx].proto) { + case htons(ETH_P_8021Q): + case htons(ETH_P_8021AD): + return VLAN_HLEN; + case htons(ETH_P_PPP_SES): + return PPPOE_SES_HLEN; + } + return 0; +} + +static void flow_offload_encap_netstats(struct net_device *dev, + __be16 encap_proto, + bool rx, u64 pkts, u64 bytes) +{ + struct pcpu_sw_netstats *tstats; + struct vlan_pcpu_stats *vstats; + + if (encap_proto =3D=3D htons(ETH_P_8021Q) || + encap_proto =3D=3D htons(ETH_P_8021AD)) { + vstats =3D this_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats); + u64_stats_update_begin(&vstats->syncp); + if (rx) { + u64_stats_add(&vstats->rx_packets, pkts); + u64_stats_add(&vstats->rx_bytes, bytes); + } else { + u64_stats_add(&vstats->tx_packets, pkts); + u64_stats_add(&vstats->tx_bytes, bytes); + } + u64_stats_update_end(&vstats->syncp); + } else if (dev->tstats) { + tstats =3D this_cpu_ptr(dev->tstats); + u64_stats_update_begin(&tstats->syncp); + if (rx) { + u64_stats_add(&tstats->rx_packets, pkts); + u64_stats_add(&tstats->rx_bytes, bytes); + } else { + u64_stats_add(&tstats->tx_packets, pkts); + u64_stats_add(&tstats->tx_bytes, bytes); + } + u64_stats_update_end(&tstats->syncp); + } +} + +/* Update sub-interface (VLAN, PPPoE) stats for hw-offloaded flows. + * + * The driver reports L3 (IP) bytes. Each sub-interface in the + * software path sees the frame with the headers of all layers + * BELOW it still present, so we add back inner-layer overhead. + * + * encap[] is ordered outermost to innermost, so walk from the + * innermost layer outward, accumulating overhead as we go. + */ +static void flow_offload_update_encap_stats(struct flow_offload *flow, + struct flow_offload_tuple *tuple, + bool rx, u64 pkts, u64 bytes) +{ + struct net_device *dev; + int inner_hlen =3D 0; + int i; + + for (i =3D tuple->encap_num - 1; i >=3D 0; i--) { + if (tuple->in_vlan_ingress & BIT(i)) + continue; + + dev =3D dev_get_by_index_rcu(dev_net(flow->ct->ct_net), + tuple->encap_ifidx[i]); + if (dev) + flow_offload_encap_netstats(dev, + tuple->encap[i].proto, rx, + pkts, + bytes + inner_hlen * pkts); + + inner_hlen +=3D flow_offload_encap_hlen(tuple, i); + } + + /* Bridge device sits outside all encap layers -- it sees + * L3 bytes plus the full encap overhead. + */ + if (tuple->bridge_ifidx) { + dev =3D dev_get_by_index_rcu(dev_net(flow->ct->ct_net), + tuple->bridge_ifidx); + if (dev && dev->tstats) + flow_offload_encap_netstats(dev, 0, rx, pkts, + bytes + inner_hlen * pkts); + } +} + +/* Compute per-direction input overhead from the encap and tunnel + * chains. Hardware flow counters report L2 frame bytes but + * conntrack expects L3 (inner IP) bytes -- matching what the + * software path sees after stripping all encap and tunnel headers. + */ +static int flow_offload_input_l2_overhead(struct flow_offload_tuple *tuple) +{ + int overhead =3D ETH_HLEN; + int i; + + for (i =3D 0; i < tuple->encap_num; i++) { + if (tuple->in_vlan_ingress & BIT(i)) + continue; + + overhead +=3D flow_offload_encap_hlen(tuple, i); + } + + if (tuple->tun_num) { + switch (tuple->tun.l3_proto) { + case IPPROTO_IPIP: + overhead +=3D sizeof(struct iphdr); + break; + case IPPROTO_IPV6: + overhead +=3D sizeof(struct ipv6hdr); + break; + } + } + + return overhead; +} + static void flow_offload_work_stats(struct flow_offload_work *offload) { + struct flow_offload_tuple *tuple; struct flow_stats stats[FLOW_OFFLOAD_DIR_MAX] =3D {}; + u64 l3_bytes[FLOW_OFFLOAD_DIR_MAX]; + int l2_overhead; u64 lastused; + int i; =20 flow_offload_tuple_stats(offload, FLOW_OFFLOAD_DIR_ORIGINAL, &stats[0]); if (test_bit(NF_FLOW_HW_BIDIRECTIONAL, &offload->flow->flags)) @@ -1022,16 +1149,59 @@ static void flow_offload_work_stats(struct flow_off= load_work *offload) offload->flow->timeout =3D max_t(u64, offload->flow->timeout, lastused + flow_offload_get_timeout(offload->flow)); =20 + /* Convert hardware byte counts to L3 based on what the driver + * reports. Drivers that already report L3 (or do not set + * byte_type) need no conversion. + */ + for (i =3D 0; i < FLOW_OFFLOAD_DIR_MAX; i++) { + l2_overhead =3D 0; + + switch (stats[i].byte_type) { + case FLOW_STATS_BYTES_INGRESS_L2: + tuple =3D &offload->flow->tuplehash[i].tuple; + l2_overhead =3D flow_offload_input_l2_overhead(tuple); + break; + case FLOW_STATS_BYTES_EGRESS_L2: + tuple =3D &offload->flow->tuplehash[!i].tuple; + l2_overhead =3D flow_offload_input_l2_overhead(tuple); + break; + default: + break; + } + l3_bytes[i] =3D stats[i].bytes - stats[i].pkts * l2_overhead; + } + if (offload->flowtable->flags & NF_FLOWTABLE_COUNTER) { if (stats[0].pkts) nf_ct_acct_add(offload->flow->ct, FLOW_OFFLOAD_DIR_ORIGINAL, - stats[0].pkts, stats[0].bytes); + stats[0].pkts, l3_bytes[0]); if (stats[1].pkts) nf_ct_acct_add(offload->flow->ct, FLOW_OFFLOAD_DIR_REPLY, - stats[1].pkts, stats[1].bytes); + stats[1].pkts, l3_bytes[1]); + } + + rcu_read_lock(); + for (i =3D 0; i < FLOW_OFFLOAD_DIR_MAX; i++) { + tuple =3D &offload->flow->tuplehash[i].tuple; + if (!tuple->encap_num) + continue; + + /* Input-side encap devices get RX stats */ + if (stats[i].pkts) + flow_offload_update_encap_stats(offload->flow, + tuple, true, + stats[i].pkts, + l3_bytes[i]); + /* Same devices get TX stats from the other direction */ + if (stats[!i].pkts) + flow_offload_update_encap_stats(offload->flow, + tuple, false, + stats[!i].pkts, + l3_bytes[!i]); } + rcu_read_unlock(); } =20 static void flow_offload_work_handler(struct work_struct *work) --=20 2.53.0 From nobody Sat Jun 20 23:04:16 2026 Received: from pidgin.makrotopia.org (pidgin.makrotopia.org [185.142.180.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC9E73CF03E; Thu, 9 Apr 2026 13:07:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.142.180.65 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775740079; cv=none; b=Oy2mTNiUNDMcLQ/MfdW5E7o36lwBaKXzgswHjqljd0pHUTOCAWGJi/dzM4N6HKDzmvm0eRiiWQkl5Y/fdBZy7I4CNi9vM+wTsqLaWhBnI+r5jlUvZqJCbL1CbLeAMou+ibGY3Rv6Zxe80fWxviZ4t/n1zXc3Z8Mdh/qMo2HACSI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775740079; c=relaxed/simple; bh=JToKvM0nCAeg2dU3OZHC3s+o3UUMhQuLTgZjYTPMY9U=; h=Date:From:To:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=d+uSLpfqDFD5lzgbm5MMeb33DslOWuNf5c88eaygTk7MWR1VxRiZnC2grKojKXdTkdWoTvg83R6AyotMpE+/ZJK+9Qbhm9xvylxb+yTGC2u6W8l9dxPdgCObM3IzHAczJTEJpWbwV84OpeUy9ZyKsxHqxAC/cVdOv9V5XCER3/w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=makrotopia.org; spf=pass smtp.mailfrom=makrotopia.org; arc=none smtp.client-ip=185.142.180.65 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=makrotopia.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=makrotopia.org Received: from local by pidgin.makrotopia.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.99) (envelope-from ) id 1wAp6w-000000001l8-25rf; Thu, 09 Apr 2026 13:07:54 +0000 Date: Thu, 9 Apr 2026 14:07:51 +0100 From: Daniel Golle To: Felix Fietkau , John Crispin , Lorenzo Bianconi , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Matthias Brugger , AngeloGioacchino Del Regno , Simon Horman , Pablo Neira Ayuso , Florian Westphal , Phil Sutter , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, netfilter-devel@vger.kernel.org, coreteam@netfilter.org Subject: [PATCH RFC net-next 4/4] net: ethernet: mtk_eth_soc: report INGRESS_L2 byte_type in flow stats Message-ID: <2a1df22e3ff326cee3a70d346fb87b4a446554f3.1775739840.git.daniel@makrotopia.org> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The MediaTek PPE MIB counters report ingress L2 frame bytes including Ethernet, VLAN and PPPoE headers. Tell the flow offload framework so it can derive correct L3 byte counts for conntrack and update sub-interface counters. Signed-off-by: Daniel Golle --- drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/= ethernet/mediatek/mtk_ppe_offload.c index cc8c4ef8038f3..68cb03a193f3f 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c @@ -557,6 +557,7 @@ mtk_flow_offload_stats(struct mtk_eth *eth, struct flow= _cls_offload *f) &diff)) { f->stats.pkts +=3D diff.packets; f->stats.bytes +=3D diff.bytes; + f->stats.byte_type =3D FLOW_STATS_BYTES_INGRESS_L2; } =20 return 0; --=20 2.53.0