]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
udp: gso: Use single MSS length in UDP header for GSO_PARTIAL
authorGal Pressman <gal@nvidia.com>
Sun, 25 Jan 2026 12:16:47 +0000 (14:16 +0200)
committerJakub Kicinski <kuba@kernel.org>
Wed, 28 Jan 2026 01:30:51 +0000 (17:30 -0800)
In GSO_PARTIAL segmentation, set the UDP length field to the single
segment size (gso_size + UDP header) instead of the large MSS size.
This provides hardware with a template length value for final
segmentation, similar to how tunnel GSO_PARTIAL handles outer headers
in UDP tunnels.

This will remove the need to manually adjust the UDP header length in
the drivers, as can be seen in subsequent patches.

This was suggested by Alex in 2018:
https://lore.kernel.org/netdev/CAKgT0UcdnUWgr3KQ=RnLKigokkiUuYefmL-ePpDvJOBNpKScFA@mail.gmail.com/

Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Gal Pressman <gal@nvidia.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260125121649.778086-2-gal@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/udp_offload.c

index 19d0b5b09ffae6bc0cda0b67fc229fa01dc37e8e..89e0b48b60ae3a5fbb8244773ac87ab1ec117089 100644 (file)
@@ -483,11 +483,11 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
        struct sock *sk = gso_skb->sk;
        unsigned int sum_truesize = 0;
        struct sk_buff *segs, *seg;
+       __be16 newlen, msslen;
        struct udphdr *uh;
        unsigned int mss;
        bool copy_dtor;
        __sum16 check;
-       __be16 newlen;
        int ret = 0;
 
        mss = skb_shinfo(gso_skb)->gso_size;
@@ -555,6 +555,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
                return segs;
        }
 
+       msslen = htons(sizeof(*uh) + mss);
+
        /* GSO partial and frag_list segmentation only requires splitting
         * the frame into an MSS multiple and possibly a remainder, both
         * cases return a GSO skb. So update the mss now.
@@ -584,7 +586,7 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
                if (!seg->next)
                        break;
 
-               uh->len = newlen;
+               uh->len = msslen;
                uh->check = check;
 
                if (seg->ip_summed == CHECKSUM_PARTIAL)