Re: [PATCH bpf-next v3 3/5] net/smc: bpf: register smc_ops info struct_ops

Zhu Yanjun
2024-12-26T19:44:27Z

在 2024/12/18 3:44, D. Wythe 写道:
> To implement injection capability for smc via struct_ops, so that
> user can make their own smc_ops to modify the behavior of smc stack.
>
> Currently, user can write their own implememtion to choose whether to
> use SMC or not before TCP 3rd handshake to be comleted. In the future,
> users can implement more complex functions on smc by expanding it.
>
> Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
> ---
> net/smc/af_smc.c | 10 +++++
> net/smc/smc_ops.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++
> net/smc/smc_ops.h | 2 +
> 3 files changed, 111 insertions(+)
>
> diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
> index 9d76e902fd77..6adedae2986d 100644
> --- a/net/smc/af_smc.c
> +++ b/net/smc/af_smc.c
> @@ -55,6 +55,7 @@
> #include "smc_sysctl.h"
> #include "smc_loopback.h"
> #include "smc_inet.h"
> +#include "smc_ops.h"
>
> static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group
> * creation on server
> @@ -3576,8 +3577,17 @@ static int __init smc_init(void)
> pr_err("%s: smc_inet_init fails with %d\n", __func__, rc);
> goto out_ulp;
> }
> +
> + rc = smc_bpf_struct_ops_init();
> + if (rc) {
> + pr_err("%s: smc_bpf_struct_ops_init fails with %d\n", __func__, rc);
> + goto out_inet;
> + }
> +
> static_branch_enable(&tcp_have_smc);
> return 0;
> +out_inet:
> + smc_inet_exit();
> out_ulp:
> tcp_unregister_ulp(&smc_ulp_ops);
> out_lo:
> diff --git a/net/smc/smc_ops.c b/net/smc/smc_ops.c
> index 0fc19cadd760..0f07652f4837 100644
> --- a/net/smc/smc_ops.c
> +++ b/net/smc/smc_ops.c
> @@ -10,6 +10,10 @@
> * Author: D. Wythe <alibuda@linux.alibaba.com>
> */
>
> +#include <linux/bpf_verifier.h>
> +#include <linux/bpf.h>
> +#include <linux/btf.h>
> +
> #include "smc_ops.h"
>
> static DEFINE_SPINLOCK(smc_ops_list_lock);
> @@ -49,3 +53,98 @@ struct smc_ops *smc_ops_find_by_name(const char *name)
> }
> return NULL;
> }
> +
> +static int __bpf_smc_stub_set_tcp_option(struct tcp_sock *tp) { return 1; }
> +static int __bpf_smc_stub_set_tcp_option_cond(const struct tcp_sock *tp,
> + struct inet_request_sock *ireq)
> +{
> + return 1;
> +}
> +
> +static struct smc_ops __bpf_smc_bpf_ops = {
> + .set_option = __bpf_smc_stub_set_tcp_option,
> + .set_option_cond = __bpf_smc_stub_set_tcp_option_cond,
> +};
> +
> +static int smc_bpf_ops_init(struct btf *btf) { return 0; }
> +
> +static int smc_bpf_ops_reg(void *kdata, struct bpf_link *link)
> +{
> + return smc_ops_reg(kdata);
> +}
> +
> +static void smc_bpf_ops_unreg(void *kdata, struct bpf_link *link)
> +{
> + smc_ops_unreg(kdata);
> +}
> +
> +static int smc_bpf_ops_init_member(const struct btf_type *t,
> + const struct btf_member *member,
> + void *kdata, const void *udata)
> +{
> + const struct smc_ops *u_ops;
> + struct smc_ops *k_ops;
> + u32 moff;
> +
> + u_ops = (const struct smc_ops *)udata;
> + k_ops = (struct smc_ops *)kdata;
> +
> + moff = __btf_member_bit_offset(t, member) / 8;
> + switch (moff) {
> + case offsetof(struct smc_ops, name):
> + if (bpf_obj_name_cpy(k_ops->name, u_ops->name,
> + sizeof(u_ops->name)) <= 0)
> + return -EINVAL;
> + return 1;
> + case offsetof(struct smc_ops, flags):
> + if (u_ops->flags & ~SMC_OPS_ALL_FLAGS)
> + return -EINVAL;
> + k_ops->flags = u_ops->flags;
> + return 1;
> + default:
> + break;
> + }
> +
> + return 0;
> +}
> +
> +static int smc_bpf_ops_check_member(const struct btf_type *t,
> + const struct btf_member *member,
> + const struct bpf_prog *prog)
> +{
> + u32 moff = __btf_member_bit_offset(t, member) / 8;
> +
> + switch (moff) {
> + case offsetof(struct smc_ops, name):
> + case offsetof(struct smc_ops, flags):
> + case offsetof(struct smc_ops, set_option):
> + case offsetof(struct smc_ops, set_option_cond):
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static const struct bpf_verifier_ops smc_bpf_verifier_ops = {
> + .get_func_proto = bpf_base_func_proto,
> + .is_valid_access = bpf_tracing_btf_ctx_access,
> +};
> +
> +static struct bpf_struct_ops bpf_smc_bpf_ops = {
> + .name = "smc_ops",
> + .init = smc_bpf_ops_init,
> + .reg = smc_bpf_ops_reg,
> + .unreg = smc_bpf_ops_unreg,
> + .cfi_stubs = &__bpf_smc_bpf_ops,
> + .verifier_ops = &smc_bpf_verifier_ops,
> + .init_member = smc_bpf_ops_init_member,
> + .check_member = smc_bpf_ops_check_member,
> + .owner = THIS_MODULE,
> +};
> +
> +int smc_bpf_struct_ops_init(void)
> +{
> + return register_bpf_struct_ops(&bpf_smc_bpf_ops, smc_ops);
> +}
> diff --git a/net/smc/smc_ops.h b/net/smc/smc_ops.h
> index 214f4c99efd4..f4e50eae13f6 100644
> --- a/net/smc/smc_ops.h
> +++ b/net/smc/smc_ops.h
> @@ -22,8 +22,10 @@
> * Note: Caller MUST ensure it's was invoked under rcu_read_lock.
> */
> struct smc_ops *smc_ops_find_by_name(const char *name);
> +int smc_bpf_struct_ops_init(void);
> #else
> static inline struct smc_ops *smc_ops_find_by_name(const char *name) { return NULL; }
> +static inline int smc_bpf_struct_ops_init(void) { return 0; }

Both smc_ops_find_by_name and smc_bpf_struct_ops_init seem to be dead
codes. Enabling/Disabling CONFIG_SMC_OPS, the above 2 inline functions
will not be called. The 2 functions should be removed.

Zhu Yanjun

> #endif /* CONFIG_SMC_OPS*/
>
> #endif /* __SMC_OPS */