xref: /linux/tools/testing/selftests/bpf/test_cpp.cpp (revision 001821b0e79716c4e17c71d8e053a23599a7a508)
1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2 #include <iostream>
3 #include <unistd.h>
4 #include <linux/bpf.h>
5 #include <linux/btf.h>
6 #include <bpf/libbpf.h>
7 #include <bpf/bpf.h>
8 #include <bpf/btf.h>
9 #include "test_core_extern.skel.h"
10 #include "struct_ops_module.skel.h"
11 
12 template <typename T>
13 class Skeleton {
14 private:
15 	T *skel;
16 public:
17 	Skeleton(): skel(nullptr) { }
18 
19 	~Skeleton() { if (skel) T::destroy(skel); }
20 
21 	int open(const struct bpf_object_open_opts *opts = nullptr)
22 	{
23 		int err;
24 
25 		if (skel)
26 			return -EBUSY;
27 
28 		skel = T::open(opts);
29 		err = libbpf_get_error(skel);
30 		if (err) {
31 			skel = nullptr;
32 			return err;
33 		}
34 
35 		return 0;
36 	}
37 
38 	int load() { return T::load(skel); }
39 
40 	int attach() { return T::attach(skel); }
41 
42 	void detach() { return T::detach(skel); }
43 
44 	const T* operator->() const { return skel; }
45 
46 	T* operator->() { return skel; }
47 
48 	const T *get() const { return skel; }
49 };
50 
51 static void dump_printf(void *ctx, const char *fmt, va_list args)
52 {
53 }
54 
55 static void try_skeleton_template()
56 {
57 	Skeleton<test_core_extern> skel;
58 	std::string prog_name;
59 	int err;
60 	LIBBPF_OPTS(bpf_object_open_opts, opts);
61 
62 	err = skel.open(&opts);
63 	if (err) {
64 		fprintf(stderr, "Skeleton open failed: %d\n", err);
65 		return;
66 	}
67 
68 	skel->data->kern_ver = 123;
69 	skel->data->int_val = skel->data->ushort_val;
70 
71 	err = skel.load();
72 	if (err) {
73 		fprintf(stderr, "Skeleton load failed: %d\n", err);
74 		return;
75 	}
76 
77 	if (!skel->kconfig->CONFIG_BPF_SYSCALL)
78 		fprintf(stderr, "Seems like CONFIG_BPF_SYSCALL isn't set?!\n");
79 
80 	err = skel.attach();
81 	if (err) {
82 		fprintf(stderr, "Skeleton attach failed: %d\n", err);
83 		return;
84 	}
85 
86 	prog_name = bpf_program__name(skel->progs.handle_sys_enter);
87 	if (prog_name != "handle_sys_enter")
88 		fprintf(stderr, "Unexpected program name: %s\n", prog_name.c_str());
89 
90 	bpf_link__destroy(skel->links.handle_sys_enter);
91 	skel->links.handle_sys_enter = bpf_program__attach(skel->progs.handle_sys_enter);
92 
93 	skel.detach();
94 
95 	/* destructor will destroy underlying skeleton */
96 }
97 
98 int main(int argc, char *argv[])
99 {
100 	struct btf_dump_opts opts = { };
101 	struct test_core_extern *skel;
102 	struct struct_ops_module *skel2;
103 	struct btf *btf;
104 	int fd;
105 
106 	try_skeleton_template();
107 
108 	/* libbpf.h */
109 	libbpf_set_print(NULL);
110 
111 	/* bpf.h */
112 	bpf_prog_get_fd_by_id(0);
113 
114 	/* btf.h */
115 	btf = btf__new(NULL, 0);
116 	if (!libbpf_get_error(btf))
117 		btf_dump__new(btf, dump_printf, nullptr, &opts);
118 
119 	/* BPF skeleton */
120 	skel = test_core_extern__open_and_load();
121 	test_core_extern__destroy(skel);
122 
123 	skel2 = struct_ops_module__open_and_load();
124 	struct_ops_module__destroy(skel2);
125 
126 	fd = bpf_enable_stats(BPF_STATS_RUN_TIME);
127 	if (fd < 0)
128 		std::cout << "FAILED to enable stats: " << fd << std::endl;
129 	else
130 		::close(fd);
131 
132 	std::cout << "DONE!" << std::endl;
133 
134 	return 0;
135 }
136