From: thinker.li@gmail.com
To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev,
song@kernel.org, kernel-team@meta.com, andrii@kernel.org
Cc: sinquersw@gmail.com, kuifeng@meta.com,
Kui-Feng Lee <thinker.li@gmail.com>
Subject: [PATCH bpf-next v3 3/5] libbpf: Convert st_ops->data to shadow type.
Date: Tue, 20 Feb 2024 17:23:27 -0800 [thread overview]
Message-ID: <20240221012329.1387275-4-thinker.li@gmail.com> (raw)
In-Reply-To: <20240221012329.1387275-1-thinker.li@gmail.com>
From: Kui-Feng Lee <thinker.li@gmail.com>
Convert st_ops->data to the shadow type of the struct_ops map. The shadow
type of a struct_ops type is a variant of the original struct type
providing a way to access/change the values in the maps of the struct_ops
type.
bpf_map__initial_value() will return st_ops->data for struct_ops types. The
skeleton is going to use it as the pointer to the shadow type of the
original struct type.
One of the main differences between the original struct type and the shadow
type is that all function pointers of the shadow type are converted to
pointers of struct bpf_program. Users can replace these bpf_program
pointers with other BPF programs. The st_ops->progs[] will be updated
before updating the value of a map to reflect the changes made by users.
Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
---
tools/lib/bpf/libbpf.c | 53 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 465b50235a01..becbb4d81012 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1102,6 +1102,9 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
if (btf_is_ptr(mtype)) {
struct bpf_program *prog;
+ /* Update the value from the shadow type */
+ st_ops->progs[i] = *(struct bpf_program **)mdata;
+
prog = st_ops->progs[i];
if (!prog)
continue;
@@ -1172,6 +1175,36 @@ static int bpf_object__init_kern_struct_ops_maps(struct bpf_object *obj)
return 0;
}
+/* Convert the data of a struct_ops map to shadow type.
+ *
+ * The function pointers are replaced with the pointers of bpf_program in
+ * st_ops->progs[].
+ */
+static void struct_ops_convert_shadow(struct bpf_map *map,
+ const struct btf_type *t)
+{
+ struct btf *btf = map->obj->btf;
+ struct bpf_struct_ops *st_ops = map->st_ops;
+ const struct btf_member *m;
+ const struct btf_type *mtype;
+ char *data;
+ int i;
+
+ data = st_ops->data;
+
+ for (i = 0, m = btf_members(t); i < btf_vlen(t); i++, m++) {
+ mtype = skip_mods_and_typedefs(btf, m->type, NULL);
+
+ if (btf_kind(mtype) != BTF_KIND_PTR)
+ continue;
+ if (!resolve_func_ptr(btf, m->type, NULL))
+ continue;
+
+ *((struct bpf_program **)(data + m->offset / 8)) =
+ st_ops->progs[i];
+ }
+}
+
static int init_struct_ops_maps(struct bpf_object *obj, const char *sec_name,
int shndx, Elf_Data *data, __u32 map_flags)
{
@@ -7531,6 +7564,19 @@ static int bpf_object_init_progs(struct bpf_object *obj, const struct bpf_object
return 0;
}
+/* Convert the data to the shadow type for each struct_ops map. */
+static void bpf_object__init_shadow(struct bpf_object *obj)
+{
+ struct bpf_map *map;
+
+ bpf_object__for_each_map(map, obj) {
+ if (!bpf_map__is_struct_ops(map))
+ continue;
+
+ struct_ops_convert_shadow(map, map->st_ops->type);
+ }
+}
+
static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf, size_t obj_buf_sz,
const struct bpf_object_open_opts *opts)
{
@@ -7631,6 +7677,7 @@ static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf,
goto out;
bpf_object__elf_finish(obj);
+ bpf_object__init_shadow(obj);
return obj;
out:
@@ -9880,6 +9927,12 @@ int bpf_map__set_initial_value(struct bpf_map *map,
void *bpf_map__initial_value(struct bpf_map *map, size_t *psize)
{
+ if (bpf_map__is_struct_ops(map)) {
+ if (psize)
+ *psize = map->def.value_size;
+ return map->st_ops->data;
+ }
+
if (!map->mmaped)
return NULL;
*psize = map->def.value_size;
--
2.34.1
next prev parent reply other threads:[~2024-02-21 1:23 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-21 1:23 [PATCH bpf-next v3 0/5] Create shadow types for struct_ops maps in skeletons thinker.li
2024-02-21 1:23 ` [PATCH bpf-next v3 1/5] libbpf: expose resolve_func_ptr() through libbpf_internal.h thinker.li
2024-02-21 11:49 ` Quentin Monnet
2024-02-21 16:32 ` Kui-Feng Lee
2024-02-21 1:23 ` [PATCH bpf-next v3 2/5] libbpf: set btf_value_type_id of struct bpf_map for struct_ops thinker.li
2024-02-21 1:23 ` thinker.li [this message]
2024-02-21 1:23 ` [PATCH bpf-next v3 4/5] bpftool: generated shadow variables for struct_ops maps thinker.li
2024-02-21 11:49 ` Quentin Monnet
2024-02-21 17:47 ` Kui-Feng Lee
2024-02-21 1:23 ` [PATCH bpf-next v3 5/5] selftests/bpf: Test if shadow types work correctly thinker.li
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=20240221012329.1387275-4-thinker.li@gmail.com \
--to=thinker.li@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=kernel-team@meta.com \
--cc=kuifeng@meta.com \
--cc=martin.lau@linux.dev \
--cc=sinquersw@gmail.com \
--cc=song@kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox