From: Eric Dumazet Date: Wed, 11 Mar 2026 19:13:40 +0000 (+0000) Subject: net: add skb_defer_disable_key static key X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=08dc30de1a402fe88fd80592cf6c72c4c2ebbcbc;p=thirdparty%2Flinux.git net: add skb_defer_disable_key static key Add a static key to bypass skb_attempt_defer_free() steps if net.core.skb_defer_max is set to zero. Main benefit is the atomic_long_inc_return() avoidance. Signed-off-by: Eric Dumazet Link: https://patch.msgid.link/20260311191340.1996888-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h index e938f25e8e86f..38e2e3ffd0bdc 100644 --- a/net/core/net-sysfs.h +++ b/net/core/net-sysfs.h @@ -13,4 +13,5 @@ int netdev_change_owner(struct net_device *, const struct net *net_old, extern struct mutex rps_default_mask_mutex; +DECLARE_STATIC_KEY_FALSE(skb_defer_disable_key); #endif diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 513cbfed19bc3..3d6978dd0aa83 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -7256,6 +7256,8 @@ static void kfree_skb_napi_cache(struct sk_buff *skb) local_bh_enable(); } +DEFINE_STATIC_KEY_FALSE(skb_defer_disable_key); + /** * skb_attempt_defer_free - queue skb for remote freeing * @skb: buffer @@ -7272,6 +7274,9 @@ void skb_attempt_defer_free(struct sk_buff *skb) bool kick; int cpu; + if (static_branch_unlikely(&skb_defer_disable_key)) + goto nodefer; + /* zero copy notifications should not be delayed. */ if (skb_zcopy(skb)) goto nodefer; diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 502705e046498..b508618bfc123 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -349,6 +349,29 @@ static int proc_do_rss_key(const struct ctl_table *table, int write, return proc_dostring(&fake_table, write, buffer, lenp, ppos); } +static int proc_do_skb_defer_max(const struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos) +{ + static DEFINE_MUTEX(skb_defer_max_mutex); + int ret, oval, nval; + + mutex_lock(&skb_defer_max_mutex); + + oval = !net_hotdata.sysctl_skb_defer_max; + ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + nval = !net_hotdata.sysctl_skb_defer_max; + + if (nval != oval) { + if (nval) + static_branch_enable(&skb_defer_disable_key); + else + static_branch_disable(&skb_defer_disable_key); + } + + mutex_unlock(&skb_defer_max_mutex); + return ret; +} + #ifdef CONFIG_BPF_JIT static int proc_dointvec_minmax_bpf_enable(const struct ctl_table *table, int write, void *buffer, size_t *lenp, @@ -650,7 +673,7 @@ static struct ctl_table net_core_table[] = { .data = &net_hotdata.sysctl_skb_defer_max, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = proc_do_skb_defer_max, .extra1 = SYSCTL_ZERO, }, };