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