public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/5] net: reduce sk_filter() (and friends) bloat
@ 2026-04-09 14:56 Eric Dumazet
  2026-04-09 14:56 ` [PATCH net-next 1/5] net: change sock_queue_rcv_skb_reason() to return a drop_reason Eric Dumazet
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Eric Dumazet @ 2026-04-09 14:56 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, netdev, eric.dumazet, Eric Dumazet

Some functions return an error by value, and a drop_reason
by an output parameter. This extra parameter can force stack canaries.

A drop_reason is enough and more efficient.

This series reduces bloat by 678 bytes on x86_64:

$ scripts/bloat-o-meter -t vmlinux.old vmlinux.final
add/remove: 0/0 grow/shrink: 3/18 up/down: 79/-757 (-678)
Function                                     old     new   delta
vsock_queue_rcv_skb                           50      79     +29
ipmr_cache_report                           1290    1315     +25
ip6mr_cache_report                          1322    1347     +25
tcp_v6_rcv                                  3169    3167      -2
packet_rcv_spkt                              329     327      -2
unix_dgram_sendmsg                          1731    1726      -5
netlink_unicast                              957     945     -12
netlink_dump                                1372    1359     -13
sk_filter_trim_cap                           889     858     -31
netlink_broadcast_filtered                  1633    1595     -38
tcp_v4_rcv                                  3152    3111     -41
raw_rcv_skb                                  122      80     -42
ping_queue_rcv_skb                           109      61     -48
ping_rcv                                     215     162     -53
rawv6_rcv_skb                                278     224     -54
__sk_receive_skb                             690     632     -58
raw_rcv                                      591     527     -64
udpv6_queue_rcv_one_skb                      935     869     -66
udp_queue_rcv_one_skb                        919     853     -66
tun_net_xmit                                1146    1074     -72
sock_queue_rcv_skb_reason                    166      76     -90
Total: Before=29722890, After=29722212, chg -0.00%

Future conversions from sock_queue_rcv_skb() to sock_queue_rcv_skb_reason()
can be done later.

Eric Dumazet (5):
  net: change sock_queue_rcv_skb_reason() to return a drop_reason
  net: always set reason in sk_filter_trim_cap()
  net: change sk_filter_reason() to return the reason by value
  tcp: change tcp_filter() to return the reason by value
  net: change sk_filter_trim_cap() to return a drop_reason by value

 drivers/net/tun.c      |  8 +++++---
 include/linux/filter.h | 15 ++++++++-------
 include/net/sock.h     | 17 ++++++++++++++---
 include/net/tcp.h      |  6 +++---
 net/can/bcm.c          |  5 ++---
 net/can/isotp.c        |  3 ++-
 net/can/j1939/socket.c |  3 ++-
 net/can/raw.c          |  3 ++-
 net/core/filter.c      | 30 +++++++++++++-----------------
 net/core/sock.c        | 29 +++++++++++------------------
 net/ipv4/ping.c        |  3 ++-
 net/ipv4/raw.c         |  3 ++-
 net/ipv4/tcp_ipv4.c    |  6 ++++--
 net/ipv4/udp.c         |  3 ++-
 net/ipv6/raw.c         |  3 ++-
 net/ipv6/tcp_ipv6.c    |  6 ++++--
 net/ipv6/udp.c         |  3 ++-
 net/rose/rose_in.c     |  3 +--
 18 files changed, 81 insertions(+), 68 deletions(-)

-- 
2.53.0.1213.gd9a14994de-goog


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH net-next 1/5] net: change sock_queue_rcv_skb_reason() to return a drop_reason
  2026-04-09 14:56 [PATCH net-next 0/5] net: reduce sk_filter() (and friends) bloat Eric Dumazet
@ 2026-04-09 14:56 ` Eric Dumazet
  2026-04-09 14:56 ` [PATCH net-next 2/5] net: always set reason in sk_filter_trim_cap() Eric Dumazet
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Dumazet @ 2026-04-09 14:56 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, netdev, eric.dumazet, Eric Dumazet

Change sock_queue_rcv_skb_reason() to return the drop_reason directly
instead of using a reference.

This is part of an effort to remove stack canaries and reduce bloat.

$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
add/remove: 0/0 grow/shrink: 3/7 up/down: 79/-301 (-222)
Function                                     old     new   delta
vsock_queue_rcv_skb                           50      79     +29
ipmr_cache_report                           1290    1315     +25
ip6mr_cache_report                          1322    1347     +25
packet_rcv_spkt                              329     327      -2
sock_queue_rcv_skb_reason                    166     128     -38
raw_rcv_skb                                  122      80     -42
ping_queue_rcv_skb                           109      61     -48
ping_rcv                                     215     162     -53
rawv6_rcv_skb                                278     224     -54
raw_rcv                                      591     527     -64
Total: Before=29722890, After=29722668, chg -0.00%

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/net/sock.h     | 17 ++++++++++++++---
 net/can/bcm.c          |  5 ++---
 net/can/isotp.c        |  3 ++-
 net/can/j1939/socket.c |  3 ++-
 net/can/raw.c          |  3 ++-
 net/core/sock.c        | 20 ++++++--------------
 net/ipv4/ping.c        |  3 ++-
 net/ipv4/raw.c         |  3 ++-
 net/ipv6/raw.c         |  3 ++-
 9 files changed, 34 insertions(+), 26 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index 7d51ac9e7d9a87a7f6f0453a3d3e2c6ed34dc151..5831a4d1ebe77e3d6f568d208fafb072f9635242 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2502,12 +2502,23 @@ int __sk_queue_drop_skb(struct sock *sk, struct sk_buff_head *sk_queue,
 					   struct sk_buff *skb));
 int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 
-int sock_queue_rcv_skb_reason(struct sock *sk, struct sk_buff *skb,
-			      enum skb_drop_reason *reason);
+enum skb_drop_reason
+sock_queue_rcv_skb_reason(struct sock *sk, struct sk_buff *skb);
 
 static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
-	return sock_queue_rcv_skb_reason(sk, skb, NULL);
+	enum skb_drop_reason drop_reason = sock_queue_rcv_skb_reason(sk, skb);
+
+	switch (drop_reason) {
+	case SKB_DROP_REASON_SOCKET_RCVBUFF:
+		return -ENOMEM;
+	case SKB_DROP_REASON_PROTO_MEM:
+		return -ENOBUFS;
+	case 0:
+		return 0;
+	default:
+		return -EPERM;
+	}
 }
 
 int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb);
diff --git a/net/can/bcm.c b/net/can/bcm.c
index fd9fa072881e22ced725fa77dd096dea07fb73a6..d6291381afb09c36b30557f1d1a328c9ed0579f7 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -363,7 +363,6 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
 	struct sockaddr_can *addr;
 	struct sock *sk = op->sk;
 	unsigned int datalen = head->nframes * op->cfsiz;
-	int err;
 	unsigned int *pflags;
 	enum skb_drop_reason reason;
 
@@ -420,8 +419,8 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
 	addr->can_family  = AF_CAN;
 	addr->can_ifindex = op->rx_ifindex;
 
-	err = sock_queue_rcv_skb_reason(sk, skb, &reason);
-	if (err < 0) {
+	reason = sock_queue_rcv_skb_reason(sk, skb);
+	if (reason) {
 		struct bcm_sock *bo = bcm_sk(sk);
 
 		sk_skb_reason_drop(sk, skb, reason);
diff --git a/net/can/isotp.c b/net/can/isotp.c
index 2770f43f4951884658d54ac90bd1e0ae21c24102..c48b4a818297e2a1348a2b64016d0f4ff613e683 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -291,7 +291,8 @@ static void isotp_rcv_skb(struct sk_buff *skb, struct sock *sk)
 	addr->can_family = AF_CAN;
 	addr->can_ifindex = skb->dev->ifindex;
 
-	if (sock_queue_rcv_skb_reason(sk, skb, &reason) < 0)
+	reason = sock_queue_rcv_skb_reason(sk, skb);
+	if (reason)
 		sk_skb_reason_drop(sk, skb, reason);
 }
 
diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
index 0502b030d23851652be252f1342861332ce97367..50a598ef5fd4a5f5e007816a341e04ddbcc724e6 100644
--- a/net/can/j1939/socket.c
+++ b/net/can/j1939/socket.c
@@ -333,7 +333,8 @@ static void j1939_sk_recv_one(struct j1939_sock *jsk, struct sk_buff *oskb)
 	if (skb->sk)
 		skcb->msg_flags |= MSG_DONTROUTE;
 
-	if (sock_queue_rcv_skb_reason(&jsk->sk, skb, &reason) < 0)
+	reason = sock_queue_rcv_skb_reason(&jsk->sk, skb);
+	if (reason)
 		sk_skb_reason_drop(&jsk->sk, skb, reason);
 }
 
diff --git a/net/can/raw.c b/net/can/raw.c
index eee244ffc31ecc0e1cc1aae29cd1d13a4e6b54ca..56c95c768778accaec42cb998c7d679a42c85894 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -207,7 +207,8 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
 	if (oskb->sk == sk)
 		*pflags |= MSG_CONFIRM;
 
-	if (sock_queue_rcv_skb_reason(sk, skb, &reason) < 0)
+	reason = sock_queue_rcv_skb_reason(sk, skb);
+	if (reason)
 		sk_skb_reason_drop(sk, skb, reason);
 }
 
diff --git a/net/core/sock.c b/net/core/sock.c
index e821b95e00151ab6b4be89209abcbaa494234433..d39a4d6ccafd9e03f4e82482d3f3e46ce5d58771 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -520,32 +520,24 @@ int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(__sock_queue_rcv_skb);
 
-int sock_queue_rcv_skb_reason(struct sock *sk, struct sk_buff *skb,
-			      enum skb_drop_reason *reason)
+enum skb_drop_reason
+sock_queue_rcv_skb_reason(struct sock *sk, struct sk_buff *skb)
 {
 	enum skb_drop_reason drop_reason;
 	int err;
 
 	err = sk_filter_reason(sk, skb, &drop_reason);
 	if (err)
-		goto out;
+		return drop_reason;
 
 	err = __sock_queue_rcv_skb(sk, skb);
 	switch (err) {
 	case -ENOMEM:
-		drop_reason = SKB_DROP_REASON_SOCKET_RCVBUFF;
-		break;
+		return SKB_DROP_REASON_SOCKET_RCVBUFF;
 	case -ENOBUFS:
-		drop_reason = SKB_DROP_REASON_PROTO_MEM;
-		break;
-	default:
-		drop_reason = SKB_NOT_DROPPED_YET;
-		break;
+		return SKB_DROP_REASON_PROTO_MEM;
 	}
-out:
-	if (reason)
-		*reason = drop_reason;
-	return err;
+	return SKB_NOT_DROPPED_YET;
 }
 EXPORT_SYMBOL(sock_queue_rcv_skb_reason);
 
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index bda245c808938cf2a26270bcd83c74898e5b36dd..1273d1028ed9ca91734481f65652bfc43efd039a 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -935,7 +935,8 @@ static enum skb_drop_reason __ping_queue_rcv_skb(struct sock *sk,
 
 	pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n",
 		 inet_sk(sk), inet_sk(sk)->inet_num, skb);
-	if (sock_queue_rcv_skb_reason(sk, skb, &reason) < 0) {
+	reason = sock_queue_rcv_skb_reason(sk, skb);
+	if (reason) {
 		sk_skb_reason_drop(sk, skb, reason);
 		pr_debug("ping_queue_rcv_skb -> failed\n");
 		return reason;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 34859e537b4926f15996dd1a684ae59a55a1643a..319428bf06bb89932c0b4295a0f96c275f8ecab1 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -300,7 +300,8 @@ static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	/* Charge it to the socket. */
 
 	ipv4_pktinfo_prepare(sk, skb, true);
-	if (sock_queue_rcv_skb_reason(sk, skb, &reason) < 0) {
+	reason = sock_queue_rcv_skb_reason(sk, skb);
+	if (reason) {
 		sk_skb_reason_drop(sk, skb, reason);
 		return NET_RX_DROP;
 	}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 0ac7046911000d30056e0d1f49a58964c61308cf..3cc58698cbbd3a16cf0145e0afff7a6cec8dc56f 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -369,7 +369,8 @@ static inline int rawv6_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
 	/* Charge it to the socket. */
 	skb_dst_drop(skb);
-	if (sock_queue_rcv_skb_reason(sk, skb, &reason) < 0) {
+	reason = sock_queue_rcv_skb_reason(sk, skb);
+	if (reason) {
 		sk_skb_reason_drop(sk, skb, reason);
 		return NET_RX_DROP;
 	}
-- 
2.53.0.1213.gd9a14994de-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next 2/5] net: always set reason in sk_filter_trim_cap()
  2026-04-09 14:56 [PATCH net-next 0/5] net: reduce sk_filter() (and friends) bloat Eric Dumazet
  2026-04-09 14:56 ` [PATCH net-next 1/5] net: change sock_queue_rcv_skb_reason() to return a drop_reason Eric Dumazet
