Add an example of how to build C++ template-based BPF skeleton wrapper. It's an actually runnable valid use of skeleton through more C++-like interface. Note that skeleton destuction happens implicitly through Skeleton<T>'s destructor. Also make test_cpp runnable as it would have crashed on invalid btf passed into btf_dump__new().
Showing the changes to tools/testing/selftests/bpf/test_cpp.cpp (1 of 1 file). Show all
Unified · Split
| @@ -5,18 +5,100 @@ · 4 unmodified lines | ||
| 5 | 5 | #include <bpf/btf.h> |
| 6 | 6 | #include "test_core_extern.skel.h" |
| 7 | 7 | |
| 8 | −/* do nothing, just make sure we can link successfully */ | |
| 8 | +template <typename T> | |
| 9 | +class Skeleton { | |
| 10 | +private: | |
| 11 | + T *skel; | |
| 12 | +public: | |
| 13 | + Skeleton(): skel(nullptr) { } | |
| 14 | + | |
| 15 | + ~Skeleton() { if (skel) T::destroy(skel); } | |
| 16 | + | |
| 17 | + int open(const struct bpf_object_open_opts *opts = nullptr) | |
| 18 | + { | |
| 19 | + int err; | |
| 20 | + | |
| 21 | + if (skel) | |
| 22 | + return -EBUSY; | |
| 23 | + | |
| 24 | + skel = T::open(opts); | |
| 25 | + err = libbpf_get_error(skel); | |
| 26 | + if (err) { | |
| 27 | + skel = nullptr; | |
| 28 | + return err; | |
| 29 | + } | |
| 30 | + | |
| 31 | + return 0; | |
| 32 | + } | |
| 33 | + | |
| 34 | + int load() { return T::load(skel); } | |
| 35 | + | |
| 36 | + int attach() { return T::attach(skel); } | |
| 37 | + | |
| 38 | + void detach() { return T::detach(skel); } | |
| 39 | + | |
| 40 | + const T* operator->() const { return skel; } | |
| 41 | + | |
| 42 | + T* operator->() { return skel; } | |
| 43 | + | |
| 44 | + const T *get() const { return skel; } | |
| 45 | +}; | |
| 9 | 46 | |
| 10 | 47 | static void dump_printf(void *ctx, const char *fmt, va_list args) |
| 11 | 48 | { |
| 12 | 49 | } |
| 13 | 50 | |
| 51 | +static void try_skeleton_template() | |
| 52 | +{ | |
| 53 | + Skeleton<test_core_extern> skel; | |
| 54 | + std::string prog_name; | |
| 55 | + int err; | |
| 56 | + LIBBPF_OPTS(bpf_object_open_opts, opts); | |
| 57 | + | |
| 58 | + err = skel.open(&opts); | |
| 59 | + if (err) { | |
| 60 | + fprintf(stderr, "Skeleton open failed: %d\n", err); | |
| 61 | + return; | |
| 62 | + } | |
| 63 | + | |
| 64 | + skel->data->kern_ver = 123; | |
| 65 | + skel->data->int_val = skel->data->ushort_val; | |
| 66 | + | |
| 67 | + err = skel.load(); | |
| 68 | + if (err) { | |
| 69 | + fprintf(stderr, "Skeleton load failed: %d\n", err); | |
| 70 | + return; | |
| 71 | + } | |
| 72 | + | |
| 73 | + if (!skel->kconfig->CONFIG_BPF_SYSCALL) | |
| 74 | + fprintf(stderr, "Seems like CONFIG_BPF_SYSCALL isn't set?!\n"); | |
| 75 | + | |
| 76 | + err = skel.attach(); | |
| 77 | + if (err) { | |
| 78 | + fprintf(stderr, "Skeleton attach failed: %d\n", err); | |
| 79 | + return; | |
| 80 | + } | |
| 81 | + | |
| 82 | + prog_name = bpf_program__name(skel->progs.handle_sys_enter); | |
| 83 | + if (prog_name != "handle_sys_enter") | |
| 84 | + fprintf(stderr, "Unexpected program name: %s\n", prog_name.c_str()); | |
| 85 | + | |
| 86 | + bpf_link__destroy(skel->links.handle_sys_enter); | |
| 87 | + skel->links.handle_sys_enter = bpf_program__attach(skel->progs.handle_sys_enter); | |
| 88 | + | |
| 89 | + skel.detach(); | |
| 90 | + | |
| 91 | + /* destructor will destory underlying skeleton */ | |
| 92 | +} | |
| 93 | + | |
| 14 | 94 | int main(int argc, char *argv[]) |
| 15 | 95 | { |
| 16 | 96 | struct btf_dump_opts opts = { }; |
| 17 | 97 | struct test_core_extern *skel; |
| 18 | 98 | struct btf *btf; |
| 19 | 99 | |
| 100 | + try_skeleton_template(); | |
| 101 | + | |
| 20 | 102 | /* libbpf.h */ |
| 21 | 103 | libbpf_set_print(NULL); |
| 22 | 104 | |
| @@ -25,7 +107,8 @@ int main(int argc, char *argv[]) · 2 unmodified lines | ||
| 25 | 107 | |
| 26 | 108 | /* btf.h */ |
| 27 | 109 | btf = btf__new(NULL, 0); |
| 28 | − btf_dump__new(btf, dump_printf, nullptr, &opts); | |
| 110 | + if (!libbpf_get_error(btf)) | |
| 111 | + btf_dump__new(btf, dump_printf, nullptr, &opts); | |
| 29 | 112 | |
| 30 | 113 | /* BPF skeleton */ |
| 31 | 114 | skel = test_core_extern__open_and_load(); |