diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index bbe2488e6440820b2014a3b126cd5e36a862f29b..66c2944917aaf3eb8e2bd89591528b48cae1f39b 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -6951,7 +6951,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 9d884b734f4c07c47848eaa903fe9ea151ffe749..16b5e86ba6fb42404e407f328d1dc5db7ed8e8be 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -1266,6 +1266,7 @@ CONFIG_SMC_DIAG=m CONFIG_SMC_LO=y CONFIG_XDP_SOCKETS=y CONFIG_XDP_SOCKETS_DIAG=y +# CONFIG_OENETCLS is not set CONFIG_NET_HANDSHAKE=y CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -8146,7 +8147,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 90b0f6ea40400bfe544fc62b7e3783ec73419b23..6a00168e67ad6c38c44fe5032929ed0f3a4d200f 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 d9b85b57a7424b902cdfc6c1dd256beed2285ad0..85bda58159f69f9a0f3bb5555d09d3ba84ac2d64 100644 --- a/drivers/hooks/vendor_hooks.c +++ b/drivers/hooks/vendor_hooks.c @@ -9,7 +9,6 @@ #define CREATE_TRACE_POINTS #include #include -#include /* * Export tracepoints that act as a bare tracehook (ie: have no trace event @@ -19,10 +18,3 @@ #ifdef CONFIG_VENDOR_BOND_HOOKS 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 0000000000000000000000000000000000000000..29c0db40971fb0dd4a4004c5d8fa5dad2047d432 --- /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 c38545d7a6a293b46be956b71554a3a46ba97abc..0000000000000000000000000000000000000000 --- 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 -#include - -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 - -#endif - diff --git a/net/core/dev.c b/net/core/dev.c index 78f94e67780f9295bee2dd7b05fc97f834620426..e2d61f786c8a57b3ef3a6afd6431c213ee78da81 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -154,11 +154,16 @@ #include #include #include -#include #include "dev.h" #include "net-sysfs.h" +#if IS_ENABLED(CONFIG_OENETCLS) +#include +const struct oecls_hook_ops __rcu *oecls_ops __read_mostly; +EXPORT_SYMBOL_GPL(oecls_ops); +#endif + static DEFINE_SPINLOCK(ptype_lock); struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; struct list_head ptype_all __read_mostly; /* Taps */ @@ -4728,10 +4733,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); @@ -5891,8 +5895,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); @@ -5930,9 +5934,8 @@ 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 ee224b196666d062f7905ace94c5b7fcab0b57a0..ab3f7dfcae94e93b18183759af2343754d2f49ee 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -121,7 +121,10 @@ #include #include -#include + +#if IS_ENABLED(CONFIG_OENETCLS) +#include +#endif /* The inetsw table contains everything that inet_create needs to * build a new socket. @@ -220,8 +223,8 @@ int __inet_listen_sk(struct sock *sk, int backlog) return err; 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 } return 0; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index aebcda267a9a348d7001c49269a592e77884309e..41c02ed1c26e858a11774bdd324c5742d8fcd01b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -279,7 +279,10 @@ #include #include #include -#include + +#if IS_ENABLED(CONFIG_OENETCLS) +#include +#endif /* Track pending CMSGs. */ enum { @@ -2578,8 +2581,8 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags, 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) && @@ -2944,8 +2947,8 @@ void __tcp_close(struct sock *sk, long timeout) 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); release_sock(sk); diff --git a/net/oenetcls/Kconfig b/net/oenetcls/Kconfig index 2ab980258c31ab366ca99783ed13667422e9178c..68d5c69043194bc5fa8dfe5b6dded8103da5ddde 100644 --- a/net/oenetcls/Kconfig +++ b/net/oenetcls/Kconfig @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only config OENETCLS tristate "Network classification" - depends on OENETCLS_HOOKS default n help Allows to configure ntuple rule, and bind interrupt to netdev diff --git a/net/oenetcls/oenetcls.h b/net/oenetcls/oenetcls.h index 215ae3e7e1535c02709ba4751328c0c48e6abda9..f4a06214f3207aca7843665336f5e66e94826074 100644 --- a/net/oenetcls/oenetcls.h +++ b/net/oenetcls/oenetcls.h @@ -121,6 +121,16 @@ struct rmgr_ctrl { __u32 size; }; +struct cfg_param { + struct work_struct work; + struct cmd_context ctx; + struct oecls_sk_rule *rule; + struct sock *sk; + bool is_del; + int devid; + int nid; +}; + extern int match_ip_flag; extern int debug; extern int oecls_netdev_num; @@ -169,9 +179,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); #endif /* _NET_OENETCLS_H */ diff --git a/net/oenetcls/oenetcls_flow.c b/net/oenetcls/oenetcls_flow.c index 5dc58e8bae254b6ae7e79373a9035eb6dc045f27..9a7550544305adfd8253e88927c04a772cdce956 100644 --- a/net/oenetcls/oenetcls_flow.c +++ b/net/oenetcls/oenetcls_flow.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "oenetcls.h" static u32 oecls_cpu_mask; @@ -27,8 +27,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; @@ -56,10 +56,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; @@ -201,7 +201,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; @@ -356,9 +356,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; } @@ -384,20 +381,37 @@ 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; } -void oecls_flow_res_init(void) +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, +}; + +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); + return 0; } 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_main.c b/net/oenetcls/oenetcls_main.c index 67c73f4595bec02b69187281cc5d89acd80199f1..181e480d571b804d2e1eacdcaa6f9247479f0e27 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; @@ -796,7 +796,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); @@ -1040,9 +1040,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 3986d86efe83743a645b3c9623ce11bfaa70e846..86fc9138b0df1652a29f7126f66a349b962163c5 100644 --- a/net/oenetcls/oenetcls_ntuple.c +++ b/net/oenetcls/oenetcls_ntuple.c @@ -8,10 +8,11 @@ #include #include #include -#include +#include #include "oenetcls.h" struct oecls_sk_rule_list oecls_sk_rules, oecls_sk_list; +static struct workqueue_struct *do_cfg_workqueue; static void init_oecls_sk_rules(void) { @@ -422,88 +423,99 @@ 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->nid, 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->nid, devid, rxq_id); + continue; + } + add_sk_rule(ctx_p->devid, ctx_p->ctx.dip4, ctx_p->ctx.dport, ctx_p->sk, + ctx_p->ctx.action, ctx_p->ctx.ret_loc, ctx_p->nid); + } else { + rule = get_rule_from_sk(ctx_p->devid, ctx_p->sk); + if (!rule) { + oecls_debug("rule not found! sk:%p, devid:%d, dip4:%pI4, dport:%d\n", + ctx_p->sk, ctx_p->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; + ctx_p->rule = rule; + err = cfg_ethtool_rule(&ctx_p->ctx, ctx_p->is_del); + // Free the bound queue + free_rxq_id(ctx_p->rule->nid, ctx_p->devid, ctx_p->rule->action); + // Delete sk rule + del_sk_rule(ctx_p->rule); + } } mutex_unlock(&oecls_sk_rules.mutex); + kfree(ctx_p); +} + +static void del_ntuple_rule(struct sock *sk) +{ + struct cfg_param *ctx_p; + + 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 = true; + ctx_p->sk = sk; + INIT_WORK(&ctx_p->work, cfg_work); + queue_work(do_cfg_workqueue, &ctx_p->work); } static void add_ntuple_rule(struct sock *sk) { - struct oecls_netdev_info *oecls_dev; - struct cmd_context ctx = { 0 }; - int cpu = smp_processor_id(); + struct cfg_param *ctx_p; + int cpu = raw_smp_processor_id(); int nid = cpu_to_node(cpu); - int rxq_id; - int devid; - int err; if (check_appname(current->comm)) 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:%pI4, dport:%d reuse!\n", &ctx.dip4, ctx.dport); - continue; - } - - // Calculate the bound queue - rxq_id = alloc_rxq_id(nid, devid); - if (rxq_id < 0) - continue; - // 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; - } + 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); - // Add sk rule - add_sk_rule(devid, ctx.dip4, ctx.dport, sk, ctx.action, ctx.ret_loc, nid); - } - mutex_unlock(&oecls_sk_rules.mutex); + ctx_p->is_del = false; + ctx_p->sk = sk; + ctx_p->nid = nid; + INIT_WORK(&ctx_p->work, cfg_work); + queue_work(do_cfg_workqueue, &ctx_p->work); } -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; @@ -511,7 +523,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) @@ -552,14 +564,28 @@ static void clean_oecls_sk_rules(void) mutex_unlock(&oecls_sk_rules.mutex); } -void oecls_ntuple_res_init(void) +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, +}; + +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(); - register_trace_ethtool_cfg_rxcls(ðtool_cfg_rxcls, NULL); + RCU_INIT_POINTER(oecls_ops, &oecls_ntuple_ops); + return 0; } 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(); }