@ 2026-04-09 14:56 ` Eric Dumazet
  2026-04-09 14:56 ` [PATCH net-next 3/5] net: change sk_filter_reason() to return the reason by value Eric Dumazet
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Dumazet @ 2026-04-09 14:56 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, netdev, eric.dumazet, Eric Dumazet

sk_filter_trim_cap() will soon return the drop reason by value.

Make sure *reason is cleared when no error is returned,
to ease this conversion.

$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-7 (-7)
Function                                     old     new   delta
sk_filter_trim_cap                           889     882      -7
Total: Before=29722668, After=29722661, chg -0.00%

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/core/filter.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index cf2113af4bc9ae7c976d7c55f3092643e1d875b6..5569d83b8be06dc1fe64ddff2ae338acd1622ed7 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -121,7 +121,7 @@ EXPORT_SYMBOL_GPL(copy_bpf_fprog_from_user);
  *	@sk: sock associated with &sk_buff
  *	@skb: buffer to filter
  *	@cap: limit on how short the eBPF program may trim the packet
- *	@reason: record drop reason on errors (negative return value)
+ *	@reason: record drop reason
  *
  * Run the eBPF program and then cut skb->data to correct size returned by
  * the program. If pkt_len is 0 we toss packet. If skb->len is smaller
@@ -168,11 +168,10 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb,
 		pkt_len = bpf_prog_run_save_cb(filter->prog, skb);
 		skb->sk = save_sk;
 		err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM;
