From 54b541e049170000665e7f95841c104f3fe170e5 Mon Sep 17 00:00:00 2001 From: yinbin8 <862511068@qq.com> Date: Mon, 16 Jun 2025 17:15:35 +0800 Subject: [PATCH] bypass nf_conntrack --- include/linux/netfilter.h | 21 ++++++++++++++++++++- kernel/sysctl.c | 10 ++++++++++ net/core/ethtool.c | 26 ++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index f5763c225dee..38cd6b8821d9 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -15,6 +15,10 @@ #include #include +extern struct static_key_false bypass_nf_conntrack_active; +int bypass_nf_conntrack_handler(struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos); + #ifdef CONFIG_NETFILTER static inline int NF_DROP_GETERR(int verdict) { @@ -200,6 +204,9 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net, struct nf_hook_entries *hook_head = NULL; int ret = 1; + if (static_branch_likely(&bypass_nf_conntrack_active)) + return 1; + #ifdef CONFIG_JUMP_LABEL if (__builtin_constant_p(pf) && __builtin_constant_p(hook) && @@ -270,6 +277,11 @@ NF_HOOK_COND(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, { int ret; + if (static_branch_likely(&bypass_nf_conntrack_active)) { + ret = okfn(net, sk, skb); + return ret; + } + if (!cond || ((ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn)) == 1)) ret = okfn(net, sk, skb); @@ -281,7 +293,12 @@ NF_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, struct struct net_device *in, struct net_device *out, int (*okfn)(struct net *, struct sock *, struct sk_buff *)) { - int ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn); + int ret; + + if (static_branch_likely(&bypass_nf_conntrack_active)) + return okfn(net, sk, skb); + + ret = nf_hook(pf, hook, net, sk, skb, in, out, okfn); if (ret == 1) ret = okfn(net, sk, skb); return ret; @@ -294,6 +311,8 @@ NF_HOOK_LIST(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, { struct nf_hook_entries *hook_head = NULL; + if (static_branch_likely(&bypass_nf_conntrack_active)) + return; #ifdef CONFIG_JUMP_LABEL if (__builtin_constant_p(pf) && __builtin_constant_p(hook) && diff --git a/kernel/sysctl.c b/kernel/sysctl.c index f64c4495bc54..e31f4e7dd597 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -1353,6 +1354,15 @@ static struct ctl_table kern_table[] = { .extra2 = &hundred_thousand, }, #endif + { + .procname = "nf_contract_ctrl", + .data = NULL, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = bypass_nf_conntrack_handler, + .extra1 = &zero, + .extra2 = &one, + }, { } }; diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 4db9512feba8..effb50bb96a8 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -28,6 +28,32 @@ #include #include +DEFINE_STATIC_KEY_FALSE(bypass_nf_conntrack_active); +EXPORT_SYMBOL(bypass_nf_conntrack_active); + +int bypass_nf_conntrack_handler(struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos) +{ + int state = !!static_branch_unlikely(&bypass_nf_conntrack_active); + int prev_state = state; + int ret = 0; + + table->data = &state; + table->maxlen = sizeof(int); + ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + state = !state; + if (ret || !write || state == prev_state) + return ret; + + if (state) + static_branch_enable(&bypass_nf_conntrack_active); + else + static_branch_disable(&bypass_nf_conntrack_active); + + pr_info("bypass nf_conntrack is %s\n", state ? "enable" : "disable"); + return ret; +} + /* * Some useful ethtool_ops methods that're device independent. * If we find that all drivers want to do the same thing here, -- Gitee