skb_gso_transport_seglen() adds the inner TCP header length for an encapsulated GSO packet, but not the inner UDP header for SKB_GSO_UDP_L4, whose gso_size covers the payload only. Every segment of a UDP GSO packet in a UDP tunnel, built by UDP GRO behind a tunnel socket or sent with UDP_SEGMENT over VXLAN, is counted 8 bytes short. ip_forward() and ip_finish_output_gso() then let DF segments that exceed the MTU by up to 8 bytes leave unfragmented. Add the inner UDP header as the unencapsulated branch does. Fixes: ee80d1ebe5ba ("udp: add udp gso") Signed-off-by: Julius Bairaktaris --- net/core/gso.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/gso.c b/net/core/gso.c index b5bd269e56e4e..eb95c9d2819b1 100644 --- a/net/core/gso.c +++ b/net/core/gso.c @@ -156,6 +156,8 @@ static unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) thlen += inner_tcp_hdrlen(skb); + else if (shinfo->gso_type & SKB_GSO_UDP_L4) + thlen += sizeof(struct udphdr); } else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) { thlen = tcp_hdrlen(skb); } else if (unlikely(skb_is_gso_sctp(skb))) { -- 2.53.0