-		if (err)
-			*reason = SKB_DROP_REASON_SOCKET_FILTER;
 	}
 	rcu_read_unlock();
 
+	*reason = err ? SKB_DROP_REASON_SOCKET_FILTER : 0;
 	return err;
 }
 EXPORT_SYMBOL(sk_filter_trim_cap);
-- 
2.53.0.1213.gd9a14994de-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next 3/5] net: change sk_filter_reason() to return the reason by value
  2026-04-09 14:56 [PATCH net-next 0/5] net: reduce sk_filter() (and friends) bloat Eric Dumazet
  2026-04-09 14:56 ` [PATCH net-next 1/5] net: change sock_queue_rcv_skb_reason() to return a drop_reason Eric Dumazet
  2026-04-09 14:56 ` [PATCH net-next 2/5] net: always set reason in sk_filter_trim_cap() Eric Dumazet
@ 2026-04-09 14:56 ` Eric Dumazet
  2026-04-09 14:56 ` [PATCH net-next 4/5] tcp: change tcp_filter() " Eric Dumazet
  2026-04-09 14:56 ` [PATCH net-next 5/5] net: change sk_filter_trim_cap() to return a drop_reason " Eric Dumazet
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Dumazet @ 2026-04-09 14:56 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, netdev, eric.dumazet, Eric Dumazet

sk_filter_trim_cap will soon return the reason by value,
do the same for sk_filter_reason().

$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-21 (-21)
Function                                     old     new   delta
sock_queue_rcv_skb_reason                    128     126      -2
tun_net_xmit                                1146    1127     -19
Total: Before=29722661, After=29722640, chg -0.00%

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 drivers/net/tun.c      | 8 +++++---
 include/linux/filter.h | 9 ++++++---
 net/core/sock.c        | 4 ++--
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index c492fda6fc15a79c13f56cb15dc273331b854422..b183189f185354051bded95f43bd77ee4f7cde24 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1031,9 +1031,11 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 		goto drop;
 	}
 
-	if (tfile->socket.sk->sk_filter &&
-	    sk_filter_reason(tfile->socket.sk, skb, &drop_reason))
-		goto drop;
+	if (tfile->socket.sk->sk_filter) {
+		drop_reason = sk_filter_reason(tfile->socket.sk, skb);
+		if (drop_reason)
+			goto drop;
+	}
 
 	len = run_ebpf_filter(tun, skb, len);
 	if (len == 0) {
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 44d7ae95ddbccd0ba72740b5547e91e1990686f2..59931e5810b4fcff5788616a3875767421dba3bc 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1102,10 +1102,13 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
 	return sk_filter_trim_cap(sk, skb, 1, &ignore_reason);
 }
 
-static inline int sk_filter_reason(struct sock *sk, struct sk_buff *skb,
-				   enum skb_drop_reason *reason)
+static inline enum skb_drop_reason
+sk_filter_reason(struct sock *sk, struct sk_buff *skb)
 {
-	return sk_filter_trim_cap(sk, skb, 1, reason);
+	enum skb_drop_reason drop_reason;
+
+	sk_filter_trim_cap(sk, skb, 1, &drop_reason);
+	return drop_reason;
 }
 
 struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err);
diff --git a/net/core/sock.c b/net/core/sock.c
index d39a4d6ccafd9e03f4e82482d3f3e46ce5d58771..1ffcb15d0fc5e39201aab24616d40a37aa41c823 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -526,8 +526,8 @@ sock_queue_rcv_skb_reason(struct sock *sk, struct sk_buff *skb)
 	enum skb_drop_reason drop_reason;
 	int err;
 
-	err = sk_filter_reason(sk, skb, &drop_reason);
-	if (err)
+	drop_reason = sk_filter_reason(sk, skb);
+	if (drop_reason)
 		return drop_reason;
 
 	err = __sock_queue_rcv_skb(sk, skb);
-- 
2.53.0.1213.gd9a14994de-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next 4/5] tcp: change tcp_filter() to return the reason by value
  2026-04-09 14:56 [PATCH net-next 0/5] net: reduce sk_filter() (and friends) bloat Eric Dumazet
                   ` (2 preceding siblings ...)
  2026-04-09 14:56 ` [PATCH net-next 3/5] net: change sk_filter_reason() to return the reason by value Eric Dumazet
@ 2026-04-09 14:56 ` Eric Dumazet
  2026-04-09 14:56 ` [PATCH net-next 5/5] net: change sk_filter_trim_cap() to return a drop_reason " Eric Dumazet
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Dumazet @ 2026-04-09 14:56 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, netdev, eric.dumazet, Eric Dumazet

sk_filter_trim_cap() will soon return the reason by value,
do the same for tcp_filter().

Note:

tcp_filter() is no longer inlined. Following patch will inline it again.

$ scripts/bloat-o-meter -t vmlinux.4 vmlinux.5
add/remove: 2/0 grow/shrink: 0/2 up/down: 186/-43 (143)
Function                                     old     new   delta
tcp_filter                                     -     154    +154
__pfx_tcp_filter                               -      32     +32
tcp_v4_rcv                                  3152    3143      -9
tcp_v6_rcv                                  3169    3135     -34
Total: Before=29722640, After=29722783, chg +0.00%

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/net/tcp.h   | 8 +++++---
 net/ipv4/tcp_ipv4.c | 6 ++++--
 net/ipv6/tcp_ipv6.c | 6 ++++--
 3 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 6156d1d068e142f696ec9dfff63e3aaebb0171bc..098e52269a04cb8938812a8f43caf11f9d5c68a3 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1683,12 +1683,14 @@ static inline bool tcp_checksum_complete(struct sk_buff *skb)
 bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb,
 		     enum skb_drop_reason *reason);
 
-static inline int tcp_filter(struct sock *sk, struct sk_buff *skb,
-			     enum skb_drop_reason *reason)
+static inline enum skb_drop_reason
+tcp_filter(struct sock *sk, struct sk_buff *skb)
 {
 	const struct tcphdr *th = (const struct tcphdr *)skb->data;
+	enum skb_drop_reason reason;
 
-	return sk_filter_trim_cap(sk, skb, __tcp_hdrlen(th), reason);
+	sk_filter_trim_cap(sk, skb, __tcp_hdrlen(th), &reason);
+	return reason;
 }
 
 void tcp_set_state(struct sock *sk, int state);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 69ab236072e7142d5ca9d0703d99f02c1e17c738..e2da3246a641e24328985cf558c322211df02b84 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2164,7 +2164,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
 		}
 		refcounted = true;
 		nsk = NULL;
-		if (!tcp_filter(sk, skb, &drop_reason)) {
+		drop_reason = tcp_filter(sk, skb);
+		if (!drop_reason) {
 			th = (const struct tcphdr *)skb->data;
 			iph = ip_hdr(skb);
 			tcp_v4_fill_cb(skb, iph, th);
@@ -2225,7 +2226,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
 
 	nf_reset_ct(skb);
 
-	if (tcp_filter(sk, skb, &drop_reason))
+	drop_reason = tcp_filter(sk, skb);
+	if (drop_reason)
 		goto discard_and_relse;
 
 	th = (const struct tcphdr *)skb->data;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 8dc3874e8b9252da60f21ad77a5ca834532e650a..d64d28e9842f7db69389034ac2ecdc76f405d379 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1794,7 +1794,8 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
 		}
 		refcounted = true;
 		nsk = NULL;
-		if (!tcp_filter(sk, skb, &drop_reason)) {
+		drop_reason = tcp_filter(sk, skb);
+		if (!drop_reason) {
 			th = (const struct tcphdr *)skb->data;
 			hdr = ipv6_hdr(skb);
 			tcp_v6_fill_cb(skb, hdr, th);
@@ -1855,7 +1856,8 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
 
 	nf_reset_ct(skb);
 
-	if (tcp_filter(sk, skb, &drop_reason))
+	drop_reason = tcp_filter(sk, skb);
+	if (drop_reason)
 		goto discard_and_relse;
 
 	th = (const struct tcphdr *)skb->data;
-- 
2.53.0.1213.gd9a14994de-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net-next 5/5] net: change sk_filter_trim_cap() to return a drop_reason by value
  2026-04-09 14:56 [PATCH net-next 0/5] net: reduce sk_filter() (and friends) bloat Eric Dumazet
                   ` (3 preceding siblings ...)
  2026-04-09 14:56 ` [PATCH net-next 4/5] tcp: change tcp_filter() " Eric Dumazet
@ 2026-04-09 14:56 ` Eric Dumazet
  4 siblings, 0 replies; 6+ messages in thread
From: Eric Dumazet @ 2026-04-09 14:56 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, netdev, eric.dumazet, Eric Dumazet

Current return value can be replaced with the drop_reason,
reducing kernel bloat:

$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
add/remove: 0/2 grow/shrink: 1/11 up/down: 32/-603 (-571)
Function                                     old     new   delta
tcp_v6_rcv                                  3135    3167     +32
unix_dgram_sendmsg                          1731    1726      -5
netlink_unicast                              957     945     -12
netlink_dump                                1372    1359     -13
sk_filter_trim_cap                           882     858     -24
tcp_v4_rcv                                  3143    3111     -32
__pfx_tcp_filter                              32       -     -32
netlink_broadcast_filtered                  1633    1595     -38
sock_queue_rcv_skb_reason                    126      76     -50
tun_net_xmit                                1127    1074     -53
__sk_receive_skb                             690     632     -58
udpv6_queue_rcv_one_skb                      935     869     -66
udp_queue_rcv_one_skb                        919     853     -66
tcp_filter                                   154       -    -154
Total: Before=29722783, After=29722212, chg -0.00%

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/linux/filter.h | 14 ++++++--------
 include/net/tcp.h      |  4 +---
 net/core/filter.c      | 31 ++++++++++++++-----------------
 net/core/sock.c        |  5 +++--
 net/ipv4/udp.c         |  3 ++-
 net/ipv6/udp.c         |  3 ++-
 net/rose/rose_in.c     |  3 +--
 7 files changed, 29 insertions(+), 34 deletions(-)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index 59931e5810b4fcff5788616a3875767421dba3bc..5ac08aa70123cf97ab91dea7e11e47b210a42d4a 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1092,23 +1092,21 @@ bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr)
 	return set_memory_rox((unsigned long)hdr, hdr->size >> PAGE_SHIFT);
 }
 
