* [PATCH v3 net-next 00/15] udp: Retire UDP-Lite.
@ 2026-03-11 5:19 Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 01/15] udp: Make udp[46]_seq_show() static Kuniyuki Iwashima
` (15 more replies)
0 siblings, 16 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev
In 2023, syzbot found a null-ptr-deref bug triggered when UDP-Lite
attempted to charge an skb after the total memory usage for UDP-Lite
_and_ UDP exceeded a system-wide threshold, net.ipv4.udp_mem[1].
Since this threshold is shared with UDP, the bug would have been
easy to trigger if any real-world applications were using UDP-Lite;
however, only syzbot ever stumbled upon it.
The bug had persisted since 2016, suggesting that UDP-Lite had
remained unused for 7 years at that point.
The bug was fixed in commit ad42a35bdfc6 ("udplite: Fix NULL pointer
dereference in __sk_mem_raise_allocated()."), and we added another
commit be28c14ac8bb ("udplite: Print deprecation notice.") to
announce the deprecation plan.
Since then, no one has complained, so it is time to officially
retire UDP-Lite.
This series first removes IPv6 and IPv4 UDP-Lite sockets, then
gradually cleans up the remaining dead/unnecessary code within
the UDP stack.
By removing a bunch of conditionals for UDP-Lite from the fast
path, udp_rr with 20,000 flows sees a 10% increase in pps
(13.3 Mpps -> 14.7 Mpps) on an AMD EPYC 7B12 (Zen 2) 64-Core
Processor platform.
[ With FDO, the baseline is much higher and the delta was ~3%,
20.1 Mpps -> 20.7 Mpps ]
Before:
$ nstat > /dev/null; sleep 1; nstat | grep Udp
Udp6InDatagrams 14013408 0.0
Udp6OutDatagrams 14013128 0.0
After:
$ nstat > /dev/null; sleep 1; nstat | grep Udp
Udp6InDatagrams 15491971 0.0
Udp6OutDatagrams 15491671 0.0
$ ./scripts/bloat-o-meter vmlinux.before vmlinux.after
add/remove: 13/75 grow/shrink: 11/75 up/down: 13777/-18401 (-4624)
Function old new delta
udp4_gro_receive 872 866 -6
udp6_gro_receive 910 903 -7
udp_rcv 32 1727 +1695
udpv6_rcv 32 1450 +1418
__udp4_lib_rcv 2045 - -2045
__udp6_lib_rcv 2084 - -2084
udp_unicast_rcv_skb 160 149 -11
udp6_unicast_rcv_skb 196 181 -15
__udp4_lib_mcast_deliver 925 846 -79
__udp6_lib_mcast_deliver 922 810 -112
__udp4_lib_lookup 973 969 -4
__udp6_lib_lookup 940 929 -11
__udp4_lib_lookup_skb 106 100 -6
__udp6_lib_lookup_skb 71 66 -5
udp4_lib_lookup_skb 132 127 -5
udp6_lib_lookup_skb 87 81 -6
udp_queue_rcv_skb 326 356 +30
udpv6_queue_rcv_skb 331 361 +30
udp_queue_rcv_one_skb 1233 914 -319
udpv6_queue_rcv_one_skb 1250 930 -320
__udp_enqueue_schedule_skb 1067 995 -72
udp_rcv_segment 520 480 -40
udp_post_segment_fix_csum 120 - -120
udp_lib_checksum_complete 200 84 -116
udp_err 27 1103 +1076
udpv6_err 36 1417 +1381
__udp4_lib_err 1112 - -1112
__udp6_lib_err 1448 - -1448
udp_recvmsg 1149 994 -155
udpv6_recvmsg 1349 1294 -55
udp_sendmsg 2730 2648 -82
udp_send_skb 909 681 -228
udpv6_sendmsg 3022 2861 -161
udp_v6_send_skb 1214 952 -262
...
Total: Before=18446744073748075501, After=18446744073748070877, chg -0.00%
Changes:
v3:
Patch 7: Correct ulen < skb->len case in __udp4_lib_rcv()
v2: https://lore.kernel.org/netdev/20260305215013.2984628-1-kuniyu@google.com/
Patch 4 : Make udp_seq_ops static
Patch 9 : Add a detailed reason in include/uapi/linux/udp.h
v1: https://lore.kernel.org/netdev/20260304193034.1870586-1-kuniyu@google.com/
Kuniyuki Iwashima (15):
udp: Make udp[46]_seq_show() static.
ipv6: Retire UDP-Lite.
ipv6: Remove UDP-Lite support for IPV6_ADDRFORM.
ipv4: Retire UDP-Lite.
udp: Remove UDP-Lite SNMP stats.
smack: Remove IPPROTO_UDPLITE support in security_sock_rcv_skb().
udp: Remove partial csum code in RX.
udp: Remove partial csum code in TX.
udp: Remove UDPLITE_SEND_CSCOV and UDPLITE_RECV_CSCOV.
udp: Remove struct proto.h.udp_table.
udp: Remove udp_table in struct udp_seq_afinfo.
udp: Remove dead check in __udp[46]_lib_lookup() for BPF.
udp: Don't pass udptable to IPv6 socket lookup functions.
udp: Don't pass udptable to IPv4 socket lookup functions.
udp: Don't pass proto to __udp4_lib_rcv() and __udp6_lib_rcv().
include/linux/udp.h | 10 +-
include/net/ipv6.h | 2 -
include/net/ipv6_stubs.h | 7 +-
include/net/netns/mib.h | 5 -
include/net/sock.h | 5 +-
include/net/transp_v6.h | 3 -
include/net/udp.h | 86 +++-----
include/net/udplite.h | 88 --------
include/uapi/linux/udp.h | 2 +
net/core/filter.c | 5 +-
net/ipv4/Makefile | 2 +-
net/ipv4/af_inet.c | 12 --
net/ipv4/proc.c | 16 --
net/ipv4/udp.c | 430 ++++++++++++-------------------------
net/ipv4/udp_bpf.c | 2 -
net/ipv4/udp_diag.c | 128 +++--------
net/ipv4/udp_impl.h | 27 ---
net/ipv4/udp_offload.c | 3 +-
net/ipv4/udplite.c | 135 ------------
net/ipv6/Makefile | 2 +-
net/ipv6/af_inet6.c | 32 +--
net/ipv6/ip6_checksum.c | 2 +-
net/ipv6/ipv6_sockglue.c | 17 +-
net/ipv6/proc.c | 16 --
net/ipv6/udp.c | 304 ++++++++++----------------
net/ipv6/udp_impl.h | 31 ---
net/ipv6/udp_offload.c | 3 +-
net/ipv6/udplite.c | 139 ------------
net/rxrpc/output.c | 2 -
security/smack/smack_lsm.c | 4 +-
30 files changed, 342 insertions(+), 1178 deletions(-)
delete mode 100644 include/net/udplite.h
delete mode 100644 net/ipv4/udp_impl.h
delete mode 100644 net/ipv4/udplite.c
delete mode 100644 net/ipv6/udp_impl.h
delete mode 100644 net/ipv6/udplite.c
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 01/15] udp: Make udp[46]_seq_show() static.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 02/15] ipv6: Retire UDP-Lite Kuniyuki Iwashima
` (14 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
Since commit a3d2599b2446 ("ipv{4,6}/udp{,lite}: simplify proc
registration"), udp4_seq_show() and udp6_seq_show() are not
used in net/ipv4/udplite.c and net/ipv6/udplite.c.
Instead, udp_seq_ops and udp6_seq_ops are exposed to UDP-Lite.
Let's make udp4_seq_show() and udp6_seq_show() static.
udp_seq_ops and udp6_seq_ops are moved to udp_impl.h so that
we can make them static when the header is removed.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
include/net/udp.h | 3 ---
net/ipv4/udp.c | 3 +--
net/ipv4/udp_impl.h | 2 +-
net/ipv6/udp.c | 3 +--
net/ipv6/udp_impl.h | 2 +-
5 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/include/net/udp.h b/include/net/udp.h
index b648003e5792..f51a51c0e468 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -576,9 +576,6 @@ void *udp_seq_start(struct seq_file *seq, loff_t *pos);
void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos);
void udp_seq_stop(struct seq_file *seq, void *v);
-extern const struct seq_operations udp_seq_ops;
-extern const struct seq_operations udp6_seq_ops;
-
int udp4_proc_init(void);
void udp4_proc_exit(void);
#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 668a0284c3d5..1fcdc5482594 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -3443,7 +3443,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
sk_drops_read(sp));
}
-int udp4_seq_show(struct seq_file *seq, void *v)
+static int udp4_seq_show(struct seq_file *seq, void *v)
{
seq_setwidth(seq, 127);
if (v == SEQ_START_TOKEN)
@@ -3753,7 +3753,6 @@ const struct seq_operations udp_seq_ops = {
.stop = udp_seq_stop,
.show = udp4_seq_show,
};
-EXPORT_IPV6_MOD(udp_seq_ops);
static struct udp_seq_afinfo udp4_seq_afinfo = {
.family = AF_INET,
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index 17a6fa8b1409..0ca4384f9afa 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -22,6 +22,6 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags);
void udp_destroy_sock(struct sock *sk);
#ifdef CONFIG_PROC_FS
-int udp4_seq_show(struct seq_file *seq, void *v);
+extern const struct seq_operations udp_seq_ops;
#endif
#endif /* _UDP4_IMPL_H */
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5a3984e59c90..5fef1c226697 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1903,7 +1903,7 @@ int udpv6_getsockopt(struct sock *sk, int level, int optname,
/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
-int udp6_seq_show(struct seq_file *seq, void *v)
+static int udp6_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN) {
seq_puts(seq, IPV6_SEQ_DGRAM_HEADER);
@@ -1924,7 +1924,6 @@ const struct seq_operations udp6_seq_ops = {
.stop = udp_seq_stop,
.show = udp6_seq_show,
};
-EXPORT_SYMBOL(udp6_seq_ops);
static struct udp_seq_afinfo udp6_seq_afinfo = {
.family = AF_INET6,
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 1bd4a573e1bb..525ea600228a 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -26,6 +26,6 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags);
void udpv6_destroy_sock(struct sock *sk);
#ifdef CONFIG_PROC_FS
-int udp6_seq_show(struct seq_file *seq, void *v);
+extern const struct seq_operations udp6_seq_ops;
#endif
#endif /* _UDP6_IMPL_H */
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 02/15] ipv6: Retire UDP-Lite.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 01/15] udp: Make udp[46]_seq_show() static Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 03/15] ipv6: Remove UDP-Lite support for IPV6_ADDRFORM Kuniyuki Iwashima
` (13 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
As announced in commit be28c14ac8bb ("udplite: Print deprecation
notice."), it's time to deprecate UDP-Lite.
As a first step, let's drop support for IPv6 UDP-Lite sockets.
We will remove the remaining dead code gradually.
Along with the removal of udplite.c, most of the functions exposed
via udp_impl.h are made static.
The prototypes of udpv6_sendmsg() and udpv6_recvmsg() are moved
to udp.h, but only udpv6_recvmsg() has INDIRECT_CALLABLE_DECLARE()
because udpv6_sendmsg() is exported for rxrpc since commit ed472b0c8783
("rxrpc: Call udp_sendmsg() directly").
Also, udpv6_recvmsg() needs INDIRECT_CALLABLE_SCOPE for
CONFIG_MITIGATION_RETPOLINE=n.
Note that udplite.h is included temporarily for udplite_csum().
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
include/net/ipv6.h | 2 -
include/net/transp_v6.h | 3 -
include/net/udp.h | 4 ++
net/ipv6/Makefile | 2 +-
net/ipv6/af_inet6.c | 23 +------
net/ipv6/proc.c | 2 -
net/ipv6/udp.c | 32 ++++-----
net/ipv6/udp_impl.h | 31 ---------
net/ipv6/udplite.c | 139 ----------------------------------------
net/rxrpc/output.c | 2 -
10 files changed, 23 insertions(+), 217 deletions(-)
delete mode 100644 net/ipv6/udp_impl.h
delete mode 100644 net/ipv6/udplite.c
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 1c0ce5151275..0958cc5c6ec3 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -1179,8 +1179,6 @@ int tcp6_proc_init(struct net *net);
void tcp6_proc_exit(struct net *net);
int udp6_proc_init(struct net *net);
void udp6_proc_exit(struct net *net);
-int udplite6_proc_init(void);
-void udplite6_proc_exit(void);
int ipv6_misc_proc_init(void);
void ipv6_misc_proc_exit(void);
int snmp6_register_dev(struct inet6_dev *idev);
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 1a97e3f32029..c0a421fe0c2a 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -8,7 +8,6 @@
/* IPv6 transport protocols */
extern struct proto rawv6_prot;
extern struct proto udpv6_prot;
-extern struct proto udplitev6_prot;
extern struct proto tcpv6_prot;
extern struct proto pingv6_prot;
@@ -28,8 +27,6 @@ int rawv6_init(void);
void rawv6_exit(void);
int udpv6_init(void);
void udpv6_exit(void);
-int udplitev6_init(void);
-void udplitev6_exit(void);
int tcpv6_init(void);
void tcpv6_exit(void);
diff --git a/include/net/udp.h b/include/net/udp.h
index f51a51c0e468..05f63e9e00a7 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -282,6 +282,10 @@ typedef struct sock *(*udp_lookup_t)(const struct sk_buff *skb, __be16 sport,
void udp_v6_early_demux(struct sk_buff *skb);
INDIRECT_CALLABLE_DECLARE(int udpv6_rcv(struct sk_buff *));
+int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
+INDIRECT_CALLABLE_DECLARE(int udpv6_recvmsg(struct sock *sk, struct msghdr *msg,
+ size_t len, int flags));
+
struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
netdev_features_t features, bool is_ipv6);
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 0492f1a0b491..2c9ce2ccbde1 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o
ipv6-y := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
addrlabel.o \
- route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
+ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o \
raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \
exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o \
udp_offload.o seg6.o fib6_notifier.o rpl.o ioam6.o
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 0b995a961359..9ad907a5a093 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -43,7 +43,6 @@
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/udp.h>
-#include <net/udplite.h>
#include <net/tcp.h>
#include <net/ping.h>
#include <net/protocol.h>
@@ -644,8 +643,6 @@ int inet6_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
EXPORT_SYMBOL_GPL(inet6_compat_ioctl);
#endif /* CONFIG_COMPAT */
-INDIRECT_CALLABLE_DECLARE(int udpv6_sendmsg(struct sock *, struct msghdr *,
- size_t));
int inet6_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
{
struct sock *sk = sock->sk;
@@ -660,8 +657,6 @@ int inet6_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
sk, msg, size);
}
-INDIRECT_CALLABLE_DECLARE(int udpv6_recvmsg(struct sock *, struct msghdr *,
- size_t, int));
int inet6_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags)
{
@@ -1088,13 +1083,9 @@ static int __init inet6_init(void)
if (err)
goto out_unregister_tcp_proto;
- err = proto_register(&udplitev6_prot, 1);
- if (err)
- goto out_unregister_udp_proto;
-
err = proto_register(&rawv6_prot, 1);
if (err)
- goto out_unregister_udplite_proto;
+ goto out_unregister_udp_proto;
err = proto_register(&pingv6_prot, 1);
if (err)
@@ -1145,8 +1136,6 @@ static int __init inet6_init(void)
err = -ENOMEM;
if (raw6_proc_init())
goto proc_raw6_fail;
- if (udplite6_proc_init())
- goto proc_udplite6_fail;
if (ipv6_misc_proc_init())
goto proc_misc6_fail;
if (if6_proc_init())
@@ -1182,10 +1171,6 @@ static int __init inet6_init(void)
if (err)
goto udpv6_fail;
- err = udplitev6_init();
- if (err)
- goto udplitev6_fail;
-
err = udpv6_offload_init();
if (err)
goto udpv6_offload_fail;
@@ -1256,8 +1241,6 @@ static int __init inet6_init(void)
tcpv6_fail:
udpv6_offload_exit();
udpv6_offload_fail:
- udplitev6_exit();
-udplitev6_fail:
udpv6_exit();
udpv6_fail:
ipv6_frag_exit();
@@ -1279,8 +1262,6 @@ static int __init inet6_init(void)
proc_if6_fail:
ipv6_misc_proc_exit();
proc_misc6_fail:
- udplite6_proc_exit();
-proc_udplite6_fail:
raw6_proc_exit();
proc_raw6_fail:
#endif
@@ -1304,8 +1285,6 @@ static int __init inet6_init(void)
proto_unregister(&pingv6_prot);
out_unregister_raw_proto:
proto_unregister(&rawv6_prot);
-out_unregister_udplite_proto:
- proto_unregister(&udplitev6_prot);
out_unregister_udp_proto:
proto_unregister(&udpv6_prot);
out_unregister_tcp_proto:
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 73296f38c252..21bfc73152f0 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -39,8 +39,6 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v)
sock_prot_inuse_get(net, &tcpv6_prot));
seq_printf(seq, "UDP6: inuse %d\n",
sock_prot_inuse_get(net, &udpv6_prot));
- seq_printf(seq, "UDPLITE6: inuse %d\n",
- sock_prot_inuse_get(net, &udplitev6_prot));
seq_printf(seq, "RAW6: inuse %d\n",
sock_prot_inuse_get(net, &rawv6_prot));
seq_printf(seq, "FRAG6: inuse %u memory %lu\n",
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5fef1c226697..aa859bb0527d 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -37,6 +37,7 @@
#include <trace/events/udp.h>
#include <net/addrconf.h>
+#include <net/aligned_data.h>
#include <net/ndisc.h>
#include <net/protocol.h>
#include <net/transp_v6.h>
@@ -57,7 +58,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <trace/events/skb.h>
-#include "udp_impl.h"
+#include <net/udplite.h>
static void udpv6_destruct_sock(struct sock *sk)
{
@@ -65,7 +66,7 @@ static void udpv6_destruct_sock(struct sock *sk)
inet6_sock_destruct(sk);
}
-int udpv6_init_sock(struct sock *sk)
+static int udpv6_init_sock(struct sock *sk)
{
int res = udp_lib_init_sock(sk);
@@ -95,7 +96,7 @@ u32 udp6_ehashfn(const struct net *net,
udp6_ehash_secret + net_hash_mix(net));
}
-int udp_v6_get_port(struct sock *sk, unsigned short snum)
+static int udp_v6_get_port(struct sock *sk, unsigned short snum)
{
unsigned int hash2_nulladdr =
ipv6_portaddr_hash(sock_net(sk), &in6addr_any, snum);
@@ -107,7 +108,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
return udp_lib_get_port(sk, snum, hash2_nulladdr);
}
-void udp_v6_rehash(struct sock *sk)
+static void udp_v6_rehash(struct sock *sk)
{
u16 new_hash = ipv6_portaddr_hash(sock_net(sk),
&sk->sk_v6_rcv_saddr,
@@ -464,6 +465,7 @@ static int udp6_skb_len(struct sk_buff *skb)
* return it, otherwise we block.
*/
+INDIRECT_CALLABLE_SCOPE
int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int flags)
{
@@ -700,9 +702,9 @@ static struct sock *__udp6_lib_err_encap(struct net *net,
return sk;
}
-int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- u8 type, u8 code, int offset, __be32 info,
- struct udp_table *udptable)
+static int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ u8 type, u8 code, int offset, __be32 info,
+ struct udp_table *udptable)
{
struct ipv6_pinfo *np;
const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
@@ -1115,8 +1117,8 @@ static int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto)
return 0;
}
-int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
- int proto)
+static int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
+ int proto)
{
enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
const struct in6_addr *saddr, *daddr;
@@ -1854,7 +1856,7 @@ static void udpv6_splice_eof(struct socket *sock)
release_sock(sk);
}
-void udpv6_destroy_sock(struct sock *sk)
+static void udpv6_destroy_sock(struct sock *sk)
{
struct udp_sock *up = udp_sk(sk);
lock_sock(sk);
@@ -1882,8 +1884,8 @@ void udpv6_destroy_sock(struct sock *sk)
/*
* Socket option code for UDP
*/
-int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
- unsigned int optlen)
+static int udpv6_setsockopt(struct sock *sk, int level, int optname,
+ sockptr_t optval, unsigned int optlen)
{
if (level == SOL_UDP || level == SOL_UDPLITE || level == SOL_SOCKET)
return udp_lib_setsockopt(sk, level, optname,
@@ -1892,8 +1894,8 @@ int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
return ipv6_setsockopt(sk, level, optname, optval, optlen);
}
-int udpv6_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
+static int udpv6_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
{
if (level == SOL_UDP || level == SOL_UDPLITE)
return udp_lib_getsockopt(sk, level, optname, optval, optlen);
@@ -1918,7 +1920,7 @@ static int udp6_seq_show(struct seq_file *seq, void *v)
return 0;
}
-const struct seq_operations udp6_seq_ops = {
+static const struct seq_operations udp6_seq_ops = {
.start = udp_seq_start,
.next = udp_seq_next,
.stop = udp_seq_stop,
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
deleted file mode 100644
index 525ea600228a..000000000000
--- a/net/ipv6/udp_impl.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _UDP6_IMPL_H
-#define _UDP6_IMPL_H
-#include <net/aligned_data.h>
-#include <net/udp.h>
-#include <net/udplite.h>
-#include <net/protocol.h>
-#include <net/addrconf.h>
-#include <net/inet_common.h>
-#include <net/transp_v6.h>
-
-int __udp6_lib_rcv(struct sk_buff *, struct udp_table *, int);
-int __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, u8, u8, int,
- __be32, struct udp_table *);
-
-int udpv6_init_sock(struct sock *sk);
-int udp_v6_get_port(struct sock *sk, unsigned short snum);
-void udp_v6_rehash(struct sock *sk);
-
-int udpv6_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen);
-int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
- unsigned int optlen);
-int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
-int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags);
-void udpv6_destroy_sock(struct sock *sk);
-
-#ifdef CONFIG_PROC_FS
-extern const struct seq_operations udp6_seq_ops;
-#endif
-#endif /* _UDP6_IMPL_H */
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
deleted file mode 100644
index e867721cda4d..000000000000
--- a/net/ipv6/udplite.c
+++ /dev/null
@@ -1,139 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * UDPLITEv6 An implementation of the UDP-Lite protocol over IPv6.
- * See also net/ipv4/udplite.c
- *
- * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk>
- *
- * Changes:
- * Fixes:
- */
-#define pr_fmt(fmt) "UDPLite6: " fmt
-
-#include <linux/export.h>
-#include <linux/proc_fs.h>
-#include "udp_impl.h"
-
-static int udplitev6_sk_init(struct sock *sk)
-{
- pr_warn_once("UDP-Lite is deprecated and scheduled to be removed in 2025, "
- "please contact the netdev mailing list\n");
- return udpv6_init_sock(sk);
-}
-
-static int udplitev6_rcv(struct sk_buff *skb)
-{
- return __udp6_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
-}
-
-static int udplitev6_err(struct sk_buff *skb,
- struct inet6_skb_parm *opt,
- u8 type, u8 code, int offset, __be32 info)
-{
- return __udp6_lib_err(skb, opt, type, code, offset, info,
- &udplite_table);
-}
-
-static const struct inet6_protocol udplitev6_protocol = {
- .handler = udplitev6_rcv,
- .err_handler = udplitev6_err,
- .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
-};
-
-struct proto udplitev6_prot = {
- .name = "UDPLITEv6",
- .owner = THIS_MODULE,
- .close = udp_lib_close,
- .connect = ip6_datagram_connect,
- .disconnect = udp_disconnect,
- .ioctl = udp_ioctl,
- .init = udplitev6_sk_init,
- .destroy = udpv6_destroy_sock,
- .setsockopt = udpv6_setsockopt,
- .getsockopt = udpv6_getsockopt,
- .sendmsg = udpv6_sendmsg,
- .recvmsg = udpv6_recvmsg,
- .hash = udp_lib_hash,
- .unhash = udp_lib_unhash,
- .rehash = udp_v6_rehash,
- .get_port = udp_v6_get_port,
-
- .memory_allocated = &net_aligned_data.udp_memory_allocated,
- .per_cpu_fw_alloc = &udp_memory_per_cpu_fw_alloc,
-
- .sysctl_mem = sysctl_udp_mem,
- .sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
- .sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
- .obj_size = sizeof(struct udp6_sock),
- .ipv6_pinfo_offset = offsetof(struct udp6_sock, inet6),
- .h.udp_table = &udplite_table,
-};
-
-static struct inet_protosw udplite6_protosw = {
- .type = SOCK_DGRAM,
- .protocol = IPPROTO_UDPLITE,
- .prot = &udplitev6_prot,
- .ops = &inet6_dgram_ops,
- .flags = INET_PROTOSW_PERMANENT,
-};
-
-int __init udplitev6_init(void)
-{
- int ret;
-
- ret = inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
- if (ret)
- goto out;
-
- ret = inet6_register_protosw(&udplite6_protosw);
- if (ret)
- goto out_udplitev6_protocol;
-out:
- return ret;
-
-out_udplitev6_protocol:
- inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
- goto out;
-}
-
-void udplitev6_exit(void)
-{
- inet6_unregister_protosw(&udplite6_protosw);
- inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
-}
-
-#ifdef CONFIG_PROC_FS
-static struct udp_seq_afinfo udplite6_seq_afinfo = {
- .family = AF_INET6,
- .udp_table = &udplite_table,
-};
-
-static int __net_init udplite6_proc_init_net(struct net *net)
-{
- if (!proc_create_net_data("udplite6", 0444, net->proc_net,
- &udp6_seq_ops, sizeof(struct udp_iter_state),
- &udplite6_seq_afinfo))
- return -ENOMEM;
- return 0;
-}
-
-static void __net_exit udplite6_proc_exit_net(struct net *net)
-{
- remove_proc_entry("udplite6", net->proc_net);
-}
-
-static struct pernet_operations udplite6_net_ops = {
- .init = udplite6_proc_init_net,
- .exit = udplite6_proc_exit_net,
-};
-
-int __init udplite6_proc_init(void)
-{
- return register_pernet_subsys(&udplite6_net_ops);
-}
-
-void udplite6_proc_exit(void)
-{
- unregister_pernet_subsys(&udplite6_net_ops);
-}
-#endif
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index d70db367e358..e5880116e087 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -16,8 +16,6 @@
#include <net/udp.h>
#include "ar-internal.h"
-extern int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
-
ssize_t do_udp_sendmsg(struct socket *socket, struct msghdr *msg, size_t len)
{
struct sockaddr *sa = msg->msg_name;
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 03/15] ipv6: Remove UDP-Lite support for IPV6_ADDRFORM.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 01/15] udp: Make udp[46]_seq_show() static Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 02/15] ipv6: Retire UDP-Lite Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 04/15] ipv4: Retire UDP-Lite Kuniyuki Iwashima
` (12 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
We cannot create IPv6 UDP-Lite sockets anymore.
Let's remove dead code in IPV6_ADDRFORM.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
net/ipv6/ipv6_sockglue.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 02c4cab60c69..b4c977434c2e 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -45,7 +45,6 @@
#include <net/inet_common.h>
#include <net/tcp.h>
#include <net/udp.h>
-#include <net/udplite.h>
#include <net/xfrm.h>
#include <net/compat.h>
#include <net/seg6.h>
@@ -563,10 +562,8 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
if (sk->sk_type == SOCK_RAW)
break;
- if (sk->sk_protocol == IPPROTO_UDP ||
- sk->sk_protocol == IPPROTO_UDPLITE) {
- struct udp_sock *up = udp_sk(sk);
- if (up->pending == AF_INET6) {
+ if (sk->sk_protocol == IPPROTO_UDP) {
+ if (udp_sk(sk)->pending == AF_INET6) {
retv = -EBUSY;
break;
}
@@ -607,16 +604,11 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
WRITE_ONCE(sk->sk_family, PF_INET);
tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
} else {
- struct proto *prot = &udp_prot;
-
- if (sk->sk_protocol == IPPROTO_UDPLITE)
- prot = &udplite_prot;
-
sock_prot_inuse_add(net, sk->sk_prot, -1);
- sock_prot_inuse_add(net, prot, 1);
+ sock_prot_inuse_add(net, &udp_prot, 1);
/* Paired with READ_ONCE(sk->sk_prot) in inet6_dgram_ops */
- WRITE_ONCE(sk->sk_prot, prot);
+ WRITE_ONCE(sk->sk_prot, &udp_prot);
WRITE_ONCE(sk->sk_socket->ops, &inet_dgram_ops);
WRITE_ONCE(sk->sk_family, PF_INET);
}
@@ -1098,7 +1090,6 @@ int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
switch (optname) {
case IPV6_ADDRFORM:
if (sk->sk_protocol != IPPROTO_UDP &&
- sk->sk_protocol != IPPROTO_UDPLITE &&
sk->sk_protocol != IPPROTO_TCP)
return -ENOPROTOOPT;
if (sk->sk_state != TCP_ESTABLISHED)
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 04/15] ipv4: Retire UDP-Lite.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (2 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 03/15] ipv6: Remove UDP-Lite support for IPV6_ADDRFORM Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 05/15] udp: Remove UDP-Lite SNMP stats Kuniyuki Iwashima
` (11 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
We have deprecated IPv6 UDP-Lite sockets.
Let's drop support for IPv4 UDP-Lite sockets as well.
Most of the changes are similar to the IPv6 patch: removing
udplite.c and udp_impl.h, marking most functions in udp_impl.h
as static, moving the prototype for udp_recvmsg() to udp.h, and
adding INDIRECT_CALLABLE_SCOPE for it.
In addition, the INET_DIAG support for UDP-Lite is dropped.
We will remove the remaining dead code in the following patches.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
v2: Make udp_seq_ops static
---
include/net/sock.h | 4 +-
include/net/udp.h | 7 ++-
include/net/udplite.h | 4 --
net/ipv4/Makefile | 2 +-
net/ipv4/af_inet.c | 6 --
net/ipv4/proc.c | 3 -
net/ipv4/udp.c | 33 ++++++-----
net/ipv4/udp_bpf.c | 2 -
net/ipv4/udp_diag.c | 47 +--------------
net/ipv4/udp_impl.h | 27 ---------
net/ipv4/udplite.c | 135 ------------------------------------------
11 files changed, 26 insertions(+), 244 deletions(-)
delete mode 100644 net/ipv4/udp_impl.h
delete mode 100644 net/ipv4/udplite.c
diff --git a/include/net/sock.h b/include/net/sock.h
index 6c3f1340e8ef..16a1b8895206 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -126,14 +126,14 @@ typedef __u64 __bitwise __addrpair;
* @skc_bypass_prot_mem: bypass the per-protocol memory accounting for skb
* @skc_bound_dev_if: bound device index if != 0
* @skc_bind_node: bind hash linkage for various protocol lookup tables
- * @skc_portaddr_node: second hash linkage for UDP/UDP-Lite protocol
+ * @skc_portaddr_node: second hash linkage for UDP
* @skc_prot: protocol handlers inside a network family
* @skc_net: reference to the network namespace of this socket
* @skc_v6_daddr: IPV6 destination address
* @skc_v6_rcv_saddr: IPV6 source address
* @skc_cookie: socket's cookie value
* @skc_node: main hash linkage for various protocol lookup tables
- * @skc_nulls_node: main hash linkage for TCP/UDP/UDP-Lite protocol
+ * @skc_nulls_node: main hash linkage for TCP
* @skc_tx_queue_mapping: tx queue number for this connection
* @skc_rx_queue_mapping: rx queue number for this connection
* @skc_flags: place holder for sk_flags
diff --git a/include/net/udp.h b/include/net/udp.h
index 05f63e9e00a7..39223e2692e9 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -105,7 +105,7 @@ struct udp_table {
unsigned int log;
};
extern struct udp_table udp_table;
-void udp_table_init(struct udp_table *, const char *);
+
static inline struct udp_hslot *udp_hashslot(struct udp_table *table,
const struct net *net,
unsigned int num)
@@ -312,7 +312,7 @@ static inline void udp_drops_inc(struct sock *sk)
numa_drop_add(&udp_sk(sk)->drop_counters, 1);
}
-/* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
+/* hash routines shared between UDPv4/6 */
static inline int udp_lib_hash(struct sock *sk)
{
BUG();
@@ -420,6 +420,8 @@ bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst);
int udp_err(struct sk_buff *, u32);
int udp_abort(struct sock *sk, int err);
int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
+INDIRECT_CALLABLE_DECLARE(int udp_recvmsg(struct sock *sk, struct msghdr *msg,
+ size_t len, int flags));
void udp_splice_eof(struct socket *sock);
int udp_push_pending_frames(struct sock *sk);
void udp_flush_pending_frames(struct sock *sk);
@@ -427,7 +429,6 @@ int udp_cmsg_send(struct sock *sk, struct msghdr *msg, u16 *gso_size);
void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
int udp_rcv(struct sk_buff *skb);
int udp_ioctl(struct sock *sk, int cmd, int *karg);
-int udp_init_sock(struct sock *sk);
int udp_pre_connect(struct sock *sk, struct sockaddr_unsized *uaddr, int addr_len);
int __udp_disconnect(struct sock *sk, int flags);
int udp_disconnect(struct sock *sk, int flags);
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 786919d29f8d..fdd769745ac4 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -12,9 +12,6 @@
#define UDPLITE_SEND_CSCOV 10 /* sender partial coverage (as sent) */
#define UDPLITE_RECV_CSCOV 11 /* receiver partial coverage (threshold ) */
-extern struct proto udplite_prot;
-extern struct udp_table udplite_table;
-
/*
* Checksum computation is all in software, hence simpler getfrag.
*/
@@ -84,5 +81,4 @@ static inline __wsum udplite_csum(struct sk_buff *skb)
return skb_checksum(skb, off, len, 0);
}
-void udplite4_register(void);
#endif /* _UDPLITE_H */
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 18108a6f0499..7f9f98813986 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -10,7 +10,7 @@ obj-y := route.o inetpeer.o protocol.o \
tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
tcp_minisocks.o tcp_cong.o tcp_metrics.o tcp_fastopen.o \
tcp_recovery.o tcp_ulp.o \
- tcp_offload.o tcp_plb.o datagram.o raw.o udp.o udplite.o \
+ tcp_offload.o tcp_plb.o datagram.o raw.o udp.o \
udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \
fib_frontend.o fib_semantics.o fib_trie.o fib_notifier.o \
inet_fragment.o ping.o ip_tunnel_core.o gre_offload.o \
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index e95ffa070568..58347619003c 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -104,7 +104,6 @@
#include <net/tcp.h>
#include <net/psp.h>
#include <net/udp.h>
-#include <net/udplite.h>
#include <net/ping.h>
#include <linux/skbuff.h>
#include <net/sock.h>
@@ -878,8 +877,6 @@ void inet_splice_eof(struct socket *sock)
}
EXPORT_SYMBOL_GPL(inet_splice_eof);
-INDIRECT_CALLABLE_DECLARE(int udp_recvmsg(struct sock *, struct msghdr *,
- size_t, int));
int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags)
{
@@ -1979,9 +1976,6 @@ static int __init inet_init(void)
/* Setup UDP memory threshold */
udp_init();
- /* Add UDP-Lite (RFC 3828) */
- udplite4_register();
-
raw_init();
ping_init();
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 974afc4ecbe2..cf51f8fcf34b 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -35,7 +35,6 @@
#include <net/mptcp.h>
#include <net/proto_memory.h>
#include <net/udp.h>
-#include <net/udplite.h>
#include <linux/bottom_half.h>
#include <linux/inetdevice.h>
#include <linux/proc_fs.h>
@@ -65,8 +64,6 @@ static int sockstat_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "UDP: inuse %d mem %ld\n",
sock_prot_inuse_get(net, &udp_prot),
proto_memory_allocated(&udp_prot));
- seq_printf(seq, "UDPLITE: inuse %d\n",
- sock_prot_inuse_get(net, &udplite_prot));
seq_printf(seq, "RAW: inuse %d\n",
sock_prot_inuse_get(net, &raw_prot));
seq_printf(seq, "FRAG: inuse %u memory %lu\n",
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1fcdc5482594..b3f63a5ea2a9 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -98,8 +98,10 @@
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <net/aligned_data.h>
#include <net/net_namespace.h>
#include <net/icmp.h>
+#include <net/inet_common.h>
#include <net/inet_hashtables.h>
#include <net/ip.h>
#include <net/ip_tunnels.h>
@@ -112,10 +114,10 @@
#include <linux/btf_ids.h>
#include <trace/events/skb.h>
#include <net/busy_poll.h>
-#include "udp_impl.h"
#include <net/sock_reuseport.h>
#include <net/addrconf.h>
#include <net/udp_tunnel.h>
+#include <net/udplite.h>
#include <net/gro.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6_stubs.h>
@@ -229,7 +231,7 @@ static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot)
}
/**
- * udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6
+ * udp_lib_get_port - UDP port lookup for IPv4 and IPv6
*
* @sk: socket struct in question
* @snum: port number to look up
@@ -353,7 +355,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
}
EXPORT_IPV6_MOD(udp_lib_get_port);
-int udp_v4_get_port(struct sock *sk, unsigned short snum)
+static int udp_v4_get_port(struct sock *sk, unsigned short snum)
{
unsigned int hash2_nulladdr =
ipv4_portaddr_hash(sock_net(sk), htonl(INADDR_ANY), snum);
@@ -928,7 +930,7 @@ static struct sock *__udp4_lib_err_encap(struct net *net,
* to find the appropriate port.
*/
-int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
+static int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
{
struct inet_sock *inet;
const struct iphdr *iph = (const struct iphdr *)skb->data;
@@ -1855,7 +1857,7 @@ static void udp_destruct_sock(struct sock *sk)
inet_sock_destruct(sk);
}
-int udp_init_sock(struct sock *sk)
+static int udp_init_sock(struct sock *sk)
{
int res = udp_lib_init_sock(sk);
@@ -2070,6 +2072,7 @@ EXPORT_IPV6_MOD(udp_read_skb);
* return it, otherwise we block.
*/
+INDIRECT_CALLABLE_SCOPE
int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags)
{
struct inet_sock *inet = inet_sk(sk);
@@ -2342,7 +2345,7 @@ void udp_lib_rehash(struct sock *sk, u16 newhash, u16 newhash4)
}
EXPORT_IPV6_MOD(udp_lib_rehash);
-void udp_v4_rehash(struct sock *sk)
+static void udp_v4_rehash(struct sock *sk)
{
u16 new_hash = ipv4_portaddr_hash(sock_net(sk),
inet_sk(sk)->inet_rcv_saddr,
@@ -2688,8 +2691,8 @@ static int udp_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
* All we need to do is get the socket, and then do a checksum.
*/
-int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
- int proto)
+static int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
+ int proto)
{
struct sock *sk = NULL;
struct udphdr *uh;
@@ -2935,7 +2938,7 @@ int udp_rcv(struct sk_buff *skb)
return __udp4_lib_rcv(skb, dev_net(skb->dev)->ipv4.udp_table, IPPROTO_UDP);
}
-void udp_destroy_sock(struct sock *sk)
+static void udp_destroy_sock(struct sock *sk)
{
struct udp_sock *up = udp_sk(sk);
bool slow = lock_sock_fast(sk);
@@ -3125,8 +3128,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
}
EXPORT_IPV6_MOD(udp_lib_setsockopt);
-int udp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
- unsigned int optlen)
+static int udp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
+ unsigned int optlen)
{
if (level == SOL_UDP || level == SOL_UDPLITE || level == SOL_SOCKET)
return udp_lib_setsockopt(sk, level, optname,
@@ -3196,8 +3199,8 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
}
EXPORT_IPV6_MOD(udp_lib_getsockopt);
-int udp_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen)
+static int udp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
{
if (level == SOL_UDP || level == SOL_UDPLITE)
return udp_lib_getsockopt(sk, level, optname, optval, optlen);
@@ -3747,7 +3750,7 @@ static unsigned short seq_file_family(const struct seq_file *seq)
return afinfo->family;
}
-const struct seq_operations udp_seq_ops = {
+static const struct seq_operations udp_seq_ops = {
.start = udp_seq_start,
.next = udp_seq_next,
.stop = udp_seq_stop,
@@ -3806,7 +3809,7 @@ static int __init set_uhash_entries(char *str)
}
__setup("uhash_entries=", set_uhash_entries);
-void __init udp_table_init(struct udp_table *table, const char *name)
+static void __init udp_table_init(struct udp_table *table, const char *name)
{
unsigned int i, slot_size;
diff --git a/net/ipv4/udp_bpf.c b/net/ipv4/udp_bpf.c
index d328a3078ae0..9f33b07b1481 100644
--- a/net/ipv4/udp_bpf.c
+++ b/net/ipv4/udp_bpf.c
@@ -7,8 +7,6 @@
#include <net/inet_common.h>
#include <asm/ioctls.h>
-#include "udp_impl.h"
-
static struct proto *udpv6_prot_saved __read_mostly;
static int sk_udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 6e491c720c90..a010d05062a0 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -10,7 +10,6 @@
#include <linux/inet_diag.h>
#include <linux/udp.h>
#include <net/udp.h>
-#include <net/udplite.h>
#include <linux/sock_diag.h>
static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
@@ -224,12 +223,6 @@ static int udp_diag_destroy(struct sk_buff *in_skb,
return __udp_diag_destroy(in_skb, req, sock_net(in_skb->sk)->ipv4.udp_table);
}
-static int udplite_diag_destroy(struct sk_buff *in_skb,
- const struct inet_diag_req_v2 *req)
-{
- return __udp_diag_destroy(in_skb, req, &udplite_table);
-}
-
#endif
static const struct inet_diag_handler udp_diag_handler = {
@@ -244,50 +237,13 @@ static const struct inet_diag_handler udp_diag_handler = {
#endif
};
-static void udplite_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
- const struct inet_diag_req_v2 *r)
-{
- udp_dump(&udplite_table, skb, cb, r);
-}
-
-static int udplite_diag_dump_one(struct netlink_callback *cb,
- const struct inet_diag_req_v2 *req)
-{
- return udp_dump_one(&udplite_table, cb, req);
-}
-
-static const struct inet_diag_handler udplite_diag_handler = {
- .owner = THIS_MODULE,
- .dump = udplite_diag_dump,
- .dump_one = udplite_diag_dump_one,
- .idiag_get_info = udp_diag_get_info,
- .idiag_type = IPPROTO_UDPLITE,
- .idiag_info_size = 0,
-#ifdef CONFIG_INET_DIAG_DESTROY
- .destroy = udplite_diag_destroy,
-#endif
-};
-
static int __init udp_diag_init(void)
{
- int err;
-
- err = inet_diag_register(&udp_diag_handler);
- if (err)
- goto out;
- err = inet_diag_register(&udplite_diag_handler);
- if (err)
- goto out_lite;
-out:
- return err;
-out_lite:
- inet_diag_unregister(&udp_diag_handler);
- goto out;
+ return inet_diag_register(&udp_diag_handler);
}
static void __exit udp_diag_exit(void)
{
- inet_diag_unregister(&udplite_diag_handler);
inet_diag_unregister(&udp_diag_handler);
}
@@ -296,4 +252,3 @@ module_exit(udp_diag_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("UDP socket monitoring via SOCK_DIAG");
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-17 /* AF_INET - IPPROTO_UDP */);
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-136 /* AF_INET - IPPROTO_UDPLITE */);
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
deleted file mode 100644
index 0ca4384f9afa..000000000000
--- a/net/ipv4/udp_impl.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _UDP4_IMPL_H
-#define _UDP4_IMPL_H
-#include <net/aligned_data.h>
-#include <net/udp.h>
-#include <net/udplite.h>
-#include <net/protocol.h>
-#include <net/inet_common.h>
-
-int __udp4_lib_rcv(struct sk_buff *, struct udp_table *, int);
-int __udp4_lib_err(struct sk_buff *, u32, struct udp_table *);
-
-int udp_v4_get_port(struct sock *sk, unsigned short snum);
-void udp_v4_rehash(struct sock *sk);
-
-int udp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
- unsigned int optlen);
-int udp_getsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int __user *optlen);
-
-int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags);
-void udp_destroy_sock(struct sock *sk);
-
-#ifdef CONFIG_PROC_FS
-extern const struct seq_operations udp_seq_ops;
-#endif
-#endif /* _UDP4_IMPL_H */
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
deleted file mode 100644
index 826e9e79eb19..000000000000
--- a/net/ipv4/udplite.c
+++ /dev/null
@@ -1,135 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * UDPLITE An implementation of the UDP-Lite protocol (RFC 3828).
- *
- * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk>
- *
- * Changes:
- * Fixes:
- */
-
-#define pr_fmt(fmt) "UDPLite: " fmt
-
-#include <linux/export.h>
-#include <linux/proc_fs.h>
-#include "udp_impl.h"
-
-struct udp_table udplite_table __read_mostly;
-EXPORT_SYMBOL(udplite_table);
-
-/* Designate sk as UDP-Lite socket */
-static int udplite_sk_init(struct sock *sk)
-{
- pr_warn_once("UDP-Lite is deprecated and scheduled to be removed in 2025, "
- "please contact the netdev mailing list\n");
- return udp_init_sock(sk);
-}
-
-static int udplite_rcv(struct sk_buff *skb)
-{
- return __udp4_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
-}
-
-static int udplite_err(struct sk_buff *skb, u32 info)
-{
- return __udp4_lib_err(skb, info, &udplite_table);
-}
-
-static const struct net_protocol udplite_protocol = {
- .handler = udplite_rcv,
- .err_handler = udplite_err,
- .no_policy = 1,
-};
-
-struct proto udplite_prot = {
- .name = "UDP-Lite",
- .owner = THIS_MODULE,
- .close = udp_lib_close,
- .connect = ip4_datagram_connect,
- .disconnect = udp_disconnect,
- .ioctl = udp_ioctl,
- .init = udplite_sk_init,
- .destroy = udp_destroy_sock,
- .setsockopt = udp_setsockopt,
- .getsockopt = udp_getsockopt,
- .sendmsg = udp_sendmsg,
- .recvmsg = udp_recvmsg,
- .hash = udp_lib_hash,
- .unhash = udp_lib_unhash,
- .rehash = udp_v4_rehash,
- .get_port = udp_v4_get_port,
-
- .memory_allocated = &net_aligned_data.udp_memory_allocated,
- .per_cpu_fw_alloc = &udp_memory_per_cpu_fw_alloc,
-
- .sysctl_mem = sysctl_udp_mem,
- .sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
- .sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
- .obj_size = sizeof(struct udp_sock),
- .h.udp_table = &udplite_table,
-};
-EXPORT_SYMBOL(udplite_prot);
-
-static struct inet_protosw udplite4_protosw = {
- .type = SOCK_DGRAM,
- .protocol = IPPROTO_UDPLITE,
- .prot = &udplite_prot,
- .ops = &inet_dgram_ops,
- .flags = INET_PROTOSW_PERMANENT,
-};
-
-#ifdef CONFIG_PROC_FS
-static struct udp_seq_afinfo udplite4_seq_afinfo = {
- .family = AF_INET,
- .udp_table = &udplite_table,
-};
-
-static int __net_init udplite4_proc_init_net(struct net *net)
-{
- if (!proc_create_net_data("udplite", 0444, net->proc_net, &udp_seq_ops,
- sizeof(struct udp_iter_state), &udplite4_seq_afinfo))
- return -ENOMEM;
- return 0;
-}
-
-static void __net_exit udplite4_proc_exit_net(struct net *net)
-{
- remove_proc_entry("udplite", net->proc_net);
-}
-
-static struct pernet_operations udplite4_net_ops = {
- .init = udplite4_proc_init_net,
- .exit = udplite4_proc_exit_net,
-};
-
-static __init int udplite4_proc_init(void)
-{
- return register_pernet_subsys(&udplite4_net_ops);
-}
-#else
-static inline int udplite4_proc_init(void)
-{
- return 0;
-}
-#endif
-
-void __init udplite4_register(void)
-{
- udp_table_init(&udplite_table, "UDP-Lite");
- if (proto_register(&udplite_prot, 1))
- goto out_register_err;
-
- if (inet_add_protocol(&udplite_protocol, IPPROTO_UDPLITE) < 0)
- goto out_unregister_proto;
-
- inet_register_protosw(&udplite4_protosw);
-
- if (udplite4_proc_init())
- pr_err("%s: Cannot register /proc!\n", __func__);
- return;
-
-out_unregister_proto:
- proto_unregister(&udplite_prot);
-out_register_err:
- pr_crit("%s: Cannot add UDP-Lite protocol\n", __func__);
-}
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 05/15] udp: Remove UDP-Lite SNMP stats.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (3 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 04/15] ipv4: Retire UDP-Lite Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 06/15] smack: Remove IPPROTO_UDPLITE support in security_sock_rcv_skb() Kuniyuki Iwashima
` (10 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
Since UDP and UDP-Lite shared most of the code, we have had
to check the protocol every time we increment SNMP stats.
Now that the UDP-Lite paths are dead, let's remove UDP-Lite
SNMP stats.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
include/net/netns/mib.h | 5 ---
include/net/udp.h | 46 ++++++++++---------------
net/ipv4/af_inet.c | 6 ----
net/ipv4/proc.c | 13 -------
net/ipv4/udp.c | 75 ++++++++++++++++++-----------------------
net/ipv6/af_inet6.c | 9 ++---
net/ipv6/proc.c | 14 --------
net/ipv6/udp.c | 48 +++++++++++---------------
8 files changed, 71 insertions(+), 145 deletions(-)
diff --git a/include/net/netns/mib.h b/include/net/netns/mib.h
index 7e373664b1e7..dce05f8e6a33 100644
--- a/include/net/netns/mib.h
+++ b/include/net/netns/mib.h
@@ -28,11 +28,6 @@ struct netns_mib {
DEFINE_SNMP_STAT(struct mptcp_mib, mptcp_statistics);
#endif
- DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics);
-#if IS_ENABLED(CONFIG_IPV6)
- DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6);
-#endif
-
DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics);
DEFINE_SNMP_STAT_ATOMIC(struct icmpmsg_mib, icmpmsg_statistics);
#if IS_ENABLED(CONFIG_IPV6)
diff --git a/include/net/udp.h b/include/net/udp.h
index 39223e2692e9..264c10607d2e 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -529,38 +529,28 @@ static inline int copy_linear_skb(struct sk_buff *skb, int len, int off,
}
/*
- * SNMP statistics for UDP and UDP-Lite
+ * SNMP statistics for UDP
*/
-#define UDP_INC_STATS(net, field, is_udplite) do { \
- if (unlikely(is_udplite)) SNMP_INC_STATS((net)->mib.udplite_statistics, field); \
- else SNMP_INC_STATS((net)->mib.udp_statistics, field); } while(0)
-#define __UDP_INC_STATS(net, field, is_udplite) do { \
- if (unlikely(is_udplite)) __SNMP_INC_STATS((net)->mib.udplite_statistics, field); \
- else __SNMP_INC_STATS((net)->mib.udp_statistics, field); } while(0)
-
-#define __UDP6_INC_STATS(net, field, is_udplite) do { \
- if (unlikely(is_udplite)) __SNMP_INC_STATS((net)->mib.udplite_stats_in6, field); \
- else __SNMP_INC_STATS((net)->mib.udp_stats_in6, field); \
-} while(0)
-#define UDP6_INC_STATS(net, field, __lite) do { \
- if (unlikely(__lite)) SNMP_INC_STATS((net)->mib.udplite_stats_in6, field); \
- else SNMP_INC_STATS((net)->mib.udp_stats_in6, field); \
-} while(0)
+#define __UDP_INC_STATS(net, field) \
+ __SNMP_INC_STATS((net)->mib.udp_statistics, field)
+#define UDP_INC_STATS(net, field) \
+ SNMP_INC_STATS((net)->mib.udp_statistics, field)
+#define __UDP6_INC_STATS(net, field) \
+ __SNMP_INC_STATS((net)->mib.udp_stats_in6, field)
+#define UDP6_INC_STATS(net, field) \
+ SNMP_INC_STATS((net)->mib.udp_stats_in6, field)
#if IS_ENABLED(CONFIG_IPV6)
-#define __UDPX_MIB(sk, ipv4) \
-({ \
- ipv4 ? (IS_UDPLITE(sk) ? sock_net(sk)->mib.udplite_statistics : \
- sock_net(sk)->mib.udp_statistics) : \
- (IS_UDPLITE(sk) ? sock_net(sk)->mib.udplite_stats_in6 : \
- sock_net(sk)->mib.udp_stats_in6); \
-})
+#define __UDPX_MIB(sk, ipv4) \
+ ({ \
+ ipv4 ? sock_net(sk)->mib.udp_statistics : \
+ sock_net(sk)->mib.udp_stats_in6; \
+ })
#else
-#define __UDPX_MIB(sk, ipv4) \
-({ \
- IS_UDPLITE(sk) ? sock_net(sk)->mib.udplite_statistics : \
- sock_net(sk)->mib.udp_statistics; \
-})
+#define __UDPX_MIB(sk, ipv4) \
+ ({ \
+ sock_net(sk)->mib.udp_statistics; \
+ })
#endif
#define __UDPX_INC_STATS(sk, field) \
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 58347619003c..4a4c290e3f7e 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1727,9 +1727,6 @@ static __net_init int ipv4_mib_init_net(struct net *net)
net->mib.udp_statistics = alloc_percpu(struct udp_mib);
if (!net->mib.udp_statistics)
goto err_udp_mib;
- net->mib.udplite_statistics = alloc_percpu(struct udp_mib);
- if (!net->mib.udplite_statistics)
- goto err_udplite_mib;
net->mib.icmp_statistics = alloc_percpu(struct icmp_mib);
if (!net->mib.icmp_statistics)
goto err_icmp_mib;
@@ -1743,8 +1740,6 @@ static __net_init int ipv4_mib_init_net(struct net *net)
err_icmpmsg_mib:
free_percpu(net->mib.icmp_statistics);
err_icmp_mib:
- free_percpu(net->mib.udplite_statistics);
-err_udplite_mib:
free_percpu(net->mib.udp_statistics);
err_udp_mib:
free_percpu(net->mib.net_statistics);
@@ -1760,7 +1755,6 @@ static __net_exit void ipv4_mib_exit_net(struct net *net)
{
kfree(net->mib.icmpmsg_statistics);
free_percpu(net->mib.icmp_statistics);
- free_percpu(net->mib.udplite_statistics);
free_percpu(net->mib.udp_statistics);
free_percpu(net->mib.net_statistics);
free_percpu(net->mib.ip_statistics);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cf51f8fcf34b..bfc06d1713ec 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -444,19 +444,6 @@ static int snmp_seq_show_tcp_udp(struct seq_file *seq, void *v)
for (i = 0; i < udp_cnt; i++)
seq_printf(seq, " %lu", buff[i]);
- memset(buff, 0, udp_cnt * sizeof(unsigned long));
-
- /* the UDP and UDP-Lite MIBs are the same */
- seq_puts(seq, "\nUdpLite:");
- snmp_get_cpu_field_batch_cnt(buff, snmp4_udp_list,
- udp_cnt,
- net->mib.udplite_statistics);
- for (i = 0; i < udp_cnt; i++)
- seq_printf(seq, " %s", snmp4_udp_list[i].name);
- seq_puts(seq, "\nUdpLite:");
- for (i = 0; i < udp_cnt; i++)
- seq_printf(seq, " %lu", buff[i]);
-
seq_putc(seq, '\n');
return 0;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index b3f63a5ea2a9..10082095e633 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1198,13 +1198,12 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
if (unlikely(err)) {
if (err == -ENOBUFS &&
!inet_test_bit(RECVERR, sk)) {
- UDP_INC_STATS(sock_net(sk),
- UDP_MIB_SNDBUFERRORS, is_udplite);
+ UDP_INC_STATS(sock_net(sk), UDP_MIB_SNDBUFERRORS);
err = 0;
}
- } else
- UDP_INC_STATS(sock_net(sk),
- UDP_MIB_OUTDATAGRAMS, is_udplite);
+ } else {
+ UDP_INC_STATS(sock_net(sk), UDP_MIB_OUTDATAGRAMS);
+ }
return err;
}
@@ -1535,10 +1534,9 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
* things). We could add another new stat but at least for now that
* seems like overkill.
*/
- if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
- UDP_INC_STATS(sock_net(sk),
- UDP_MIB_SNDBUFERRORS, is_udplite);
- }
+ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags))
+ UDP_INC_STATS(sock_net(sk), UDP_MIB_SNDBUFERRORS);
+
return err;
do_confirm:
@@ -1897,10 +1895,10 @@ static struct sk_buff *__first_packet_length(struct sock *sk,
while ((skb = skb_peek(rcvq)) != NULL) {
if (udp_lib_checksum_complete(skb)) {
- __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS,
- IS_UDPLITE(sk));
- __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS,
- IS_UDPLITE(sk));
+ struct net *net = sock_net(sk);
+
+ __UDP_INC_STATS(net, UDP_MIB_CSUMERRORS);
+ __UDP_INC_STATS(net, UDP_MIB_INERRORS);
udp_drops_inc(sk);
__skb_unlink(skb, rcvq);
*total += skb->truesize;
@@ -2052,11 +2050,10 @@ int udp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
return err;
if (udp_lib_checksum_complete(skb)) {
- int is_udplite = IS_UDPLITE(sk);
struct net *net = sock_net(sk);
- __UDP_INC_STATS(net, UDP_MIB_CSUMERRORS, is_udplite);
- __UDP_INC_STATS(net, UDP_MIB_INERRORS, is_udplite);
+ __UDP_INC_STATS(net, UDP_MIB_CSUMERRORS);
+ __UDP_INC_STATS(net, UDP_MIB_INERRORS);
udp_drops_inc(sk);
kfree_skb_reason(skb, SKB_DROP_REASON_UDP_CSUM);
goto try_again;
@@ -2081,6 +2078,7 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags)
unsigned int ulen, copied;
int off, err, peeking = flags & MSG_PEEK;
int is_udplite = IS_UDPLITE(sk);
+ struct net *net = sock_net(sk);
bool checksum_valid = false;
if (flags & MSG_ERRQUEUE)
@@ -2128,16 +2126,14 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags)
if (unlikely(err)) {
if (!peeking) {
udp_drops_inc(sk);
- UDP_INC_STATS(sock_net(sk),
- UDP_MIB_INERRORS, is_udplite);
+ UDP_INC_STATS(net, UDP_MIB_INERRORS);
}
kfree_skb(skb);
return err;
}
if (!peeking)
- UDP_INC_STATS(sock_net(sk),
- UDP_MIB_INDATAGRAMS, is_udplite);
+ UDP_INC_STATS(net, UDP_MIB_INDATAGRAMS);
sock_recv_cmsgs(msg, sk, skb);
@@ -2170,8 +2166,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags)
csum_copy_err:
if (!__sk_queue_drop_skb(sk, &udp_sk(sk)->reader_queue, skb, flags,
udp_skb_destructor)) {
- UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
- UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
+ UDP_INC_STATS(net, UDP_MIB_CSUMERRORS);
+ UDP_INC_STATS(net, UDP_MIB_INERRORS);
}
kfree_skb_reason(skb, SKB_DROP_REASON_UDP_CSUM);
@@ -2371,20 +2367,18 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
rc = __udp_enqueue_schedule_skb(sk, skb);
if (rc < 0) {
- int is_udplite = IS_UDPLITE(sk);
+ struct net *net = sock_net(sk);
int drop_reason;
/* Note that an ENOMEM error is charged twice */
if (rc == -ENOMEM) {
- UDP_INC_STATS(sock_net(sk), UDP_MIB_RCVBUFERRORS,
- is_udplite);
+ UDP_INC_STATS(net, UDP_MIB_RCVBUFERRORS);
drop_reason = SKB_DROP_REASON_SOCKET_RCVBUFF;
} else {
- UDP_INC_STATS(sock_net(sk), UDP_MIB_MEMERRORS,
- is_udplite);
+ UDP_INC_STATS(net, UDP_MIB_MEMERRORS);
drop_reason = SKB_DROP_REASON_PROTO_MEM;
}
- UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
+ UDP_INC_STATS(net, UDP_MIB_INERRORS);
trace_udp_fail_queue_rcv_skb(rc, sk, skb);
sk_skb_reason_drop(sk, skb, drop_reason);
return -1;
@@ -2405,7 +2399,7 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
{
enum skb_drop_reason drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
struct udp_sock *up = udp_sk(sk);
- int is_udplite = IS_UDPLITE(sk);
+ struct net *net = sock_net(sk);
/*
* Charge it to the socket, dropping if the queue is full.
@@ -2442,9 +2436,7 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
ret = encap_rcv(sk, skb);
if (ret <= 0) {
- __UDP_INC_STATS(sock_net(sk),
- UDP_MIB_INDATAGRAMS,
- is_udplite);
+ __UDP_INC_STATS(net, UDP_MIB_INDATAGRAMS);
return -ret;
}
}
@@ -2503,9 +2495,9 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
csum_error:
drop_reason = SKB_DROP_REASON_UDP_CSUM;
- __UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
+ __UDP_INC_STATS(net, UDP_MIB_CSUMERRORS);
drop:
- __UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
+ __UDP_INC_STATS(net, UDP_MIB_INERRORS);
udp_drops_inc(sk);
sk_skb_reason_drop(sk, skb, drop_reason);
return -1;
@@ -2592,10 +2584,8 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
if (unlikely(!nskb)) {
udp_drops_inc(sk);
- __UDP_INC_STATS(net, UDP_MIB_RCVBUFERRORS,
- IS_UDPLITE(sk));
- __UDP_INC_STATS(net, UDP_MIB_INERRORS,
- IS_UDPLITE(sk));
+ __UDP_INC_STATS(net, UDP_MIB_RCVBUFERRORS);
+ __UDP_INC_STATS(net, UDP_MIB_INERRORS);
continue;
}
if (udp_queue_rcv_skb(sk, nskb) > 0)
@@ -2613,8 +2603,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
consume_skb(skb);
} else {
kfree_skb(skb);
- __UDP_INC_STATS(net, UDP_MIB_IGNOREDMULTI,
- proto == IPPROTO_UDPLITE);
+ __UDP_INC_STATS(net, UDP_MIB_IGNOREDMULTI);
}
return 0;
}
@@ -2764,7 +2753,7 @@ static int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
goto csum_error;
drop_reason = SKB_DROP_REASON_NO_SOCKET;
- __UDP_INC_STATS(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
+ __UDP_INC_STATS(net, UDP_MIB_NOPORTS);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
/*
@@ -2793,9 +2782,9 @@ static int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
proto == IPPROTO_UDPLITE ? "Lite" : "",
&saddr, ntohs(uh->source), &daddr, ntohs(uh->dest),
ulen);
- __UDP_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
+ __UDP_INC_STATS(net, UDP_MIB_CSUMERRORS);
drop:
- __UDP_INC_STATS(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
+ __UDP_INC_STATS(net, UDP_MIB_INERRORS);
sk_skb_reason_drop(sk, skb, drop_reason);
return 0;
}
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 9ad907a5a093..97d0bbce1720 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -894,9 +894,7 @@ static int __net_init ipv6_init_mibs(struct net *net)
net->mib.udp_stats_in6 = alloc_percpu(struct udp_mib);
if (!net->mib.udp_stats_in6)
return -ENOMEM;
- net->mib.udplite_stats_in6 = alloc_percpu(struct udp_mib);
- if (!net->mib.udplite_stats_in6)
- goto err_udplite_mib;
+
net->mib.ipv6_statistics = alloc_percpu(struct ipstats_mib);
if (!net->mib.ipv6_statistics)
goto err_ip_mib;
@@ -907,10 +905,10 @@ static int __net_init ipv6_init_mibs(struct net *net)
u64_stats_init(&af_inet6_stats->syncp);
}
-
net->mib.icmpv6_statistics = alloc_percpu(struct icmpv6_mib);
if (!net->mib.icmpv6_statistics)
goto err_icmp_mib;
+
net->mib.icmpv6msg_statistics = kzalloc_obj(struct icmpv6msg_mib);
if (!net->mib.icmpv6msg_statistics)
goto err_icmpmsg_mib;
@@ -921,8 +919,6 @@ static int __net_init ipv6_init_mibs(struct net *net)
err_icmp_mib:
free_percpu(net->mib.ipv6_statistics);
err_ip_mib:
- free_percpu(net->mib.udplite_stats_in6);
-err_udplite_mib:
free_percpu(net->mib.udp_stats_in6);
return -ENOMEM;
}
@@ -930,7 +926,6 @@ static int __net_init ipv6_init_mibs(struct net *net)
static void ipv6_cleanup_mibs(struct net *net)
{
free_percpu(net->mib.udp_stats_in6);
- free_percpu(net->mib.udplite_stats_in6);
free_percpu(net->mib.ipv6_statistics);
free_percpu(net->mib.icmpv6_statistics);
kfree(net->mib.icmpv6msg_statistics);
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 21bfc73152f0..813013ca4e75 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -108,17 +108,6 @@ static const struct snmp_mib snmp6_udp6_list[] = {
SNMP_MIB_ITEM("Udp6MemErrors", UDP_MIB_MEMERRORS),
};
-static const struct snmp_mib snmp6_udplite6_list[] = {
- SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS),
- SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS),
- SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS),
- SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
- SNMP_MIB_ITEM("UdpLite6RcvbufErrors", UDP_MIB_RCVBUFERRORS),
- SNMP_MIB_ITEM("UdpLite6SndbufErrors", UDP_MIB_SNDBUFERRORS),
- SNMP_MIB_ITEM("UdpLite6InCsumErrors", UDP_MIB_CSUMERRORS),
- SNMP_MIB_ITEM("UdpLite6MemErrors", UDP_MIB_MEMERRORS),
-};
-
static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, atomic_long_t *smib)
{
char name[32];
@@ -226,9 +215,6 @@ static int snmp6_seq_show(struct seq_file *seq, void *v)
snmp6_seq_show_item(seq, net->mib.udp_stats_in6,
NULL, snmp6_udp6_list,
ARRAY_SIZE(snmp6_udp6_list));
- snmp6_seq_show_item(seq, net->mib.udplite_stats_in6,
- NULL, snmp6_udplite6_list,
- ARRAY_SIZE(snmp6_udplite6_list));
return 0;
}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index aa859bb0527d..07308b7156a6 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -796,20 +796,18 @@ static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
rc = __udp_enqueue_schedule_skb(sk, skb);
if (rc < 0) {
- int is_udplite = IS_UDPLITE(sk);
enum skb_drop_reason drop_reason;
+ struct net *net = sock_net(sk);
/* Note that an ENOMEM error is charged twice */
if (rc == -ENOMEM) {
- UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_RCVBUFERRORS, is_udplite);
+ UDP6_INC_STATS(net, UDP_MIB_RCVBUFERRORS);
drop_reason = SKB_DROP_REASON_SOCKET_RCVBUFF;
} else {
- UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_MEMERRORS, is_udplite);
+ UDP6_INC_STATS(net, UDP_MIB_MEMERRORS);
drop_reason = SKB_DROP_REASON_PROTO_MEM;
}
- UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
+ UDP6_INC_STATS(net, UDP_MIB_INERRORS);
trace_udp_fail_queue_rcv_skb(rc, sk, skb);
sk_skb_reason_drop(sk, skb, drop_reason);
return -1;
@@ -830,7 +828,7 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
{
enum skb_drop_reason drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
struct udp_sock *up = udp_sk(sk);
- int is_udplite = IS_UDPLITE(sk);
+ struct net *net = sock_net(sk);
if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
drop_reason = SKB_DROP_REASON_XFRM_POLICY;
@@ -864,9 +862,7 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
ret = encap_rcv(sk, skb);
if (ret <= 0) {
- __UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_INDATAGRAMS,
- is_udplite);
+ __UDP6_INC_STATS(net, UDP_MIB_INDATAGRAMS);
return -ret;
}
}
@@ -909,9 +905,9 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
csum_error:
drop_reason = SKB_DROP_REASON_UDP_CSUM;
- __UDP6_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
+ __UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS);
drop:
- __UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
+ __UDP6_INC_STATS(net, UDP_MIB_INERRORS);
udp_drops_inc(sk);
sk_skb_reason_drop(sk, skb, drop_reason);
return -1;
@@ -1018,10 +1014,8 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
nskb = skb_clone(skb, GFP_ATOMIC);
if (unlikely(!nskb)) {
udp_drops_inc(sk);
- __UDP6_INC_STATS(net, UDP_MIB_RCVBUFERRORS,
- IS_UDPLITE(sk));
- __UDP6_INC_STATS(net, UDP_MIB_INERRORS,
- IS_UDPLITE(sk));
+ __UDP6_INC_STATS(net, UDP_MIB_RCVBUFERRORS);
+ __UDP6_INC_STATS(net, UDP_MIB_INERRORS);
continue;
}
@@ -1040,8 +1034,7 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
consume_skb(skb);
} else {
kfree_skb(skb);
- __UDP6_INC_STATS(net, UDP_MIB_IGNOREDMULTI,
- proto == IPPROTO_UDPLITE);
+ __UDP6_INC_STATS(net, UDP_MIB_IGNOREDMULTI);
}
return 0;
}
@@ -1213,7 +1206,7 @@ static int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
if (udp_lib_checksum_complete(skb))
goto csum_error;
- __UDP6_INC_STATS(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
+ __UDP6_INC_STATS(net, UDP_MIB_NOPORTS);
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
sk_skb_reason_drop(sk, skb, reason);
@@ -1234,9 +1227,9 @@ static int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
csum_error:
if (reason == SKB_DROP_REASON_NOT_SPECIFIED)
reason = SKB_DROP_REASON_UDP_CSUM;
- __UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
+ __UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS);
discard:
- __UDP6_INC_STATS(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
+ __UDP6_INC_STATS(net, UDP_MIB_INERRORS);
sk_skb_reason_drop(sk, skb, reason);
return 0;
}
@@ -1490,13 +1483,11 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
err = ip6_send_skb(skb);
if (unlikely(err)) {
if (err == -ENOBUFS && !inet6_test_bit(RECVERR6, sk)) {
- UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_SNDBUFERRORS, is_udplite);
+ UDP6_INC_STATS(sock_net(sk), UDP_MIB_SNDBUFERRORS);
err = 0;
}
} else {
- UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_OUTDATAGRAMS, is_udplite);
+ UDP6_INC_STATS(sock_net(sk), UDP_MIB_OUTDATAGRAMS);
}
return err;
}
@@ -1826,10 +1817,9 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
* things). We could add another new stat but at least for now that
* seems like overkill.
*/
- if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
- UDP6_INC_STATS(sock_net(sk),
- UDP_MIB_SNDBUFERRORS, is_udplite);
- }
+ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags))
+ UDP6_INC_STATS(sock_net(sk), UDP_MIB_SNDBUFERRORS);
+
return err;
do_confirm:
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 06/15] smack: Remove IPPROTO_UDPLITE support in security_sock_rcv_skb().
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (4 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 05/15] udp: Remove UDP-Lite SNMP stats Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 07/15] udp: Remove partial csum code in RX Kuniyuki Iwashima
` (9 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn, Casey Schaufler,
Paul Moore, James Morris, Serge E. Hallyn, linux-security-module
smack_socket_sock_rcv_skb() is registered as socket_sock_rcv_skb,
which is called as security_sock_rcv_skb() in sk_filter_trim_cap().
Now that UDP-Lite is gone, let's remove the IPPROTO_UDPLITE support
in smack_socket_sock_rcv_skb().
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
---
Cc: Paul Moore <paul@paul-moore.com>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: linux-security-module@vger.kernel.org
---
security/smack/smack_lsm.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 98af9d7b9434..e581d6465946 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4176,7 +4176,6 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
sip->sin6_port = th->source;
break;
case IPPROTO_UDP:
- case IPPROTO_UDPLITE:
uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
if (uh != NULL)
sip->sin6_port = uh->source;
@@ -4301,8 +4300,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
#if IS_ENABLED(CONFIG_IPV6)
case PF_INET6:
proto = smk_skb_to_addr_ipv6(skb, &sadd);
- if (proto != IPPROTO_UDP && proto != IPPROTO_UDPLITE &&
- proto != IPPROTO_TCP)
+ if (proto != IPPROTO_UDP && proto != IPPROTO_TCP)
break;
#ifdef SMACK_IPV6_SECMARK_LABELING
skp = smack_from_skb(skb);
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 07/15] udp: Remove partial csum code in RX.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (5 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 06/15] smack: Remove IPPROTO_UDPLITE support in security_sock_rcv_skb() Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-13 1:04 ` Jakub Kicinski
2026-03-13 2:20 ` Willem de Bruijn
2026-03-11 5:19 ` [PATCH v3 net-next 08/15] udp: Remove partial csum code in TX Kuniyuki Iwashima
` (8 subsequent siblings)
15 siblings, 2 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev
UDP-Lite supports the partial checksum and the coverage is
stored in the position of the length field of struct udphdr.
In RX paths, udp4_csum_init() / udp6_csum_init() save the value
in UDP_SKB_CB(skb)->cscov and set UDP_SKB_CB(skb)->partial_cov
to 1 if the coverage is not full.
The subsequent processing diverges depending on the value,
but such paths are now dead.
Also, these functions have some code guarded for UDP:
* udp_unicast_rcv_skb / udp6_unicast_rcv_skb
* __udp4_lib_rcv() and __udp6_lib_rcv().
Let's remove the partial csum code and the unnecessary
guard for UDP-Lite in RX.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
v3: Correct ulen < skb->len case in __udp4_lib_rcv()
---
include/net/udp.h | 17 ++-------
include/net/udplite.h | 34 -----------------
net/ipv4/udp.c | 85 ++++++++-----------------------------------
net/ipv6/udp.c | 82 ++++++++++-------------------------------
4 files changed, 39 insertions(+), 179 deletions(-)
diff --git a/include/net/udp.h b/include/net/udp.h
index 264c10607d2e..bc275cda9f8c 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -32,11 +32,9 @@
#include <linux/math.h>
/**
- * struct udp_skb_cb - UDP(-Lite) private variables
+ * struct udp_skb_cb - UDP private variables
*
* @header: private variables used by IPv4/IPv6
- * @cscov: checksum coverage length (UDP-Lite only)
- * @partial_cov: if set indicates partial csum coverage
*/
struct udp_skb_cb {
union {
@@ -45,8 +43,6 @@ struct udp_skb_cb {
struct inet6_skb_parm h6;
#endif
} header;
- __u16 cscov;
- __u8 partial_cov;
};
#define UDP_SKB_CB(__skb) ((struct udp_skb_cb *)((__skb)->cb))
@@ -216,13 +212,11 @@ extern int sysctl_udp_wmem_min;
struct sk_buff;
/*
- * Generic checksumming routines for UDP(-Lite) v4 and v6
+ * Generic checksumming routines for UDP v4 and v6
*/
static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb)
{
- return (UDP_SKB_CB(skb)->cscov == skb->len ?
- __skb_checksum_complete(skb) :
- __skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov));
+ return __skb_checksum_complete(skb);
}
static inline int udp_lib_checksum_complete(struct sk_buff *skb)
@@ -273,7 +267,6 @@ static inline void udp_csum_pull_header(struct sk_buff *skb)
skb->csum = csum_partial(skb->data, sizeof(struct udphdr),
skb->csum);
skb_pull_rcsum(skb, sizeof(struct udphdr));
- UDP_SKB_CB(skb)->cscov -= sizeof(struct udphdr);
}
typedef struct sock *(*udp_lookup_t)(const struct sk_buff *skb, __be16 sport,
@@ -641,9 +634,6 @@ static inline struct sk_buff *udp_rcv_segment(struct sock *sk,
static inline void udp_post_segment_fix_csum(struct sk_buff *skb)
{
- /* UDP-lite can't land here - no GRO */
- WARN_ON_ONCE(UDP_SKB_CB(skb)->partial_cov);
-
/* UDP packets generated with UDP_SEGMENT and traversing:
*
* UDP tunnel(xmit) -> veth (segmentation) -> veth (gro) -> UDP tunnel (rx)
@@ -657,7 +647,6 @@ static inline void udp_post_segment_fix_csum(struct sk_buff *skb)
* a valid csum after the segmentation.
* Additionally fixup the UDP CB.
*/
- UDP_SKB_CB(skb)->cscov = skb->len;
if (skb->ip_summed == CHECKSUM_NONE && !skb->csum_valid)
skb->csum_valid = 1;
}
diff --git a/include/net/udplite.h b/include/net/udplite.h
index fdd769745ac4..0456a14c993b 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -25,40 +25,6 @@ static __inline__ int udplite_getfrag(void *from, char *to, int offset,
/*
* Checksumming routines
*/
-static inline int udplite_checksum_init(struct sk_buff *skb, struct udphdr *uh)
-{
- u16 cscov;
-
- /* In UDPv4 a zero checksum means that the transmitter generated no
- * checksum. UDP-Lite (like IPv6) mandates checksums, hence packets
- * with a zero checksum field are illegal. */
- if (uh->check == 0) {
- net_dbg_ratelimited("UDPLite: zeroed checksum field\n");
- return 1;
- }
-
- cscov = ntohs(uh->len);
-
- if (cscov == 0) /* Indicates that full coverage is required. */
- ;
- else if (cscov < 8 || cscov > skb->len) {
- /*
- * Coverage length violates RFC 3828: log and discard silently.
- */
- net_dbg_ratelimited("UDPLite: bad csum coverage %d/%d\n",
- cscov, skb->len);
- return 1;
-
- } else if (cscov < skb->len) {
- UDP_SKB_CB(skb)->partial_cov = 1;
- UDP_SKB_CB(skb)->cscov = cscov;
- if (skb->ip_summed == CHECKSUM_COMPLETE)
- skb->ip_summed = CHECKSUM_NONE;
- skb->csum_valid = 0;
- }
-
- return 0;
-}
/* Fast-path computation of checksum. Socket may not be locked. */
static inline __wsum udplite_csum(struct sk_buff *skb)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 10082095e633..d42fb9330c22 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2072,14 +2072,13 @@ EXPORT_IPV6_MOD(udp_read_skb);
INDIRECT_CALLABLE_SCOPE
int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags)
{
- struct inet_sock *inet = inet_sk(sk);
DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
- struct sk_buff *skb;
- unsigned int ulen, copied;
int off, err, peeking = flags & MSG_PEEK;
- int is_udplite = IS_UDPLITE(sk);
+ struct inet_sock *inet = inet_sk(sk);
struct net *net = sock_net(sk);
bool checksum_valid = false;
+ unsigned int ulen, copied;
+ struct sk_buff *skb;
if (flags & MSG_ERRQUEUE)
return ip_recv_error(sk, msg, len);
@@ -2097,14 +2096,10 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags)
else if (copied < ulen)
msg->msg_flags |= MSG_TRUNC;
- /*
- * If checksum is needed at all, try to do it while copying the
- * data. If the data is truncated, or if we only want a partial
- * coverage checksum (UDP-Lite), do it before the copy.
+ /* If checksum is needed at all, try to do it while copying the
+ * data. If the data is truncated, do it before the copy.
*/
-
- if (copied < ulen || peeking ||
- (is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
+ if (copied < ulen || peeking) {
checksum_valid = udp_skb_csum_unnecessary(skb) ||
!__udp_lib_checksum_complete(skb);
if (!checksum_valid)
@@ -2444,42 +2439,6 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
/* FALLTHROUGH -- it's a UDP Packet */
}
- /*
- * UDP-Lite specific tests, ignored on UDP sockets
- */
- if (unlikely(udp_test_bit(UDPLITE_RECV_CC, sk) &&
- UDP_SKB_CB(skb)->partial_cov)) {
- u16 pcrlen = READ_ONCE(up->pcrlen);
-
- /*
- * MIB statistics other than incrementing the error count are
- * disabled for the following two types of errors: these depend
- * on the application settings, not on the functioning of the
- * protocol stack as such.
- *
- * RFC 3828 here recommends (sec 3.3): "There should also be a
- * way ... to ... at least let the receiving application block
- * delivery of packets with coverage values less than a value
- * provided by the application."
- */
- if (pcrlen == 0) { /* full coverage was set */
- net_dbg_ratelimited("UDPLite: partial coverage %d while full coverage %d requested\n",
- UDP_SKB_CB(skb)->cscov, skb->len);
- goto drop;
- }
- /* The next case involves violating the min. coverage requested
- * by the receiver. This is subtle: if receiver wants x and x is
- * greater than the buffersize/MTU then receiver will complain
- * that it wants x while sender emits packets of smaller size y.
- * Therefore the above ...()->partial_cov statement is essential.
- */
- if (UDP_SKB_CB(skb)->cscov < pcrlen) {
- net_dbg_ratelimited("UDPLite: coverage %d too small, need min %d\n",
- UDP_SKB_CB(skb)->cscov, pcrlen);
- goto drop;
- }
- }
-
prefetch(&sk->sk_rmem_alloc);
if (rcu_access_pointer(sk->sk_filter) &&
udp_lib_checksum_complete(skb))
@@ -2613,29 +2572,14 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
* Otherwise, csum completion requires checksumming packet body,
* including udp header and folding it to skb->csum.
*/
-static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
- int proto)
+static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh)
{
int err;
- UDP_SKB_CB(skb)->partial_cov = 0;
- UDP_SKB_CB(skb)->cscov = skb->len;
-
- if (proto == IPPROTO_UDPLITE) {
- err = udplite_checksum_init(skb, uh);
- if (err)
- return err;
-
- if (UDP_SKB_CB(skb)->partial_cov) {
- skb->csum = inet_compute_pseudo(skb, proto);
- return 0;
- }
- }
-
/* Note, we are only interested in != 0 or == 0, thus the
* force to int.
*/
- err = (__force int)skb_checksum_init_zero_check(skb, proto, uh->check,
+ err = (__force int)skb_checksum_init_zero_check(skb, IPPROTO_UDP, uh->check,
inet_compute_pseudo);
if (err)
return err;
@@ -2663,7 +2607,7 @@ static int udp_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
{
int ret;
- if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk))
+ if (inet_get_convert_csum(sk) && uh->check)
skb_checksum_try_convert(skb, IPPROTO_UDP, inet_compute_pseudo);
ret = udp_queue_rcv_skb(sk, skb);
@@ -2708,14 +2652,17 @@ static int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
if (ulen > skb->len)
goto short_packet;
- if (proto == IPPROTO_UDP) {
- /* UDP validates ulen. */
- if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))
+ if (ulen < sizeof(*uh))
+ goto short_packet;
+
+ if (ulen < skb->len) {
+ if (pskb_trim_rcsum(skb, ulen))
goto short_packet;
+
uh = udp_hdr(skb);
}
- if (udp4_csum_init(skb, uh, proto))
+ if (udp4_csum_init(skb, uh))
goto csum_error;
sk = inet_steal_sock(net, skb, sizeof(struct udphdr), saddr, uh->source, daddr, uh->dest,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 07308b7156a6..bf5430ea66f0 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -469,15 +469,13 @@ INDIRECT_CALLABLE_SCOPE
int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int flags)
{
+ int off, is_udp4, err, peeking = flags & MSG_PEEK;
struct ipv6_pinfo *np = inet6_sk(sk);
struct inet_sock *inet = inet_sk(sk);
- struct sk_buff *skb;
- unsigned int ulen, copied;
- int off, err, peeking = flags & MSG_PEEK;
- int is_udplite = IS_UDPLITE(sk);
struct udp_mib __percpu *mib;
bool checksum_valid = false;
- int is_udp4;
+ unsigned int ulen, copied;
+ struct sk_buff *skb;
if (flags & MSG_ERRQUEUE)
return ipv6_recv_error(sk, msg, len);
@@ -501,14 +499,10 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
is_udp4 = (skb->protocol == htons(ETH_P_IP));
mib = __UDPX_MIB(sk, is_udp4);
- /*
- * If checksum is needed at all, try to do it while copying the
- * data. If the data is truncated, or if we only want a partial
- * coverage checksum (UDP-Lite), do it before the copy.
+ /* If checksum is needed at all, try to do it while copying the
+ * data. If the data is truncated, do it before the copy.
*/
-
- if (copied < ulen || peeking ||
- (is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
+ if (copied < ulen || peeking) {
checksum_valid = udp_skb_csum_unnecessary(skb) ||
!__udp_lib_checksum_complete(skb);
if (!checksum_valid)
@@ -870,25 +864,6 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
/* FALLTHROUGH -- it's a UDP Packet */
}
- /*
- * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c).
- */
- if (unlikely(udp_test_bit(UDPLITE_RECV_CC, sk) &&
- UDP_SKB_CB(skb)->partial_cov)) {
- u16 pcrlen = READ_ONCE(up->pcrlen);
-
- if (pcrlen == 0) { /* full coverage was set */
- net_dbg_ratelimited("UDPLITE6: partial coverage %d while full coverage %d requested\n",
- UDP_SKB_CB(skb)->cscov, skb->len);
- goto drop;
- }
- if (UDP_SKB_CB(skb)->cscov < pcrlen) {
- net_dbg_ratelimited("UDPLITE6: coverage %d too small, need min %d\n",
- UDP_SKB_CB(skb)->cscov, pcrlen);
- goto drop;
- }
- }
-
prefetch(&sk->sk_rmem_alloc);
if (rcu_access_pointer(sk->sk_filter) &&
udp_lib_checksum_complete(skb))
@@ -1053,7 +1028,7 @@ static int udp6_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
{
int ret;
- if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk))
+ if (inet_get_convert_csum(sk) && uh->check)
skb_checksum_try_convert(skb, IPPROTO_UDP, ip6_compute_pseudo);
ret = udpv6_queue_rcv_skb(sk, skb);
@@ -1064,24 +1039,10 @@ static int udp6_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
return 0;
}
-static int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto)
+static int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh)
{
int err;
- UDP_SKB_CB(skb)->partial_cov = 0;
- UDP_SKB_CB(skb)->cscov = skb->len;
-
- if (proto == IPPROTO_UDPLITE) {
- err = udplite_checksum_init(skb, uh);
- if (err)
- return err;
-
- if (UDP_SKB_CB(skb)->partial_cov) {
- skb->csum = ip6_compute_pseudo(skb, proto);
- return 0;
- }
- }
-
/* To support RFC 6936 (allow zero checksum in UDP/IPV6 for tunnels)
* we accept a checksum of zero here. When we find the socket
* for the UDP packet we'll check if that socket allows zero checksum
@@ -1090,7 +1051,7 @@ static int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto)
* Note, we are only interested in != 0 or == 0, thus the
* force to int.
*/
- err = (__force int)skb_checksum_init_zero_check(skb, proto, uh->check,
+ err = (__force int)skb_checksum_init_zero_check(skb, IPPROTO_UDP, uh->check,
ip6_compute_pseudo);
if (err)
return err;
@@ -1132,26 +1093,23 @@ static int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
if (ulen > skb->len)
goto short_packet;
- if (proto == IPPROTO_UDP) {
- /* UDP validates ulen. */
+ /* Check for jumbo payload */
+ if (ulen == 0)
+ ulen = skb->len;
- /* Check for jumbo payload */
- if (ulen == 0)
- ulen = skb->len;
+ if (ulen < sizeof(*uh))
+ goto short_packet;
- if (ulen < sizeof(*uh))
+ if (ulen < skb->len) {
+ if (pskb_trim_rcsum(skb, ulen))
goto short_packet;
- if (ulen < skb->len) {
- if (pskb_trim_rcsum(skb, ulen))
- goto short_packet;
- saddr = &ipv6_hdr(skb)->saddr;
- daddr = &ipv6_hdr(skb)->daddr;
- uh = udp_hdr(skb);
- }
+ saddr = &ipv6_hdr(skb)->saddr;
+ daddr = &ipv6_hdr(skb)->daddr;
+ uh = udp_hdr(skb);
}
- if (udp6_csum_init(skb, uh, proto))
+ if (udp6_csum_init(skb, uh))
goto csum_error;
/* Check if the socket is already available, e.g. due to early demux */
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 08/15] udp: Remove partial csum code in TX.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (6 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 07/15] udp: Remove partial csum code in RX Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 09/15] udp: Remove UDPLITE_SEND_CSCOV and UDPLITE_RECV_CSCOV Kuniyuki Iwashima
` (7 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
UDP TX paths also have some code for UDP-Lite partial
checksum:
* udplite_csum() in udp_send_skb() and udp_v6_send_skb()
* udplite_getfrag() in udp_sendmsg() and udpv6_sendmsg()
Let's remove such code.
Now, we can use IPPROTO_UDP directly instead of sk->sk_protocol
or fl6->flowi6_proto for csum_tcpudp_magic() and csum_ipv6_magic().
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
include/net/udplite.h | 35 --------------------------
net/ipv4/udp.c | 58 ++++++++++++++++---------------------------
net/ipv6/udp.c | 54 +++++++++++++++++++---------------------
3 files changed, 47 insertions(+), 100 deletions(-)
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 0456a14c993b..6bfa1d6833d1 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -12,39 +12,4 @@
#define UDPLITE_SEND_CSCOV 10 /* sender partial coverage (as sent) */
#define UDPLITE_RECV_CSCOV 11 /* receiver partial coverage (threshold ) */
-/*
- * Checksum computation is all in software, hence simpler getfrag.
- */
-static __inline__ int udplite_getfrag(void *from, char *to, int offset,
- int len, int odd, struct sk_buff *skb)
-{
- struct msghdr *msg = from;
- return copy_from_iter_full(to, len, &msg->msg_iter) ? 0 : -EFAULT;
-}
-
-/*
- * Checksumming routines
- */
-
-/* Fast-path computation of checksum. Socket may not be locked. */
-static inline __wsum udplite_csum(struct sk_buff *skb)
-{
- const int off = skb_transport_offset(skb);
- const struct sock *sk = skb->sk;
- int len = skb->len - off;
-
- if (udp_test_bit(UDPLITE_SEND_CC, sk)) {
- u16 pcslen = READ_ONCE(udp_sk(sk)->pcslen);
-
- if (pcslen < len) {
- if (pcslen > 0)
- len = pcslen;
- udp_hdr(skb)->len = htons(pcslen);
- }
- }
- skb->ip_summed = CHECKSUM_NONE; /* no HW support for checksumming */
-
- return skb_checksum(skb, off, len, 0);
-}
-
#endif /* _UDPLITE_H */
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d42fb9330c22..9a2c8ff96e83 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1120,20 +1120,19 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
struct inet_cork *cork)
{
struct sock *sk = skb->sk;
- struct inet_sock *inet = inet_sk(sk);
+ int offset, len, datalen;
struct udphdr *uh;
int err;
- int is_udplite = IS_UDPLITE(sk);
- int offset = skb_transport_offset(skb);
- int len = skb->len - offset;
- int datalen = len - sizeof(*uh);
- __wsum csum = 0;
+
+ offset = skb_transport_offset(skb);
+ len = skb->len - offset;
+ datalen = len - sizeof(*uh);
/*
* Create a UDP header
*/
uh = udp_hdr(skb);
- uh->source = inet->inet_sport;
+ uh->source = inet_sk(sk)->inet_sport;
uh->dest = fl4->fl4_dport;
uh->len = htons(len);
uh->check = 0;
@@ -1154,7 +1153,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
kfree_skb(skb);
return -EINVAL;
}
- if (is_udplite || dst_xfrm(skb_dst(skb))) {
+ if (dst_xfrm(skb_dst(skb))) {
kfree_skb(skb);
return -EIO;
}
@@ -1170,26 +1169,18 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
}
}
- if (is_udplite) /* UDP-Lite */
- csum = udplite_csum(skb);
-
- else if (sk->sk_no_check_tx) { /* UDP csum off */
-
+ if (sk->sk_no_check_tx) { /* UDP csum off */
skb->ip_summed = CHECKSUM_NONE;
goto send;
-
} else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
csum_partial:
-
udp4_hwcsum(skb, fl4->saddr, fl4->daddr);
goto send;
-
- } else
- csum = udp_csum(skb);
+ }
/* add protocol-dependent pseudo-header */
uh->check = csum_tcpudp_magic(fl4->saddr, fl4->daddr, len,
- sk->sk_protocol, csum);
+ IPPROTO_UDP, udp_csum(skb));
if (uh->check == 0)
uh->check = CSUM_MANGLED_0;
@@ -1270,26 +1261,23 @@ EXPORT_IPV6_MOD_GPL(udp_cmsg_send);
int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
{
+ int corkreq = udp_test_bit(CORK, sk) || msg->msg_flags & MSG_MORE;
DEFINE_RAW_FLEX(struct ip_options_rcu, opt_copy, opt.__data,
IP_OPTIONS_DATA_FIXED_SIZE);
+ DECLARE_SOCKADDR(struct sockaddr_in *, usin, msg->msg_name);
+ int ulen = len, free = 0, connected = 0;
struct inet_sock *inet = inet_sk(sk);
struct udp_sock *up = udp_sk(sk);
- DECLARE_SOCKADDR(struct sockaddr_in *, usin, msg->msg_name);
+ __be32 daddr, faddr, saddr;
+ struct rtable *rt = NULL;
struct flowi4 fl4_stack;
- struct flowi4 *fl4;
- int ulen = len;
struct ipcm_cookie ipc;
- struct rtable *rt = NULL;
- int free = 0;
- int connected = 0;
- __be32 daddr, faddr, saddr;
- u8 scope;
- __be16 dport;
- int err, is_udplite = IS_UDPLITE(sk);
- int corkreq = udp_test_bit(CORK, sk) || msg->msg_flags & MSG_MORE;
- int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
struct sk_buff *skb;
+ struct flowi4 *fl4;
+ __be16 dport;
int uc_index;
+ u8 scope;
+ int err;
if (len > 0xFFFF)
return -EMSGSIZE;
@@ -1301,8 +1289,6 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (msg->msg_flags & MSG_OOB) /* Mirror BSD error message compatibility */
return -EOPNOTSUPP;
- getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
-
fl4 = &inet->cork.fl.u.ip4;
if (READ_ONCE(up->pending)) {
/*
@@ -1444,7 +1430,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
flowi4_init_output(fl4, ipc.oif, ipc.sockc.mark,
ipc.tos & INET_DSCP_MASK, scope,
- sk->sk_protocol, flow_flags, faddr, saddr,
+ IPPROTO_UDP, flow_flags, faddr, saddr,
dport, inet->inet_sport,
sk_uid(sk));
@@ -1478,7 +1464,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (!corkreq) {
struct inet_cork cork;
- skb = ip_make_skb(sk, fl4, getfrag, msg, ulen,
+ skb = ip_make_skb(sk, fl4, ip_generic_getfrag, msg, ulen,
sizeof(struct udphdr), &ipc, &rt,
&cork, msg->msg_flags);
err = PTR_ERR(skb);
@@ -1509,7 +1495,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
do_append_data:
up->len += ulen;
- err = ip_append_data(sk, fl4, getfrag, msg, ulen,
+ err = ip_append_data(sk, fl4, ip_generic_getfrag, msg, ulen,
sizeof(struct udphdr), &ipc, &rt,
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
if (err)
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index bf5430ea66f0..511e3f898be5 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1370,13 +1370,13 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
struct inet_cork *cork)
{
struct sock *sk = skb->sk;
+ int offset, len, datalen;
struct udphdr *uh;
int err = 0;
- int is_udplite = IS_UDPLITE(sk);
- __wsum csum = 0;
- int offset = skb_transport_offset(skb);
- int len = skb->len - offset;
- int datalen = len - sizeof(*uh);
+
+ offset = skb_transport_offset(skb);
+ len = skb->len - offset;
+ datalen = len - sizeof(*uh);
/*
* Create a UDP header
@@ -1403,7 +1403,7 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
kfree_skb(skb);
return -EINVAL;
}
- if (is_udplite || dst_xfrm(skb_dst(skb))) {
+ if (dst_xfrm(skb_dst(skb))) {
kfree_skb(skb);
return -EIO;
}
@@ -1419,21 +1419,18 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
}
}
- if (is_udplite)
- csum = udplite_csum(skb);
- else if (udp_get_no_check6_tx(sk)) { /* UDP csum disabled */
+ if (udp_get_no_check6_tx(sk)) { /* UDP csum disabled */
skb->ip_summed = CHECKSUM_NONE;
goto send;
} else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
csum_partial:
udp6_hwcsum_outgoing(sk, skb, &fl6->saddr, &fl6->daddr, len);
goto send;
- } else
- csum = udp_csum(skb);
+ }
/* add protocol-dependent pseudo-header */
uh->check = csum_ipv6_magic(&fl6->saddr, &fl6->daddr,
- len, fl6->flowi6_proto, csum);
+ len, IPPROTO_UDP, udp_csum(skb));
if (uh->check == 0)
uh->check = CSUM_MANGLED_0;
@@ -1473,27 +1470,26 @@ static int udp_v6_push_pending_frames(struct sock *sk)
int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
{
- struct ipv6_txoptions opt_space;
- struct udp_sock *up = udp_sk(sk);
- struct inet_sock *inet = inet_sk(sk);
- struct ipv6_pinfo *np = inet6_sk(sk);
+ int corkreq = udp_test_bit(CORK, sk) || msg->msg_flags & MSG_MORE;
DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
- struct in6_addr *daddr, *final_p, final;
- struct ipv6_txoptions *opt = NULL;
struct ipv6_txoptions *opt_to_free = NULL;
+ struct in6_addr *daddr, *final_p, final;
struct ip6_flowlabel *flowlabel = NULL;
+ struct inet_sock *inet = inet_sk(sk);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_txoptions *opt = NULL;
+ struct udp_sock *up = udp_sk(sk);
+ struct ipv6_txoptions opt_space;
+ int addr_len = msg->msg_namelen;
struct inet_cork_full cork;
- struct flowi6 *fl6 = &cork.fl.u.ip6;
- struct dst_entry *dst;
struct ipcm6_cookie ipc6;
- int addr_len = msg->msg_namelen;
bool connected = false;
+ struct dst_entry *dst;
+ struct flowi6 *fl6;
int ulen = len;
- int corkreq = udp_test_bit(CORK, sk) || msg->msg_flags & MSG_MORE;
int err;
- int is_udplite = IS_UDPLITE(sk);
- int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
+ fl6 = &cork.fl.u.ip6;
ipcm6_init_sk(&ipc6, sk);
ipc6.gso_size = READ_ONCE(up->gso_size);
@@ -1552,7 +1548,6 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (len > INT_MAX - sizeof(struct udphdr))
return -EMSGSIZE;
- getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
if (READ_ONCE(up->pending)) {
if (READ_ONCE(up->pending) == AF_INET)
return udp_sendmsg(sk, msg, len);
@@ -1654,7 +1649,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
opt = ipv6_fixup_options(&opt_space, opt);
ipc6.opt = opt;
- fl6->flowi6_proto = sk->sk_protocol;
+ fl6->flowi6_proto = IPPROTO_UDP;
fl6->flowi6_mark = ipc6.sockc.mark;
fl6->daddr = *daddr;
if (ipv6_addr_any(&fl6->saddr) && !ipv6_addr_any(&np->saddr))
@@ -1721,7 +1716,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (!corkreq) {
struct sk_buff *skb;
- skb = ip6_make_skb(sk, getfrag, msg, ulen,
+ skb = ip6_make_skb(sk, ip_generic_getfrag, msg, ulen,
sizeof(struct udphdr), &ipc6,
dst_rt6_info(dst),
msg->msg_flags, &cork);
@@ -1747,8 +1742,9 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
do_append_data:
up->len += ulen;
- err = ip6_append_data(sk, getfrag, msg, ulen, sizeof(struct udphdr),
- &ipc6, fl6, dst_rt6_info(dst),
+ err = ip6_append_data(sk, ip_generic_getfrag, msg, ulen,
+ sizeof(struct udphdr), &ipc6, fl6,
+ dst_rt6_info(dst),
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
if (err)
udp_v6_flush_pending_frames(sk);
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 09/15] udp: Remove UDPLITE_SEND_CSCOV and UDPLITE_RECV_CSCOV.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (7 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 08/15] udp: Remove partial csum code in TX Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 10/15] udp: Remove struct proto.h.udp_table Kuniyuki Iwashima
` (6 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
UDP-Lite supports variable-length checksum and has two socket
options, UDPLITE_SEND_CSCOV and UDPLITE_RECV_CSCOV, to control
the checksum coverage.
Let's remove the support.
setsockopt(UDPLITE_SEND_CSCOV / UDPLITE_RECV_CSCOV) was only
available for UDP-Lite and returned -ENOPROTOOPT for UDP.
Now, the options are handled in ip_setsockopt() and
ipv6_setsockopt(), which still return the same error.
getsockopt(UDPLITE_SEND_CSCOV / UDPLITE_RECV_CSCOV) was available
for UDP and always returned 0, meaning full checksum, but now
-ENOPROTOOPT is returned.
Given that getsockopt() is meaningless for UDP and even the options
are not defined under include/uapi/, this should not be a problem.
$ man 7 udplite
...
BUGS
Where glibc support is missing, the following definitions
are needed:
#define IPPROTO_UDPLITE 136
#define UDPLITE_SEND_CSCOV 10
#define UDPLITE_RECV_CSCOV 11
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
v2: Add a detailed reason in include/uapi/linux/udp.h
---
include/linux/udp.h | 10 +--------
include/net/udplite.h | 15 -------------
include/uapi/linux/udp.h | 2 ++
net/ipv4/udp.c | 46 ++--------------------------------------
net/ipv6/ip6_checksum.c | 2 +-
net/ipv6/udp.c | 5 ++---
6 files changed, 8 insertions(+), 72 deletions(-)
delete mode 100644 include/net/udplite.h
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 1cbf6b4d3aab..ce56ebcee5cb 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -40,8 +40,6 @@ enum {
UDP_FLAGS_ACCEPT_FRAGLIST,
UDP_FLAGS_ACCEPT_L4,
UDP_FLAGS_ENCAP_ENABLED, /* This socket enabled encap */
- UDP_FLAGS_UDPLITE_SEND_CC, /* set via udplite setsockopt */
- UDP_FLAGS_UDPLITE_RECV_CC, /* set via udplite setsockopt */
};
/* per NUMA structure for lockless producer usage. */
@@ -74,11 +72,7 @@ struct udp_sock {
*/
__u16 len; /* total length of pending frames */
__u16 gso_size;
- /*
- * Fields specific to UDP-Lite.
- */
- __u16 pcslen;
- __u16 pcrlen;
+
/*
* For encapsulation sockets.
*/
@@ -236,8 +230,6 @@ static inline void udp_allow_gso(struct sock *sk)
hlist_nulls_for_each_entry_rcu(__up, node, list, udp_lrpa_node)
#endif
-#define IS_UDPLITE(__sk) (unlikely(__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)
diff --git a/include/net/udplite.h b/include/net/udplite.h
deleted file mode 100644
index 6bfa1d6833d1..000000000000
--- a/include/net/udplite.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Definitions for the UDP-Lite (RFC 3828) code.
- */
-#ifndef _UDPLITE_H
-#define _UDPLITE_H
-
-#include <net/ip6_checksum.h>
-#include <net/udp.h>
-
-/* UDP-Lite socket options */
-#define UDPLITE_SEND_CSCOV 10 /* sender partial coverage (as sent) */
-#define UDPLITE_RECV_CSCOV 11 /* receiver partial coverage (threshold ) */
-
-#endif /* _UDPLITE_H */
diff --git a/include/uapi/linux/udp.h b/include/uapi/linux/udp.h
index edca3e430305..877fb02df8fb 100644
--- a/include/uapi/linux/udp.h
+++ b/include/uapi/linux/udp.h
@@ -29,6 +29,8 @@ struct udphdr {
/* UDP socket options */
#define UDP_CORK 1 /* Never send partially complete segments */
+/* Deprecated, reserved for UDPLITE_SEND_CSCOV 10 */
+/* Deprecated, reserved for UDPLITE_RECV_CSCOV 11 */
#define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */
#define UDP_NO_CHECK6_TX 101 /* Disable sending checksum for UDP6X */
#define UDP_NO_CHECK6_RX 102 /* Disable accepting checksum for UDP6 */
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 9a2c8ff96e83..d47ca721ef0d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -117,7 +117,6 @@
#include <net/sock_reuseport.h>
#include <net/addrconf.h>
#include <net/udp_tunnel.h>
-#include <net/udplite.h>
#include <net/gro.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6_stubs.h>
@@ -2924,7 +2923,6 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
struct udp_sock *up = udp_sk(sk);
int val, valbool;
int err = 0;
- int is_udplite = IS_UDPLITE(sk);
if (level == SOL_SOCKET) {
err = sk_setsockopt(sk, level, optname, optval, optlen);
@@ -3011,36 +3009,6 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
sockopt_release_sock(sk);
break;
- /*
- * UDP-Lite's partial checksum coverage (RFC 3828).
- */
- /* The sender sets actual checksum coverage length via this option.
- * The case coverage > packet length is handled by send module. */
- case UDPLITE_SEND_CSCOV:
- if (!is_udplite) /* Disable the option on UDP sockets */
- return -ENOPROTOOPT;
- if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
- val = 8;
- else if (val > USHRT_MAX)
- val = USHRT_MAX;
- WRITE_ONCE(up->pcslen, val);
- udp_set_bit(UDPLITE_SEND_CC, sk);
- break;
-
- /* The receiver specifies a minimum checksum coverage value. To make
- * sense, this should be set to at least 8 (as done below). If zero is
- * used, this again means full checksum coverage. */
- case UDPLITE_RECV_CSCOV:
- if (!is_udplite) /* Disable the option on UDP sockets */
- return -ENOPROTOOPT;
- if (val != 0 && val < 8) /* Avoid silly minimal values. */
- val = 8;
- else if (val > USHRT_MAX)
- val = USHRT_MAX;
- WRITE_ONCE(up->pcrlen, val);
- udp_set_bit(UDPLITE_RECV_CC, sk);
- break;
-
default:
err = -ENOPROTOOPT;
break;
@@ -3053,7 +3021,7 @@ EXPORT_IPV6_MOD(udp_lib_setsockopt);
static int udp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
unsigned int optlen)
{
- if (level == SOL_UDP || level == SOL_UDPLITE || level == SOL_SOCKET)
+ if (level == SOL_UDP || level == SOL_SOCKET)
return udp_lib_setsockopt(sk, level, optname,
optval, optlen,
udp_push_pending_frames);
@@ -3099,16 +3067,6 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
val = udp_test_bit(GRO_ENABLED, sk);
break;
- /* The following two cannot be changed on UDP sockets, the return is
- * always 0 (which corresponds to the full checksum coverage of UDP). */
- case UDPLITE_SEND_CSCOV:
- val = READ_ONCE(up->pcslen);
- break;
-
- case UDPLITE_RECV_CSCOV:
- val = READ_ONCE(up->pcrlen);
- break;
-
default:
return -ENOPROTOOPT;
}
@@ -3124,7 +3082,7 @@ EXPORT_IPV6_MOD(udp_lib_getsockopt);
static int udp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
- if (level == SOL_UDP || level == SOL_UDPLITE)
+ if (level == SOL_UDP)
return udp_lib_getsockopt(sk, level, optname, optval, optlen);
return ip_getsockopt(sk, level, optname, optval, optlen);
}
diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c
index 8bb68a0cdfd6..e1a594873675 100644
--- a/net/ipv6/ip6_checksum.c
+++ b/net/ipv6/ip6_checksum.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <net/ip.h>
+#include <net/ip6_checksum.h>
#include <net/udp.h>
-#include <net/udplite.h>
#include <asm/checksum.h>
#ifndef _HAVE_ARCH_IPV6_CSUM
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 511e3f898be5..c3d8b5ede164 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -58,7 +58,6 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <trace/events/skb.h>
-#include <net/udplite.h>
static void udpv6_destruct_sock(struct sock *sk)
{
@@ -1831,7 +1830,7 @@ static void udpv6_destroy_sock(struct sock *sk)
static int udpv6_setsockopt(struct sock *sk, int level, int optname,
sockptr_t optval, unsigned int optlen)
{
- if (level == SOL_UDP || level == SOL_UDPLITE || level == SOL_SOCKET)
+ if (level == SOL_UDP || level == SOL_SOCKET)
return udp_lib_setsockopt(sk, level, optname,
optval, optlen,
udp_v6_push_pending_frames);
@@ -1841,7 +1840,7 @@ static int udpv6_setsockopt(struct sock *sk, int level, int optname,
static int udpv6_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen)
{
- if (level == SOL_UDP || level == SOL_UDPLITE)
+ if (level == SOL_UDP)
return udp_lib_getsockopt(sk, level, optname, optval, optlen);
return ipv6_getsockopt(sk, level, optname, optval, optlen);
}
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 10/15] udp: Remove struct proto.h.udp_table.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (8 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 09/15] udp: Remove UDPLITE_SEND_CSCOV and UDPLITE_RECV_CSCOV Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 11/15] udp: Remove udp_table in struct udp_seq_afinfo Kuniyuki Iwashima
` (5 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
Since UDP and UDP-Lite had dedicated socket hash tables for
each, we have had to fetch them from different pointers.
UDP always has its global or per-netns table in
net->ipv4.udp_table and struct proto.h.udp_table is NULL.
OTOH, UDP-Lite had only one global table in the pointer.
We no longer use the field.
Let's remove it and udp_get_table_prot().
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
include/net/sock.h | 1 -
net/ipv4/udp.c | 26 ++++++++++++--------------
net/ipv6/udp.c | 1 -
3 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 16a1b8895206..7d51ac9e7d9a 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1392,7 +1392,6 @@ struct proto {
union {
struct inet_hashinfo *hashinfo;
- struct udp_table *udp_table;
struct raw_hashinfo *raw_hash;
struct smc_hashinfo *smc_hash;
} h;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index d47ca721ef0d..a7ca727347ce 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -134,11 +134,6 @@ EXPORT_PER_CPU_SYMBOL_GPL(udp_memory_per_cpu_fw_alloc);
#define MAX_UDP_PORTS 65536
#define PORTS_PER_CHAIN (MAX_UDP_PORTS / UDP_HTABLE_SIZE_MIN_PERNET)
-static struct udp_table *udp_get_table_prot(struct sock *sk)
-{
- return sk->sk_prot->h.udp_table ? : sock_net(sk)->ipv4.udp_table;
-}
-
static int udp_lib_lport_inuse(struct net *net, __u16 num,
const struct udp_hslot *hslot,
unsigned long *bitmap,
@@ -240,11 +235,13 @@ static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot)
int udp_lib_get_port(struct sock *sk, unsigned short snum,
unsigned int hash2_nulladdr)
{
- struct udp_table *udptable = udp_get_table_prot(sk);
struct udp_hslot *hslot, *hslot2;
struct net *net = sock_net(sk);
+ struct udp_table *udptable;
int error = -EADDRINUSE;
+ udptable = net->ipv4.udp_table;
+
if (!snum) {
DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN);
unsigned short first, last;
@@ -2224,12 +2221,13 @@ EXPORT_IPV6_MOD(udp_disconnect);
void udp_lib_unhash(struct sock *sk)
{
if (sk_hashed(sk)) {
- struct udp_table *udptable = udp_get_table_prot(sk);
struct udp_hslot *hslot, *hslot2;
+ struct net *net = sock_net(sk);
+ struct udp_table *udptable;
sock_rps_delete_flow(sk);
- hslot = udp_hashslot(udptable, sock_net(sk),
- udp_sk(sk)->udp_port_hash);
+ udptable = net->ipv4.udp_table;
+ hslot = udp_hashslot(udptable, net, udp_sk(sk)->udp_port_hash);
hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
spin_lock_bh(&hslot->lock);
@@ -2238,7 +2236,7 @@ void udp_lib_unhash(struct sock *sk)
if (sk_del_node_init_rcu(sk)) {
hslot->count--;
inet_sk(sk)->inet_num = 0;
- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ sock_prot_inuse_add(net, sk->sk_prot, -1);
spin_lock(&hslot2->lock);
hlist_del_init_rcu(&udp_sk(sk)->udp_portaddr_node);
@@ -2258,11 +2256,12 @@ EXPORT_IPV6_MOD(udp_lib_unhash);
void udp_lib_rehash(struct sock *sk, u16 newhash, u16 newhash4)
{
if (sk_hashed(sk)) {
- struct udp_table *udptable = udp_get_table_prot(sk);
struct udp_hslot *hslot, *hslot2, *nhslot2;
+ struct net *net = sock_net(sk);
+ struct udp_table *udptable;
- hslot = udp_hashslot(udptable, sock_net(sk),
- udp_sk(sk)->udp_port_hash);
+ udptable = net->ipv4.udp_table;
+ hslot = udp_hashslot(udptable, net, udp_sk(sk)->udp_port_hash);
hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
nhslot2 = udp_hashslot2(udptable, newhash);
@@ -3175,7 +3174,6 @@ struct proto udp_prot = {
.sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
.sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
.obj_size = sizeof(struct udp_sock),
- .h.udp_table = NULL,
.diag_destroy = udp_abort,
};
EXPORT_SYMBOL(udp_prot);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index c3d8b5ede164..5bddbf457b61 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1924,7 +1924,6 @@ struct proto udpv6_prot = {
.sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
.obj_size = sizeof(struct udp6_sock),
.ipv6_pinfo_offset = offsetof(struct udp6_sock, inet6),
- .h.udp_table = NULL,
.diag_destroy = udp_abort,
};
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 11/15] udp: Remove udp_table in struct udp_seq_afinfo.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (9 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 10/15] udp: Remove struct proto.h.udp_table Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 12/15] udp: Remove dead check in __udp[46]_lib_lookup() for BPF Kuniyuki Iwashima
` (4 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
Since UDP and UDP-Lite had dedicated socket hash tables for
each, we have had to fetch them from different pointers for
procfs or bpf iterator.
UDP always has its global or per-netns table in
net->ipv4.udp_table and struct udp_seq_afinfo.udp_table
is NULL.
OTOH, UDP-Lite had only one global table in the pointer.
We no longer use the field.
Let's remove it and udp_get_table_seq().
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
include/net/udp.h | 1 -
net/ipv4/udp.c | 22 ++++------------------
net/ipv6/udp.c | 1 -
3 files changed, 4 insertions(+), 20 deletions(-)
diff --git a/include/net/udp.h b/include/net/udp.h
index bc275cda9f8c..76f401988353 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -552,7 +552,6 @@ static inline int copy_linear_skb(struct sk_buff *skb, int len, int off,
#ifdef CONFIG_PROC_FS
struct udp_seq_afinfo {
sa_family_t family;
- struct udp_table *udp_table;
};
struct udp_iter_state {
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index a7ca727347ce..14b372b211be 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -3193,21 +3193,8 @@ static bool seq_sk_match(struct seq_file *seq, const struct sock *sk)
#ifdef CONFIG_BPF_SYSCALL
static const struct seq_operations bpf_iter_udp_seq_ops;
-#endif
-static struct udp_table *udp_get_table_seq(struct seq_file *seq,
- struct net *net)
-{
- const struct udp_seq_afinfo *afinfo;
-
-#ifdef CONFIG_BPF_SYSCALL
- if (seq->op == &bpf_iter_udp_seq_ops)
- return net->ipv4.udp_table;
#endif
- afinfo = pde_data(file_inode(seq->file));
- return afinfo->udp_table ? : net->ipv4.udp_table;
-}
-
static struct sock *udp_get_first(struct seq_file *seq, int start)
{
struct udp_iter_state *state = seq->private;
@@ -3215,7 +3202,7 @@ static struct sock *udp_get_first(struct seq_file *seq, int start)
struct udp_table *udptable;
struct sock *sk;
- udptable = udp_get_table_seq(seq, net);
+ udptable = net->ipv4.udp_table;
for (state->bucket = start; state->bucket <= udptable->mask;
++state->bucket) {
@@ -3247,7 +3234,7 @@ static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk)
} while (sk && !seq_sk_match(seq, sk));
if (!sk) {
- udptable = udp_get_table_seq(seq, net);
+ udptable = net->ipv4.udp_table;
if (state->bucket <= udptable->mask)
spin_unlock_bh(&udptable->hash[state->bucket].lock);
@@ -3295,7 +3282,7 @@ void udp_seq_stop(struct seq_file *seq, void *v)
struct udp_iter_state *state = seq->private;
struct udp_table *udptable;
- udptable = udp_get_table_seq(seq, seq_file_net(seq));
+ udptable = seq_file_net(seq)->ipv4.udp_table;
if (state->bucket <= udptable->mask)
spin_unlock_bh(&udptable->hash[state->bucket].lock);
@@ -3399,7 +3386,7 @@ static struct sock *bpf_iter_udp_batch(struct seq_file *seq)
if (iter->cur_sk == iter->end_sk)
state->bucket++;
- udptable = udp_get_table_seq(seq, net);
+ udptable = net->ipv4.udp_table;
again:
/* New batch for the next bucket.
@@ -3637,7 +3624,6 @@ static const struct seq_operations udp_seq_ops = {
static struct udp_seq_afinfo udp4_seq_afinfo = {
.family = AF_INET,
- .udp_table = NULL,
};
static int __net_init udp4_proc_init_net(struct net *net)
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5bddbf457b61..eeb77363a556 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1872,7 +1872,6 @@ static const struct seq_operations udp6_seq_ops = {
static struct udp_seq_afinfo udp6_seq_afinfo = {
.family = AF_INET6,
- .udp_table = NULL,
};
int __net_init udp6_proc_init(struct net *net)
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 12/15] udp: Remove dead check in __udp[46]_lib_lookup() for BPF.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (10 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 11/15] udp: Remove udp_table in struct udp_seq_afinfo Kuniyuki Iwashima
@ 2026-03-11 5:19 ` Kuniyuki Iwashima
2026-03-11 5:20 ` [PATCH v3 net-next 13/15] udp: Don't pass udptable to IPv6 socket lookup functions Kuniyuki Iwashima
` (3 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:19 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
BPF socket lookup for SO_REUSEPORT does not support UDP-Lite.
In __udp4_lib_lookup() and __udp6_lib_lookup(), it checks if
the passed udptable pointer is the same as net->ipv4.udp_table,
which is only true for UDP.
Now, the condition is always true.
Let's remove the check.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
net/ipv4/udp.c | 3 +--
net/ipv6/udp.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 14b372b211be..fd0bad44d111 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -699,8 +699,7 @@ struct sock *__udp4_lib_lookup(const struct net *net, __be32 saddr,
goto done;
/* Lookup redirect from BPF */
- if (static_branch_unlikely(&bpf_sk_lookup_enabled) &&
- udptable == net->ipv4.udp_table) {
+ if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
sk = inet_lookup_run_sk_lookup(net, IPPROTO_UDP, skb, sizeof(struct udphdr),
saddr, sport, daddr, hnum, dif,
udp_ehashfn);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index eeb77363a556..5ba399218d07 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -370,8 +370,7 @@ struct sock *__udp6_lib_lookup(const struct net *net,
goto done;
/* Lookup redirect from BPF */
- if (static_branch_unlikely(&bpf_sk_lookup_enabled) &&
- udptable == net->ipv4.udp_table) {
+ if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
sk = inet6_lookup_run_sk_lookup(net, IPPROTO_UDP, skb, sizeof(struct udphdr),
saddr, sport, daddr, hnum, dif,
udp6_ehashfn);
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 13/15] udp: Don't pass udptable to IPv6 socket lookup functions.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (11 preceding siblings ...)
2026-03-11 5:19 ` [PATCH v3 net-next 12/15] udp: Remove dead check in __udp[46]_lib_lookup() for BPF Kuniyuki Iwashima
@ 2026-03-11 5:20 ` Kuniyuki Iwashima
2026-03-11 5:20 ` [PATCH v3 net-next 14/15] udp: Don't pass udptable to IPv4 " Kuniyuki Iwashima
` (2 subsequent siblings)
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:20 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
Since UDP and UDP-Lite had dedicated socket hash tables for
each, we have had to pass the pointer down to many socket
lookup functions.
UDP-Lite gone, and we do not need to do that.
Let's fetch net->ipv4.udp_table only where needed in IPv6
stack: __udp6_lib_lookup() and __udp6_lib_mcast_deliver().
__udp6_lib_err() is renamed to udpv6_err() as its wrapper
is no longer needed.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
include/net/ipv6_stubs.h | 7 ++--
include/net/udp.h | 3 +-
net/core/filter.c | 3 +-
net/ipv4/udp_diag.c | 20 +++++-----
net/ipv6/udp.c | 82 ++++++++++++++++++----------------------
net/ipv6/udp_offload.c | 3 +-
6 files changed, 53 insertions(+), 65 deletions(-)
diff --git a/include/net/ipv6_stubs.h b/include/net/ipv6_stubs.h
index d3013e721b14..907681cecde8 100644
--- a/include/net/ipv6_stubs.h
+++ b/include/net/ipv6_stubs.h
@@ -83,10 +83,9 @@ struct ipv6_bpf_stub {
int (*inet6_bind)(struct sock *sk, struct sockaddr_unsized *uaddr, int addr_len,
u32 flags);
struct sock *(*udp6_lib_lookup)(const struct net *net,
- const struct in6_addr *saddr, __be16 sport,
- const struct in6_addr *daddr, __be16 dport,
- int dif, int sdif, struct udp_table *tbl,
- struct sk_buff *skb);
+ const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif, int sdif, struct sk_buff *skb);
int (*ipv6_setsockopt)(struct sock *sk, int level, int optname,
sockptr_t optval, unsigned int optlen);
int (*ipv6_getsockopt)(struct sock *sk, int level, int optname,
diff --git a/include/net/udp.h b/include/net/udp.h
index 76f401988353..adec74531ee1 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -449,8 +449,7 @@ struct sock *udp6_lib_lookup(const struct net *net,
struct sock *__udp6_lib_lookup(const struct net *net,
const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport,
- int dif, int sdif, struct udp_table *tbl,
- struct sk_buff *skb);
+ int dif, int sdif, struct sk_buff *skb);
struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
__be16 sport, __be16 dport);
int udp_read_skb(struct sock *sk, skb_read_actor_t recv_actor);
diff --git a/net/core/filter.c b/net/core/filter.c
index a77d23fe2359..04e2a3ad0340 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -6897,8 +6897,7 @@ static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple,
sk = ipv6_bpf_stub->udp6_lib_lookup(net,
src6, tuple->ipv6.sport,
dst6, tuple->ipv6.dport,
- dif, sdif,
- net->ipv4.udp_table, NULL);
+ dif, sdif, NULL);
#endif
}
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index a010d05062a0..0899c60cce53 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -44,11 +44,11 @@ static int udp_dump_one(struct udp_table *tbl,
#if IS_ENABLED(CONFIG_IPV6)
else if (req->sdiag_family == AF_INET6)
sk = __udp6_lib_lookup(net,
- (struct in6_addr *)req->id.idiag_src,
- req->id.idiag_sport,
- (struct in6_addr *)req->id.idiag_dst,
- req->id.idiag_dport,
- req->id.idiag_if, 0, tbl, NULL);
+ (struct in6_addr *)req->id.idiag_src,
+ req->id.idiag_sport,
+ (struct in6_addr *)req->id.idiag_dst,
+ req->id.idiag_dport,
+ req->id.idiag_if, 0, NULL);
#endif
if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
sk = NULL;
@@ -185,11 +185,11 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
else
sk = __udp6_lib_lookup(net,
- (struct in6_addr *)req->id.idiag_dst,
- req->id.idiag_dport,
- (struct in6_addr *)req->id.idiag_src,
- req->id.idiag_sport,
- req->id.idiag_if, 0, tbl, NULL);
+ (struct in6_addr *)req->id.idiag_dst,
+ req->id.idiag_dport,
+ (struct in6_addr *)req->id.idiag_src,
+ req->id.idiag_sport,
+ req->id.idiag_if, 0, NULL);
}
#endif
else {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5ba399218d07..dd958e2b552b 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -344,9 +344,9 @@ static void udp6_hash4(struct sock *sk)
struct sock *__udp6_lib_lookup(const struct net *net,
const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport,
- int dif, int sdif, struct udp_table *udptable,
- struct sk_buff *skb)
+ int dif, int sdif, struct sk_buff *skb)
{
+ struct udp_table *udptable = net->ipv4.udp_table;
unsigned short hnum = ntohs(dport);
struct udp_hslot *hslot2;
struct sock *result, *sk;
@@ -406,14 +406,13 @@ struct sock *__udp6_lib_lookup(const struct net *net,
EXPORT_SYMBOL_GPL(__udp6_lib_lookup);
static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
- __be16 sport, __be16 dport,
- struct udp_table *udptable)
+ __be16 sport, __be16 dport)
{
const struct ipv6hdr *iph = ipv6_hdr(skb);
return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
&iph->daddr, dport, inet6_iif(skb),
- inet6_sdif(skb), udptable, skb);
+ inet6_sdif(skb), skb);
}
struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
@@ -421,14 +420,12 @@ struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
{
const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
const struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + offset);
- struct net *net = dev_net(skb->dev);
int iif, sdif;
inet6_get_iif_sdif(skb, &iif, &sdif);
- return __udp6_lib_lookup(net, &iph->saddr, sport,
- &iph->daddr, dport, iif,
- sdif, net->ipv4.udp_table, NULL);
+ return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
+ &iph->daddr, dport, iif, sdif, NULL);
}
/* Must be called under rcu_read_lock().
@@ -440,8 +437,7 @@ struct sock *udp6_lib_lookup(const struct net *net, const struct in6_addr *saddr
{
struct sock *sk;
- sk = __udp6_lib_lookup(net, saddr, sport, daddr, dport,
- dif, 0, net->ipv4.udp_table, NULL);
+ sk = __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, 0, NULL);
if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
sk = NULL;
return sk;
@@ -642,7 +638,6 @@ static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb,
static struct sock *__udp6_lib_err_encap(struct net *net,
const struct ipv6hdr *hdr, int offset,
struct udphdr *uh,
- struct udp_table *udptable,
struct sock *sk,
struct sk_buff *skb,
struct inet6_skb_parm *opt,
@@ -673,7 +668,7 @@ static struct sock *__udp6_lib_err_encap(struct net *net,
sk = __udp6_lib_lookup(net, &hdr->daddr, uh->source,
&hdr->saddr, uh->dest,
- inet6_iif(skb), 0, udptable, skb);
+ inet6_iif(skb), 0, skb);
if (sk) {
up = udp_sk(sk);
@@ -694,29 +689,28 @@ static struct sock *__udp6_lib_err_encap(struct net *net,
return sk;
}
-static int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- u8 type, u8 code, int offset, __be32 info,
- struct udp_table *udptable)
+static int udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ u8 type, u8 code, int offset, __be32 info)
{
- struct ipv6_pinfo *np;
const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
- const struct in6_addr *saddr = &hdr->saddr;
- const struct in6_addr *daddr = seg6_get_daddr(skb, opt) ? : &hdr->daddr;
- struct udphdr *uh = (struct udphdr *)(skb->data+offset);
+ struct udphdr *uh = (struct udphdr *)(skb->data + offset);
+ const struct in6_addr *saddr, *daddr;
+ struct net *net = dev_net(skb->dev);
+ struct ipv6_pinfo *np;
bool tunnel = false;
struct sock *sk;
int harderr;
int err;
- struct net *net = dev_net(skb->dev);
+ daddr = seg6_get_daddr(skb, opt) ? : &hdr->daddr;
+ saddr = &hdr->saddr;
sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source,
- inet6_iif(skb), inet6_sdif(skb), udptable, NULL);
+ inet6_iif(skb), inet6_sdif(skb), NULL);
if (!sk || READ_ONCE(udp_sk(sk)->encap_type)) {
/* No socket for error: try tunnels before discarding */
if (static_branch_unlikely(&udpv6_encap_needed_key)) {
- sk = __udp6_lib_err_encap(net, hdr, offset, uh,
- udptable, sk, skb,
+ sk = __udp6_lib_err_encap(net, hdr, offset, uh, sk, skb,
opt, type, code, info);
if (!sk)
return 0;
@@ -808,14 +802,6 @@ static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
return 0;
}
-static __inline__ int udpv6_err(struct sk_buff *skb,
- struct inet6_skb_parm *opt, u8 type,
- u8 code, int offset, __be32 info)
-{
- return __udp6_lib_err(skb, opt, type, code, offset, info,
- dev_net(skb->dev)->ipv4.udp_table);
-}
-
static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
{
enum skb_drop_reason drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;
@@ -947,19 +933,27 @@ static void udp6_csum_zero_error(struct sk_buff *skb)
* so we don't need to lock the hashes.
*/
static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
- const struct in6_addr *saddr, const struct in6_addr *daddr,
- struct udp_table *udptable, int proto)
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ int proto)
{
- struct sock *sk, *first = NULL;
+ struct udp_table *udptable = net->ipv4.udp_table;
const struct udphdr *uh = udp_hdr(skb);
+ unsigned int hash2, hash2_any, offset;
unsigned short hnum = ntohs(uh->dest);
- struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum);
- unsigned int offset = offsetof(typeof(*sk), sk_node);
- unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10);
- int dif = inet6_iif(skb);
+ struct sock *sk, *first = NULL;
int sdif = inet6_sdif(skb);
+ int dif = inet6_iif(skb);
struct hlist_node *node;
+ struct udp_hslot *hslot;
struct sk_buff *nskb;
+ bool use_hash2;
+
+ hash2_any = 0;
+ hash2 = 0;
+ hslot = udp_hashslot(udptable, net, hnum);
+ use_hash2 = hslot->count > 10;
+ offset = offsetof(typeof(*sk), sk_node);
if (use_hash2) {
hash2_any = ipv6_portaddr_hash(net, &in6addr_any, hnum) &
@@ -1069,8 +1063,7 @@ static int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh)
return 0;
}
-static int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
- int proto)
+static int __udp6_lib_rcv(struct sk_buff *skb, int proto)
{
enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
const struct in6_addr *saddr, *daddr;
@@ -1139,11 +1132,10 @@ static int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
* Multicast receive code
*/
if (ipv6_addr_is_multicast(daddr))
- return __udp6_lib_mcast_deliver(net, skb,
- saddr, daddr, udptable, proto);
+ return __udp6_lib_mcast_deliver(net, skb, saddr, daddr, proto);
/* Unicast */
- sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
+ sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest);
if (sk) {
if (!uh->check && !udp_get_no_check6_rx(sk))
goto report_csum_error;
@@ -1261,7 +1253,7 @@ void udp_v6_early_demux(struct sk_buff *skb)
INDIRECT_CALLABLE_SCOPE int udpv6_rcv(struct sk_buff *skb)
{
- return __udp6_lib_rcv(skb, dev_net(skb->dev)->ipv4.udp_table, IPPROTO_UDP);
+ return __udp6_lib_rcv(skb, IPPROTO_UDP);
}
/*
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index e003b8494dc0..778afc7453ce 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -128,8 +128,7 @@ static struct sock *udp6_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
inet6_get_iif_sdif(skb, &iif, &sdif);
return __udp6_lib_lookup(net, &iph->saddr, sport,
- &iph->daddr, dport, iif,
- sdif, net->ipv4.udp_table, NULL);
+ &iph->daddr, dport, iif, sdif, NULL);
}
struct sk_buff *udp6_gro_receive(struct list_head *head, struct sk_buff *skb)
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 14/15] udp: Don't pass udptable to IPv4 socket lookup functions.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (12 preceding siblings ...)
2026-03-11 5:20 ` [PATCH v3 net-next 13/15] udp: Don't pass udptable to IPv6 socket lookup functions Kuniyuki Iwashima
@ 2026-03-11 5:20 ` Kuniyuki Iwashima
2026-03-11 5:20 ` [PATCH v3 net-next 15/15] udp: Don't pass proto to __udp4_lib_rcv() and __udp6_lib_rcv() Kuniyuki Iwashima
2026-03-14 2:20 ` [PATCH v3 net-next 00/15] udp: Retire UDP-Lite patchwork-bot+netdevbpf
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:20 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
Since UDP and UDP-Lite had dedicated socket hash tables for
each, we have had to pass the pointer down to many socket
lookup functions.
UDP-Lite gone, and we do not need to do that.
Let's fetch net->ipv4.udp_table only where needed in IPv4
stack: __udp4_lib_lookup(), __udp4_lib_mcast_deliver(),
and udp_diag_dump().
Some functions are renamed as the wrapper functions are no
longer needed.
__udp4_lib_err() -> udp_err()
__udp_diag_destroy() -> udp_diag_destroy()
udp_dump_one() -> udp_diag_dump_one()
udp_dump() -> udp_diag_dump()
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
include/net/udp.h | 5 ++-
net/core/filter.c | 2 +-
net/ipv4/udp.c | 75 +++++++++++++++++++-----------------------
net/ipv4/udp_diag.c | 61 ++++++++++++----------------------
net/ipv4/udp_offload.c | 3 +-
5 files changed, 59 insertions(+), 87 deletions(-)
diff --git a/include/net/udp.h b/include/net/udp.h
index adec74531ee1..8262e2b215b4 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -437,9 +437,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
struct sock *udp4_lib_lookup(const struct net *net, __be32 saddr, __be16 sport,
__be32 daddr, __be16 dport, int dif);
struct sock *__udp4_lib_lookup(const struct net *net, __be32 saddr,
- __be16 sport,
- __be32 daddr, __be16 dport, int dif, int sdif,
- struct udp_table *tbl, struct sk_buff *skb);
+ __be16 sport, __be32 daddr, __be16 dport,
+ int dif, int sdif, struct sk_buff *skb);
struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
__be16 sport, __be16 dport);
struct sock *udp6_lib_lookup(const struct net *net,
diff --git a/net/core/filter.c b/net/core/filter.c
index 04e2a3ad0340..9746bf588a00 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -6882,7 +6882,7 @@ static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple,
else
sk = __udp4_lib_lookup(net, src4, tuple->ipv4.sport,
dst4, tuple->ipv4.dport,
- dif, sdif, net->ipv4.udp_table, NULL);
+ dif, sdif, NULL);
#if IS_ENABLED(CONFIG_IPV6)
} else {
struct in6_addr *src6 = (struct in6_addr *)&tuple->ipv6.saddr;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index fd0bad44d111..dff803e7d6a8 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -673,9 +673,10 @@ EXPORT_IPV6_MOD(udp4_hash4);
* harder than this. -DaveM
*/
struct sock *__udp4_lib_lookup(const struct net *net, __be32 saddr,
- __be16 sport, __be32 daddr, __be16 dport, int dif,
- int sdif, struct udp_table *udptable, struct sk_buff *skb)
+ __be16 sport, __be32 daddr, __be16 dport,
+ int dif, int sdif, struct sk_buff *skb)
{
+ struct udp_table *udptable = net->ipv4.udp_table;
unsigned short hnum = ntohs(dport);
struct udp_hslot *hslot2;
struct sock *result, *sk;
@@ -741,14 +742,13 @@ struct sock *__udp4_lib_lookup(const struct net *net, __be32 saddr,
EXPORT_SYMBOL_GPL(__udp4_lib_lookup);
static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
- __be16 sport, __be16 dport,
- struct udp_table *udptable)
+ __be16 sport, __be16 dport)
{
const struct iphdr *iph = ip_hdr(skb);
return __udp4_lib_lookup(dev_net(skb->dev), iph->saddr, sport,
iph->daddr, dport, inet_iif(skb),
- inet_sdif(skb), udptable, skb);
+ inet_sdif(skb), skb);
}
struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
@@ -756,14 +756,12 @@ struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
{
const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
const struct iphdr *iph = (struct iphdr *)(skb->data + offset);
- struct net *net = dev_net(skb->dev);
int iif, sdif;
inet_get_iif_sdif(skb, &iif, &sdif);
- return __udp4_lib_lookup(net, iph->saddr, sport,
- iph->daddr, dport, iif,
- sdif, net->ipv4.udp_table, NULL);
+ return __udp4_lib_lookup(dev_net(skb->dev), iph->saddr, sport,
+ iph->daddr, dport, iif, sdif, NULL);
}
/* Must be called under rcu_read_lock().
@@ -775,8 +773,7 @@ struct sock *udp4_lib_lookup(const struct net *net, __be32 saddr, __be16 sport,
{
struct sock *sk;
- sk = __udp4_lib_lookup(net, saddr, sport, daddr, dport,
- dif, 0, net->ipv4.udp_table, NULL);
+ sk = __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, 0, NULL);
if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
sk = NULL;
return sk;
@@ -866,7 +863,6 @@ static int __udp4_lib_err_encap_no_sk(struct sk_buff *skb, u32 info)
static struct sock *__udp4_lib_err_encap(struct net *net,
const struct iphdr *iph,
struct udphdr *uh,
- struct udp_table *udptable,
struct sock *sk,
struct sk_buff *skb, u32 info)
{
@@ -894,8 +890,7 @@ static struct sock *__udp4_lib_err_encap(struct net *net,
}
sk = __udp4_lib_lookup(net, iph->daddr, uh->source,
- iph->saddr, uh->dest, skb->dev->ifindex, 0,
- udptable, NULL);
+ iph->saddr, uh->dest, skb->dev->ifindex, 0, NULL);
if (sk) {
up = udp_sk(sk);
@@ -924,29 +919,28 @@ static struct sock *__udp4_lib_err_encap(struct net *net,
* header points to the first 8 bytes of the udp header. We need
* to find the appropriate port.
*/
-
-static int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
+int udp_err(struct sk_buff *skb, u32 info)
{
- struct inet_sock *inet;
const struct iphdr *iph = (const struct iphdr *)skb->data;
- struct udphdr *uh = (struct udphdr *)(skb->data+(iph->ihl<<2));
const int type = icmp_hdr(skb)->type;
const int code = icmp_hdr(skb)->code;
+ struct net *net = dev_net(skb->dev);
+ struct inet_sock *inet;
bool tunnel = false;
+ struct udphdr *uh;
struct sock *sk;
int harderr;
int err;
- struct net *net = dev_net(skb->dev);
+ uh = (struct udphdr *)(skb->data + (iph->ihl << 2));
sk = __udp4_lib_lookup(net, iph->daddr, uh->dest,
iph->saddr, uh->source, skb->dev->ifindex,
- inet_sdif(skb), udptable, NULL);
+ inet_sdif(skb), NULL);
if (!sk || READ_ONCE(udp_sk(sk)->encap_type)) {
/* No socket for error: try tunnels before discarding */
if (static_branch_unlikely(&udp_encap_needed_key)) {
- sk = __udp4_lib_err_encap(net, iph, uh, udptable, sk, skb,
- info);
+ sk = __udp4_lib_err_encap(net, iph, uh, sk, skb, info);
if (!sk)
return 0;
} else
@@ -1019,11 +1013,6 @@ static int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udpta
return 0;
}
-int udp_err(struct sk_buff *skb, u32 info)
-{
- return __udp4_lib_err(skb, info, dev_net(skb->dev)->ipv4.udp_table);
-}
-
/*
* Throw away all pending data and cancel the corking. Socket is locked.
*/
@@ -2491,18 +2480,24 @@ EXPORT_IPV6_MOD(udp_sk_rx_dst_set);
static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
struct udphdr *uh,
__be32 saddr, __be32 daddr,
- struct udp_table *udptable,
int proto)
{
- struct sock *sk, *first = NULL;
+ struct udp_table *udptable = net->ipv4.udp_table;
+ unsigned int hash2, hash2_any, offset;
unsigned short hnum = ntohs(uh->dest);
- struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum);
- unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10);
- unsigned int offset = offsetof(typeof(*sk), sk_node);
+ struct sock *sk, *first = NULL;
int dif = skb->dev->ifindex;
int sdif = inet_sdif(skb);
struct hlist_node *node;
+ struct udp_hslot *hslot;
struct sk_buff *nskb;
+ bool use_hash2;
+
+ hash2_any = 0;
+ hash2 = 0;
+ hslot = udp_hashslot(udptable, net, hnum);
+ use_hash2 = hslot->count > 10;
+ offset = offsetof(typeof(*sk), sk_node);
if (use_hash2) {
hash2_any = ipv4_portaddr_hash(net, htonl(INADDR_ANY), hnum) &
@@ -2607,15 +2602,14 @@ static int udp_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
* All we need to do is get the socket, and then do a checksum.
*/
-static int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
- int proto)
+static int __udp4_lib_rcv(struct sk_buff *skb, int proto)
{
+ struct rtable *rt = skb_rtable(skb);
+ struct net *net = dev_net(skb->dev);
struct sock *sk = NULL;
- struct udphdr *uh;
unsigned short ulen;
- struct rtable *rt = skb_rtable(skb);
__be32 saddr, daddr;
- struct net *net = dev_net(skb->dev);
+ struct udphdr *uh;
bool refcounted;
int drop_reason;
@@ -2667,10 +2661,9 @@ static int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
}
if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
- return __udp4_lib_mcast_deliver(net, skb, uh,
- saddr, daddr, udptable, proto);
+ return __udp4_lib_mcast_deliver(net, skb, uh, saddr, daddr, proto);
- sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
+ sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest);
if (sk)
return udp_unicast_rcv_skb(sk, skb, uh);
no_sk:
@@ -2854,7 +2847,7 @@ enum skb_drop_reason udp_v4_early_demux(struct sk_buff *skb)
int udp_rcv(struct sk_buff *skb)
{
- return __udp4_lib_rcv(skb, dev_net(skb->dev)->ipv4.udp_table, IPPROTO_UDP);
+ return __udp4_lib_rcv(skb, IPPROTO_UDP);
}
static void udp_destroy_sock(struct sock *sk)
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 0899c60cce53..f4b24e628cf8 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -24,23 +24,24 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
net_admin);
}
-static int udp_dump_one(struct udp_table *tbl,
- struct netlink_callback *cb,
- const struct inet_diag_req_v2 *req)
+static int udp_diag_dump_one(struct netlink_callback *cb,
+ const struct inet_diag_req_v2 *req)
{
struct sk_buff *in_skb = cb->skb;
- int err;
struct sock *sk = NULL;
struct sk_buff *rep;
- struct net *net = sock_net(in_skb->sk);
+ struct net *net;
+ int err;
+
+ net = sock_net(in_skb->sk);
rcu_read_lock();
if (req->sdiag_family == AF_INET)
/* src and dst are swapped for historical reasons */
sk = __udp4_lib_lookup(net,
- req->id.idiag_src[0], req->id.idiag_sport,
- req->id.idiag_dst[0], req->id.idiag_dport,
- req->id.idiag_if, 0, tbl, NULL);
+ req->id.idiag_src[0], req->id.idiag_sport,
+ req->id.idiag_dst[0], req->id.idiag_dport,
+ req->id.idiag_if, 0, NULL);
#if IS_ENABLED(CONFIG_IPV6)
else if (req->sdiag_family == AF_INET6)
sk = __udp6_lib_lookup(net,
@@ -85,14 +86,15 @@ static int udp_dump_one(struct udp_table *tbl,
return err;
}
-static void udp_dump(struct udp_table *table, struct sk_buff *skb,
- struct netlink_callback *cb,
- const struct inet_diag_req_v2 *r)
+static void udp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
+ const struct inet_diag_req_v2 *r)
{
bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
struct net *net = sock_net(skb->sk);
int num, s_num, slot, s_slot;
+ struct udp_table *table;
+ table = net->ipv4.udp_table;
s_slot = cb->args[0];
num = s_num = cb->args[1];
@@ -139,18 +141,6 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb,
cb->args[1] = num;
}
-static void udp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
- const struct inet_diag_req_v2 *r)
-{
- udp_dump(sock_net(cb->skb->sk)->ipv4.udp_table, skb, cb, r);
-}
-
-static int udp_diag_dump_one(struct netlink_callback *cb,
- const struct inet_diag_req_v2 *req)
-{
- return udp_dump_one(sock_net(cb->skb->sk)->ipv4.udp_table, cb, req);
-}
-
static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
void *info)
{
@@ -159,9 +149,8 @@ static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
}
#ifdef CONFIG_INET_DIAG_DESTROY
-static int __udp_diag_destroy(struct sk_buff *in_skb,
- const struct inet_diag_req_v2 *req,
- struct udp_table *tbl)
+static int udp_diag_destroy(struct sk_buff *in_skb,
+ const struct inet_diag_req_v2 *req)
{
struct net *net = sock_net(in_skb->sk);
struct sock *sk;
@@ -171,18 +160,17 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
if (req->sdiag_family == AF_INET)
sk = __udp4_lib_lookup(net,
- req->id.idiag_dst[0], req->id.idiag_dport,
- req->id.idiag_src[0], req->id.idiag_sport,
- req->id.idiag_if, 0, tbl, NULL);
+ req->id.idiag_dst[0], req->id.idiag_dport,
+ req->id.idiag_src[0], req->id.idiag_sport,
+ req->id.idiag_if, 0, NULL);
#if IS_ENABLED(CONFIG_IPV6)
else if (req->sdiag_family == AF_INET6) {
if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) &&
ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_src))
sk = __udp4_lib_lookup(net,
- req->id.idiag_dst[3], req->id.idiag_dport,
- req->id.idiag_src[3], req->id.idiag_sport,
- req->id.idiag_if, 0, tbl, NULL);
-
+ req->id.idiag_dst[3], req->id.idiag_dport,
+ req->id.idiag_src[3], req->id.idiag_sport,
+ req->id.idiag_if, 0, NULL);
else
sk = __udp6_lib_lookup(net,
(struct in6_addr *)req->id.idiag_dst,
@@ -216,13 +204,6 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
return err;
}
-
-static int udp_diag_destroy(struct sk_buff *in_skb,
- const struct inet_diag_req_v2 *req)
-{
- return __udp_diag_destroy(in_skb, req, sock_net(in_skb->sk)->ipv4.udp_table);
-}
-
#endif
static const struct inet_diag_handler udp_diag_handler = {
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 6b1654c1ad4a..98e92da726b5 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -869,8 +869,7 @@ static struct sock *udp4_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
inet_get_iif_sdif(skb, &iif, &sdif);
return __udp4_lib_lookup(net, iph->saddr, sport,
- iph->daddr, dport, iif,
- sdif, net->ipv4.udp_table, NULL);
+ iph->daddr, dport, iif, sdif, NULL);
}
INDIRECT_CALLABLE_SCOPE
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v3 net-next 15/15] udp: Don't pass proto to __udp4_lib_rcv() and __udp6_lib_rcv().
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (13 preceding siblings ...)
2026-03-11 5:20 ` [PATCH v3 net-next 14/15] udp: Don't pass udptable to IPv4 " Kuniyuki Iwashima
@ 2026-03-11 5:20 ` Kuniyuki Iwashima
2026-03-14 2:20 ` [PATCH v3 net-next 00/15] udp: Retire UDP-Lite patchwork-bot+netdevbpf
15 siblings, 0 replies; 19+ messages in thread
From: Kuniyuki Iwashima @ 2026-03-11 5:20 UTC (permalink / raw)
To: Willem de Bruijn, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev, Willem de Bruijn
UDP and UDP-Lite shared __udp4_lib_rcv() and __udp6_lib_rcv()
by passing IPPROTO_UDP or IPPROTO_UDPLITE.
Now, @proto is always IPPROTO_UDP.
Let's not pass it and rename the functions accordingly.
With this series removing a bunch of conditionals for UDP-Lite
from the fast path, udp_rr with 20,000 flows sees a 10% increase
in pps (13.3 Mpps -> 14.7 Mpps) on an AMD EPYC 7B12 (Zen 2)
64-Core Processor platform.
[ With FDO, the baseline is much higher and the delta was ~3%,
20.1 Mpps -> 20.7 Mpps ]
Before:
$ nstat > /dev/null; sleep 1; nstat | grep Udp
Udp6InDatagrams 14013408 0.0
Udp6OutDatagrams 14013128 0.0
After:
$ nstat > /dev/null; sleep 1; nstat | grep Udp
Udp6InDatagrams 15491971 0.0
Udp6OutDatagrams 15491671 0.0
$ ./scripts/bloat-o-meter vmlinux.before vmlinux.after
add/remove: 13/75 grow/shrink: 11/75 up/down: 13777/-18401 (-4624)
Function old new delta
udp4_gro_receive 872 866 -6
udp6_gro_receive 910 903 -7
udp_rcv 32 1727 +1695
udpv6_rcv 32 1450 +1418
__udp4_lib_rcv 2045 - -2045
__udp6_lib_rcv 2084 - -2084
udp_unicast_rcv_skb 160 149 -11
udp6_unicast_rcv_skb 196 181 -15
__udp4_lib_mcast_deliver 925 846 -79
__udp6_lib_mcast_deliver 922 810 -112
__udp4_lib_lookup 973 969 -4
__udp6_lib_lookup 940 929 -11
__udp4_lib_lookup_skb 106 100 -6
__udp6_lib_lookup_skb 71 66 -5
udp4_lib_lookup_skb 132 127 -5
udp6_lib_lookup_skb 87 81 -6
udp_queue_rcv_skb 326 356 +30
udpv6_queue_rcv_skb 331 361 +30
udp_queue_rcv_one_skb 1233 914 -319
udpv6_queue_rcv_one_skb 1250 930 -320
__udp_enqueue_schedule_skb 1067 995 -72
udp_rcv_segment 520 480 -40
udp_post_segment_fix_csum 120 - -120
udp_lib_checksum_complete 200 84 -116
udp_err 27 1103 +1076
udpv6_err 36 1417 +1381
__udp4_lib_err 1112 - -1112
__udp6_lib_err 1448 - -1448
udp_recvmsg 1149 994 -155
udpv6_recvmsg 1349 1294 -55
udp_sendmsg 2730 2648 -82
udp_send_skb 909 681 -228
udpv6_sendmsg 3022 2861 -161
udp_v6_send_skb 1214 952 -262
...
Total: Before=18446744073748075501, After=18446744073748070877, chg -0.00%
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
net/ipv4/udp.c | 18 +++++-------------
net/ipv6/udp.c | 15 ++++-----------
2 files changed, 9 insertions(+), 24 deletions(-)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index dff803e7d6a8..7e3f9fd9de19 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2479,8 +2479,7 @@ EXPORT_IPV6_MOD(udp_sk_rx_dst_set);
*/
static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
struct udphdr *uh,
- __be32 saddr, __be32 daddr,
- int proto)
+ __be32 saddr, __be32 daddr)
{
struct udp_table *udptable = net->ipv4.udp_table;
unsigned int hash2, hash2_any, offset;
@@ -2602,7 +2601,7 @@ static int udp_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
* All we need to do is get the socket, and then do a checksum.
*/
-static int __udp4_lib_rcv(struct sk_buff *skb, int proto)
+int udp_rcv(struct sk_buff *skb)
{
struct rtable *rt = skb_rtable(skb);
struct net *net = dev_net(skb->dev);
@@ -2661,7 +2660,7 @@ static int __udp4_lib_rcv(struct sk_buff *skb, int proto)
}
if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
- return __udp4_lib_mcast_deliver(net, skb, uh, saddr, daddr, proto);
+ return __udp4_lib_mcast_deliver(net, skb, uh, saddr, daddr);
sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest);
if (sk)
@@ -2688,8 +2687,7 @@ static int __udp4_lib_rcv(struct sk_buff *skb, int proto)
short_packet:
drop_reason = SKB_DROP_REASON_PKT_TOO_SMALL;
- net_dbg_ratelimited("UDP%s: short packet: From %pI4:%u %d/%d to %pI4:%u\n",
- proto == IPPROTO_UDPLITE ? "Lite" : "",
+ net_dbg_ratelimited("UDP: short packet: From %pI4:%u %d/%d to %pI4:%u\n",
&saddr, ntohs(uh->source),
ulen, skb->len,
&daddr, ntohs(uh->dest));
@@ -2701,8 +2699,7 @@ static int __udp4_lib_rcv(struct sk_buff *skb, int proto)
* the network is concerned, anyway) as per 4.1.3.4 (MUST).
*/
drop_reason = SKB_DROP_REASON_UDP_CSUM;
- net_dbg_ratelimited("UDP%s: bad checksum. From %pI4:%u to %pI4:%u ulen %d\n",
- proto == IPPROTO_UDPLITE ? "Lite" : "",
+ net_dbg_ratelimited("UDP: bad checksum. From %pI4:%u to %pI4:%u ulen %d\n",
&saddr, ntohs(uh->source), &daddr, ntohs(uh->dest),
ulen);
__UDP_INC_STATS(net, UDP_MIB_CSUMERRORS);
@@ -2845,11 +2842,6 @@ enum skb_drop_reason udp_v4_early_demux(struct sk_buff *skb)
return SKB_NOT_DROPPED_YET;
}
-int udp_rcv(struct sk_buff *skb)
-{
- return __udp4_lib_rcv(skb, IPPROTO_UDP);
-}
-
static void udp_destroy_sock(struct sock *sk)
{
struct udp_sock *up = udp_sk(sk);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index dd958e2b552b..d7cf4c9508b2 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -934,8 +934,7 @@ static void udp6_csum_zero_error(struct sk_buff *skb)
*/
static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
const struct in6_addr *saddr,
- const struct in6_addr *daddr,
- int proto)
+ const struct in6_addr *daddr)
{
struct udp_table *udptable = net->ipv4.udp_table;
const struct udphdr *uh = udp_hdr(skb);
@@ -1063,7 +1062,7 @@ static int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh)
return 0;
}
-static int __udp6_lib_rcv(struct sk_buff *skb, int proto)
+INDIRECT_CALLABLE_SCOPE int udpv6_rcv(struct sk_buff *skb)
{
enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
const struct in6_addr *saddr, *daddr;
@@ -1132,7 +1131,7 @@ static int __udp6_lib_rcv(struct sk_buff *skb, int proto)
* Multicast receive code
*/
if (ipv6_addr_is_multicast(daddr))
- return __udp6_lib_mcast_deliver(net, skb, saddr, daddr, proto);
+ return __udp6_lib_mcast_deliver(net, skb, saddr, daddr);
/* Unicast */
sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest);
@@ -1163,8 +1162,7 @@ static int __udp6_lib_rcv(struct sk_buff *skb, int proto)
short_packet:
if (reason == SKB_DROP_REASON_NOT_SPECIFIED)
reason = SKB_DROP_REASON_PKT_TOO_SMALL;
- net_dbg_ratelimited("UDP%sv6: short packet: From [%pI6c]:%u %d/%d to [%pI6c]:%u\n",
- proto == IPPROTO_UDPLITE ? "-Lite" : "",
+ net_dbg_ratelimited("UDPv6: short packet: From [%pI6c]:%u %d/%d to [%pI6c]:%u\n",
saddr, ntohs(uh->source),
ulen, skb->len,
daddr, ntohs(uh->dest));
@@ -1251,11 +1249,6 @@ void udp_v6_early_demux(struct sk_buff *skb)
}
}
-INDIRECT_CALLABLE_SCOPE int udpv6_rcv(struct sk_buff *skb)
-{
- return __udp6_lib_rcv(skb, IPPROTO_UDP);
-}
-
/*
* Throw away all pending data and cancel the corking. Socket is locked.
*/
--
2.53.0.473.g4a7958ca14-goog
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v3 net-next 07/15] udp: Remove partial csum code in RX.
2026-03-11 5:19 ` [PATCH v3 net-next 07/15] udp: Remove partial csum code in RX Kuniyuki Iwashima
@ 2026-03-13 1:04 ` Jakub Kicinski
2026-03-13 2:20 ` Willem de Bruijn
1 sibling, 0 replies; 19+ messages in thread
From: Jakub Kicinski @ 2026-03-13 1:04 UTC (permalink / raw)
To: Willem de Bruijn
Cc: Kuniyuki Iwashima, David Ahern, David S . Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, Florian Westphal, Kuniyuki Iwashima,
netdev
On Wed, 11 Mar 2026 05:19:54 +0000 Kuniyuki Iwashima wrote:
> UDP-Lite supports the partial checksum and the coverage is
> stored in the position of the length field of struct udphdr.
>
> In RX paths, udp4_csum_init() / udp6_csum_init() save the value
> in UDP_SKB_CB(skb)->cscov and set UDP_SKB_CB(skb)->partial_cov
> to 1 if the coverage is not full.
>
> The subsequent processing diverges depending on the value,
> but such paths are now dead.
>
> Also, these functions have some code guarded for UDP:
>
> * udp_unicast_rcv_skb / udp6_unicast_rcv_skb
> * __udp4_lib_rcv() and __udp6_lib_rcv().
>
> Let's remove the partial csum code and the unnecessary
> guard for UDP-Lite in RX.
Hi Willem, this lost your ack due to a bug fix, could you re-review?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 net-next 07/15] udp: Remove partial csum code in RX.
2026-03-11 5:19 ` [PATCH v3 net-next 07/15] udp: Remove partial csum code in RX Kuniyuki Iwashima
2026-03-13 1:04 ` Jakub Kicinski
@ 2026-03-13 2:20 ` Willem de Bruijn
1 sibling, 0 replies; 19+ messages in thread
From: Willem de Bruijn @ 2026-03-13 2:20 UTC (permalink / raw)
To: Kuniyuki Iwashima, Willem de Bruijn, David Ahern,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Florian Westphal, Kuniyuki Iwashima,
Kuniyuki Iwashima, netdev
Kuniyuki Iwashima wrote:
> UDP-Lite supports the partial checksum and the coverage is
> stored in the position of the length field of struct udphdr.
>
> In RX paths, udp4_csum_init() / udp6_csum_init() save the value
> in UDP_SKB_CB(skb)->cscov and set UDP_SKB_CB(skb)->partial_cov
> to 1 if the coverage is not full.
>
> The subsequent processing diverges depending on the value,
> but such paths are now dead.
>
> Also, these functions have some code guarded for UDP:
>
> * udp_unicast_rcv_skb / udp6_unicast_rcv_skb
> * __udp4_lib_rcv() and __udp6_lib_rcv().
>
> Let's remove the partial csum code and the unnecessary
> guard for UDP-Lite in RX.
>
> Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
> ---
> v3: Correct ulen < skb->len case in __udp4_lib_rcv()
Reviewed-by: Willem de Bruijn <willemb@google.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 net-next 00/15] udp: Retire UDP-Lite.
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
` (14 preceding siblings ...)
2026-03-11 5:20 ` [PATCH v3 net-next 15/15] udp: Don't pass proto to __udp4_lib_rcv() and __udp6_lib_rcv() Kuniyuki Iwashima
@ 2026-03-14 2:20 ` patchwork-bot+netdevbpf
15 siblings, 0 replies; 19+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-03-14 2:20 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: willemdebruijn.kernel, dsahern, davem, edumazet, kuba, pabeni,
horms, fw, kuni1840, netdev
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 11 Mar 2026 05:19:47 +0000 you wrote:
> In 2023, syzbot found a null-ptr-deref bug triggered when UDP-Lite
> attempted to charge an skb after the total memory usage for UDP-Lite
> _and_ UDP exceeded a system-wide threshold, net.ipv4.udp_mem[1].
>
> Since this threshold is shared with UDP, the bug would have been
> easy to trigger if any real-world applications were using UDP-Lite;
> however, only syzbot ever stumbled upon it.
>
> [...]
Here is the summary with links:
- [v3,net-next,01/15] udp: Make udp[46]_seq_show() static.
https://git.kernel.org/netdev/net-next/c/86a41d957ba0
- [v3,net-next,02/15] ipv6: Retire UDP-Lite.
https://git.kernel.org/netdev/net-next/c/62554a51c584
- [v3,net-next,03/15] ipv6: Remove UDP-Lite support for IPV6_ADDRFORM.
https://git.kernel.org/netdev/net-next/c/92586f02f8a5
- [v3,net-next,04/15] ipv4: Retire UDP-Lite.
https://git.kernel.org/netdev/net-next/c/56520b398e5e
- [v3,net-next,05/15] udp: Remove UDP-Lite SNMP stats.
https://git.kernel.org/netdev/net-next/c/7accba6fd1ab
- [v3,net-next,06/15] smack: Remove IPPROTO_UDPLITE support in security_sock_rcv_skb().
https://git.kernel.org/netdev/net-next/c/b972cb5d397e
- [v3,net-next,07/15] udp: Remove partial csum code in RX.
https://git.kernel.org/netdev/net-next/c/c2539d4f2df7
- [v3,net-next,08/15] udp: Remove partial csum code in TX.
https://git.kernel.org/netdev/net-next/c/b2a1d719be4f
- [v3,net-next,09/15] udp: Remove UDPLITE_SEND_CSCOV and UDPLITE_RECV_CSCOV.
https://git.kernel.org/netdev/net-next/c/74f0cca1100b
- [v3,net-next,10/15] udp: Remove struct proto.h.udp_table.
https://git.kernel.org/netdev/net-next/c/5c2738588621
- [v3,net-next,11/15] udp: Remove udp_table in struct udp_seq_afinfo.
https://git.kernel.org/netdev/net-next/c/c570bd25d88a
- [v3,net-next,12/15] udp: Remove dead check in __udp[46]_lib_lookup() for BPF.
https://git.kernel.org/netdev/net-next/c/5a88b2810f26
- [v3,net-next,13/15] udp: Don't pass udptable to IPv6 socket lookup functions.
https://git.kernel.org/netdev/net-next/c/deffb85478a4
- [v3,net-next,14/15] udp: Don't pass udptable to IPv4 socket lookup functions.
https://git.kernel.org/netdev/net-next/c/68aeb21ef0e1
- [v3,net-next,15/15] udp: Don't pass proto to __udp4_lib_rcv() and __udp6_lib_rcv().
https://git.kernel.org/netdev/net-next/c/14ce9a47c5b7
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-03-14 2:20 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-11 5:19 [PATCH v3 net-next 00/15] udp: Retire UDP-Lite Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 01/15] udp: Make udp[46]_seq_show() static Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 02/15] ipv6: Retire UDP-Lite Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 03/15] ipv6: Remove UDP-Lite support for IPV6_ADDRFORM Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 04/15] ipv4: Retire UDP-Lite Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 05/15] udp: Remove UDP-Lite SNMP stats Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 06/15] smack: Remove IPPROTO_UDPLITE support in security_sock_rcv_skb() Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 07/15] udp: Remove partial csum code in RX Kuniyuki Iwashima
2026-03-13 1:04 ` Jakub Kicinski
2026-03-13 2:20 ` Willem de Bruijn
2026-03-11 5:19 ` [PATCH v3 net-next 08/15] udp: Remove partial csum code in TX Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 09/15] udp: Remove UDPLITE_SEND_CSCOV and UDPLITE_RECV_CSCOV Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 10/15] udp: Remove struct proto.h.udp_table Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 11/15] udp: Remove udp_table in struct udp_seq_afinfo Kuniyuki Iwashima
2026-03-11 5:19 ` [PATCH v3 net-next 12/15] udp: Remove dead check in __udp[46]_lib_lookup() for BPF Kuniyuki Iwashima
2026-03-11 5:20 ` [PATCH v3 net-next 13/15] udp: Don't pass udptable to IPv6 socket lookup functions Kuniyuki Iwashima
2026-03-11 5:20 ` [PATCH v3 net-next 14/15] udp: Don't pass udptable to IPv4 " Kuniyuki Iwashima
2026-03-11 5:20 ` [PATCH v3 net-next 15/15] udp: Don't pass proto to __udp4_lib_rcv() and __udp6_lib_rcv() Kuniyuki Iwashima
2026-03-14 2:20 ` [PATCH v3 net-next 00/15] udp: Retire UDP-Lite patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox