]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
vmxnet3: correctly report gso type for UDP tunnels
authorRonak Doshi <ronak.doshi@broadcom.com>
Fri, 30 May 2025 15:27:00 +0000 (15:27 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 19 Jun 2025 13:32:18 +0000 (15:32 +0200)
[ Upstream commit 982d30c30eaa2ec723df42e3bf526c014c1dbb88 ]

Commit 3d010c8031e3 ("udp: do not accept non-tunnel GSO skbs landing
in a tunnel") added checks in linux stack to not accept non-tunnel
GRO packets landing in a tunnel. This exposed an issue in vmxnet3
which was not correctly reporting GRO packets for tunnel packets.

This patch fixes this issue by setting correct GSO type for the
tunnel packets.

Currently, vmxnet3 does not support reporting inner fields for LRO
tunnel packets. The issue is not seen for egress drivers that do not
use skb inner fields. The workaround is to enable tnl-segmentation
offload on the egress interfaces if the driver supports it. This
problem pre-exists this patch fix and can be addressed as a separate
future patch.

Fixes: dacce2be3312 ("vmxnet3: add geneve and vxlan tunnel offload support")
Signed-off-by: Ronak Doshi <ronak.doshi@broadcom.com>
Acked-by: Guolin Yang <guolin.yang@broadcom.com>
Link: https://patch.msgid.link/20250530152701.70354-1-ronak.doshi@broadcom.com
[pabeni@redhat.com: dropped the changelog]
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/vmxnet3/vmxnet3_drv.c

index 151d7cdfc4802343605f0bbbe7ec49a31601988c..c48c2de6f961f7f06b9e3deb4258a3b27ac1bcc4 100644 (file)
@@ -1560,6 +1560,30 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,
        return (hlen + (hdr.tcp->doff << 2));
 }
 
+static void
+vmxnet3_lro_tunnel(struct sk_buff *skb, __be16 ip_proto)
+{
+       struct udphdr *uh = NULL;
+
+       if (ip_proto == htons(ETH_P_IP)) {
+               struct iphdr *iph = (struct iphdr *)skb->data;
+
+               if (iph->protocol == IPPROTO_UDP)
+                       uh = (struct udphdr *)(iph + 1);
+       } else {
+               struct ipv6hdr *iph = (struct ipv6hdr *)skb->data;
+
+               if (iph->nexthdr == IPPROTO_UDP)
+                       uh = (struct udphdr *)(iph + 1);
+       }
+       if (uh) {
+               if (uh->check)
+                       skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM;
+               else
+                       skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
+       }
+}
+
 static int
 vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
                       struct vmxnet3_adapter *adapter, int quota)
@@ -1873,6 +1897,8 @@ sop_done:
                        if (segCnt != 0 && mss != 0) {
                                skb_shinfo(skb)->gso_type = rcd->v4 ?
                                        SKB_GSO_TCPV4 : SKB_GSO_TCPV6;
+                               if (encap_lro)
+                                       vmxnet3_lro_tunnel(skb, skb->protocol);
                                skb_shinfo(skb)->gso_size = mss;
                                skb_shinfo(skb)->gso_segs = segCnt;
                        } else if ((segCnt != 0 || skb->len > mtu) && !encap_lro) {