From: Junnan Zhang <zhangjn_dev@163.com>
To: willemdebruijn.kernel@gmail.com
Cc: davem@davemloft.net, edumazet@google.com, horms@kernel.org,
kuba@kernel.org, linux-kernel@vger.kernel.org,
liuhangbin@gmail.com, mst@redhat.com, netdev@vger.kernel.org,
pabeni@redhat.com, sunshx@chinatelecom.cn,
zhangjn11@chinatelecom.cn, zhangjn_dev@163.com
Subject: Re: [PATCH] net/packet: fix network header offset-VLAN raw packets on VLAN subinterfaces
Date: Tue, 25 Aug 2026 01:37:45 +0800 [thread overview]
Message-ID: <20260824173745.16757-1-zhangjn_dev@163.com> (raw)
In-Reply-To: <willemdebruijn.kernel.2d3e4407199d8@gmail.com>
Hi Willem,
Thank you for the review.
> > AF_PACKET SOCK_RAW reserves dev->hard_header_len bytes of headroom. For
> > VLAN subinterfaces, hard_header_len VLAN tag space (18 bytes)
>
> Does it?
>
> vlan_dev_init:
>
> dev->hard_header_len = real_dev->hard_header_len;
You are right that this is only true when VLAN hardware offloading is
available, i.e. vlan_hw_offload_capable() returns true and vlan_dev_init()
takes the first branch. The bug I am fixing only happens in the else
branch:
dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
I observed it on a virtio_net device, which advertises
NETIF_F_HW_VLAN_CTAG_FILTER but not IF_F_HW_VLAN_CTAG_TX. So any VLAN
subinterface created on top of it uses software VLAN tag insertion and
has hard_header_len = 18 while min_header_len stays at 14.
> > while min_header_len is the real Ethernet header length (14 bytes). When
>
> Which device did you observe this with?
virtio_net (in a KVM/QEMU guest).
> > userspace sends a standard untagged Ethernet frame through a VLAN
> > subinterface, packet_parse_headers() only correct_header for
> > VLAN-tagged frames. For non-VLAN frames it leaves network_header at
> > hard_header_len, so the IP header is found 4 bytes too late and
> > inet_gso_segment() fails with -EINVAL.
>
> Which path did you observe generating these untagged packets through
> a VLAN interface?
The reproducer is an AF_PACKET SOCK_RAW socket bound to the VLAN
subinterface, with PACKET_VNET_HDR enabled. Userspace sends a large
IPv4/TCP frame that exceeds the path MTU; the virtio-net header in the
packet sets gso_type, so the skb goes through GSO. The userspace frame
contains a plain Ethernet + IP + TCP layout, without a VLAN tag. The VLAN
sub inserts the 802.1Q tag in vlan_dev_hard_start_xmit().
Before the fix, packet_snd() leaves network_header at base +
hard_header_len (18), while the real IP header starts at base + 14 + 14 =
base + 28. network_header points 4 bytes past the IP header, so
inet_gso_segment() gets a misaligned ip_hdr(skb) and returns -EINVAL.
> > + bool has_vlan;
>
> nit: confusing variable, combining test on packet and device.
Ag. In v2 I will restructure the function to test dev->type once and
use a clearly packet-only variable. For example:
if (likely(skb->dev->type == ARPHRD_ETHER)) {
bool is_vlan = eth_type_vlan(skb->protocol);
if (!is_vlan && sock->type == SOCK_RAW &&
skb->dev->min_header_len < skb->dev->hard_header_len)
skb_set_network_header(skb, skb->dev->min_header_len);
skb_probe_transport_header(skb);
if (is_vlan &&
vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
skb_set_network_header(skb, depth);
} else {
skb_probe_transport_header(skb);
}
> > + likely(skb->dev->type == ARPHRD_ETHER) &&
>
> nit: repeat test, also included in that has_vlan
Yes, this is fixed by the above restructuring. ARPHRD_ETHER is tested
only once.
I will update the commit message to make the "non-offload VLAN
subinterface" scope explicit, add the virtio_net observation and the
reproducer, and fix the code nits. I will then send v2 as a separate
thread per netdev posting rules.
Thanks,
Junnan Zhang
next prev parent reply other threads:[~2026-08-24 17:38 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 8:57 [PATCH] net/packet: fix network header offset for non-VLAN raw packets on VLAN subinterfaces Junnan Zhang
2026-08-22 19:21 ` Willem de Bruijn
2026-08-24 17:37 ` Junnan Zhang [this message]
2026-08-25 16:26 ` [PATCH] net/packet: fix network header offset-VLAN " Willem de Bruijn
2026-08-26 15:58 ` Junnan Zhang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260824173745.16757-1-zhangjn_dev@163.com \
--to=zhangjn_dev@163.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=liuhangbin@gmail.com \
--cc=mst@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sunshx@chinatelecom.cn \
--cc=willemdebruijn.kernel@gmail.com \
--cc=zhangjn11@chinatelecom.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.