-int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap,
-		       enum skb_drop_reason *reason);
+enum skb_drop_reason
+sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap);
 
 static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
 {
-	enum skb_drop_reason ignore_reason;
+	enum skb_drop_reason drop_reason;
 
-	return sk_filter_trim_cap(sk, skb, 1, &ignore_reason);
+	drop_reason = sk_filter_trim_cap(sk, skb, 1);
+	return drop_reason ? -EPERM : 0;
 }
 
 static inline enum skb_drop_reason
 sk_filter_reason(struct sock *sk, struct sk_buff *skb)
 {
-	enum skb_drop_reason drop_reason;
-
-	sk_filter_trim_cap(sk, skb, 1, &drop_reason);
-	return drop_reason;
+	return sk_filter_trim_cap(sk, skb, 1);
 }
 
 struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 098e52269a04cb8938812a8f43caf11f9d5c68a3..49f45bcff917942e993c627dd3d0017369186f67 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1687,10 +1687,8 @@ static inline enum skb_drop_reason
 tcp_filter(struct sock *sk, struct sk_buff *skb)
 {
 	const struct tcphdr *th = (const struct tcphdr *)skb->data;
-	enum skb_drop_reason reason;
 
-	sk_filter_trim_cap(sk, skb, __tcp_hdrlen(th), &reason);
-	return reason;
+	return sk_filter_trim_cap(sk, skb, __tcp_hdrlen(th));
 }
 
 void tcp_set_state(struct sock *sk, int state);
