* [PATCH] udp: resubmit encapsulation packets on all multicast listeners
@ 2026-08-15 14:11 Mariano Baragiola
0 siblings, 0 replies; only message in thread
From: Mariano Baragiola @ 2026-08-15 14:11 UTC (permalink / raw)
To: netdev
Cc: davem, edumazet, kuba, pabeni, horms, willemb, kuniyu,
littlesmilingcloud, Mariano Baragiola
UDP encapsulation handlers (FOU/GUE and similar) return a positive
protocol number from udp_queue_rcv_skb()/udpv6_queue_rcv_skb() when the
UDP header has been consumed and the packet must be resubmitted to the
IP protocol handler. Unicast paths already propagate that return value.
Multicast delivery called consume_skb() on every positive return, so the
inner packet was dropped instead of being reinjected.
Commit 3cb8d4b9bfeb ("udp: fix encapsulation packet resubmit in multicast
deliver") fixed only the primary ("first") socket path on net-next and is
not yet in net. Secondary listeners still clone the skb and drop it on a
positive return, and net itself still drops the primary socket path too.
Resubmit secondary clones inline via ip_protocol_deliver_rcu() /
ip6_protocol_deliver_rcu() (matching the GSO segment path in
udp_queue_rcv_skb()/udpv6_queue_rcv_skb()), and propagate the primary
socket return value with the same IPv4/IPv6 sign convention as the
unicast helpers.
Fixes: ca065d0cf80f ("udp: no longer use SLAB_DESTROY_BY_RCU")
Signed-off-by: Mariano Baragiola <mbaragiola@linux.com>
---
net/ipv4/udp.c | 16 ++++++++++++----
net/ipv6/udp.c | 16 ++++++++++++----
2 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 70f6cbd4ef73..d6a17b0462b6 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2475,6 +2475,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
struct udp_hslot *hslot;
struct sk_buff *nskb;
bool use_hash2;
+ int ret;
hash2_any = 0;
hash2 = 0;
@@ -2508,8 +2509,13 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
__UDP_INC_STATS(net, UDP_MIB_INERRORS);
continue;
}
- if (udp_queue_rcv_skb(sk, nskb) > 0)
- consume_skb(nskb);
+ /* >0 means the encap handler wants IP-level resubmit. Do that
+ * inline for secondary listeners; only the first socket can
+ * propagate the protocol number to the caller.
+ */
+ ret = udp_queue_rcv_skb(sk, nskb);
+ if (ret > 0)
+ ip_protocol_deliver_rcu(net, nskb, ret);
}
/* Also lookup *:port if we are using hash2 and haven't done so yet. */
@@ -2519,8 +2525,10 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
}
if (first) {
- if (udp_queue_rcv_skb(first, skb) > 0)
- consume_skb(skb);
+ ret = udp_queue_rcv_skb(first, skb);
+ /* Match udp_unicast_rcv_skb(): return -protocol for IPv4. */
+ if (ret > 0)
+ return -ret;
} else {
kfree_skb(skb);
__UDP_INC_STATS(net, UDP_MIB_IGNOREDMULTI);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 15e032194ecc..65dd944211e9 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -949,6 +949,7 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
struct udp_hslot *hslot;
struct sk_buff *nskb;
bool use_hash2;
+ int ret;
hash2_any = 0;
hash2 = 0;
@@ -987,8 +988,13 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
continue;
}
- if (udpv6_queue_rcv_skb(sk, nskb) > 0)
- consume_skb(nskb);
+ /* >0 means the encap handler wants IP-level resubmit. Do that
+ * inline for secondary listeners; only the first socket can
+ * propagate the nexthdr to the caller.
+ */
+ ret = udpv6_queue_rcv_skb(sk, nskb);
+ if (ret > 0)
+ ip6_protocol_deliver_rcu(net, nskb, ret, true);
}
/* Also lookup *:port if we are using hash2 and haven't done so yet. */
@@ -998,8 +1004,10 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
}
if (first) {
- if (udpv6_queue_rcv_skb(first, skb) > 0)
- consume_skb(skb);
+ ret = udpv6_queue_rcv_skb(first, skb);
+ /* Match udp6_unicast_rcv_skb(): return protocol for IPv6. */
+ if (ret > 0)
+ return ret;
} else {
kfree_skb(skb);
__UDP6_INC_STATS(net, UDP_MIB_IGNOREDMULTI);
--
2.55.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-08-15 14:11 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-15 14:11 [PATCH] udp: resubmit encapsulation packets on all multicast listeners Mariano Baragiola
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox