[PATCH net] ipmr: do not drop GSO packets that fit the MTU after segmentation

From: Julius Bairaktaris

Date: Sat Oct 10 2026 - 09:18:55 EST


ipmr_prepare_xmit() drops a packet with DF set when skb->len exceeds the
route MTU, without checking whether it is a GSO packet. A UDP multicast
stream received with fraglist GRO or UDP GRO forwarding enabled is
aggregated into GSO packets, and every aggregate is dropped with
FragFails, while ip_forward() lets the same packets pass by checking
skb_gso_validate_network_len(). Do the same for multicast routing.
ip6mr has no such check and leaves GSO packets to ip6_output().

On an IPQ8074 router with fraglist GRO on, a 10 Mbit/s stream of
1316-byte DF datagrams routed by igmpproxy loses 14.5 to 15.5% (n=3)
and 0% with this change.

Fixes: 9fd1ff5d2ac7 ("udp: Support UDP fraglist GRO/GSO.")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@xxxxxxxxxxxxxx>
---
net/ipv4/ipmr.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index b9c544d48c452..06c37b4e653bf 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1908,6 +1908,7 @@ static int ipmr_prepare_xmit(struct net *net, struct mr_table *mrt,
struct rtable *rt;
struct flowi4 fl4;
int encap = 0;
+ unsigned int mtu;

vif_dev = vif_dev_read(vif);
if (!vif_dev)
@@ -1940,7 +1941,9 @@ static int ipmr_prepare_xmit(struct net *net, struct mr_table *mrt,
return -1;
}

- if (skb->len+encap > dst4_mtu(&rt->dst) && (ntohs(iph->frag_off) & IP_DF)) {
+ mtu = dst4_mtu(&rt->dst) - encap;
+ if (skb->len > mtu && (ntohs(iph->frag_off) & IP_DF) &&
+ !(skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu))) {
/* Do not fragment multicasts. Alas, IPv4 does not
* allow to send ICMP, so that packets will disappear
* to blackhole.
--
2.53.0