From: Greg Kroah-Hartman Date: Wed, 18 Jun 2025 13:13:02 +0000 (+0200) Subject: drop some udp 6.15 patches X-Git-Tag: v6.6.94~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d0c31b217f2bf8628b3948debd2060c8879c74c1;p=thirdparty%2Fkernel%2Fstable-queue.git drop some udp 6.15 patches --- diff --git a/queue-6.15/series b/queue-6.15/series index b1cb45e4a0..631d8c822f 100644 --- a/queue-6.15/series +++ b/queue-6.15/series @@ -182,9 +182,6 @@ wifi-ath12k-fix-ath12k_flag_registered-flag-handling.patch f2fs-clean-up-unnecessary-indentation.patch f2fs-prevent-the-current-section-from-being-selected.patch f2fs-fix-to-do-sanity-check-on-sbi-total_valid_block.patch -udp_tunnel-create-a-fastpath-gro-lookup.patch -udp_tunnel-use-static-call-for-gro-hooks-when-possib.patch -udp-properly-deal-with-xfrm-encap-and-addrform.patch page_pool-move-pp_magic-check-into-helper-functions.patch page_pool-track-dma-mapped-pages-and-unmap-them-when.patch net-mlx5-hws-fix-matcher-action-template-attach.patch diff --git a/queue-6.15/udp-properly-deal-with-xfrm-encap-and-addrform.patch b/queue-6.15/udp-properly-deal-with-xfrm-encap-and-addrform.patch deleted file mode 100644 index 3978af261c..0000000000 --- a/queue-6.15/udp-properly-deal-with-xfrm-encap-and-addrform.patch +++ /dev/null @@ -1,190 +0,0 @@ -From 7379d064b4e3a412604ed33592bdaee2468b6c95 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 9 Apr 2025 22:00:56 +0200 -Subject: udp: properly deal with xfrm encap and ADDRFORM - -From: Paolo Abeni - -[ Upstream commit c26c192c3d486a2a7d83d254bae294c2f8f50abf ] - -UDP GRO accounting assumes that the GRO receive callback is always -set when the UDP tunnel is enabled, but syzkaller proved otherwise, -leading tot the following splat: - -WARNING: CPU: 0 PID: 5837 at net/ipv4/udp_offload.c:123 udp_tunnel_update_gro_rcv+0x28d/0x4c0 net/ipv4/udp_offload.c:123 -Modules linked in: -CPU: 0 UID: 0 PID: 5837 Comm: syz-executor850 Not tainted 6.14.0-syzkaller-13320-g420aabef3ab5 #0 PREEMPT(full) -Hardware name: Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2025 -RIP: 0010:udp_tunnel_update_gro_rcv+0x28d/0x4c0 net/ipv4/udp_offload.c:123 -Code: 00 00 e8 c6 5a 2f f7 48 c1 e5 04 48 8d b5 20 53 c7 9a ba 10 - 00 00 00 4c 89 ff e8 ce 87 99 f7 e9 ce 00 00 00 e8 a4 5a 2f - f7 90 <0f> 0b 90 e9 de fd ff ff bf 01 00 00 00 89 ee e8 cf - 5e 2f f7 85 ed -RSP: 0018:ffffc90003effa88 EFLAGS: 00010293 -RAX: ffffffff8a93fc9c RBX: 0000000000000000 RCX: ffff8880306f9e00 -RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 -RBP: 0000000000000000 R08: ffffffff8a93fabe R09: 1ffffffff20bfb2e -R10: dffffc0000000000 R11: fffffbfff20bfb2f R12: ffff88814ef21738 -R13: dffffc0000000000 R14: ffff88814ef21778 R15: 1ffff11029de42ef -FS: 0000000000000000(0000) GS:ffff888124f96000(0000) knlGS:0000000000000000 -CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 -CR2: 00007f04eec760d0 CR3: 000000000eb38000 CR4: 00000000003526f0 -DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 -DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 -Call Trace: - - udp_tunnel_cleanup_gro include/net/udp_tunnel.h:205 [inline] - udpv6_destroy_sock+0x212/0x270 net/ipv6/udp.c:1829 - sk_common_release+0x71/0x2e0 net/core/sock.c:3896 - inet_release+0x17d/0x200 net/ipv4/af_inet.c:435 - __sock_release net/socket.c:647 [inline] - sock_close+0xbc/0x240 net/socket.c:1391 - __fput+0x3e9/0x9f0 fs/file_table.c:465 - task_work_run+0x251/0x310 kernel/task_work.c:227 - exit_task_work include/linux/task_work.h:40 [inline] - do_exit+0xa11/0x27f0 kernel/exit.c:953 - do_group_exit+0x207/0x2c0 kernel/exit.c:1102 - __do_sys_exit_group kernel/exit.c:1113 [inline] - __se_sys_exit_group kernel/exit.c:1111 [inline] - __x64_sys_exit_group+0x3f/0x40 kernel/exit.c:1111 - x64_sys_call+0x26c3/0x26d0 arch/x86/include/generated/asm/syscalls_64.h:232 - do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] - do_syscall_64+0xf3/0x230 arch/x86/entry/syscall_64.c:94 - entry_SYSCALL_64_after_hwframe+0x77/0x7f -RIP: 0033:0x7f04eebfac79 -Code: Unable to access opcode bytes at 0x7f04eebfac4f. -RSP: 002b:00007fffdcaa34a8 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7 -RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f04eebfac79 -RDX: 000000000000003c RSI: 00000000000000e7 RDI: 0000000000000000 -RBP: 00007f04eec75270 R08: ffffffffffffffb8 R09: 00007fffdcaa36c8 -R10: 0000200000000000 R11: 0000000000000246 R12: 00007f04eec75270 -R13: 0000000000000000 R14: 00007f04eec75cc0 R15: 00007f04eebcca70 - -Address the issue moving the accounting hook into -setup_udp_tunnel_sock() and set_xfrm_gro_udp_encap_rcv(), where -the GRO callback is actually set. - -set_xfrm_gro_udp_encap_rcv() is prone to races with IPV6_ADDRFORM, -run the relevant setsockopt under the socket lock to ensure using -consistent values of sk_family and up->encap_type. - -Refactor the GRO callback selection code, to make it clear that -the function pointer is always initialized. - -Reported-by: syzbot+8c469a2260132cd095c1@syzkaller.appspotmail.com -Closes: https://syzkaller.appspot.com/bug?extid=8c469a2260132cd095c1 -Fixes: 172bf009c18d ("xfrm: Support GRO for IPv4 ESP in UDP encapsulation") -Fixes: 5d7f5b2f6b935 ("udp_tunnel: use static call for GRO hooks when possible") -Signed-off-by: Paolo Abeni -Reviewed-by: Sabrina Dubroca -Link: https://patch.msgid.link/92bcdb6899145a9a387c8fa9e3ca656642a43634.1744228733.git.pabeni@redhat.com -Signed-off-by: Jakub Kicinski -Signed-off-by: Sasha Levin ---- - include/net/udp_tunnel.h | 1 - - net/ipv4/udp.c | 31 ++++++++++++++++++++++++++----- - net/ipv4/udp_tunnel_core.c | 2 ++ - 3 files changed, 28 insertions(+), 6 deletions(-) - -diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h -index 288f06f23a804..2df3b8344eb52 100644 ---- a/include/net/udp_tunnel.h -+++ b/include/net/udp_tunnel.h -@@ -215,7 +215,6 @@ static inline void udp_tunnel_encap_enable(struct sock *sk) - if (READ_ONCE(sk->sk_family) == PF_INET6) - ipv6_stub->udpv6_encap_enable(); - #endif -- udp_tunnel_update_gro_rcv(sk, true); - udp_encap_enable(); - } - -diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c -index 04cd3353f1d46..af943b905804a 100644 ---- a/net/ipv4/udp.c -+++ b/net/ipv4/udp.c -@@ -2904,15 +2904,33 @@ void udp_destroy_sock(struct sock *sk) - } - } - -+typedef struct sk_buff *(*udp_gro_receive_t)(struct sock *sk, -+ struct list_head *head, -+ struct sk_buff *skb); -+ - static void set_xfrm_gro_udp_encap_rcv(__u16 encap_type, unsigned short family, - struct sock *sk) - { - #ifdef CONFIG_XFRM -+ udp_gro_receive_t new_gro_receive; -+ - if (udp_test_bit(GRO_ENABLED, sk) && encap_type == UDP_ENCAP_ESPINUDP) { -- if (family == AF_INET) -- WRITE_ONCE(udp_sk(sk)->gro_receive, xfrm4_gro_udp_encap_rcv); -- else if (IS_ENABLED(CONFIG_IPV6) && family == AF_INET6) -- WRITE_ONCE(udp_sk(sk)->gro_receive, ipv6_stub->xfrm6_gro_udp_encap_rcv); -+ if (IS_ENABLED(CONFIG_IPV6) && family == AF_INET6) -+ new_gro_receive = ipv6_stub->xfrm6_gro_udp_encap_rcv; -+ else -+ new_gro_receive = xfrm4_gro_udp_encap_rcv; -+ -+ if (udp_sk(sk)->gro_receive != new_gro_receive) { -+ /* -+ * With IPV6_ADDRFORM the gro callback could change -+ * after being set, unregister the old one, if valid. -+ */ -+ if (udp_sk(sk)->gro_receive) -+ udp_tunnel_update_gro_rcv(sk, false); -+ -+ WRITE_ONCE(udp_sk(sk)->gro_receive, new_gro_receive); -+ udp_tunnel_update_gro_rcv(sk, true); -+ } - } - #endif - } -@@ -2962,6 +2980,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, - break; - - case UDP_ENCAP: -+ sockopt_lock_sock(sk); - switch (val) { - case 0: - #ifdef CONFIG_XFRM -@@ -2985,6 +3004,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, - err = -ENOPROTOOPT; - break; - } -+ sockopt_release_sock(sk); - break; - - case UDP_NO_CHECK6_TX: -@@ -3002,13 +3022,14 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, - break; - - case UDP_GRO: -- -+ sockopt_lock_sock(sk); - /* when enabling GRO, accept the related GSO packet type */ - if (valbool) - udp_tunnel_encap_enable(sk); - udp_assign_bit(GRO_ENABLED, sk, valbool); - udp_assign_bit(ACCEPT_L4, sk, valbool); - set_xfrm_gro_udp_encap_rcv(up->encap_type, sk->sk_family, sk); -+ sockopt_release_sock(sk); - break; - - /* -diff --git a/net/ipv4/udp_tunnel_core.c b/net/ipv4/udp_tunnel_core.c -index 3d1214e6df0ea..2326548997d3f 100644 ---- a/net/ipv4/udp_tunnel_core.c -+++ b/net/ipv4/udp_tunnel_core.c -@@ -90,6 +90,8 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, - - udp_tunnel_encap_enable(sk); - -+ udp_tunnel_update_gro_rcv(sk, true); -+ - if (!sk->sk_dport && !sk->sk_bound_dev_if && sk_saddr_any(sk) && - sk->sk_kern_sock) - udp_tunnel_update_gro_lookup(net, sk, true); --- -2.39.5 - diff --git a/queue-6.15/udp_tunnel-create-a-fastpath-gro-lookup.patch b/queue-6.15/udp_tunnel-create-a-fastpath-gro-lookup.patch deleted file mode 100644 index 8e2a770f99..0000000000 --- a/queue-6.15/udp_tunnel-create-a-fastpath-gro-lookup.patch +++ /dev/null @@ -1,319 +0,0 @@ -From 57f99d8615549a5172faf93150703db31f61f6eb Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 7 Apr 2025 17:45:41 +0200 -Subject: udp_tunnel: create a fastpath GRO lookup. - -From: Paolo Abeni - -[ Upstream commit a36283e2b683f172aa1760c77325e50b16c0f792 ] - -Most UDP tunnels bind a socket to a local port, with ANY address, no -peer and no interface index specified. -Additionally it's quite common to have a single tunnel device per -namespace. - -Track in each namespace the UDP tunnel socket respecting the above. -When only a single one is present, store a reference in the netns. - -When such reference is not NULL, UDP tunnel GRO lookup just need to -match the incoming packet destination port vs the socket local port. - -The tunnel socket never sets the reuse[port] flag[s]. When bound to no -address and interface, no other socket can exist in the same netns -matching the specified local port. - -Matching packets with non-local destination addresses will be -aggregated, and eventually segmented as needed - no behavior changes -intended. - -Restrict the optimization to kernel sockets only: it covers all the -relevant use-cases, and user-space owned sockets could be disconnected -and rebound after setup_udp_tunnel_sock(), breaking the uniqueness -assumption - -Note that the UDP tunnel socket reference is stored into struct -netns_ipv4 for both IPv4 and IPv6 tunnels. That is intentional to keep -all the fastpath-related netns fields in the same struct and allow -cacheline-based optimization. Currently both the IPv4 and IPv6 socket -pointer share the same cacheline as the `udp_table` field. - -Signed-off-by: Paolo Abeni -Reviewed-by: Willem de Bruijn -Link: https://patch.msgid.link/41d16bc8d1257d567f9344c445b4ae0b4a91ede4.1744040675.git.pabeni@redhat.com -Signed-off-by: Jakub Kicinski -Stable-dep-of: c26c192c3d48 ("udp: properly deal with xfrm encap and ADDRFORM") -Signed-off-by: Sasha Levin ---- - include/linux/udp.h | 16 ++++++++++++++++ - include/net/netns/ipv4.h | 11 +++++++++++ - include/net/udp.h | 1 + - include/net/udp_tunnel.h | 12 ++++++++++++ - net/ipv4/udp.c | 13 ++++++++++++- - net/ipv4/udp_offload.c | 37 +++++++++++++++++++++++++++++++++++++ - net/ipv4/udp_tunnel_core.c | 13 +++++++++++++ - net/ipv6/udp.c | 2 ++ - net/ipv6/udp_offload.c | 5 +++++ - 9 files changed, 109 insertions(+), 1 deletion(-) - -diff --git a/include/linux/udp.h b/include/linux/udp.h -index 0807e21cfec95..895240177f4f4 100644 ---- a/include/linux/udp.h -+++ b/include/linux/udp.h -@@ -101,6 +101,13 @@ struct udp_sock { - - /* Cache friendly copy of sk->sk_peek_off >= 0 */ - bool peeking_with_offset; -+ -+ /* -+ * Accounting for the tunnel GRO fastpath. -+ * Unprotected by compilers guard, as it uses space available in -+ * the last UDP socket cacheline. -+ */ -+ struct hlist_node tunnel_list; - }; - - #define udp_test_bit(nr, sk) \ -@@ -219,4 +226,13 @@ static inline void udp_allow_gso(struct sock *sk) - - #define IS_UDPLITE(__sk) (__sk->sk_protocol == IPPROTO_UDPLITE) - -+static inline struct sock *udp_tunnel_sk(const struct net *net, bool is_ipv6) -+{ -+#if IS_ENABLED(CONFIG_NET_UDP_TUNNEL) -+ return rcu_dereference(net->ipv4.udp_tunnel_gro[is_ipv6].sk); -+#else -+ return NULL; -+#endif -+} -+ - #endif /* _LINUX_UDP_H */ -diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h -index 650b2dc9199f4..6373e3f17da84 100644 ---- a/include/net/netns/ipv4.h -+++ b/include/net/netns/ipv4.h -@@ -47,6 +47,11 @@ struct sysctl_fib_multipath_hash_seed { - }; - #endif - -+struct udp_tunnel_gro { -+ struct sock __rcu *sk; -+ struct hlist_head list; -+}; -+ - struct netns_ipv4 { - /* Cacheline organization can be found documented in - * Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst. -@@ -85,6 +90,11 @@ struct netns_ipv4 { - struct inet_timewait_death_row tcp_death_row; - struct udp_table *udp_table; - -+#if IS_ENABLED(CONFIG_NET_UDP_TUNNEL) -+ /* Not in a pernet subsys because need to be available at GRO stage */ -+ struct udp_tunnel_gro udp_tunnel_gro[2]; -+#endif -+ - #ifdef CONFIG_SYSCTL - struct ctl_table_header *forw_hdr; - struct ctl_table_header *frags_hdr; -@@ -277,4 +287,5 @@ struct netns_ipv4 { - struct hlist_head *inet_addr_lst; - struct delayed_work addr_chk_work; - }; -+ - #endif -diff --git a/include/net/udp.h b/include/net/udp.h -index 6e89520e100dc..a772510b2aa58 100644 ---- a/include/net/udp.h -+++ b/include/net/udp.h -@@ -290,6 +290,7 @@ static inline void udp_lib_init_sock(struct sock *sk) - struct udp_sock *up = udp_sk(sk); - - skb_queue_head_init(&up->reader_queue); -+ INIT_HLIST_NODE(&up->tunnel_list); - up->forward_threshold = sk->sk_rcvbuf >> 2; - set_bit(SOCK_CUSTOM_SOCKOPT, &sk->sk_socket->flags); - } -diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h -index a93dc51f6323e..1bb2b852e90eb 100644 ---- a/include/net/udp_tunnel.h -+++ b/include/net/udp_tunnel.h -@@ -191,6 +191,18 @@ static inline int udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum) - } - #endif - -+#if IS_ENABLED(CONFIG_NET_UDP_TUNNEL) -+void udp_tunnel_update_gro_lookup(struct net *net, struct sock *sk, bool add); -+#else -+static inline void udp_tunnel_update_gro_lookup(struct net *net, -+ struct sock *sk, bool add) {} -+#endif -+ -+static inline void udp_tunnel_cleanup_gro(struct sock *sk) -+{ -+ udp_tunnel_update_gro_lookup(sock_net(sk), sk, false); -+} -+ - static inline void udp_tunnel_encap_enable(struct sock *sk) - { - if (udp_test_and_set_bit(ENCAP_ENABLED, sk)) -diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c -index 2742cc7602bb5..04cd3353f1d46 100644 ---- a/net/ipv4/udp.c -+++ b/net/ipv4/udp.c -@@ -2897,8 +2897,10 @@ void udp_destroy_sock(struct sock *sk) - if (encap_destroy) - encap_destroy(sk); - } -- if (udp_test_bit(ENCAP_ENABLED, sk)) -+ if (udp_test_bit(ENCAP_ENABLED, sk)) { - static_branch_dec(&udp_encap_needed_key); -+ udp_tunnel_cleanup_gro(sk); -+ } - } - } - -@@ -3810,6 +3812,15 @@ static void __net_init udp_set_table(struct net *net) - - static int __net_init udp_pernet_init(struct net *net) - { -+#if IS_ENABLED(CONFIG_NET_UDP_TUNNEL) -+ int i; -+ -+ /* No tunnel is configured */ -+ for (i = 0; i < ARRAY_SIZE(net->ipv4.udp_tunnel_gro); ++i) { -+ INIT_HLIST_HEAD(&net->ipv4.udp_tunnel_gro[i].list); -+ RCU_INIT_POINTER(net->ipv4.udp_tunnel_gro[i].sk, NULL); -+ } -+#endif - udp_sysctl_init(net); - udp_set_table(net); - -diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c -index 9a8142ccbabe4..67641945ba3a3 100644 ---- a/net/ipv4/udp_offload.c -+++ b/net/ipv4/udp_offload.c -@@ -12,6 +12,38 @@ - #include - #include - #include -+#include -+ -+#if IS_ENABLED(CONFIG_NET_UDP_TUNNEL) -+static DEFINE_SPINLOCK(udp_tunnel_gro_lock); -+ -+void udp_tunnel_update_gro_lookup(struct net *net, struct sock *sk, bool add) -+{ -+ bool is_ipv6 = sk->sk_family == AF_INET6; -+ struct udp_sock *tup, *up = udp_sk(sk); -+ struct udp_tunnel_gro *udp_tunnel_gro; -+ -+ spin_lock(&udp_tunnel_gro_lock); -+ udp_tunnel_gro = &net->ipv4.udp_tunnel_gro[is_ipv6]; -+ if (add) -+ hlist_add_head(&up->tunnel_list, &udp_tunnel_gro->list); -+ else if (up->tunnel_list.pprev) -+ hlist_del_init(&up->tunnel_list); -+ -+ if (udp_tunnel_gro->list.first && -+ !udp_tunnel_gro->list.first->next) { -+ tup = hlist_entry(udp_tunnel_gro->list.first, struct udp_sock, -+ tunnel_list); -+ -+ rcu_assign_pointer(udp_tunnel_gro->sk, (struct sock *)tup); -+ } else { -+ RCU_INIT_POINTER(udp_tunnel_gro->sk, NULL); -+ } -+ -+ spin_unlock(&udp_tunnel_gro_lock); -+} -+EXPORT_SYMBOL_GPL(udp_tunnel_update_gro_lookup); -+#endif - - static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, - netdev_features_t features, -@@ -694,8 +726,13 @@ static struct sock *udp4_gro_lookup_skb(struct sk_buff *skb, __be16 sport, - { - const struct iphdr *iph = skb_gro_network_header(skb); - struct net *net = dev_net_rcu(skb->dev); -+ struct sock *sk; - int iif, sdif; - -+ sk = udp_tunnel_sk(net, false); -+ if (sk && dport == htons(sk->sk_num)) -+ return sk; -+ - inet_get_iif_sdif(skb, &iif, &sdif); - - return __udp4_lib_lookup(net, iph->saddr, sport, -diff --git a/net/ipv4/udp_tunnel_core.c b/net/ipv4/udp_tunnel_core.c -index 619a53eb672da..3d1214e6df0ea 100644 ---- a/net/ipv4/udp_tunnel_core.c -+++ b/net/ipv4/udp_tunnel_core.c -@@ -58,6 +58,15 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg, - } - EXPORT_SYMBOL(udp_sock_create4); - -+static bool sk_saddr_any(struct sock *sk) -+{ -+#if IS_ENABLED(CONFIG_IPV6) -+ return ipv6_addr_any(&sk->sk_v6_rcv_saddr); -+#else -+ return !sk->sk_rcv_saddr; -+#endif -+} -+ - void setup_udp_tunnel_sock(struct net *net, struct socket *sock, - struct udp_tunnel_sock_cfg *cfg) - { -@@ -80,6 +89,10 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, - udp_sk(sk)->gro_complete = cfg->gro_complete; - - udp_tunnel_encap_enable(sk); -+ -+ if (!sk->sk_dport && !sk->sk_bound_dev_if && sk_saddr_any(sk) && -+ sk->sk_kern_sock) -+ udp_tunnel_update_gro_lookup(net, sk, true); - } - EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock); - -diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c -index 024458ef163c9..7317f8e053f1c 100644 ---- a/net/ipv6/udp.c -+++ b/net/ipv6/udp.c -@@ -46,6 +46,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1825,6 +1826,7 @@ void udpv6_destroy_sock(struct sock *sk) - if (udp_test_bit(ENCAP_ENABLED, sk)) { - static_branch_dec(&udpv6_encap_needed_key); - udp_encap_disable(); -+ udp_tunnel_cleanup_gro(sk); - } - } - } -diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c -index 404212dfc99ab..d8445ac1b2e43 100644 ---- a/net/ipv6/udp_offload.c -+++ b/net/ipv6/udp_offload.c -@@ -118,8 +118,13 @@ static struct sock *udp6_gro_lookup_skb(struct sk_buff *skb, __be16 sport, - { - const struct ipv6hdr *iph = skb_gro_network_header(skb); - struct net *net = dev_net_rcu(skb->dev); -+ struct sock *sk; - int iif, sdif; - -+ sk = udp_tunnel_sk(net, true); -+ if (sk && dport == htons(sk->sk_num)) -+ return sk; -+ - inet6_get_iif_sdif(skb, &iif, &sdif); - - return __udp6_lib_lookup(net, &iph->saddr, sport, --- -2.39.5 - diff --git a/queue-6.15/udp_tunnel-use-static-call-for-gro-hooks-when-possib.patch b/queue-6.15/udp_tunnel-use-static-call-for-gro-hooks-when-possib.patch deleted file mode 100644 index a981a378e9..0000000000 --- a/queue-6.15/udp_tunnel-use-static-call-for-gro-hooks-when-possib.patch +++ /dev/null @@ -1,232 +0,0 @@ -From ad8d1ce2b68078680a685515600fbafbb35fa691 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 7 Apr 2025 17:45:42 +0200 -Subject: udp_tunnel: use static call for GRO hooks when possible - -From: Paolo Abeni - -[ Upstream commit 5d7f5b2f6b935517ee5fd8058dc32342a5cba3e1 ] - -It's quite common to have a single UDP tunnel type active in the -whole system. In such a case we can replace the indirect call for -the UDP tunnel GRO callback with a static call. - -Add the related accounting in the control path and switch to static -call when possible. To keep the code simple use a static array for -the registered tunnel types, and size such array based on the kernel -config. - -Note that there are valid kernel configurations leading to -UDP_MAX_TUNNEL_TYPES == 0 even with IS_ENABLED(CONFIG_NET_UDP_TUNNEL), -Explicitly skip the accounting in such a case, to avoid compile warning -when accessing "udp_tunnel_gro_types". - -Signed-off-by: Paolo Abeni -Reviewed-by: Willem de Bruijn -Link: https://patch.msgid.link/53d156cdfddcc9678449e873cc83e68fa1582653.1744040675.git.pabeni@redhat.com -Signed-off-by: Jakub Kicinski -Stable-dep-of: c26c192c3d48 ("udp: properly deal with xfrm encap and ADDRFORM") -Signed-off-by: Sasha Levin ---- - include/net/udp_tunnel.h | 4 ++ - net/ipv4/udp_offload.c | 135 ++++++++++++++++++++++++++++++++++++++- - 2 files changed, 138 insertions(+), 1 deletion(-) - -diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h -index 1bb2b852e90eb..288f06f23a804 100644 ---- a/include/net/udp_tunnel.h -+++ b/include/net/udp_tunnel.h -@@ -193,13 +193,16 @@ static inline int udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum) - - #if IS_ENABLED(CONFIG_NET_UDP_TUNNEL) - void udp_tunnel_update_gro_lookup(struct net *net, struct sock *sk, bool add); -+void udp_tunnel_update_gro_rcv(struct sock *sk, bool add); - #else - static inline void udp_tunnel_update_gro_lookup(struct net *net, - struct sock *sk, bool add) {} -+static inline void udp_tunnel_update_gro_rcv(struct sock *sk, bool add) {} - #endif - - static inline void udp_tunnel_cleanup_gro(struct sock *sk) - { -+ udp_tunnel_update_gro_rcv(sk, false); - udp_tunnel_update_gro_lookup(sock_net(sk), sk, false); - } - -@@ -212,6 +215,7 @@ static inline void udp_tunnel_encap_enable(struct sock *sk) - if (READ_ONCE(sk->sk_family) == PF_INET6) - ipv6_stub->udpv6_encap_enable(); - #endif -+ udp_tunnel_update_gro_rcv(sk, true); - udp_encap_enable(); - } - -diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c -index 67641945ba3a3..9c775f8aa4385 100644 ---- a/net/ipv4/udp_offload.c -+++ b/net/ipv4/udp_offload.c -@@ -15,6 +15,38 @@ - #include - - #if IS_ENABLED(CONFIG_NET_UDP_TUNNEL) -+ -+/* -+ * Dummy GRO tunnel callback, exists mainly to avoid dangling/NULL -+ * values for the udp tunnel static call. -+ */ -+static struct sk_buff *dummy_gro_rcv(struct sock *sk, -+ struct list_head *head, -+ struct sk_buff *skb) -+{ -+ NAPI_GRO_CB(skb)->flush = 1; -+ return NULL; -+} -+ -+typedef struct sk_buff *(*udp_tunnel_gro_rcv_t)(struct sock *sk, -+ struct list_head *head, -+ struct sk_buff *skb); -+ -+struct udp_tunnel_type_entry { -+ udp_tunnel_gro_rcv_t gro_receive; -+ refcount_t count; -+}; -+ -+#define UDP_MAX_TUNNEL_TYPES (IS_ENABLED(CONFIG_GENEVE) + \ -+ IS_ENABLED(CONFIG_VXLAN) * 2 + \ -+ IS_ENABLED(CONFIG_NET_FOU) * 2 + \ -+ IS_ENABLED(CONFIG_XFRM) * 2) -+ -+DEFINE_STATIC_CALL(udp_tunnel_gro_rcv, dummy_gro_rcv); -+static DEFINE_STATIC_KEY_FALSE(udp_tunnel_static_call); -+static struct mutex udp_tunnel_gro_type_lock; -+static struct udp_tunnel_type_entry udp_tunnel_gro_types[UDP_MAX_TUNNEL_TYPES]; -+static unsigned int udp_tunnel_gro_type_nr; - static DEFINE_SPINLOCK(udp_tunnel_gro_lock); - - void udp_tunnel_update_gro_lookup(struct net *net, struct sock *sk, bool add) -@@ -43,6 +75,105 @@ void udp_tunnel_update_gro_lookup(struct net *net, struct sock *sk, bool add) - spin_unlock(&udp_tunnel_gro_lock); - } - EXPORT_SYMBOL_GPL(udp_tunnel_update_gro_lookup); -+ -+void udp_tunnel_update_gro_rcv(struct sock *sk, bool add) -+{ -+ struct udp_tunnel_type_entry *cur = NULL; -+ struct udp_sock *up = udp_sk(sk); -+ int i, old_gro_type_nr; -+ -+ if (!UDP_MAX_TUNNEL_TYPES || !up->gro_receive) -+ return; -+ -+ mutex_lock(&udp_tunnel_gro_type_lock); -+ -+ /* Check if the static call is permanently disabled. */ -+ if (udp_tunnel_gro_type_nr > UDP_MAX_TUNNEL_TYPES) -+ goto out; -+ -+ for (i = 0; i < udp_tunnel_gro_type_nr; i++) -+ if (udp_tunnel_gro_types[i].gro_receive == up->gro_receive) -+ cur = &udp_tunnel_gro_types[i]; -+ -+ old_gro_type_nr = udp_tunnel_gro_type_nr; -+ if (add) { -+ /* -+ * Update the matching entry, if found, or add a new one -+ * if needed -+ */ -+ if (cur) { -+ refcount_inc(&cur->count); -+ goto out; -+ } -+ -+ if (unlikely(udp_tunnel_gro_type_nr == UDP_MAX_TUNNEL_TYPES)) { -+ pr_err_once("Too many UDP tunnel types, please increase UDP_MAX_TUNNEL_TYPES\n"); -+ /* Ensure static call will never be enabled */ -+ udp_tunnel_gro_type_nr = UDP_MAX_TUNNEL_TYPES + 1; -+ } else { -+ cur = &udp_tunnel_gro_types[udp_tunnel_gro_type_nr++]; -+ refcount_set(&cur->count, 1); -+ cur->gro_receive = up->gro_receive; -+ } -+ } else { -+ /* -+ * The stack cleanups only successfully added tunnel, the -+ * lookup on removal should never fail. -+ */ -+ if (WARN_ON_ONCE(!cur)) -+ goto out; -+ -+ if (!refcount_dec_and_test(&cur->count)) -+ goto out; -+ -+ /* Avoid gaps, so that the enable tunnel has always id 0 */ -+ *cur = udp_tunnel_gro_types[--udp_tunnel_gro_type_nr]; -+ } -+ -+ if (udp_tunnel_gro_type_nr == 1) { -+ static_call_update(udp_tunnel_gro_rcv, -+ udp_tunnel_gro_types[0].gro_receive); -+ static_branch_enable(&udp_tunnel_static_call); -+ } else if (old_gro_type_nr == 1) { -+ static_branch_disable(&udp_tunnel_static_call); -+ static_call_update(udp_tunnel_gro_rcv, dummy_gro_rcv); -+ } -+ -+out: -+ mutex_unlock(&udp_tunnel_gro_type_lock); -+} -+EXPORT_SYMBOL_GPL(udp_tunnel_update_gro_rcv); -+ -+static void udp_tunnel_gro_init(void) -+{ -+ mutex_init(&udp_tunnel_gro_type_lock); -+} -+ -+static struct sk_buff *udp_tunnel_gro_rcv(struct sock *sk, -+ struct list_head *head, -+ struct sk_buff *skb) -+{ -+ if (static_branch_likely(&udp_tunnel_static_call)) { -+ if (unlikely(gro_recursion_inc_test(skb))) { -+ NAPI_GRO_CB(skb)->flush |= 1; -+ return NULL; -+ } -+ return static_call(udp_tunnel_gro_rcv)(sk, head, skb); -+ } -+ return call_gro_receive_sk(udp_sk(sk)->gro_receive, sk, head, skb); -+} -+ -+#else -+ -+static void udp_tunnel_gro_init(void) {} -+ -+static struct sk_buff *udp_tunnel_gro_rcv(struct sock *sk, -+ struct list_head *head, -+ struct sk_buff *skb) -+{ -+ return call_gro_receive_sk(udp_sk(sk)->gro_receive, sk, head, skb); -+} -+ - #endif - - static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, -@@ -713,7 +844,7 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb, - - skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */ - skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr)); -- pp = call_gro_receive_sk(udp_sk(sk)->gro_receive, sk, head, skb); -+ pp = udp_tunnel_gro_rcv(sk, head, skb); - - out: - skb_gro_flush_final(skb, pp, flush); -@@ -863,5 +994,7 @@ int __init udpv4_offload_init(void) - .gro_complete = udp4_gro_complete, - }, - }; -+ -+ udp_tunnel_gro_init(); - return inet_add_offload(&net_hotdata.udpv4_offload, IPPROTO_UDP); - } --- -2.39.5 -