[PATCH net-next v2 1/2] ipvlan: fix RX byte accounting for local traffic
From: Xia Yan
Date: Wed Nov 11 2026 - 21:57:13 EST
For traffic between ipvlan devices on the same lower device,
skb->len already includes the Ethernet header. Adding ETH_HLEN
again in ipvlan_rcv_frame() overcounts rx_bytes by 14 bytes per
packet. ipvlan_process_multicast() does the same for local broadcast
and multicast traffic.
Packets received from the lower device have had the Ethernet header
pulled by eth_type_trans(), so their counters still need ETH_HLEN.
Use the existing local and tx_pkt flags to distinguish these paths.
Found during a code review of the ipvlan receive paths.
Sending five IPv4 UDP packets with 32-byte payloads between ipvlan
devices in separate network namespaces increases rx_bytes by 440
instead of 370. With this change the count is 370. External RX byte
counts are unchanged in the same tests.
Tested before and after the change with custom IPv4 and IPv6 UDP
tests in UML, covering L2 unicast, broadcast and joined multicast,
and L3 unicast.
Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.")
Signed-off-by: Xia Yan <yanxia@xxxxxxxxxxxxxxxxxxxx>
---
drivers/net/ipvlan/ipvlan_core.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 7ad12dc78..ba646293a 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -276,7 +276,7 @@ void ipvlan_process_multicast(struct work_struct *work)
if (!(ipvlan->dev->flags & IFF_UP))
continue;
ret = NET_RX_DROP;
- len = skb->len + ETH_HLEN;
+ len = skb->len + (tx_pkt ? 0 : ETH_HLEN);
nskb = skb_clone(skb, GFP_ATOMIC);
local_bh_disable();
if (nskb) {
@@ -331,7 +331,7 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb,
bool success = false;
struct sk_buff *skb = *pskb;
- len = skb->len + ETH_HLEN;
+ len = skb->len + (local ? 0 : ETH_HLEN);
/* Only packets exchanged between two local slaves need to have
* device-up check as well as skb-share check.
*/