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