@@ -473,7 +473,7 @@ struct bpf_program {
struct bpf_object *obj;
int fd;
- bool autoload;
+ enum bpf_prog_load_type load_type;
bool autoattach;
bool sym_global;
bool mark_btf_static;
@@ -824,11 +824,11 @@ bpf_object__init_prog(struct bpf_object *obj, struct bpf_program *prog,
* autoload set to false.
*/
if (sec_name[0] == '?') {
- prog->autoload = false;
+ prog->load_type = BPF_PROG_LOAD_TYPE_DISABLED;
/* from now on forget there was ? in section name */
sec_name++;
} else {
- prog->autoload = true;
+ prog->load_type = BPF_PROG_LOAD_TYPE_AUTO;
}
prog->autoattach = true;
@@ -1117,7 +1117,8 @@ static int bpf_object_adjust_struct_ops_autoload(struct bpf_object *obj)
}
}
if (use_cnt)
- prog->autoload = should_load;
+ prog->load_type = should_load ? BPF_PROG_LOAD_TYPE_AUTO
+ : BPF_PROG_LOAD_TYPE_DISABLED;
}
return 0;
@@ -1202,7 +1203,7 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
* then bpf_object_adjust_struct_ops_autoload() will update its
* autoload accordingly.
*/
- st_ops->progs[i]->autoload = false;
+ st_ops->progs[i]->load_type = BPF_PROG_LOAD_TYPE_DISABLED;
st_ops->progs[i] = NULL;
}
@@ -1241,7 +1242,7 @@ static int bpf_map__init_kern_struct_ops(struct bpf_map *map)
* if user replaced it with another program or NULL
*/
if (st_ops->progs[i] && st_ops->progs[i] != prog)
- st_ops->progs[i]->autoload = false;
+ st_ops->progs[i]->load_type = BPF_PROG_LOAD_TYPE_DISABLED;
/* Update the value from the shadow type */
st_ops->progs[i] = prog;
@@ -3482,7 +3483,7 @@ static bool obj_needs_vmlinux_btf(const struct bpf_object *obj)
}
bpf_object__for_each_program(prog, obj) {
- if (!prog->autoload)
+ if (prog->load_type == BPF_PROG_LOAD_TYPE_DISABLED)
continue;
if (prog_needs_vmlinux_btf(prog))
return true;
@@ -5973,7 +5974,7 @@ bpf_object__relocate_core(struct bpf_object *obj, const char *targ_btf_path)
/* no need to apply CO-RE relocation if the program is
* not going to be loaded
*/
- if (!prog->autoload)
+ if (prog->load_type == BPF_PROG_LOAD_TYPE_DISABLED)
continue;
/* adjust insn_idx from section frame of reference to the local
@@ -7106,7 +7107,7 @@ static int bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_pat
*/
if (prog_is_subprog(obj, prog))
continue;
- if (!prog->autoload)
+ if (prog->load_type == BPF_PROG_LOAD_TYPE_DISABLED)
continue;
err = bpf_object__relocate_calls(obj, prog);
@@ -7142,7 +7143,7 @@ static int bpf_object__relocate(struct bpf_object *obj, const char *targ_btf_pat
prog = &obj->programs[i];
if (prog_is_subprog(obj, prog))
continue;
- if (!prog->autoload)
+ if (prog->load_type == BPF_PROG_LOAD_TYPE_DISABLED)
continue;
/* Process data relos for main programs */
@@ -7906,8 +7907,8 @@ bpf_object__load_progs(struct bpf_object *obj, int log_level)
prog = &obj->programs[i];
if (prog_is_subprog(obj, prog))
continue;
- if (!prog->autoload) {
- pr_debug("prog '%s': skipped loading\n", prog->name);
+ if (prog->load_type != BPF_PROG_LOAD_TYPE_AUTO) {
+ pr_debug("prog '%s': skipped auto-loading\n", prog->name);
continue;
}
prog->log_level |= log_level;
@@ -9224,16 +9225,13 @@ const char *bpf_program__section_name(const struct bpf_program *prog)
bool bpf_program__autoload(const struct bpf_program *prog)
{
- return prog->autoload;
+ return prog->load_type == BPF_PROG_LOAD_TYPE_AUTO;
}
int bpf_program__set_autoload(struct bpf_program *prog, bool autoload)
{
- if (prog->obj->loaded)
- return libbpf_err(-EINVAL);
-
- prog->autoload = autoload;
- return 0;
+ return bpf_program__set_load_type(prog,
+ autoload ? BPF_PROG_LOAD_TYPE_AUTO : BPF_PROG_LOAD_TYPE_DISABLED);
}
bool bpf_program__autoattach(const struct bpf_program *prog)
@@ -13983,7 +13981,7 @@ int bpf_object__attach_skeleton(struct bpf_object_skeleton *s)
struct bpf_program *prog = *prog_skel->prog;
struct bpf_link **link = prog_skel->link;
- if (!prog->autoload || !prog->autoattach)
+ if (prog->load_type != BPF_PROG_LOAD_TYPE_AUTO || !prog->autoattach)
continue;
/* auto-attaching not supported for this program */
@@ -14087,3 +14085,17 @@ void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s)
free(s->progs);
free(s);
}
+
+int bpf_program__set_load_type(struct bpf_program *prog, enum bpf_prog_load_type type)
+{
+ if (prog->obj->loaded)
+ return libbpf_err(-EINVAL);
+
+ prog->load_type = type;
+ return 0;
+}
+
+enum bpf_prog_load_type bpf_program__load_type(const struct bpf_program *prog)
+{
+ return prog->load_type;
+}
@@ -1918,6 +1918,22 @@ LIBBPF_API int libbpf_register_prog_handler(const char *sec,
*/
LIBBPF_API int libbpf_unregister_prog_handler(int handler_id);
+/**
+ * The program load type:
+ *
+ * - BPF_PROG_LOAD_TYPE_DISABLED: the program is not loaded.
+ * - BPF_PROG_LOAD_TYPE_AUTO: the program is autoloaded when the bpf_object is loaded.
+ */
+enum bpf_prog_load_type {
+ BPF_PROG_LOAD_TYPE_DISABLED = 0,
+ BPF_PROG_LOAD_TYPE_AUTO,
+};
+
+LIBBPF_API int bpf_program__set_load_type(struct bpf_program *prog,
+ enum bpf_prog_load_type loadtype);
+LIBBPF_API enum bpf_prog_load_type bpf_program__load_type(const struct bpf_program *prog);
+
+
#ifdef __cplusplus
} /* extern "C" */
#endif
@@ -436,4 +436,6 @@ LIBBPF_1.6.0 {
bpf_linker__add_buf;
bpf_linker__add_fd;
bpf_linker__new_fd;
+ bpf_program__load_type;
+ bpf_program__set_load_type;
} LIBBPF_1.5.0;
new file mode 100644
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <test_progs.h>
+#include <time.h>
+#include "test_load_type.skel.h"
+
+void test_load_type(void)
+{
+ int duration = 0, err;
+ struct test_load_type *skel;
+
+ skel = test_load_type__open();
+ if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
+ goto cleanup;
+
+ /* don't load prog1 */
+ bpf_program__set_load_type(skel->progs.prog1, BPF_PROG_LOAD_TYPE_DISABLED);
+
+ /* load and attach prog2 */
+ bpf_program__set_load_type(skel->progs.prog2, BPF_PROG_LOAD_TYPE_AUTO);
+ CHECK(!bpf_program__autoload(skel->progs.prog2), "prog2", "not autoload?!\n");
+
+ err = test_load_type__load(skel);
+ if (CHECK(err, "skel_load", "failed to load skeleton: %d\n", err))
+ goto cleanup;
+
+ CHECK(!bpf_program__autoattach(skel->progs.prog2), "prog2", "not autoattach?!\n");
+
+ err = test_load_type__attach(skel);
+ if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err))
+ goto cleanup;
+
+ usleep(1);
+
+ CHECK(skel->bss->prog1_called, "prog1", "called?!\n");
+ CHECK(!skel->bss->prog2_called, "prog2", "not called\n");
+
+cleanup:
+ test_load_type__destroy(skel);
+}
new file mode 100644
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+
+bool prog1_called = false;
+bool prog2_called = false;
+
+SEC("raw_tp/sys_enter")
+int prog1(const void *ctx)
+{
+ prog1_called = true;
+ return 0;
+}
+
+SEC("raw_tp/sys_enter")
+int prog2(const void *ctx)
+{
+ prog2_called = true;
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
Replacing the boolean field with an enum simplifies the addition of new load types. Currently, the bpf_program structure defines the autoload type using a boolean field. This field is now replaced with an enum, allowing new BPF program loading types to be introduced by extending the enum value range. This patch is the first in a series of two. Signed-off-by: Slava Imameev <slava.imameev@crowdstrike.com> --- tools/lib/bpf/libbpf.c | 50 ++++++++++++------- tools/lib/bpf/libbpf.h | 16 ++++++ tools/lib/bpf/libbpf.map | 2 + .../selftests/bpf/prog_tests/load_type.c | 40 +++++++++++++++ .../selftests/bpf/progs/test_load_type.c | 23 +++++++++ 5 files changed, 112 insertions(+), 19 deletions(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/load_type.c create mode 100644 tools/testing/selftests/bpf/progs/test_load_type.c