Message ID | 20220513224827.662254-2-mathew.j.martineau@linux.intel.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | bpf: mptcp: Support for mptcp_sock | expand |
On Fri, May 13, 2022 at 03:48:21PM -0700, Mat Martineau wrote: [ ... ] > diff --git a/include/net/mptcp.h b/include/net/mptcp.h > index 8b1afd6f5cc4..2ba09de955c7 100644 > --- a/include/net/mptcp.h > +++ b/include/net/mptcp.h > @@ -284,4 +284,10 @@ static inline int mptcpv6_init(void) { return 0; } > static inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { } > #endif > > +#if defined(CONFIG_MPTCP) && defined(CONFIG_BPF_SYSCALL) > +struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk); Can this be inline ? > +#else > +static inline struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk) { return NULL; } > +#endif > + > #endif /* __NET_MPTCP_H */ [ ... ] > diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c > new file mode 100644 > index 000000000000..535602ba2582 > --- /dev/null > +++ b/net/mptcp/bpf.c > @@ -0,0 +1,22 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Multipath TCP > + * > + * Copyright (c) 2020, Tessares SA. > + * Copyright (c) 2022, SUSE. > + * > + * Author: Nicolas Rybowski <nicolas.rybowski@tessares.net> > + */ > + > +#define pr_fmt(fmt) "MPTCP: " fmt > + > +#include <linux/bpf.h> > +#include "protocol.h" > + > +struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk) > +{ > + if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP && sk_is_mptcp(sk)) > + return mptcp_sk(mptcp_subflow_ctx(sk)->conn); > + > + return NULL; > +} > +EXPORT_SYMBOL(bpf_mptcp_sock_from_subflow); Is EXPORT_SYMBOL needed ?
Martin KaFai Lau <kafai@fb.com> 于2022年5月17日周二 09:07写道: > > On Fri, May 13, 2022 at 03:48:21PM -0700, Mat Martineau wrote: > [ ... ] > > > diff --git a/include/net/mptcp.h b/include/net/mptcp.h > > index 8b1afd6f5cc4..2ba09de955c7 100644 > > --- a/include/net/mptcp.h > > +++ b/include/net/mptcp.h > > @@ -284,4 +284,10 @@ static inline int mptcpv6_init(void) { return 0; } > > static inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { } > > #endif > > > > +#if defined(CONFIG_MPTCP) && defined(CONFIG_BPF_SYSCALL) > > +struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk); > Can this be inline ? This function can't be inline since it uses struct mptcp_subflow_context. mptcp_subflow_context is defined in net/mptcp/protocol.h, and we don't want to export it to user space in net/mptcp/protocol.h. > > > +#else > > +static inline struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk) { return NULL; } > > +#endif > > + > > #endif /* __NET_MPTCP_H */ > > [ ... ] > > > diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c > > new file mode 100644 > > index 000000000000..535602ba2582 > > --- /dev/null > > +++ b/net/mptcp/bpf.c > > @@ -0,0 +1,22 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* Multipath TCP > > + * > > + * Copyright (c) 2020, Tessares SA. > > + * Copyright (c) 2022, SUSE. > > + * > > + * Author: Nicolas Rybowski <nicolas.rybowski@tessares.net> > > + */ > > + > > +#define pr_fmt(fmt) "MPTCP: " fmt > > + > > +#include <linux/bpf.h> > > +#include "protocol.h" > > + > > +struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk) > > +{ > > + if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP && sk_is_mptcp(sk)) > > + return mptcp_sk(mptcp_subflow_ctx(sk)->conn); > > + > > + return NULL; > > +} > > +EXPORT_SYMBOL(bpf_mptcp_sock_from_subflow); > Is EXPORT_SYMBOL needed ? Will drop in v5. Thanks, -Geliang >
On Mon, May 16, 2022 at 10:26 PM Geliang Tang <geliangtang@gmail.com> wrote: > > Martin KaFai Lau <kafai@fb.com> 于2022年5月17日周二 09:07写道: > > > > On Fri, May 13, 2022 at 03:48:21PM -0700, Mat Martineau wrote: > > [ ... ] > > > > > diff --git a/include/net/mptcp.h b/include/net/mptcp.h > > > index 8b1afd6f5cc4..2ba09de955c7 100644 > > > --- a/include/net/mptcp.h > > > +++ b/include/net/mptcp.h > > > @@ -284,4 +284,10 @@ static inline int mptcpv6_init(void) { return 0; } > > > static inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { } > > > #endif > > > > > > +#if defined(CONFIG_MPTCP) && defined(CONFIG_BPF_SYSCALL) > > > +struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk); > > Can this be inline ? > > This function can't be inline since it uses struct mptcp_subflow_context. > > mptcp_subflow_context is defined in net/mptcp/protocol.h, and we don't > want to export it to user space in net/mptcp/protocol.h. The above function can be made static inline in a header file. That doesn't automatically expose it to user space.
On Tue, 17 May 2022, Alexei Starovoitov wrote: > On Mon, May 16, 2022 at 10:26 PM Geliang Tang <geliangtang@gmail.com> wrote: >> >> Martin KaFai Lau <kafai@fb.com> 于2022年5月17日周二 09:07写道: >>> >>> On Fri, May 13, 2022 at 03:48:21PM -0700, Mat Martineau wrote: >>> [ ... ] >>> >>>> diff --git a/include/net/mptcp.h b/include/net/mptcp.h >>>> index 8b1afd6f5cc4..2ba09de955c7 100644 >>>> --- a/include/net/mptcp.h >>>> +++ b/include/net/mptcp.h >>>> @@ -284,4 +284,10 @@ static inline int mptcpv6_init(void) { return 0; } >>>> static inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { } >>>> #endif >>>> >>>> +#if defined(CONFIG_MPTCP) && defined(CONFIG_BPF_SYSCALL) >>>> +struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk); >>> Can this be inline ? >> >> This function can't be inline since it uses struct mptcp_subflow_context. >> >> mptcp_subflow_context is defined in net/mptcp/protocol.h, and we don't >> want to export it to user space in net/mptcp/protocol.h. > > The above function can be made static inline in a header file. > That doesn't automatically expose it to user space. > True, it's not a question of userspace exposure. But making this one function inline involves a bunch of churn in the (non-BPF) mptcp headers that I'd rather avoid. The definitions in protocol.h are there because they aren't relevant outside of the mptcp subsystem code. Does making this one function inline benefit BPF, specifically, in a meaningful way? If not, I'd like to leave it as-is. -- Mat Martineau Intel
On Wed, May 18, 2022 at 05:38:43PM -0700, Mat Martineau wrote: > On Tue, 17 May 2022, Alexei Starovoitov wrote: > > > On Mon, May 16, 2022 at 10:26 PM Geliang Tang <geliangtang@gmail.com> wrote: > > > > > > Martin KaFai Lau <kafai@fb.com> 于2022年5月17日周二 09:07写道: > > > > > > > > On Fri, May 13, 2022 at 03:48:21PM -0700, Mat Martineau wrote: > > > > [ ... ] > > > > > > > > > diff --git a/include/net/mptcp.h b/include/net/mptcp.h > > > > > index 8b1afd6f5cc4..2ba09de955c7 100644 > > > > > --- a/include/net/mptcp.h > > > > > +++ b/include/net/mptcp.h > > > > > @@ -284,4 +284,10 @@ static inline int mptcpv6_init(void) { return 0; } > > > > > static inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { } > > > > > #endif > > > > > > > > > > +#if defined(CONFIG_MPTCP) && defined(CONFIG_BPF_SYSCALL) > > > > > +struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk); > > > > Can this be inline ? > > > > > > This function can't be inline since it uses struct mptcp_subflow_context. > > > > > > mptcp_subflow_context is defined in net/mptcp/protocol.h, and we don't > > > want to export it to user space in net/mptcp/protocol.h. > > > > The above function can be made static inline in a header file. > > That doesn't automatically expose it to user space. > > > > True, it's not a question of userspace exposure. But making this one > function inline involves a bunch of churn in the (non-BPF) mptcp headers > that I'd rather avoid. The definitions in protocol.h are there because they > aren't relevant outside of the mptcp subsystem code. > > Does making this one function inline benefit BPF, specifically, in a > meaningful way? I believe this is similar to the already inlined mptcp_subflow_ctx(). > If not, I'd like to leave it as-is. Sure, it is fine to leave it if the churn is too much. Was suggesting because all other bpf_skc_to_* cast helpers don't have this call-out. Just in case if those cast helpers will be inlined by verifier in the future, this won't be the only one that got left behind.
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 5061ccd8b2dc..c129c2e2dd95 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -2229,6 +2229,7 @@ extern const struct bpf_func_proto bpf_skc_to_tcp_timewait_sock_proto; extern const struct bpf_func_proto bpf_skc_to_tcp_request_sock_proto; extern const struct bpf_func_proto bpf_skc_to_udp6_sock_proto; extern const struct bpf_func_proto bpf_skc_to_unix_sock_proto; +extern const struct bpf_func_proto bpf_skc_to_mptcp_sock_proto; extern const struct bpf_func_proto bpf_copy_from_user_proto; extern const struct bpf_func_proto bpf_snprintf_btf_proto; extern const struct bpf_func_proto bpf_snprintf_proto; diff --git a/include/linux/btf_ids.h b/include/linux/btf_ids.h index bc5d9cc34e4c..335a19092368 100644 --- a/include/linux/btf_ids.h +++ b/include/linux/btf_ids.h @@ -178,7 +178,8 @@ extern struct btf_id_set name; BTF_SOCK_TYPE(BTF_SOCK_TYPE_TCP6, tcp6_sock) \ BTF_SOCK_TYPE(BTF_SOCK_TYPE_UDP, udp_sock) \ BTF_SOCK_TYPE(BTF_SOCK_TYPE_UDP6, udp6_sock) \ - BTF_SOCK_TYPE(BTF_SOCK_TYPE_UNIX, unix_sock) + BTF_SOCK_TYPE(BTF_SOCK_TYPE_UNIX, unix_sock) \ + BTF_SOCK_TYPE(BTF_SOCK_TYPE_MPTCP, mptcp_sock) enum { #define BTF_SOCK_TYPE(name, str) name, diff --git a/include/net/mptcp.h b/include/net/mptcp.h index 8b1afd6f5cc4..2ba09de955c7 100644 --- a/include/net/mptcp.h +++ b/include/net/mptcp.h @@ -284,4 +284,10 @@ static inline int mptcpv6_init(void) { return 0; } static inline void mptcpv6_handle_mapped(struct sock *sk, bool mapped) { } #endif +#if defined(CONFIG_MPTCP) && defined(CONFIG_BPF_SYSCALL) +struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk); +#else +static inline struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk) { return NULL; } +#endif + #endif /* __NET_MPTCP_H */ diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 0210f85131b3..56688bee20d9 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -5172,6 +5172,12 @@ union bpf_attr { * Return * Map value associated to *key* on *cpu*, or **NULL** if no entry * was found or *cpu* is invalid. + * + * struct mptcp_sock *bpf_skc_to_mptcp_sock(void *sk) + * Description + * Dynamically cast a *sk* pointer to a *mptcp_sock* pointer. + * Return + * *sk* if casting is valid, or **NULL** otherwise. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5370,6 +5376,7 @@ union bpf_attr { FN(ima_file_hash), \ FN(kptr_xchg), \ FN(map_lookup_percpu_elem), \ + FN(skc_to_mptcp_sock), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 05c1b6656824..10ed10b24860 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -509,6 +509,7 @@ static bool is_ptr_cast_function(enum bpf_func_id func_id) func_id == BPF_FUNC_skc_to_tcp_sock || func_id == BPF_FUNC_skc_to_tcp6_sock || func_id == BPF_FUNC_skc_to_udp6_sock || + func_id == BPF_FUNC_skc_to_mptcp_sock || func_id == BPF_FUNC_skc_to_tcp_timewait_sock || func_id == BPF_FUNC_skc_to_tcp_request_sock; } diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 7141ca8a1c2d..10b157a6d73e 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1705,6 +1705,8 @@ tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_skc_to_udp6_sock_proto; case BPF_FUNC_skc_to_unix_sock: return &bpf_skc_to_unix_sock_proto; + case BPF_FUNC_skc_to_mptcp_sock: + return &bpf_skc_to_mptcp_sock_proto; case BPF_FUNC_sk_storage_get: return &bpf_sk_storage_get_tracing_proto; case BPF_FUNC_sk_storage_delete: diff --git a/net/core/filter.c b/net/core/filter.c index fe0da529d00f..5af58eb48587 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -78,6 +78,7 @@ #include <linux/btf_ids.h> #include <net/tls.h> #include <net/xdp.h> +#include <net/mptcp.h> static const struct bpf_func_proto * bpf_sk_base_func_proto(enum bpf_func_id func_id); @@ -11281,6 +11282,20 @@ const struct bpf_func_proto bpf_skc_to_unix_sock_proto = { .ret_btf_id = &btf_sock_ids[BTF_SOCK_TYPE_UNIX], }; +BPF_CALL_1(bpf_skc_to_mptcp_sock, struct sock *, sk) +{ + BTF_TYPE_EMIT(struct mptcp_sock); + return (unsigned long)bpf_mptcp_sock_from_subflow(sk); +} + +const struct bpf_func_proto bpf_skc_to_mptcp_sock_proto = { + .func = bpf_skc_to_mptcp_sock, + .gpl_only = false, + .ret_type = RET_PTR_TO_BTF_ID_OR_NULL, + .arg1_type = ARG_PTR_TO_SOCK_COMMON, + .ret_btf_id = &btf_sock_ids[BTF_SOCK_TYPE_MPTCP], +}; + BPF_CALL_1(bpf_sock_from_file, struct file *, file) { return (unsigned long)sock_from_file(file); @@ -11323,6 +11338,9 @@ bpf_sk_base_func_proto(enum bpf_func_id func_id) case BPF_FUNC_skc_to_unix_sock: func = &bpf_skc_to_unix_sock_proto; break; + case BPF_FUNC_skc_to_mptcp_sock: + func = &bpf_skc_to_mptcp_sock_proto; + break; case BPF_FUNC_ktime_get_coarse_ns: return &bpf_ktime_get_coarse_ns_proto; default: diff --git a/net/mptcp/Makefile b/net/mptcp/Makefile index e54daceac58b..99dddf08ca73 100644 --- a/net/mptcp/Makefile +++ b/net/mptcp/Makefile @@ -10,3 +10,5 @@ obj-$(CONFIG_INET_MPTCP_DIAG) += mptcp_diag.o mptcp_crypto_test-objs := crypto_test.o mptcp_token_test-objs := token_test.o obj-$(CONFIG_MPTCP_KUNIT_TEST) += mptcp_crypto_test.o mptcp_token_test.o + +obj-$(CONFIG_BPF_SYSCALL) += bpf.o diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c new file mode 100644 index 000000000000..535602ba2582 --- /dev/null +++ b/net/mptcp/bpf.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Multipath TCP + * + * Copyright (c) 2020, Tessares SA. + * Copyright (c) 2022, SUSE. + * + * Author: Nicolas Rybowski <nicolas.rybowski@tessares.net> + */ + +#define pr_fmt(fmt) "MPTCP: " fmt + +#include <linux/bpf.h> +#include "protocol.h" + +struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk) +{ + if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP && sk_is_mptcp(sk)) + return mptcp_sk(mptcp_subflow_ctx(sk)->conn); + + return NULL; +} +EXPORT_SYMBOL(bpf_mptcp_sock_from_subflow); diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index 096625242475..d5452f7eb996 100755 --- a/scripts/bpf_doc.py +++ b/scripts/bpf_doc.py @@ -633,6 +633,7 @@ class PrinterHelpers(Printer): 'struct socket', 'struct file', 'struct bpf_timer', + 'struct mptcp_sock', ] known_types = { '...', @@ -682,6 +683,7 @@ class PrinterHelpers(Printer): 'struct socket', 'struct file', 'struct bpf_timer', + 'struct mptcp_sock', } mapped_types = { 'u8': '__u8', diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 0210f85131b3..56688bee20d9 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -5172,6 +5172,12 @@ union bpf_attr { * Return * Map value associated to *key* on *cpu*, or **NULL** if no entry * was found or *cpu* is invalid. + * + * struct mptcp_sock *bpf_skc_to_mptcp_sock(void *sk) + * Description + * Dynamically cast a *sk* pointer to a *mptcp_sock* pointer. + * Return + * *sk* if casting is valid, or **NULL** otherwise. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5370,6 +5376,7 @@ union bpf_attr { FN(ima_file_hash), \ FN(kptr_xchg), \ FN(map_lookup_percpu_elem), \ + FN(skc_to_mptcp_sock), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper