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().
Unified · Split
| @@ -5,18 +5,100 @@ · 4 unmodified lines | |||
| 5 | #include <bpf/btf.h> | 5 | #include <bpf/btf.h> |
| 6 | #include "test_core_extern.skel.h" | 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 | static void dump_printf(void *ctx, const char *fmt, va_list args) | 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 | int main(int argc, char *argv[]) | 94 | int main(int argc, char *argv[]) |
| 15 | { | 95 | { |
| 16 | struct btf_dump_opts opts = { }; | 96 | struct btf_dump_opts opts = { }; |
| 17 | struct test_core_extern *skel; | 97 | struct test_core_extern *skel; |
| 18 | struct btf *btf; | 98 | struct btf *btf; |
| 19 | 99 | ||
| 100 | try_skeleton_template(); | ||
| 101 | |||
| 20 | /* libbpf.h */ | 102 | /* libbpf.h */ |
| 21 | libbpf_set_print(NULL); | 103 | libbpf_set_print(NULL); |
| 22 | 104 | ||
| @@ -25,7 +107,8 @@ int main(int argc, char *argv[]) · 2 unmodified lines | |||
| 25 | 107 | ||
| 26 | /* btf.h */ | 108 | /* btf.h */ |
| 27 | btf = btf__new(NULL, 0); | 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 | /* BPF skeleton */ | 113 | /* BPF skeleton */ |
| 31 | skel = test_core_extern__open_and_load(); | 114 | skel = test_core_extern__open_and_load(); |