[Intel-wired-lan] [PATCH iwl-net] idpf: account for VLAN header when parsing RSC packet header
Joshua Hay <[email protected]> Mon, 27 Jul 2026 16:08:48 -0700
| Newsgroups | org.osuosl.intel-wired-lan,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
While parsing the header of a Receive Side Coalesced (RSC) packet, check
if a VLAN tag is present and adjust the header parsing accordingly.
Otherwise, Rx TCP traffic is completely broken for any VLAN interface
whose underlying interface has RSC (rx-gro-hw) enabled.
We only need to worry about one VLAN header since Rx packets with
multiple VLAN headers are not candidates for RSC.
Fixes: 3a8845af66edb ("idpf: add RX splitq napi poll support")
Signed-off-by: Joshua Hay <[email protected]>
Reviewed-by: Emil Tantilov <[email protected]>
---
drivers/net/ethernet/intel/idpf/idpf_txrx.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
index c724d429a7aa..70553f64f770 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -3299,6 +3299,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
struct libeth_rx_pt decoded)
{
u16 rsc_segments, rsc_seg_len;
+ u16 l3_start = 0;
bool ipv4, ipv6;
int len;
@@ -3321,7 +3322,10 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
NAPI_GRO_CB(skb)->count = rsc_segments;
skb_shinfo(skb)->gso_size = rsc_seg_len;
- skb_reset_network_header(skb);
+ if (unlikely(eth_type_vlan(skb->protocol)))
+ l3_start = VLAN_HLEN;
+
+ skb_set_network_header(skb, l3_start);
if (ipv4) {
struct iphdr *ipv4h = ip_hdr(skb);
@@ -3329,7 +3333,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
/* Reset and set transport header offset in skb */
- skb_set_transport_header(skb, sizeof(struct iphdr));
+ skb_set_transport_header(skb, l3_start + sizeof(struct iphdr));
len = skb->len - skb_transport_offset(skb);
/* Compute the TCP pseudo header checksum*/
@@ -3339,7 +3343,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
- skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+ skb_set_transport_header(skb, l3_start + sizeof(struct ipv6hdr));
len = skb->len - skb_transport_offset(skb);
tcp_hdr(skb)->check =
~tcp_v6_check(len, &ipv6h->saddr, &ipv6h->daddr, 0);
--
2.39.2