16bf6affeSStanislav Fomichev /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
27c8dce4bSAndrii Nakryiko #include <iostream>
3f8186bf6SAndrii Nakryiko #include <unistd.h>
4f8186bf6SAndrii Nakryiko #include <linux/bpf.h>
5f8186bf6SAndrii Nakryiko #include <linux/btf.h>
63e689141SToke Høiland-Jørgensen #include <bpf/libbpf.h>
73e689141SToke Høiland-Jørgensen #include <bpf/bpf.h>
83e689141SToke Høiland-Jørgensen #include <bpf/btf.h>
97c8dce4bSAndrii Nakryiko #include "test_core_extern.skel.h"
10*c2a0257cSKui-Feng Lee #include "struct_ops_module.skel.h"
116bf6affeSStanislav Fomichev 
12189e0ecaSAndrii Nakryiko template <typename T>
13189e0ecaSAndrii Nakryiko class Skeleton {
14189e0ecaSAndrii Nakryiko private:
15189e0ecaSAndrii Nakryiko 	T *skel;
16189e0ecaSAndrii Nakryiko public:
17189e0ecaSAndrii Nakryiko 	Skeleton(): skel(nullptr) { }
18189e0ecaSAndrii Nakryiko 
19189e0ecaSAndrii Nakryiko 	~Skeleton() { if (skel) T::destroy(skel); }
20189e0ecaSAndrii Nakryiko 
21189e0ecaSAndrii Nakryiko 	int open(const struct bpf_object_open_opts *opts = nullptr)
22189e0ecaSAndrii Nakryiko 	{
23189e0ecaSAndrii Nakryiko 		int err;
24189e0ecaSAndrii Nakryiko 
25189e0ecaSAndrii Nakryiko 		if (skel)
26189e0ecaSAndrii Nakryiko 			return -EBUSY;
27189e0ecaSAndrii Nakryiko 
28189e0ecaSAndrii Nakryiko 		skel = T::open(opts);
29189e0ecaSAndrii Nakryiko 		err = libbpf_get_error(skel);
30189e0ecaSAndrii Nakryiko 		if (err) {
31189e0ecaSAndrii Nakryiko 			skel = nullptr;
32189e0ecaSAndrii Nakryiko 			return err;
33189e0ecaSAndrii Nakryiko 		}
34189e0ecaSAndrii Nakryiko 
35189e0ecaSAndrii Nakryiko 		return 0;
36189e0ecaSAndrii Nakryiko 	}
37189e0ecaSAndrii Nakryiko 
38189e0ecaSAndrii Nakryiko 	int load() { return T::load(skel); }
39189e0ecaSAndrii Nakryiko 
40189e0ecaSAndrii Nakryiko 	int attach() { return T::attach(skel); }
41189e0ecaSAndrii Nakryiko 
42189e0ecaSAndrii Nakryiko 	void detach() { return T::detach(skel); }
43189e0ecaSAndrii Nakryiko 
44189e0ecaSAndrii Nakryiko 	const T* operator->() const { return skel; }
45189e0ecaSAndrii Nakryiko 
46189e0ecaSAndrii Nakryiko 	T* operator->() { return skel; }
47189e0ecaSAndrii Nakryiko 
48189e0ecaSAndrii Nakryiko 	const T *get() const { return skel; }
49189e0ecaSAndrii Nakryiko };
506bf6affeSStanislav Fomichev 
51ecf45e60SJiri Olsa static void dump_printf(void *ctx, const char *fmt, va_list args)
52ecf45e60SJiri Olsa {
53ecf45e60SJiri Olsa }
54ecf45e60SJiri Olsa 
55189e0ecaSAndrii Nakryiko static void try_skeleton_template()
56189e0ecaSAndrii Nakryiko {
57189e0ecaSAndrii Nakryiko 	Skeleton<test_core_extern> skel;
58189e0ecaSAndrii Nakryiko 	std::string prog_name;
59189e0ecaSAndrii Nakryiko 	int err;
60189e0ecaSAndrii Nakryiko 	LIBBPF_OPTS(bpf_object_open_opts, opts);
61189e0ecaSAndrii Nakryiko 
62189e0ecaSAndrii Nakryiko 	err = skel.open(&opts);
63189e0ecaSAndrii Nakryiko 	if (err) {
64189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Skeleton open failed: %d\n", err);
65189e0ecaSAndrii Nakryiko 		return;
66189e0ecaSAndrii Nakryiko 	}
67189e0ecaSAndrii Nakryiko 
68189e0ecaSAndrii Nakryiko 	skel->data->kern_ver = 123;
69189e0ecaSAndrii Nakryiko 	skel->data->int_val = skel->data->ushort_val;
70189e0ecaSAndrii Nakryiko 
71189e0ecaSAndrii Nakryiko 	err = skel.load();
72189e0ecaSAndrii Nakryiko 	if (err) {
73189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Skeleton load failed: %d\n", err);
74189e0ecaSAndrii Nakryiko 		return;
75189e0ecaSAndrii Nakryiko 	}
76189e0ecaSAndrii Nakryiko 
77189e0ecaSAndrii Nakryiko 	if (!skel->kconfig->CONFIG_BPF_SYSCALL)
78189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Seems like CONFIG_BPF_SYSCALL isn't set?!\n");
79189e0ecaSAndrii Nakryiko 
80189e0ecaSAndrii Nakryiko 	err = skel.attach();
81189e0ecaSAndrii Nakryiko 	if (err) {
82189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Skeleton attach failed: %d\n", err);
83189e0ecaSAndrii Nakryiko 		return;
84189e0ecaSAndrii Nakryiko 	}
85189e0ecaSAndrii Nakryiko 
86189e0ecaSAndrii Nakryiko 	prog_name = bpf_program__name(skel->progs.handle_sys_enter);
87189e0ecaSAndrii Nakryiko 	if (prog_name != "handle_sys_enter")
88189e0ecaSAndrii Nakryiko 		fprintf(stderr, "Unexpected program name: %s\n", prog_name.c_str());
89189e0ecaSAndrii Nakryiko 
90189e0ecaSAndrii Nakryiko 	bpf_link__destroy(skel->links.handle_sys_enter);
91189e0ecaSAndrii Nakryiko 	skel->links.handle_sys_enter = bpf_program__attach(skel->progs.handle_sys_enter);
92189e0ecaSAndrii Nakryiko 
93189e0ecaSAndrii Nakryiko 	skel.detach();
94189e0ecaSAndrii Nakryiko 
95df71a42cSTaichi Nishimura 	/* destructor will destroy underlying skeleton */
96189e0ecaSAndrii Nakryiko }
97189e0ecaSAndrii Nakryiko 
986bf6affeSStanislav Fomichev int main(int argc, char *argv[])
996bf6affeSStanislav Fomichev {
100ecf45e60SJiri Olsa 	struct btf_dump_opts opts = { };
1017c8dce4bSAndrii Nakryiko 	struct test_core_extern *skel;
102*c2a0257cSKui-Feng Lee 	struct struct_ops_module *skel2;
103ecf45e60SJiri Olsa 	struct btf *btf;
104f8186bf6SAndrii Nakryiko 	int fd;
1057c8dce4bSAndrii Nakryiko 
106189e0ecaSAndrii Nakryiko 	try_skeleton_template();
107189e0ecaSAndrii Nakryiko 
1086bf6affeSStanislav Fomichev 	/* libbpf.h */
1096bf6affeSStanislav Fomichev 	libbpf_set_print(NULL);
1106bf6affeSStanislav Fomichev 
1116bf6affeSStanislav Fomichev 	/* bpf.h */
1126bf6affeSStanislav Fomichev 	bpf_prog_get_fd_by_id(0);
1136bf6affeSStanislav Fomichev 
1146bf6affeSStanislav Fomichev 	/* btf.h */
115ecf45e60SJiri Olsa 	btf = btf__new(NULL, 0);
116189e0ecaSAndrii Nakryiko 	if (!libbpf_get_error(btf))
117ecf45e60SJiri Olsa 		btf_dump__new(btf, dump_printf, nullptr, &opts);
1186bf6affeSStanislav Fomichev 
1197c8dce4bSAndrii Nakryiko 	/* BPF skeleton */
1207c8dce4bSAndrii Nakryiko 	skel = test_core_extern__open_and_load();
1217c8dce4bSAndrii Nakryiko 	test_core_extern__destroy(skel);
1227c8dce4bSAndrii Nakryiko 
123*c2a0257cSKui-Feng Lee 	skel2 = struct_ops_module__open_and_load();
124*c2a0257cSKui-Feng Lee 	struct_ops_module__destroy(skel2);
125*c2a0257cSKui-Feng Lee 
126f8186bf6SAndrii Nakryiko 	fd = bpf_enable_stats(BPF_STATS_RUN_TIME);
127f8186bf6SAndrii Nakryiko 	if (fd < 0)
128f8186bf6SAndrii Nakryiko 		std::cout << "FAILED to enable stats: " << fd << std::endl;
129f8186bf6SAndrii Nakryiko 	else
130f8186bf6SAndrii Nakryiko 		::close(fd);
131f8186bf6SAndrii Nakryiko 
1327c8dce4bSAndrii Nakryiko 	std::cout << "DONE!" << std::endl;
1337c8dce4bSAndrii Nakryiko 
1346bf6affeSStanislav Fomichev 	return 0;
1356bf6affeSStanislav Fomichev }
136