
Wang Liang (4): net/oenetcls: Fix oecls_numa_info_table memleak net/oenetcls: use raw_smp_processor_id() instead of smp_processor_id() net/oenetcls: remove oenetcls trace hook net/oenetcls: use workqueue for ntuple cfg arch/arm64/configs/openeuler_defconfig | 1 - arch/x86/configs/openeuler_defconfig | 2 +- drivers/hooks/Kconfig | 10 -- drivers/hooks/vendor_hooks.c | 7 - include/linux/oenetcls.h | 81 +++++++++++ include/trace/hooks/oenetcls.h | 44 ------ net/core/dev.c | 23 ++-- net/ipv4/af_inet.c | 9 +- net/ipv4/tcp.c | 13 +- net/oenetcls/Kconfig | 2 +- net/oenetcls/oenetcls.h | 14 +- net/oenetcls/oenetcls_flow.c | 49 ++++--- net/oenetcls/oenetcls_main.c | 29 ++-- net/oenetcls/oenetcls_ntuple.c | 181 ++++++++++++++++--------- 14 files changed, 289 insertions(+), 176 deletions(-) create mode 100644 include/linux/oenetcls.h delete mode 100644 include/trace/hooks/oenetcls.h -- 2.34.1

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/18052 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/CMP... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/18052 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/CMP...

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ICBFCS -------------------------------- Free oecls_numa_info_table memory when remove module. Fixes: d7d9edb24c1c ("net/oenetcls: Support cluster sched") Signed-off-by: Wang Liang <wangliang74@huawei.com> --- net/oenetcls/oenetcls_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/oenetcls/oenetcls_main.c b/net/oenetcls/oenetcls_main.c index 8e90552112b9..0117d181f379 100644 --- a/net/oenetcls/oenetcls_main.c +++ b/net/oenetcls/oenetcls_main.c @@ -591,6 +591,7 @@ struct oecls_numa_info *get_oecls_numa_info(unsigned int nid) static void clean_oecls_numa_info(void) { oecls_numa_num = 0; + free_to_l0(oecls_numa_info_table); } static void init_numa_avail_cpus(int nid, struct oecls_numa_info *numa_info) -- 2.34.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ICBFCS -------------------------------- Function smp_processor_id() should not be used in preemptible code. Fixes: d60758b0ffcd ("net/oenetcls: introduce oenetcls for network optimization") Signed-off-by: Wang Liang <wangliang74@huawei.com> --- net/oenetcls/oenetcls_main.c | 4 ++-- net/oenetcls/oenetcls_ntuple.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/oenetcls/oenetcls_main.c b/net/oenetcls/oenetcls_main.c index 0117d181f379..88ddaec1a363 100644 --- a/net/oenetcls/oenetcls_main.c +++ b/net/oenetcls/oenetcls_main.c @@ -671,7 +671,7 @@ static int init_numa_rxq_bitmap(int nid, struct oecls_numa_info *numa_info) static int get_cluster_rxq(struct oecls_numa_bound_dev_info *bound_dev) { - int cpu = smp_processor_id(); + int cpu = raw_smp_processor_id(); int cluster_id = cpu / oecls_cluster_cpu_num; int i, j, rxq_id; @@ -795,7 +795,7 @@ static int init_oecls_numa_info(void) return ret; } - oecls_cluster_cpu_num = cpumask_weight(topology_cluster_cpumask(smp_processor_id())); + oecls_cluster_cpu_num = cpumask_weight(topology_cluster_cpumask(raw_smp_processor_id())); oecls_cluster_per_numa = (nr_cpu_ids / oecls_cluster_cpu_num) / oecls_numa_num; oecls_debug("oecls_numa_num=%d cluster_cpu_num:%d cluster_cpu_num:%d\n", oecls_numa_num, oecls_cluster_per_numa, oecls_cluster_cpu_num); diff --git a/net/oenetcls/oenetcls_ntuple.c b/net/oenetcls/oenetcls_ntuple.c index 0ac69eb08f24..79358eb589bb 100644 --- a/net/oenetcls/oenetcls_ntuple.c +++ b/net/oenetcls/oenetcls_ntuple.c @@ -464,7 +464,7 @@ static void add_ntuple_rule(struct sock *sk) { struct oecls_netdev_info *oecls_dev; struct cmd_context ctx = { 0 }; - int cpu = smp_processor_id(); + int cpu = raw_smp_processor_id(); int nid = cpu_to_node(cpu); int rxq_id; int devid; @@ -510,7 +510,7 @@ static void ethtool_cfg_rxcls(void *data, struct sock *sk, int is_del) if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6) return; - oecls_debug("[cpu:%d] app:%s, sk:%p, is_del:%d, ip:%pI4, port:%d\n", smp_processor_id(), + oecls_debug("[cpu:%d] app:%s, sk:%p, is_del:%d, ip:%pI4, port:%d\n", raw_smp_processor_id(), current->comm, sk, is_del, &sk->sk_rcv_saddr, (u16)sk->sk_num); if (is_del) -- 2.34.1

hulk inclusion category: cleanup bugzilla: https://gitee.com/openeuler/kernel/issues/ICBFCS -------------------------------- Use oecls_hook_ops instead of trace hook. Signed-off-by: Wang Liang <wangliang74@huawei.com> --- arch/arm64/configs/openeuler_defconfig | 1 - arch/x86/configs/openeuler_defconfig | 2 +- drivers/hooks/Kconfig | 10 ---- drivers/hooks/vendor_hooks.c | 7 --- include/linux/oenetcls.h | 81 ++++++++++++++++++++++++++ include/trace/hooks/oenetcls.h | 44 -------------- net/core/dev.c | 23 ++++---- net/ipv4/af_inet.c | 9 ++- net/ipv4/tcp.c | 13 +++-- net/oenetcls/Kconfig | 2 +- net/oenetcls/oenetcls_flow.c | 27 +++++---- net/oenetcls/oenetcls_ntuple.c | 15 +++-- 12 files changed, 136 insertions(+), 98 deletions(-) create mode 100644 include/linux/oenetcls.h delete mode 100644 include/trace/hooks/oenetcls.h diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 9d58c2d8eb5e..f9d2080e7399 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -6273,7 +6273,6 @@ CONFIG_USB4=m # CONFIG_VENDOR_HOOKS=y CONFIG_VENDOR_BOND_HOOKS=y -CONFIG_OENETCLS_HOOKS=y CONFIG_OENETCLS=m # end of Vendor Hooks diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index f76767da2c93..d6730b618101 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -1161,6 +1161,7 @@ CONFIG_SMC_LO=y CONFIG_XDP_SOCKETS=y # CONFIG_XDP_SOCKETS_DIAG is not set # CONFIG_XSK_MULTI_BUF is not set +# CONFIG_OENETCLS is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y @@ -7327,7 +7328,6 @@ CONFIG_USB4=m # CONFIG_VENDOR_HOOKS=y CONFIG_VENDOR_BOND_HOOKS=y -# CONFIG_OENETCLS_HOOKS is not set # end of Vendor Hooks CONFIG_LIBNVDIMM=m diff --git a/drivers/hooks/Kconfig b/drivers/hooks/Kconfig index 90b0f6ea4040..6a00168e67ad 100644 --- a/drivers/hooks/Kconfig +++ b/drivers/hooks/Kconfig @@ -20,14 +20,4 @@ config VENDOR_BOND_HOOKS Allow vendor modules to attach bonding driver hooks defined via DECLARE_HOOK or DECLARE_RESTRICTED_HOOK. -config OENETCLS_HOOKS - bool "Oenetcls driver Hooks" - depends on VENDOR_HOOKS - default n - help - Enable oenetcls vendor hooks - Allow vendor modules to attach oenetcls hooks defined via - DECLARE_HOOK or DECLARE_RESTRICTED_HOOK. - Use OENETCLS && OENETCLS_HOOKS to enable oenetcls feature. - endmenu diff --git a/drivers/hooks/vendor_hooks.c b/drivers/hooks/vendor_hooks.c index d9b85b57a742..e71f4e6f7d58 100644 --- a/drivers/hooks/vendor_hooks.c +++ b/drivers/hooks/vendor_hooks.c @@ -9,7 +9,6 @@ #define CREATE_TRACE_POINTS #include <trace/hooks/vendor_hooks.h> #include <trace/hooks/bonding.h> -#include <trace/hooks/oenetcls.h> /* * Export tracepoints that act as a bare tracehook (ie: have no trace event @@ -20,9 +19,3 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(vendor_bond_check_dev_link); #endif -#ifdef CONFIG_OENETCLS_HOOKS -EXPORT_TRACEPOINT_SYMBOL_GPL(oecls_flow_update); -EXPORT_TRACEPOINT_SYMBOL_GPL(oecls_set_cpu); -EXPORT_TRACEPOINT_SYMBOL_GPL(oecls_timeout); -EXPORT_TRACEPOINT_SYMBOL_GPL(ethtool_cfg_rxcls); -#endif diff --git a/include/linux/oenetcls.h b/include/linux/oenetcls.h new file mode 100644 index 000000000000..29c0db40971f --- /dev/null +++ b/include/linux/oenetcls.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _LINUX_OENETCLS_H +#define _LINUX_OENETCLS_H + +struct oecls_hook_ops { + void (*oecls_cfg_rxcls)(struct sock *sk, int is_del); + void (*oecls_flow_update)(struct sock *sk); + void (*oecls_set_cpu)(struct sk_buff *skb); + bool (*oecls_timeout)(struct net_device *dev, u16 rxq_index, + u32 flow_id, u16 filter_id); +}; + +extern const struct oecls_hook_ops __rcu *oecls_ops; + +static inline void oenetcls_cfg_rxcls(struct sock *sk, int is_del) +{ + const struct oecls_hook_ops *ops; + + rcu_read_lock(); + ops = rcu_dereference(oecls_ops); + if (ops && ops->oecls_cfg_rxcls) + ops->oecls_cfg_rxcls(sk, is_del); + rcu_read_unlock(); +} + +static inline void oenetcls_flow_update(struct sock *sk) +{ + const struct oecls_hook_ops *ops; + + rcu_read_lock(); + ops = rcu_dereference(oecls_ops); + if (ops && ops->oecls_flow_update) + ops->oecls_flow_update(sk); + rcu_read_unlock(); +} + +static inline void oenetcls_skb_set_cpu(struct sk_buff *skb) +{ + const struct oecls_hook_ops *ops; + + rcu_read_lock(); + ops = rcu_dereference(oecls_ops); + if (ops && ops->oecls_set_cpu) + ops->oecls_set_cpu(skb); + rcu_read_unlock(); +} + +static inline void oenetcls_skblist_set_cpu(struct list_head *head) +{ + const struct oecls_hook_ops *ops; + struct sk_buff *skb, *next; + + rcu_read_lock(); + ops = rcu_dereference(oecls_ops); + if (ops && ops->oecls_set_cpu) { + list_for_each_entry_safe(skb, next, head, list) + ops->oecls_set_cpu(skb); + } + rcu_read_unlock(); +} + +static inline bool oenetcls_may_expire_flow(struct net_device *dev, + u16 rxq_index, u32 flow_id, + u16 filter_id, bool *expire) +{ + const struct oecls_hook_ops *ops; + + rcu_read_lock(); + ops = rcu_dereference(oecls_ops); + if (ops && ops->oecls_timeout) { + *expire = ops->oecls_timeout(dev, rxq_index, flow_id, filter_id); + rcu_read_unlock(); + return true; + } + rcu_read_unlock(); + + return false; +} + +#endif /* _LINUX_OENETCLS_H */ + diff --git a/include/trace/hooks/oenetcls.h b/include/trace/hooks/oenetcls.h deleted file mode 100644 index c38545d7a6a2..000000000000 --- a/include/trace/hooks/oenetcls.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * oenetcls driver Hooks - * - * Copyright (c) 2025, Huawei Tech. Co., Ltd. - */ - -#ifdef CONFIG_OENETCLS_HOOKS - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM oenetcls - -#define TRACE_INCLUDE_PATH trace/hooks -#if !defined(_TRACE_OENETCLS_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_OENETCLS_H -#include <linux/tracepoint.h> -#include <trace/hooks/vendor_hooks.h> - -struct sock; -struct sk_buff; -struct net_device; - -DECLARE_HOOK(oecls_flow_update, -TP_PROTO(struct sock *sk), -TP_ARGS(sk)); - -DECLARE_HOOK(oecls_set_cpu, -TP_PROTO(struct sk_buff *skb), -TP_ARGS(skb)); - -DECLARE_HOOK(oecls_timeout, -TP_PROTO(struct net_device *dev, u16 rxq_index, u32 flow_id, u16 filter_id, bool *ret), -TP_ARGS(dev, rxq_index, flow_id, filter_id, ret)); - -DECLARE_HOOK(ethtool_cfg_rxcls, -TP_PROTO(struct sock *sk, int is_del), -TP_ARGS(sk, is_del)); - -#endif -/* This part must be outside protection */ -#include <trace/define_trace.h> - -#endif - diff --git a/net/core/dev.c b/net/core/dev.c index b8a0887c32c8..05477c431afd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -149,7 +149,12 @@ #include <net/net_rship.h> #include "net-sysfs.h" -#include <trace/hooks/oenetcls.h> + +#if IS_ENABLED(CONFIG_OENETCLS) +#include <linux/oenetcls.h> +const struct oecls_hook_ops __rcu *oecls_ops __read_mostly; +EXPORT_SYMBOL_GPL(oecls_ops); +#endif #define MAX_GRO_SKBS 8 @@ -4485,10 +4490,9 @@ bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, bool expire = true; unsigned int cpu; -#if IS_ENABLED(CONFIG_OENETCLS_HOOKS) - trace_oecls_timeout(dev, rxq_index, flow_id, filter_id, &expire); - if (expire) - return true; +#if IS_ENABLED(CONFIG_OENETCLS) + if (oenetcls_may_expire_flow(dev, rxq_index, flow_id, filter_id, &expire)) + return expire; #endif rcu_read_lock(); flow_table = rcu_dereference(rxqueue->rps_flow_table); @@ -5897,8 +5901,8 @@ static int netif_receive_skb_internal(struct sk_buff *skb) } #endif -#if IS_ENABLED(CONFIG_OENETCLS_HOOKS) - trace_oecls_set_cpu(skb); +#if IS_ENABLED(CONFIG_OENETCLS) + oenetcls_skb_set_cpu(skb); #endif ret = __netif_receive_skb(skb); @@ -5936,9 +5940,8 @@ static void netif_receive_skb_list_internal(struct list_head *head) } #endif -#if IS_ENABLED(CONFIG_OENETCLS_HOOKS) - list_for_each_entry_safe(skb, next, head, list) - trace_oecls_set_cpu(skb); +#if IS_ENABLED(CONFIG_OENETCLS) + oenetcls_skblist_set_cpu(head); #endif __netif_receive_skb_list(head); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index b09b1d6575a4..7b3d011755af 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -119,7 +119,10 @@ #include <net/compat.h> #include <trace/events/sock.h> -#include <trace/hooks/oenetcls.h> + +#if IS_ENABLED(CONFIG_OENETCLS) +#include <linux/oenetcls.h> +#endif /* The inetsw table contains everything that inet_create needs to * build a new socket. @@ -234,8 +237,8 @@ int inet_listen(struct socket *sock, int backlog) goto out; tcp_call_bpf(sk, BPF_SOCK_OPS_TCP_LISTEN_CB, 0, NULL); -#if IS_ENABLED(CONFIG_OENETCLS_HOOKS) - trace_ethtool_cfg_rxcls(sk, 0); +#if IS_ENABLED(CONFIG_OENETCLS) + oenetcls_cfg_rxcls(sk, 0); #endif } err = 0; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f014fad55bbf..e0248166a8c2 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -280,7 +280,10 @@ #include <asm/ioctls.h> #include <net/busy_poll.h> #include <net/net_rship.h> -#include <trace/hooks/oenetcls.h> + +#if IS_ENABLED(CONFIG_OENETCLS) +#include <linux/oenetcls.h> +#endif DEFINE_PER_CPU(unsigned int, tcp_orphan_count); EXPORT_PER_CPU_SYMBOL_GPL(tcp_orphan_count); @@ -2177,8 +2180,8 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, if (unlikely(flags & MSG_ERRQUEUE)) return inet_recv_error(sk, msg, len, addr_len); -#if IS_ENABLED(CONFIG_OENETCLS_HOOKS) - trace_oecls_flow_update(sk); +#if IS_ENABLED(CONFIG_OENETCLS) + oenetcls_flow_update(sk); #endif if (sk_can_busy_loop(sk) && skb_queue_empty_lockless(&sk->sk_receive_queue) && @@ -2756,8 +2759,8 @@ void tcp_close(struct sock *sk, long timeout) { lock_sock(sk); -#if IS_ENABLED(CONFIG_OENETCLS_HOOKS) - trace_ethtool_cfg_rxcls(sk, 1); +#if IS_ENABLED(CONFIG_OENETCLS) + oenetcls_cfg_rxcls(sk, 1); #endif __tcp_close(sk, timeout); diff --git a/net/oenetcls/Kconfig b/net/oenetcls/Kconfig index 128b798d6b7f..9057782d8cab 100644 --- a/net/oenetcls/Kconfig +++ b/net/oenetcls/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config OENETCLS tristate "Network classification" - depends on HISI_L0 && OENETCLS_HOOKS + depends on HISI_L0 default n help Allows to configure ntuple rule, and bind interrupt to netdev diff --git a/net/oenetcls/oenetcls_flow.c b/net/oenetcls/oenetcls_flow.c index c35ce5aca416..37daee93b205 100644 --- a/net/oenetcls/oenetcls_flow.c +++ b/net/oenetcls/oenetcls_flow.c @@ -6,7 +6,7 @@ #include <linux/irqdesc.h> #include <linux/inet.h> #include <net/sock.h> -#include <trace/hooks/oenetcls.h> +#include <linux/oenetcls.h> #include "oenetcls.h" static u32 oecls_cpu_mask; @@ -26,8 +26,8 @@ bool is_oecls_config_netdev(const char *name) return false; } -static void oecls_timeout(void *data, struct net_device *dev, u16 rxq_index, - u32 flow_id, u16 filter_id, bool *ret) +static bool _oecls_timeout(struct net_device *dev, u16 rxq_index, + u32 flow_id, u16 filter_id) { struct netdev_rx_queue *rxqueue = dev->_rx + rxq_index; struct oecls_dev_flow_table *flow_table; @@ -55,10 +55,10 @@ static void oecls_timeout(void *data, struct net_device *dev, u16 rxq_index, rcu_read_unlock(); oecls_debug("%s, dev:%s, rxq:%d, flow_id:%u, filter_id:%d, expire:%d\n", __func__, dev->name, rxq_index, flow_id, filter_id, expire); - *ret = expire; + return expire; } -static void oecls_flow_update(void *data, struct sock *sk) +static void _oecls_flow_update(struct sock *sk) { struct oecls_sock_flow_table *tb; unsigned int hash, index; @@ -200,7 +200,7 @@ static void __oecls_set_cpu(struct sk_buff *skb, struct net_device *ndev, set_oecls_cpu(ndev, skb, rflow, old_rxq_id, last_recv_cpu); } -static void oecls_set_cpu(void *data, struct sk_buff *skb) +static void _oecls_set_cpu(struct sk_buff *skb) { struct net_device *ndev = skb->dev; struct oecls_sock_flow_table *stb; @@ -355,9 +355,6 @@ static int oecls_sock_flow_table_release(void) synchronize_rcu(); vfree(tb); - unregister_trace_oecls_flow_update(&oecls_flow_update, NULL); - unregister_trace_oecls_set_cpu(&oecls_set_cpu, NULL); - unregister_trace_oecls_timeout(&oecls_timeout, NULL); return 0; } @@ -383,20 +380,26 @@ static int oecls_sock_flow_table_init(void) rcu_assign_pointer(oecls_sock_flow_table, table); mutex_unlock(&oecls_sock_flow_mutex); - register_trace_oecls_flow_update(oecls_flow_update, NULL); - register_trace_oecls_set_cpu(&oecls_set_cpu, NULL); - register_trace_oecls_timeout(&oecls_timeout, NULL); return 0; } +static const struct oecls_hook_ops oecls_flow_ops = { + .oecls_flow_update = _oecls_flow_update, + .oecls_set_cpu = _oecls_set_cpu, + .oecls_timeout = _oecls_timeout, + .oecls_cfg_rxcls = NULL, +}; + void oecls_flow_res_init(void) { oecls_sock_flow_table_init(); oecls_dev_flow_table_init(); + RCU_INIT_POINTER(oecls_ops, &oecls_flow_ops); } void oecls_flow_res_clean(void) { + RCU_INIT_POINTER(oecls_ops, NULL); oecls_sock_flow_table_release(); oecls_dev_flow_table_release(); } diff --git a/net/oenetcls/oenetcls_ntuple.c b/net/oenetcls/oenetcls_ntuple.c index 79358eb589bb..53b877294dc5 100644 --- a/net/oenetcls/oenetcls_ntuple.c +++ b/net/oenetcls/oenetcls_ntuple.c @@ -7,7 +7,7 @@ #include <linux/inet.h> #include <linux/jhash.h> #include <net/sock.h> -#include <trace/hooks/oenetcls.h> +#include <linux/oenetcls.h> #include "oenetcls.h" struct oecls_sk_rule_list oecls_sk_rules, oecls_sk_list; @@ -502,7 +502,7 @@ static void add_ntuple_rule(struct sock *sk) mutex_unlock(&oecls_sk_rules.mutex); } -static void ethtool_cfg_rxcls(void *data, struct sock *sk, int is_del) +static void ethtool_cfg_rxcls(struct sock *sk, int is_del) { if (sk->sk_state != TCP_LISTEN) return; @@ -551,14 +551,21 @@ static void clean_oecls_sk_rules(void) mutex_unlock(&oecls_sk_rules.mutex); } +static const struct oecls_hook_ops oecls_ntuple_ops = { + .oecls_flow_update = NULL, + .oecls_set_cpu = NULL, + .oecls_timeout = NULL, + .oecls_cfg_rxcls = ethtool_cfg_rxcls, +}; + void oecls_ntuple_res_init(void) { init_oecls_sk_rules(); - register_trace_ethtool_cfg_rxcls(ðtool_cfg_rxcls, NULL); + RCU_INIT_POINTER(oecls_ops, &oecls_ntuple_ops); } void oecls_ntuple_res_clean(void) { - unregister_trace_ethtool_cfg_rxcls(ðtool_cfg_rxcls, NULL); + RCU_INIT_POINTER(oecls_ops, NULL); clean_oecls_sk_rules(); } -- 2.34.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/ICBFCS -------------------------------- Use workqueue for ntuple cfg to avoid mutex_lock in rcu context. Fixes: d60758b0ffcd ("net/oenetcls: introduce oenetcls for network optimization") Signed-off-by: Wang Liang <wangliang74@huawei.com> --- net/oenetcls/oenetcls.h | 14 ++- net/oenetcls/oenetcls_flow.c | 24 ++++- net/oenetcls/oenetcls_main.c | 26 ++++-- net/oenetcls/oenetcls_ntuple.c | 166 +++++++++++++++++++++------------ 4 files changed, 152 insertions(+), 78 deletions(-) diff --git a/net/oenetcls/oenetcls.h b/net/oenetcls/oenetcls.h index b2c4a3c61956..f2726582db91 100644 --- a/net/oenetcls/oenetcls.h +++ b/net/oenetcls/oenetcls.h @@ -74,7 +74,7 @@ struct oecls_sk_rule { int dport; int action; int ruleid; - int nid; + int cpu; }; struct oecls_sk_entry { @@ -121,6 +121,14 @@ struct rmgr_ctrl { __u32 size; }; +struct cfg_param { + struct work_struct work; + struct cmd_context ctx; + struct sock *sk; + bool is_del; + int cpu; +}; + extern int match_ip_flag; extern int debug; extern int oecls_netdev_num; @@ -169,9 +177,9 @@ int check_appname(char *task_name); int send_ethtool_ioctl(struct cmd_context *ctx, void *cmd); int alloc_rxq_id(int nid, int devid); void free_rxq_id(int nid, int devid, int rxq_id); -void oecls_ntuple_res_init(void); +int oecls_ntuple_res_init(void); void oecls_ntuple_res_clean(void); -void oecls_flow_res_init(void); +int oecls_flow_res_init(void); void oecls_flow_res_clean(void); #define L0_MAX_PAGE_SIZE (8192) diff --git a/net/oenetcls/oenetcls_flow.c b/net/oenetcls/oenetcls_flow.c index 37daee93b205..3834f500f75d 100644 --- a/net/oenetcls/oenetcls_flow.c +++ b/net/oenetcls/oenetcls_flow.c @@ -40,7 +40,7 @@ static bool _oecls_timeout(struct net_device *dev, u16 rxq_index, if (flow_table && flow_id <= flow_table->mask) { rflow = &flow_table->flows[flow_id]; cpu = READ_ONCE(rflow->cpu); - oecls_debug("dev:%s, rxq:%d, flow_id:%u, filter_id:%d/%d, cpu:%d", dev->name, + oecls_debug("dev:%s, rxq:%d, flow_id:%u, filter_id:%d/%d, cpu:%d\n", dev->name, rxq_index, flow_id, filter_id, rflow->filter, cpu); if (rflow->filter == filter_id && cpu < nr_cpu_ids) { @@ -390,16 +390,30 @@ static const struct oecls_hook_ops oecls_flow_ops = { .oecls_cfg_rxcls = NULL, }; -void oecls_flow_res_init(void) +int oecls_flow_res_init(void) { - oecls_sock_flow_table_init(); - oecls_dev_flow_table_init(); + int err; + + err = oecls_sock_flow_table_init(); + if (err) + return err; + + err = oecls_dev_flow_table_init(); + if (err) { + oecls_sock_flow_table_release(); + return err; + } + RCU_INIT_POINTER(oecls_ops, &oecls_flow_ops); + synchronize_rcu(); + return 0; } void oecls_flow_res_clean(void) { - RCU_INIT_POINTER(oecls_ops, NULL); + rcu_assign_pointer(oecls_ops, NULL); + synchronize_rcu(); + oecls_sock_flow_table_release(); oecls_dev_flow_table_release(); } diff --git a/net/oenetcls/oenetcls_main.c b/net/oenetcls/oenetcls_main.c index 88ddaec1a363..e5920351aada 100644 --- a/net/oenetcls/oenetcls_main.c +++ b/net/oenetcls/oenetcls_main.c @@ -39,6 +39,10 @@ static int strategy; module_param(strategy, int, 0444); MODULE_PARM_DESC(strategy, "strategy, default 0"); +static int check_cap = 1; +module_param(check_cap, int, 0444); +MODULE_PARM_DESC(check_cap, "check_cap, default 1"); + static bool check_params(void) { if (mode != 0 && mode != 1) @@ -288,7 +292,7 @@ static int dev_ethtool_kern(struct net *net, struct ifreq *ifr) case ETHTOOL_GCHANNELS: break; default: - if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + if (check_cap && !ns_capable(net->user_ns, CAP_NET_ADMIN)) return -EPERM; } @@ -669,9 +673,8 @@ static int init_numa_rxq_bitmap(int nid, struct oecls_numa_info *numa_info) return ret; } -static int get_cluster_rxq(struct oecls_numa_bound_dev_info *bound_dev) +static int get_cluster_rxq(int cpu, struct oecls_numa_bound_dev_info *bound_dev) { - int cpu = raw_smp_processor_id(); int cluster_id = cpu / oecls_cluster_cpu_num; int i, j, rxq_id; @@ -710,10 +713,11 @@ static int put_cluster_rxq(struct oecls_numa_bound_dev_info *bound_dev, int rxq_ return -1; } -int alloc_rxq_id(int nid, int devid) +int alloc_rxq_id(int cpu, int devid) { struct oecls_numa_bound_dev_info *bound_dev; struct oecls_numa_info *numa_info; + int nid = cpu_to_node(cpu); int rxq_id; numa_info = get_oecls_numa_info(nid); @@ -729,7 +733,7 @@ int alloc_rxq_id(int nid, int devid) bound_dev = &numa_info->bound_dev[devid]; if (strategy == 1) { - rxq_id = get_cluster_rxq(bound_dev); + rxq_id = get_cluster_rxq(cpu, bound_dev); if (rxq_id < 0 || rxq_id >= OECLS_MAX_RXQ_NUM_PER_DEV) pr_info("failed to get rxq_id:%d in cluster, try numa\n", rxq_id); else @@ -744,14 +748,15 @@ int alloc_rxq_id(int nid, int devid) found: clear_bit(rxq_id, bound_dev->bitmap_rxq); - oecls_debug("alloc nid:%d, dev_id:%d, rxq_id:%d\n", nid, devid, rxq_id); + oecls_debug("alloc cpu:%d, nid:%d, devid:%d, rxq_id:%d\n", cpu, nid, devid, rxq_id); return rxq_id; } -void free_rxq_id(int nid, int devid, int rxq_id) +void free_rxq_id(int cpu, int devid, int rxq_id) { struct oecls_numa_bound_dev_info *bound_dev; struct oecls_numa_info *numa_info; + int nid = cpu_to_node(cpu); numa_info = get_oecls_numa_info(nid); if (!numa_info) { @@ -1039,9 +1044,12 @@ static __init int oecls_init(void) #endif if (mode == 0) - oecls_ntuple_res_init(); + err = oecls_ntuple_res_init(); else - oecls_flow_res_init(); + err = oecls_flow_res_init(); + + if (err) + goto clean_rxq; return 0; diff --git a/net/oenetcls/oenetcls_ntuple.c b/net/oenetcls/oenetcls_ntuple.c index 53b877294dc5..5bb1b1916a4c 100644 --- a/net/oenetcls/oenetcls_ntuple.c +++ b/net/oenetcls/oenetcls_ntuple.c @@ -11,6 +11,8 @@ #include "oenetcls.h" struct oecls_sk_rule_list oecls_sk_rules, oecls_sk_list; +static struct workqueue_struct *do_cfg_workqueue; +static atomic_t oecls_worker_count = ATOMIC_INIT(0); static void init_oecls_sk_rules(void) { @@ -31,8 +33,7 @@ static inline struct hlist_head *get_sk_hashlist(void *sk) return oecls_sk_list.hash + (jhash(sk, sizeof(sk), 0) & OECLS_SK_RULE_HASHMASK); } -static void add_sk_rule(int devid, u32 dip4, u16 dport, void *sk, int action, - int ruleid, int nid) +static void add_sk_rule(int devid, u32 dip4, u16 dport, void *sk, int action, int ruleid, int cpu) { struct hlist_head *hlist = get_rule_hashlist(dip4, dport); struct hlist_head *sk_hlist = get_sk_hashlist(sk); @@ -50,7 +51,7 @@ static void add_sk_rule(int devid, u32 dip4, u16 dport, void *sk, int action, rule->devid = devid; rule->action = action; rule->ruleid = ruleid; - rule->nid = nid; + rule->cpu = cpu; hlist_add_head(&rule->node, hlist); entry->sk = sk; @@ -421,85 +422,113 @@ static int cfg_ethtool_rule(struct cmd_context *ctx, bool is_del) return ret; } -static void del_ntuple_rule(struct sock *sk) +static void cfg_work(struct work_struct *work) { + struct cfg_param *ctx_p = container_of(work, struct cfg_param, work); struct oecls_netdev_info *oecls_dev; - struct cmd_context ctx = { 0 }; struct oecls_sk_rule *rule; - int devid; - u16 dport; - u32 dip4; + int devid, rxq_id; int err; - get_sk_rule_addr(sk, &dip4, &dport); - mutex_lock(&oecls_sk_rules.mutex); for_each_oecls_netdev(devid, oecls_dev) { - strncpy(ctx.netdev, oecls_dev->dev_name, IFNAMSIZ); - rule = get_rule_from_sk(devid, sk); - if (!rule) { - oecls_debug("rule not found! sk:%p, devid:%d, dip4:%pI4, dport:%d\n", - sk, devid, &dip4, ntohs(dport)); - continue; - } + strncpy(ctx_p->ctx.netdev, oecls_dev->dev_name, IFNAMSIZ); + if (!ctx_p->is_del) { + if (reuseport_check(devid, ctx_p->ctx.dip4, ctx_p->ctx.dport)) { + oecls_error("dip4:%pI4, dport:%d reuse!\n", &ctx_p->ctx.dip4, + ctx_p->ctx.dport); + continue; + } - // Config Ntuple rule to dev - ctx.del_ruleid = rule->ruleid; - err = cfg_ethtool_rule(&ctx, true); - if (err) { - oecls_error("del sk:%p, nid:%d, devid:%d, action:%d, ruleid:%d, err:%d\n", - sk, rule->nid, devid, rule->action, rule->ruleid, err); - } + // Calculate the bound queue + rxq_id = alloc_rxq_id(ctx_p->cpu, devid); + if (rxq_id < 0) + continue; - // Free the bound queue - free_rxq_id(rule->nid, devid, rule->action); + // Config Ntuple rule to dev + ctx_p->ctx.action = (u16)rxq_id; + err = cfg_ethtool_rule(&ctx_p->ctx, ctx_p->is_del); + // Add sk rule only on success + if (err) { + free_rxq_id(ctx_p->cpu, devid, rxq_id); + continue; + } + add_sk_rule(devid, ctx_p->ctx.dip4, ctx_p->ctx.dport, ctx_p->sk, + ctx_p->ctx.action, ctx_p->ctx.ret_loc, ctx_p->cpu); + } else { + rule = get_rule_from_sk(devid, ctx_p->sk); + if (!rule) { + oecls_debug("rule not found! sk:%p, devid:%d, dip4:%pI4, dport:%d\n", + ctx_p->sk, devid, &ctx_p->ctx.dip4, + ntohs(ctx_p->ctx.dport)); + continue; + } - // Delete sk rule - del_sk_rule(rule); + // Config Ntuple rule to dev + ctx_p->ctx.del_ruleid = rule->ruleid; + err = cfg_ethtool_rule(&ctx_p->ctx, ctx_p->is_del); + // Free the bound queue + free_rxq_id(rule->cpu, devid, rule->action); + // Delete sk rule + del_sk_rule(rule); + } } mutex_unlock(&oecls_sk_rules.mutex); + kfree(ctx_p); + atomic_dec(&oecls_worker_count); } -static void add_ntuple_rule(struct sock *sk) +static bool has_sock_rule(struct sock *sk) { struct oecls_netdev_info *oecls_dev; - struct cmd_context ctx = { 0 }; - int cpu = raw_smp_processor_id(); - int nid = cpu_to_node(cpu); - int rxq_id; + struct oecls_sk_rule *rule; int devid; - int err; - if (check_appname(current->comm)) + for_each_oecls_netdev(devid, oecls_dev) { + rule = get_rule_from_sk(devid, sk); + if (rule) + return true; + } + return false; +} + +static void del_ntuple_rule(struct sock *sk) +{ + struct cfg_param *ctx_p; + + if (!has_sock_rule(sk)) return; - get_sk_rule_addr(sk, &ctx.dip4, &ctx.dport); - mutex_lock(&oecls_sk_rules.mutex); - for_each_oecls_netdev(devid, oecls_dev) { - strncpy(ctx.netdev, oecls_dev->dev_name, IFNAMSIZ); - if (reuseport_check(devid, ctx.dip4, ctx.dport)) { - oecls_error("dip4:0x%x, dport:%d reuse!\n", ctx.dip4, ctx.dport); - continue; - } + ctx_p = kzalloc(sizeof(*ctx_p), GFP_ATOMIC); + if (!ctx_p) + return; + get_sk_rule_addr(sk, &ctx_p->ctx.dip4, &ctx_p->ctx.dport); - // Calculate the bound queue - rxq_id = alloc_rxq_id(nid, devid); - if (rxq_id < 0) - continue; + ctx_p->is_del = true; + ctx_p->sk = sk; + INIT_WORK(&ctx_p->work, cfg_work); + queue_work(do_cfg_workqueue, &ctx_p->work); + atomic_inc(&oecls_worker_count); +} - // Config Ntuple rule to dev - ctx.action = (u16)rxq_id; - err = cfg_ethtool_rule(&ctx, false); - if (err) { - oecls_error("add sk:%p, nid:%d, devid:%d, action:%d, ruleid:%d, err:%d\n", - sk, nid, devid, ctx.action, ctx.ret_loc, err); - continue; - } +static void add_ntuple_rule(struct sock *sk) +{ + struct cfg_param *ctx_p; - // Add sk rule - add_sk_rule(devid, ctx.dip4, ctx.dport, sk, ctx.action, ctx.ret_loc, nid); - } - mutex_unlock(&oecls_sk_rules.mutex); + if (check_appname(current->comm)) + return; + + ctx_p = kzalloc(sizeof(*ctx_p), GFP_ATOMIC); + if (!ctx_p) + return; + get_sk_rule_addr(sk, &ctx_p->ctx.dip4, &ctx_p->ctx.dport); + + ctx_p->is_del = false; + ctx_p->sk = sk; + ctx_p->cpu = raw_smp_processor_id(); + INIT_WORK(&ctx_p->work, cfg_work); + queue_work(do_cfg_workqueue, &ctx_p->work); + atomic_inc(&oecls_worker_count); } static void ethtool_cfg_rxcls(struct sock *sk, int is_del) @@ -558,14 +587,29 @@ static const struct oecls_hook_ops oecls_ntuple_ops = { .oecls_cfg_rxcls = ethtool_cfg_rxcls, }; -void oecls_ntuple_res_init(void) +int oecls_ntuple_res_init(void) { + do_cfg_workqueue = alloc_ordered_workqueue("oecls_cfg", 0); + if (!do_cfg_workqueue) { + oecls_debug("alloc_ordered_workqueue fails\n"); + return -ENOMEM; + } + init_oecls_sk_rules(); RCU_INIT_POINTER(oecls_ops, &oecls_ntuple_ops); + synchronize_rcu(); + return 0; } void oecls_ntuple_res_clean(void) { - RCU_INIT_POINTER(oecls_ops, NULL); + rcu_assign_pointer(oecls_ops, NULL); + synchronize_rcu(); + + oecls_debug("oecls_worker_count:%d\n", atomic_read(&oecls_worker_count)); + while (atomic_read(&oecls_worker_count) != 0) + mdelay(1); + + destroy_workqueue(do_cfg_workqueue); clean_oecls_sk_rules(); } -- 2.34.1
participants (2)
-
patchwork bot
-
Wang Liang