diff --git a/net/core/filter.c b/net/core/filter.c
index 5569d83b8be06dc1fe64ddff2ae338acd1622ed7..bf9c37b27646943e3a6fdad2fadf00f5e1ea8244 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -121,20 +121,20 @@ EXPORT_SYMBOL_GPL(copy_bpf_fprog_from_user);
  *	@sk: sock associated with &sk_buff
  *	@skb: buffer to filter
  *	@cap: limit on how short the eBPF program may trim the packet
- *	@reason: record drop reason
  *
  * Run the eBPF program and then cut skb->data to correct size returned by
  * the program. If pkt_len is 0 we toss packet. If skb->len is smaller
  * than pkt_len we keep whole skb->data. This is the socket level
  * wrapper to bpf_prog_run. It returns 0 if the packet should
- * be accepted or -EPERM if the packet should be tossed.
+ * be accepted or a drop_reason if the packet should be tossed.
  *
  */
-int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb,
-		       unsigned int cap, enum skb_drop_reason *reason)
+enum skb_drop_reason
+sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap)
 {
-	int err;
+	enum skb_drop_reason drop_reason;
 	struct sk_filter *filter;
+	int err;
 
 	/*
 	 * If the skb was allocated from pfmemalloc reserves, only
@@ -143,21 +143,17 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb,
 	 */
 	if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC)) {
 		NET_INC_STATS(sock_net(sk), LINUX_MIB_PFMEMALLOCDROP);
-		*reason = SKB_DROP_REASON_PFMEMALLOC;
-		return -ENOMEM;
+		return SKB_DROP_REASON_PFMEMALLOC;
 	}
 	err = BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb);
-	if (err) {
-		*reason = SKB_DROP_REASON_SOCKET_FILTER;
-		return err;
-	}
+	if (err)
+		return SKB_DROP_REASON_SOCKET_FILTER;
 
 	err = security_sock_rcv_skb(sk, skb);
-	if (err) {
-		*reason = SKB_DROP_REASON_SECURITY_HOOK;
-		return err;
-	}
+	if (err)
+		return SKB_DROP_REASON_SECURITY_HOOK;
 
+	drop_reason = 0;
 	rcu_read_lock();
 	filter = rcu_dereference(sk->sk_filter);
 	if (filter) {
@@ -168,11 +164,12 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb,
 		pkt_len = bpf_prog_run_save_cb(filter->prog, skb);
 		skb->sk = save_sk;
 		err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM;
+		if (err)
+			drop_reason = SKB_DROP_REASON_SOCKET_FILTER;
 	}
 	rcu_read_unlock();
 
-	*reason = err ? SKB_DROP_REASON_SOCKET_FILTER : 0;
-	return err;
+	return drop_reason;
 }
 EXPORT_SYMBOL(sk_filter_trim_cap);
 
diff --git a/net/core/sock.c b/net/core/sock.c
index 1ffcb15d0fc5e39201aab24616d40a37aa41c823..367fd7bad4ac2e6557dc73519ac0c04debb43cb3 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -544,11 +544,12 @@ EXPORT_SYMBOL(sock_queue_rcv_skb_reason);
 int __sk_receive_skb(struct sock *sk, struct sk_buff *skb,
 		     const int nested, unsigned int trim_cap, bool refcounted)
 {
-	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
+	enum skb_drop_reason reason;
 	int rc = NET_RX_SUCCESS;
 	int err;
 
-	if (sk_filter_trim_cap(sk, skb, trim_cap, &reason))
+	reason = sk_filter_trim_cap(sk, skb, trim_cap);
+	if (reason)
 		goto discard_and_relse;
 
 	skb->dev = NULL;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index ab415de32443c5d32eedca5f093d5d96681f6b48..2fddc7b6b7172045286a8a0902f8bcf41aaca7c4 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2392,7 +2392,8 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
 	    udp_lib_checksum_complete(skb))
 			goto csum_error;
 
