From: Geliang Tang <geliang.tang@suse.com>
To: mptcp@lists.linux.dev
Subject: Re: [PATCH mptcp-next v10 08/13] bpf: Add mptcp_storage helpers
Date: Mon, 26 Jun 2023 17:40:47 +0800 [thread overview]
Message-ID: <20230626094047.GB11120@bogon> (raw)
In-Reply-To: <b2ec9149c3161152699aa6ac331d439b15a8380a.1687746021.git.geliang.tang@suse.com>
On Mon, Jun 26, 2023 at 10:23:09AM +0800, Geliang Tang wrote:
> Add two helpers bpf_mptcp_storage_get() and bpf_mptcp_storage_delete()
> for mptcp_storage map type to get or delete a bpf_local_storage from
> the given msk.
>
> Signed-off-by: Geliang Tang <geliang.tang@suse.com>
> ---
> include/linux/bpf.h | 2 +
> include/linux/btf_ids.h | 1 +
> include/uapi/linux/bpf.h | 39 ++++++++++++++++
> kernel/bpf/helpers.c | 4 ++
> kernel/bpf/verifier.c | 13 +++++-
> net/mptcp/bpf.c | 84 ++++++++++++++++++++++++++++++++++
> tools/include/uapi/linux/bpf.h | 39 ++++++++++++++++
> 7 files changed, 181 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index f58895830ada..ac4b5748451a 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -2909,6 +2909,8 @@ extern const struct bpf_func_proto bpf_get_retval_proto;
> extern const struct bpf_func_proto bpf_user_ringbuf_drain_proto;
> extern const struct bpf_func_proto bpf_cgrp_storage_get_proto;
> extern const struct bpf_func_proto bpf_cgrp_storage_delete_proto;
> +extern const struct bpf_func_proto bpf_mptcp_storage_get_proto;
> +extern const struct bpf_func_proto bpf_mptcp_storage_delete_proto;
>
> const struct bpf_func_proto *tracing_prog_func_proto(
> enum bpf_func_id func_id, const struct bpf_prog *prog);
> diff --git a/include/linux/btf_ids.h b/include/linux/btf_ids.h
> index 00950cc03bff..abd56cfcb03f 100644
> --- a/include/linux/btf_ids.h
> +++ b/include/linux/btf_ids.h
> @@ -267,5 +267,6 @@ MAX_BTF_TRACING_TYPE,
> extern u32 btf_tracing_ids[];
> extern u32 bpf_cgroup_btf_id[];
> extern u32 bpf_local_storage_map_btf_id[];
> +extern u32 bpf_mptcp_btf_id[];
>
> #endif
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index f43cf69e47ea..137e0620fd69 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -5570,6 +5570,43 @@ union bpf_attr {
> * 0 on success.
> *
> * **-ENOENT** if the bpf_local_storage cannot be found.
> + *
> + * void *bpf_mptcp_storage_get(struct bpf_map *map, struct mptcp_sock *msk, void *value, u64 flags)
> + * Description
> + * Get a bpf_local_storage from the *msk*.
> + *
> + * Logically, it could be thought of as getting the value from
> + * a *map* with *msk* as the **key**. From this
> + * perspective, the usage is not much different from
> + * **bpf_map_lookup_elem**\ (*map*, **&**\ *msk*) except this
> + * helper enforces the key must be a mptcp_sock and the map must also
> + * be a **BPF_MAP_TYPE_MPTCP_STORAGE**.
> + *
> + * Underneath, the value is stored locally at *msk* instead of
> + * the *map*. The *map* is used as the bpf-local-storage
> + * "type". The bpf-local-storage "type" (i.e. the *map*) is
> + * searched against all bpf_local_storage residing at *msk*.
> + *
> + * An optional *flags* (**BPF_LOCAL_STORAGE_GET_F_CREATE**) can be
> + * used such that a new bpf_local_storage will be
> + * created if one does not exist. *value* can be used
> + * together with **BPF_LOCAL_STORAGE_GET_F_CREATE** to specify
> + * the initial value of a bpf_local_storage. If *value* is
> + * **NULL**, the new bpf_local_storage will be zero initialized.
> + * Return
> + * A bpf_local_storage pointer is returned on success.
> + *
> + * **NULL** if not found or there was an error in adding
> + * a new bpf_local_storage.
> + *
> + * long bpf_mptcp_storage_delete(struct bpf_map *map, struct mptcp_sock *msk)
> + * Description
> + * Delete a bpf_local_storage from the *msk*.
> + *
> + * Return
> + * 0 on success.
> + *
> + * **-ENOENT** if the bpf_local_storage cannot be found.
> */
> #define ___BPF_FUNC_MAPPER(FN, ctx...) \
> FN(unspec, 0, ##ctx) \
> @@ -5784,6 +5821,8 @@ union bpf_attr {
> FN(user_ringbuf_drain, 209, ##ctx) \
> FN(cgrp_storage_get, 210, ##ctx) \
> FN(cgrp_storage_delete, 211, ##ctx) \
> + FN(mptcp_storage_get, 212, ##ctx) \
> + FN(mptcp_storage_delete, 213, ##ctx) \
> /* */
>
> /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index 4ef4c4f8a355..381b680007fb 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -1768,6 +1768,10 @@ bpf_base_func_proto(enum bpf_func_id func_id)
> case BPF_FUNC_get_current_ancestor_cgroup_id:
> return &bpf_get_current_ancestor_cgroup_id_proto;
> #endif
> + case BPF_FUNC_mptcp_storage_get:
> + return &bpf_mptcp_storage_get_proto;
> + case BPF_FUNC_mptcp_storage_delete:
> + return &bpf_mptcp_storage_delete_proto;
> default:
> break;
> }
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index d8482a4ef465..c7479628acf7 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -553,7 +553,8 @@ static bool is_storage_get_function(enum bpf_func_id func_id)
> return func_id == BPF_FUNC_sk_storage_get ||
> func_id == BPF_FUNC_inode_storage_get ||
> func_id == BPF_FUNC_task_storage_get ||
> - func_id == BPF_FUNC_cgrp_storage_get;
> + func_id == BPF_FUNC_cgrp_storage_get ||
> + func_id == BPF_FUNC_mptcp_storage_get;
> }
>
> static bool helper_multiple_ref_obj_use(enum bpf_func_id func_id,
> @@ -8241,6 +8242,11 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
> func_id != BPF_FUNC_map_push_elem)
> goto error;
> break;
> + case BPF_MAP_TYPE_MPTCP_STORAGE:
> + if (func_id != BPF_FUNC_mptcp_storage_get &&
> + func_id != BPF_FUNC_mptcp_storage_delete)
> + goto error;
> + break;
> default:
> break;
> }
> @@ -8353,6 +8359,11 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
> if (map->map_type != BPF_MAP_TYPE_CGRP_STORAGE)
> goto error;
> break;
> + case BPF_FUNC_mptcp_storage_get:
> + case BPF_FUNC_mptcp_storage_delete:
> + if (map->map_type != BPF_MAP_TYPE_MPTCP_STORAGE)
> + goto error;
> + break;
> default:
> break;
> }
> diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c
> index 764c670e843b..0bf3409cf288 100644
> --- a/net/mptcp/bpf.c
> +++ b/net/mptcp/bpf.c
> @@ -201,6 +201,17 @@ static void bpf_mptcp_storage_unlock(void)
> migrate_enable();
> }
>
> +static bool bpf_mptcp_storage_trylock(void)
> +{
> + migrate_disable();
> + if (unlikely(this_cpu_inc_return(bpf_mptcp_storage_busy) != 1)) {
> + this_cpu_dec(bpf_mptcp_storage_busy);
> + migrate_enable();
> + return false;
> + }
> + return true;
> +}
> +
> static struct bpf_local_storage __rcu **mptcp_storage_ptr(void *owner)
> {
> struct mptcp_sock *msk = owner;
> @@ -305,6 +316,59 @@ static long bpf_mptcp_storage_delete_elem(struct bpf_map *map, void *key)
> return ret;
> }
>
> +/* Called by bpf_mptcp_storage_get*() helpers */
> +static void *__bpf_mptcp_storage_get(struct bpf_map *map,
> + struct mptcp_sock *msk, void *value,
> + u64 flags, gfp_t gfp_flags, bool nobusy)
> +{
> + struct bpf_local_storage_data *sdata;
> +
> + sdata = mptcp_storage_lookup(msk, map, nobusy);
> + if (sdata)
> + return sdata->data;
> +
> + if ((flags & BPF_LOCAL_STORAGE_GET_F_CREATE) && nobusy) {
> + sdata = bpf_local_storage_update(
> + msk, (struct bpf_local_storage_map *)map, value,
> + BPF_NOEXIST, gfp_flags);
> + return IS_ERR(sdata) ? NULL : sdata->data;
> + }
> +
> + return NULL;
> +}
> +
> +/* *gfp_flags* is a hidden argument provided by the verifier */
> +BPF_CALL_5(bpf_mptcp_storage_get, struct bpf_map *, map, struct mptcp_sock *, msk,
> + void *, value, u64, flags, gfp_t, gfp_flags)
> +{
> + void *data;
> +
> + WARN_ON_ONCE(!bpf_rcu_lock_held());
> + if (flags & ~BPF_LOCAL_STORAGE_GET_F_CREATE || !msk)
> + return (unsigned long)NULL;
> +
> + bpf_mptcp_storage_lock();
> + data = __bpf_mptcp_storage_get(map, msk, value, flags, gfp_flags, true);
> + bpf_mptcp_storage_unlock();
> + return (unsigned long)data;
> +}
> +
> +BPF_CALL_2(bpf_mptcp_storage_delete, struct bpf_map *, map, struct mptcp_sock *, msk)
> +{
> + int ret;
> +
> + WARN_ON_ONCE(!bpf_rcu_lock_held());
> + if (!msk)
> + return -EINVAL;
> +
> + if (!bpf_mptcp_storage_trylock())
> + return -EBUSY;
> +
> + ret = mptcp_storage_delete(msk, map);
> + bpf_mptcp_storage_unlock();
> + return ret;
> +}
> +
> static int notsupp_get_next_key(struct bpf_map *map, void *key, void *next_key)
> {
> return -ENOTSUPP;
> @@ -334,6 +398,26 @@ const struct bpf_map_ops mptcp_storage_map_ops = {
> .map_btf_id = &bpf_local_storage_map_btf_id[0],
> .map_owner_storage_ptr = mptcp_storage_ptr,
> };
> +
> +const struct bpf_func_proto bpf_mptcp_storage_get_proto = {
> + .func = bpf_mptcp_storage_get,
> + .gpl_only = false,
> + .ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL,
> + .arg1_type = ARG_CONST_MAP_PTR,
> + .arg2_type = ARG_PTR_TO_BTF_ID_OR_NULL,
> + .arg2_btf_id = &bpf_mptcp_btf_id[0],
No need to add this bpf_mptcp_btf_id, we can use
&btf_sock_ids[BTF_SOCK_TYPE_MPTCP] instead.
> + .arg3_type = ARG_PTR_TO_MAP_VALUE_OR_NULL,
> + .arg4_type = ARG_ANYTHING,
> +};
> +
> +const struct bpf_func_proto bpf_mptcp_storage_delete_proto = {
> + .func = bpf_mptcp_storage_delete,
> + .gpl_only = false,
> + .ret_type = RET_INTEGER,
> + .arg1_type = ARG_CONST_MAP_PTR,
> + .arg2_type = ARG_PTR_TO_BTF_ID_OR_NULL,
> + .arg2_btf_id = &bpf_mptcp_btf_id[0],
Add here too.
-Geliang
> +};
> #endif /* CONFIG_BPF_JIT */
>
> struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk)
> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index f43cf69e47ea..137e0620fd69 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -5570,6 +5570,43 @@ union bpf_attr {
> * 0 on success.
> *
> * **-ENOENT** if the bpf_local_storage cannot be found.
> + *
> + * void *bpf_mptcp_storage_get(struct bpf_map *map, struct mptcp_sock *msk, void *value, u64 flags)
> + * Description
> + * Get a bpf_local_storage from the *msk*.
> + *
> + * Logically, it could be thought of as getting the value from
> + * a *map* with *msk* as the **key**. From this
> + * perspective, the usage is not much different from
> + * **bpf_map_lookup_elem**\ (*map*, **&**\ *msk*) except this
> + * helper enforces the key must be a mptcp_sock and the map must also
> + * be a **BPF_MAP_TYPE_MPTCP_STORAGE**.
> + *
> + * Underneath, the value is stored locally at *msk* instead of
> + * the *map*. The *map* is used as the bpf-local-storage
> + * "type". The bpf-local-storage "type" (i.e. the *map*) is
> + * searched against all bpf_local_storage residing at *msk*.
> + *
> + * An optional *flags* (**BPF_LOCAL_STORAGE_GET_F_CREATE**) can be
> + * used such that a new bpf_local_storage will be
> + * created if one does not exist. *value* can be used
> + * together with **BPF_LOCAL_STORAGE_GET_F_CREATE** to specify
> + * the initial value of a bpf_local_storage. If *value* is
> + * **NULL**, the new bpf_local_storage will be zero initialized.
> + * Return
> + * A bpf_local_storage pointer is returned on success.
> + *
> + * **NULL** if not found or there was an error in adding
> + * a new bpf_local_storage.
> + *
> + * long bpf_mptcp_storage_delete(struct bpf_map *map, struct mptcp_sock *msk)
> + * Description
> + * Delete a bpf_local_storage from the *msk*.
> + *
> + * Return
> + * 0 on success.
> + *
> + * **-ENOENT** if the bpf_local_storage cannot be found.
> */
> #define ___BPF_FUNC_MAPPER(FN, ctx...) \
> FN(unspec, 0, ##ctx) \
> @@ -5784,6 +5821,8 @@ union bpf_attr {
> FN(user_ringbuf_drain, 209, ##ctx) \
> FN(cgrp_storage_get, 210, ##ctx) \
> FN(cgrp_storage_delete, 211, ##ctx) \
> + FN(mptcp_storage_get, 212, ##ctx) \
> + FN(mptcp_storage_delete, 213, ##ctx) \
> /* */
>
> /* backwards-compatibility macros for users of __BPF_FUNC_MAPPER that don't
> --
> 2.35.3
>
next prev parent reply other threads:[~2023-06-26 9:40 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-26 2:23 [PATCH mptcp-next v10 00/13] BPF packet scheduler updates part 1 Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 01/13] Squash to "mptcp: drop last_snd and MPTCP_RESET_SCHEDULER" Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 02/13] Squash to "mptcp: add struct mptcp_sched_ops" Geliang Tang
2023-06-26 9:37 ` Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 03/13] Squash to "mptcp: add sched_data_set_contexts helper" Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 04/13] mptcp: register default scheduler Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 05/13] Squash to "bpf: Add bpf_mptcp_sched_ops" Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 06/13] Squash to "bpf: Add bpf_mptcp_sched_kfunc_set" Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 07/13] bpf: Add mptcp_storage map type Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 08/13] bpf: Add mptcp_storage helpers Geliang Tang
2023-06-26 9:40 ` Geliang Tang [this message]
2023-06-26 2:23 ` [PATCH mptcp-next v10 09/13] Squash to "selftests/bpf: Add mptcp sched structs" Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 10/13] Squash to "selftests/bpf: Add bpf_first scheduler" Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 11/13] Squash to "selftests/bpf: Add bpf_bkup scheduler" Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 12/13] Squash to "selftests/bpf: Add bpf_rr scheduler" Geliang Tang
2023-06-26 2:23 ` [PATCH mptcp-next v10 13/13] Squash to "selftests/bpf: Add bpf_red scheduler" Geliang Tang
2023-06-26 2:57 ` Squash to "selftests/bpf: Add bpf_red scheduler": Build Failure MPTCP CI
2023-06-26 3:07 ` Squash to "selftests/bpf: Add bpf_red scheduler": Tests Results MPTCP CI
2023-06-26 9:19 ` Matthieu Baerts
2023-06-26 9:38 ` Squash to "selftests/bpf: Add bpf_red scheduler": Build Failure MPTCP CI
2023-06-26 10:14 ` Squash to "selftests/bpf: Add bpf_red scheduler": Tests Results MPTCP CI
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230626094047.GB11120@bogon \
--to=geliang.tang@suse.com \
--cc=mptcp@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.