* [PATCH net v4 0/4] ipmr: forward GSO multicast packets
@ 2026-11-01 16:42 Julius Bairaktaris
2026-11-01 16:42 ` [PATCH net v4 1/4] net: make room for the tunnel header in skb_segment_list() Julius Bairaktaris
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Julius Bairaktaris @ 2026-11-01 16:42 UTC (permalink / raw)
To: netdev
Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms,
steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina,
bigeasy, richardbgobert, ecree.xilinx, linux-kernel
With fraglist GRO or UDP GRO forwarding on, a routed IPv4 multicast
stream arrives as GSO packets. ipmr_prepare_xmit() drops every DF
aggregate larger than the MTU, and ip_encap() sets no tunnel GSO state,
so a GSO packet sent to a VIFF_TUNNEL vif is dropped during
segmentation. With that state set, a fraglist aggregate reaches
skb_segment_list() with tunnel headers, which can write before the head
of a frag_list member; this also happens today when such a packet is
routed into a tunnel device. Checking the segment length instead of
skb->len relies on skb_gso_transport_seglen(), which counts the inner
UDP header of an encapsulated UDP GSO packet 8 bytes short.
Patch 1 makes room for the tunnel headers in skb_segment_list().
Patch 2 counts the inner UDP header of encapsulated UDP GSO packets.
Patch 3 sets up IPXIP4 GSO state, outer IP IDs and length in ip_encap().
Patch 4 lets DF GSO packets pass when their segments fit the MTU.
Tested in QEMU (KASAN) on veth, one run per arm: an MFC entry to a plain
vif and a tunnel vif, 40 x 1316-byte datagrams per GSO packet, 4000
datagrams per arm, UDP_SEGMENT, fraglist GRO and UDP GRO forwarding, DF
set and clear, software and device segmentation on egress:
- net (7076f684d513): every DF aggregate dropped on both vifs (FragFails
2 per aggregate), and with software segmentation nothing arrives over
the tunnel vif; fraglist GRO routed into VXLAN reports a KASAN
slab-out-of-bounds write in skb_segment_list(), then panics.
- this series, all 12 arms: 4000 of 4000 datagrams on the plain vif,
FragFails 0; on the tunnel vif 4000 of 4000 IPIP packets with unique
outer IDs with software segmentation, and the 100 GSO packets of 52688
bytes whole with device segmentation.
- VXLAN with DF, 1404-byte outer segments, route MTU 1400: net and this
series without patch 2 forward all 1000 segments at 1404 bytes through
ip_forward(), and the series without patch 2 also through the MFC
entry; with patch 2 none leave and FragFails counts them.
- a GRE GSO packet (skb->encapsulation set) multicast-routed to both
vifs: all 1000 segments on the plain vif, none on the tunnel vif.
- fraglist GRO routed into VXLAN and IPIP with software segmentation:
every segment reaches the peer, no KASAN report.
Changes in v4:
- Add patch 2 (Sashiko).
- Patch 3: drop GSO packets that are already encapsulated, and set the
outer length with iph_set_totlen() (Sashiko).
- Drop v3 patch 2 (TCP fixed-ID flag on encapsulation): multicast
routing does not carry TCP, and the flag also needs the decap and
GRE/UDP segmentation paths, which go to a separate series (Sashiko).
- Rebase onto net.
- v3: https://lore.kernel.org/netdev/cover.1792293419.git.julius@bairaktaris.de/
Changes in v3:
- Patch 1: name the VXLAN out-of-bounds write (Sashiko).
- Add patch 2 (Sashiko).
- Patch 3: reserve one outer IP ID per segment (Sashiko).
- v2: https://lore.kernel.org/netdev/20261011162957.1328474-1-julius@bairaktaris.de/
Changes in v2:
- Add patches 1 and 3; v1 let DF GSO packets reach ip_encap() on tunnel
vifs, where they were dropped during segmentation (Sashiko).
- Keep the additive MTU comparison and check mtu > encap before
subtracting, so a route MTU below 20 cannot wrap (Sashiko).
- v1: https://lore.kernel.org/netdev/20261010131842.2157365-1-julius@bairaktaris.de/
I used Claude (Anthropic) to help write these patches.
Julius Bairaktaris (4):
net: make room for the tunnel header in skb_segment_list()
net: gso: count the inner UDP header of encapsulated UDP GSO packets
ipmr: set up GSO state for tunnel vifs
ipmr: do not drop GSO packets that fit the MTU after segmentation
net/core/gso.c | 2 ++
net/core/skbuff.c | 4 ++++
net/ipv4/ipmr.c | 29 ++++++++++++++++++++++-------
3 files changed, 28 insertions(+), 7 deletions(-)
base-commit: 7076f684d5132e6a6145e1da2fa74771ecd052e5
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH net v4 1/4] net: make room for the tunnel header in skb_segment_list() 2026-11-01 16:42 [PATCH net v4 0/4] ipmr: forward GSO multicast packets Julius Bairaktaris @ 2026-11-01 16:42 ` Julius Bairaktaris 2026-11-03 12:43 ` Simon Horman 2026-11-01 16:42 ` [PATCH net v4 2/4] net: gso: count the inner UDP header of encapsulated UDP GSO packets Julius Bairaktaris ` (2 subsequent siblings) 3 siblings, 1 reply; 13+ messages in thread From: Julius Bairaktaris @ 2026-11-01 16:42 UTC (permalink / raw) To: netdev Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel skb_segment_list() pushes each frag_list member back to the outer MAC header and copies the tunnel headers in front of it, but never checks that the member has the headroom. A fraglist GRO packet forwarded into a tunnel and segmented in software then hits skb_under_panic() on IPIP, and on VXLAN the copy writes before the member's head (KASAN: slab-out-of-bounds write in skb_segment_list()). Call skb_cow_head() on each member before pushing it. Fixes: 3a1296a38d0c ("net: Support GRO/GSO fraglist chaining.") Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> --- net/core/skbuff.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 48f6764117243..48291a2d21241 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4777,6 +4777,10 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, } } + if (!err) + err = skb_cow_head(nskb, offset + tnl_hlen - + skb_network_offset(nskb)); + if (!tail) skb->next = nskb; else -- 2.53.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net v4 1/4] net: make room for the tunnel header in skb_segment_list() 2026-11-01 16:42 ` [PATCH net v4 1/4] net: make room for the tunnel header in skb_segment_list() Julius Bairaktaris @ 2026-11-03 12:43 ` Simon Horman 2026-11-03 13:05 ` Eric Dumazet 0 siblings, 1 reply; 13+ messages in thread From: Simon Horman @ 2026-11-03 12:43 UTC (permalink / raw) To: Julius Bairaktaris Cc: netdev, dsahern, idosch, davem, edumazet, kuba, pabeni, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel On Sun, Nov 01, 2026 at 05:42:29PM +0100, Julius Bairaktaris wrote: > skb_segment_list() pushes each frag_list member back to the outer MAC > header and copies the tunnel headers in front of it, but never checks > that the member has the headroom. A fraglist GRO packet forwarded into > a tunnel and segmented in software then hits skb_under_panic() on IPIP, > and on VXLAN the copy writes before the member's head (KASAN: > slab-out-of-bounds write in skb_segment_list()). > > Call skb_cow_head() on each member before pushing it. > > Fixes: 3a1296a38d0c ("net: Support GRO/GSO fraglist chaining.") > Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> Reviewed-by: Simon Horman <horms@kernel.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net v4 1/4] net: make room for the tunnel header in skb_segment_list() 2026-11-03 12:43 ` Simon Horman @ 2026-11-03 13:05 ` Eric Dumazet 0 siblings, 0 replies; 13+ messages in thread From: Eric Dumazet @ 2026-11-03 13:05 UTC (permalink / raw) To: Simon Horman Cc: Julius Bairaktaris, netdev, dsahern, idosch, davem, kuba, pabeni, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel Le mar. 3 nov. 2026 à 13:43, Simon Horman <horms@kernel.org> a écrit : > > On Sun, Nov 01, 2026 at 05:42:29PM +0100, Julius Bairaktaris wrote: > > skb_segment_list() pushes each frag_list member back to the outer MAC > > header and copies the tunnel headers in front of it, but never checks > > that the member has the headroom. A fraglist GRO packet forwarded into > > a tunnel and segmented in software then hits skb_under_panic() on IPIP, > > and on VXLAN the copy writes before the member's head (KASAN: > > slab-out-of-bounds write in skb_segment_list()). > > > > Call skb_cow_head() on each member before pushing it. > > > > Fixes: 3a1296a38d0c ("net: Support GRO/GSO fraglist chaining.") > > Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> > > Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: Eric Dumazet <edumazet@kernel.org> Thanks! ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net v4 2/4] net: gso: count the inner UDP header of encapsulated UDP GSO packets 2026-11-01 16:42 [PATCH net v4 0/4] ipmr: forward GSO multicast packets Julius Bairaktaris 2026-11-01 16:42 ` [PATCH net v4 1/4] net: make room for the tunnel header in skb_segment_list() Julius Bairaktaris @ 2026-11-01 16:42 ` Julius Bairaktaris 2026-11-03 12:44 ` Simon Horman 2026-11-01 16:42 ` [PATCH net v4 3/4] ipmr: set up GSO state for tunnel vifs Julius Bairaktaris 2026-11-01 16:42 ` [PATCH net v4 4/4] ipmr: do not drop GSO packets that fit the MTU after segmentation Julius Bairaktaris 3 siblings, 1 reply; 13+ messages in thread From: Julius Bairaktaris @ 2026-11-01 16:42 UTC (permalink / raw) To: netdev Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel 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 <julius@bairaktaris.de> --- 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 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net v4 2/4] net: gso: count the inner UDP header of encapsulated UDP GSO packets 2026-11-01 16:42 ` [PATCH net v4 2/4] net: gso: count the inner UDP header of encapsulated UDP GSO packets Julius Bairaktaris @ 2026-11-03 12:44 ` Simon Horman 2026-11-03 13:08 ` Eric Dumazet 0 siblings, 1 reply; 13+ messages in thread From: Simon Horman @ 2026-11-03 12:44 UTC (permalink / raw) To: Julius Bairaktaris Cc: netdev, dsahern, idosch, davem, edumazet, kuba, pabeni, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel On Sun, Nov 01, 2026 at 05:42:30PM +0100, Julius Bairaktaris wrote: > 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 <julius@bairaktaris.de> Reviewed-by: Simon Horman <horms@kernel.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net v4 2/4] net: gso: count the inner UDP header of encapsulated UDP GSO packets 2026-11-03 12:44 ` Simon Horman @ 2026-11-03 13:08 ` Eric Dumazet 0 siblings, 0 replies; 13+ messages in thread From: Eric Dumazet @ 2026-11-03 13:08 UTC (permalink / raw) To: Simon Horman Cc: Julius Bairaktaris, netdev, dsahern, idosch, davem, kuba, pabeni, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel Le mar. 3 nov. 2026 à 13:44, Simon Horman <horms@kernel.org> a écrit : > > On Sun, Nov 01, 2026 at 05:42:30PM +0100, Julius Bairaktaris wrote: > > 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 <julius@bairaktaris.de> > > Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: Eric Dumazet <edumazet@kernel.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net v4 3/4] ipmr: set up GSO state for tunnel vifs 2026-11-01 16:42 [PATCH net v4 0/4] ipmr: forward GSO multicast packets Julius Bairaktaris 2026-11-01 16:42 ` [PATCH net v4 1/4] net: make room for the tunnel header in skb_segment_list() Julius Bairaktaris 2026-11-01 16:42 ` [PATCH net v4 2/4] net: gso: count the inner UDP header of encapsulated UDP GSO packets Julius Bairaktaris @ 2026-11-01 16:42 ` Julius Bairaktaris 2026-11-03 12:44 ` Simon Horman 2026-11-03 13:13 ` Eric Dumazet 2026-11-01 16:42 ` [PATCH net v4 4/4] ipmr: do not drop GSO packets that fit the MTU after segmentation Julius Bairaktaris 3 siblings, 2 replies; 13+ messages in thread From: Julius Bairaktaris @ 2026-11-01 16:42 UTC (permalink / raw) To: netdev Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel ip_encap() pushes the outer IPv4 header but does not set SKB_GSO_IPXIP4, skb->encapsulation or the inner headers. A GSO packet forwarded to a VIFF_TUNNEL vif is then rejected by ipip_gso_segment() and dropped in validate_xmit_skb(), after being counted as sent. A device with UDP segmentation offload is handed a GSO packet whose transport header points at the inner IP header. Call iptunnel_handle_offloads() and skb_set_inner_ipproto() as ipip_tunnel_xmit() does, reserve one outer IP ID per segment as iptunnel_xmit() does, and set the outer length with iph_set_totlen(), since a GSO packet plus the outer header can exceed 64 KB. A GSO packet that GRE or UDP tunnel GRO marked as encapsulated already uses the inner headers for its own tunnel; drop it, as segmentation did before. Fixes: 9fd1ff5d2ac7 ("udp: Support UDP fraglist GRO/GSO.") Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> --- net/ipv4/ipmr.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index acacaae05cc49..98e38839f8ccb 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1849,12 +1849,21 @@ static struct notifier_block ip_mr_notifier = { * This avoids tunnel drivers and other mess and gives us the speed so * important for multicast video. */ -static void ip_encap(struct net *net, struct sk_buff *skb, - __be32 saddr, __be32 daddr) +static int ip_encap(struct net *net, struct sk_buff *skb, + __be32 saddr, __be32 daddr) { + const struct iphdr *old_iph; struct iphdr *iph; - const struct iphdr *old_iph = ip_hdr(skb); + /* The inner headers can describe one tunnel only */ + if (skb_is_gso(skb) && skb->encapsulation) + return -1; + + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4)) + return -1; + skb_set_inner_ipproto(skb, IPPROTO_IPIP); + + old_iph = ip_hdr(skb); skb_push(skb, sizeof(struct iphdr)); skb->transport_header = skb->network_header; skb_reset_network_header(skb); @@ -1868,12 +1877,13 @@ static void ip_encap(struct net *net, struct sk_buff *skb, iph->saddr = saddr; iph->protocol = IPPROTO_IPIP; iph->ihl = 5; - iph->tot_len = htons(skb->len); - ip_select_ident(net, skb, NULL); + iph_set_totlen(iph, skb->len); + ip_select_ident_segs(net, skb, NULL, skb_shinfo(skb)->gso_segs ?: 1); ip_send_check(iph); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); nf_reset_ct(skb); + return 0; } static inline int ipmr_forward_finish(struct net *net, struct sock *sk, @@ -1982,7 +1992,8 @@ static int ipmr_prepare_xmit(struct net *net, struct mr_table *mrt, * What do we do with netfilter? -- RR */ if (vif->flags & VIFF_TUNNEL) { - ip_encap(net, skb, vif->local, vif->remote); + if (ip_encap(net, skb, vif->local, vif->remote)) + return -1; /* FIXME: extra output firewall step used to be here. --RR */ DEV_STATS_INC(vif_dev, tx_packets); DEV_STATS_ADD(vif_dev, tx_bytes, skb->len); -- 2.53.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net v4 3/4] ipmr: set up GSO state for tunnel vifs 2026-11-01 16:42 ` [PATCH net v4 3/4] ipmr: set up GSO state for tunnel vifs Julius Bairaktaris @ 2026-11-03 12:44 ` Simon Horman 2026-11-03 13:13 ` Eric Dumazet 1 sibling, 0 replies; 13+ messages in thread From: Simon Horman @ 2026-11-03 12:44 UTC (permalink / raw) To: Julius Bairaktaris Cc: netdev, dsahern, idosch, davem, edumazet, kuba, pabeni, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel On Sun, Nov 01, 2026 at 05:42:31PM +0100, Julius Bairaktaris wrote: > ip_encap() pushes the outer IPv4 header but does not set SKB_GSO_IPXIP4, > skb->encapsulation or the inner headers. A GSO packet forwarded to a > VIFF_TUNNEL vif is then rejected by ipip_gso_segment() and dropped in > validate_xmit_skb(), after being counted as sent. A device with UDP > segmentation offload is handed a GSO packet whose transport header > points at the inner IP header. > > Call iptunnel_handle_offloads() and skb_set_inner_ipproto() as > ipip_tunnel_xmit() does, reserve one outer IP ID per segment as > iptunnel_xmit() does, and set the outer length with iph_set_totlen(), > since a GSO packet plus the outer header can exceed 64 KB. A GSO packet > that GRE or UDP tunnel GRO marked as encapsulated already uses the inner > headers for its own tunnel; drop it, as segmentation did before. > > Fixes: 9fd1ff5d2ac7 ("udp: Support UDP fraglist GRO/GSO.") > Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> Reviewed-by: Simon Horman <horms@kernel.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net v4 3/4] ipmr: set up GSO state for tunnel vifs 2026-11-01 16:42 ` [PATCH net v4 3/4] ipmr: set up GSO state for tunnel vifs Julius Bairaktaris 2026-11-03 12:44 ` Simon Horman @ 2026-11-03 13:13 ` Eric Dumazet 1 sibling, 0 replies; 13+ messages in thread From: Eric Dumazet @ 2026-11-03 13:13 UTC (permalink / raw) To: Julius Bairaktaris Cc: netdev, dsahern, idosch, davem, kuba, pabeni, horms, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel Le dim. 1 nov. 2026 à 17:42, Julius Bairaktaris <julius@bairaktaris.de> a écrit : > > ip_encap() pushes the outer IPv4 header but does not set SKB_GSO_IPXIP4, > skb->encapsulation or the inner headers. A GSO packet forwarded to a > VIFF_TUNNEL vif is then rejected by ipip_gso_segment() and dropped in > validate_xmit_skb(), after being counted as sent. A device with UDP > segmentation offload is handed a GSO packet whose transport header > points at the inner IP header. > > Call iptunnel_handle_offloads() and skb_set_inner_ipproto() as > ipip_tunnel_xmit() does, reserve one outer IP ID per segment as > iptunnel_xmit() does, and set the outer length with iph_set_totlen(), > since a GSO packet plus the outer header can exceed 64 KB. A GSO packet > that GRE or UDP tunnel GRO marked as encapsulated already uses the inner > headers for its own tunnel; drop it, as segmentation did before. > > Fixes: 9fd1ff5d2ac7 ("udp: Support UDP fraglist GRO/GSO.") > Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> > --- > net/ipv4/ipmr.c | 23 +++++++++++++++++------ > 1 file changed, 17 insertions(+), 6 deletions(-) > > diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c > index acacaae05cc49..98e38839f8ccb 100644 > --- a/net/ipv4/ipmr.c > +++ b/net/ipv4/ipmr.c > @@ -1849,12 +1849,21 @@ static struct notifier_block ip_mr_notifier = { > * This avoids tunnel drivers and other mess and gives us the speed so > * important for multicast video. > */ > -static void ip_encap(struct net *net, struct sk_buff *skb, > - __be32 saddr, __be32 daddr) > +static int ip_encap(struct net *net, struct sk_buff *skb, > + __be32 saddr, __be32 daddr) > { > + const struct iphdr *old_iph; > struct iphdr *iph; > - const struct iphdr *old_iph = ip_hdr(skb); > > + /* The inner headers can describe one tunnel only */ > + if (skb_is_gso(skb) && skb->encapsulation) > + return -1; > + > + if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4)) > + return -1; By the time ip_encap() runs, ipmr_prepare_xmit() has already bumped vif->pkt_out/bytes_out and decreased the TTL, so these drops are still counted as sent, which is what the changelog complains about. Could you move the encapsulation check into ipmr_prepare_xmit(), in the VIFF_TUNNEL branch before the route lookup ? if (vif->flags & VIFF_TUNNEL) { /* The inner headers can describe one tunnel only */ if (skb_is_gso(skb) && skb->encapsulation) return -1; rt = ip_route_output_ports(...); Also note that iptunnel_handle_offloads() can not fail here: skb_cow() was called before, so skb_header_unclone() has nothing to do. > + skb_set_inner_ipproto(skb, IPPROTO_IPIP); > + > + old_iph = ip_hdr(skb); > skb_push(skb, sizeof(struct iphdr)); > skb->transport_header = skb->network_header; > skb_reset_network_header(skb); > @@ -1868,12 +1877,13 @@ static void ip_encap(struct net *net, struct sk_buff *skb, > iph->saddr = saddr; > iph->protocol = IPPROTO_IPIP; > iph->ihl = 5; > - iph->tot_len = htons(skb->len); > - ip_select_ident(net, skb, NULL); > + iph_set_totlen(iph, skb->len); Minor: a fraglist aggregate can reach 65535 bytes, so with the outer header tot_len can now be 0. The packet then goes through the NF_INET_FORWARD hook, where iph_totlen() only handles TCP GSO packets, so nft will consider it malformed. Still better than the silent truncation we had, but maybe worth a mention in the changelog. Thanks. pw-bot: cr > + ip_select_ident_segs(net, skb, NULL, skb_shinfo(skb)->gso_segs ?: 1); > ip_send_check(iph); > > memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); > nf_reset_ct(skb); > + return 0; > } > > static inline int ipmr_forward_finish(struct net *net, struct sock *sk, > @@ -1982,7 +1992,8 @@ static int ipmr_prepare_xmit(struct net *net, struct mr_table *mrt, > * What do we do with netfilter? -- RR > */ > if (vif->flags & VIFF_TUNNEL) { > - ip_encap(net, skb, vif->local, vif->remote); > + if (ip_encap(net, skb, vif->local, vif->remote)) > + return -1; > /* FIXME: extra output firewall step used to be here. --RR */ > DEV_STATS_INC(vif_dev, tx_packets); > DEV_STATS_ADD(vif_dev, tx_bytes, skb->len); > -- > 2.53.0 > ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH net v4 4/4] ipmr: do not drop GSO packets that fit the MTU after segmentation 2026-11-01 16:42 [PATCH net v4 0/4] ipmr: forward GSO multicast packets Julius Bairaktaris ` (2 preceding siblings ...) 2026-11-01 16:42 ` [PATCH net v4 3/4] ipmr: set up GSO state for tunnel vifs Julius Bairaktaris @ 2026-11-01 16:42 ` Julius Bairaktaris 2026-11-03 12:44 ` Simon Horman 3 siblings, 1 reply; 13+ messages in thread From: Julius Bairaktaris @ 2026-11-01 16:42 UTC (permalink / raw) To: netdev Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel 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, leaving room for the outer header on tunnel vifs. 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.") Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> --- net/ipv4/ipmr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 98e38839f8ccb..1fb728fb15741 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1932,6 +1932,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) @@ -1964,7 +1965,10 @@ 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); + if (skb->len + encap > mtu && (ntohs(iph->frag_off) & IP_DF) && + !(skb_is_gso(skb) && mtu > encap && + skb_gso_validate_network_len(skb, mtu - encap))) { /* Do not fragment multicasts. Alas, IPv4 does not * allow to send ICMP, so that packets will disappear * to blackhole. -- 2.53.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net v4 4/4] ipmr: do not drop GSO packets that fit the MTU after segmentation 2026-11-01 16:42 ` [PATCH net v4 4/4] ipmr: do not drop GSO packets that fit the MTU after segmentation Julius Bairaktaris @ 2026-11-03 12:44 ` Simon Horman 2026-11-03 13:15 ` Eric Dumazet 0 siblings, 1 reply; 13+ messages in thread From: Simon Horman @ 2026-11-03 12:44 UTC (permalink / raw) To: Julius Bairaktaris Cc: netdev, dsahern, idosch, davem, edumazet, kuba, pabeni, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel On Sun, Nov 01, 2026 at 05:42:32PM +0100, Julius Bairaktaris wrote: > 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, > leaving room for the outer header on tunnel vifs. 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.") > Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> Reviewed-by: Simon Horman <horms@kernel.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH net v4 4/4] ipmr: do not drop GSO packets that fit the MTU after segmentation 2026-11-03 12:44 ` Simon Horman @ 2026-11-03 13:15 ` Eric Dumazet 0 siblings, 0 replies; 13+ messages in thread From: Eric Dumazet @ 2026-11-03 13:15 UTC (permalink / raw) To: Simon Horman Cc: Julius Bairaktaris, netdev, dsahern, idosch, davem, kuba, pabeni, steffen.klassert, willemb, jiayuan.chen, mfleming, almasrymina, bigeasy, richardbgobert, ecree.xilinx, linux-kernel Le mar. 3 nov. 2026 à 13:44, Simon Horman <horms@kernel.org> a écrit : > > On Sun, Nov 01, 2026 at 05:42:32PM +0100, Julius Bairaktaris wrote: > > 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, > > leaving room for the outer header on tunnel vifs. 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.") > > Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de> > > Reviewed-by: Simon Horman <horms@kernel.org> Reviewed-by: Eric Dumazet <edumazet@kernel.org> ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-11-03 13:15 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-11-01 16:42 [PATCH net v4 0/4] ipmr: forward GSO multicast packets Julius Bairaktaris 2026-11-01 16:42 ` [PATCH net v4 1/4] net: make room for the tunnel header in skb_segment_list() Julius Bairaktaris 2026-11-03 12:43 ` Simon Horman 2026-11-03 13:05 ` Eric Dumazet 2026-11-01 16:42 ` [PATCH net v4 2/4] net: gso: count the inner UDP header of encapsulated UDP GSO packets Julius Bairaktaris 2026-11-03 12:44 ` Simon Horman 2026-11-03 13:08 ` Eric Dumazet 2026-11-01 16:42 ` [PATCH net v4 3/4] ipmr: set up GSO state for tunnel vifs Julius Bairaktaris 2026-11-03 12:44 ` Simon Horman 2026-11-03 13:13 ` Eric Dumazet 2026-11-01 16:42 ` [PATCH net v4 4/4] ipmr: do not drop GSO packets that fit the MTU after segmentation Julius Bairaktaris 2026-11-03 12:44 ` Simon Horman 2026-11-03 13:15 ` Eric Dumazet
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®