-	if (sk_filter_trim_cap(sk, skb, sizeof(struct udphdr), &drop_reason))
+	drop_reason = sk_filter_trim_cap(sk, skb, sizeof(struct udphdr));
+	if (drop_reason)
 		goto drop;
 
 	udp_csum_pull_header(skb);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index d7cf4c9508b2c5c92753eddf8de1717f52347fbf..3fac9cb47ae00fe26c60ba2aee61748b4a241221 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -853,7 +853,8 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
 	    udp_lib_checksum_complete(skb))
 		goto csum_error;
 
-	if (sk_filter_trim_cap(sk, skb, sizeof(struct udphdr), &drop_reason))
+	drop_reason = sk_filter_trim_cap(sk, skb, sizeof(struct udphdr));
+	if (drop_reason)
 		goto drop;
 
 	udp_csum_pull_header(skb);
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index 0276b393f0e530ea2d8f689a3dd95364849910ac..3aff3c2d45a956a5c791beb5c2d5c4e4d7063d6a 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -101,7 +101,6 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety
  */
 static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m)
 {
-	enum skb_drop_reason dr; /* ignored */
 	struct rose_sock *rose = rose_sk(sk);
 	int queued = 0;
 
@@ -163,7 +162,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety
 		rose_frames_acked(sk, nr);
 		if (ns == rose->vr) {
 			rose_start_idletimer(sk);
-			if (!sk_filter_trim_cap(sk, skb, ROSE_MIN_LEN, &dr) &&
+			if (!sk_filter_trim_cap(sk, skb, ROSE_MIN_LEN) &&
 			    __sock_queue_rcv_skb(sk, skb) == 0) {
 				rose->vr = (rose->vr + 1) % ROSE_MODULUS;
 				queued = 1;
-- 
2.53.0.1213.gd9a14994de-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-04-09 14:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-09 14:56 [PATCH net-next 0/5] net: reduce sk_filter() (and friends) bloat Eric Dumazet
2026-04-09 14:56 ` [PATCH net-next 1/5] net: change sock_queue_rcv_skb_reason() to return a drop_reason Eric Dumazet
2026-04-09 14:56 ` [PATCH net-next 2/5] net: always set reason in sk_filter_trim_cap() Eric Dumazet
2026-04-09 14:56 ` [PATCH net-next 3/5] net: change sk_filter_reason() to return the reason by value Eric Dumazet
2026-04-09 14:56 ` [PATCH net-next 4/5] tcp: change tcp_filter() " Eric Dumazet
2026-04-09 14:56 ` [PATCH net-next 5/5] net: change sk_filter_trim_cap() to return a drop_reason " Eric Dumazet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox