167234743SAlexei Starovoitov /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 267234743SAlexei Starovoitov /* Copyright (c) 2021 Facebook */ 367234743SAlexei Starovoitov #ifndef __SKEL_INTERNAL_H 467234743SAlexei Starovoitov #define __SKEL_INTERNAL_H 567234743SAlexei Starovoitov 667234743SAlexei Starovoitov #include <unistd.h> 767234743SAlexei Starovoitov #include <sys/syscall.h> 867234743SAlexei Starovoitov #include <sys/mman.h> 967234743SAlexei Starovoitov 10e32cb12fSTiezhu Yang #ifndef __NR_bpf 11e32cb12fSTiezhu Yang # if defined(__mips__) && defined(_ABIO32) 12e32cb12fSTiezhu Yang # define __NR_bpf 4355 13e32cb12fSTiezhu Yang # elif defined(__mips__) && defined(_ABIN32) 14e32cb12fSTiezhu Yang # define __NR_bpf 6319 15e32cb12fSTiezhu Yang # elif defined(__mips__) && defined(_ABI64) 16e32cb12fSTiezhu Yang # define __NR_bpf 5315 17e32cb12fSTiezhu Yang # endif 18e32cb12fSTiezhu Yang #endif 19e32cb12fSTiezhu Yang 2067234743SAlexei Starovoitov /* This file is a base header for auto-generated *.lskel.h files. 2167234743SAlexei Starovoitov * Its contents will change and may become part of auto-generation in the future. 2267234743SAlexei Starovoitov * 2367234743SAlexei Starovoitov * The layout of bpf_[map|prog]_desc and bpf_loader_ctx is feature dependent 2467234743SAlexei Starovoitov * and will change from one version of libbpf to another and features 2567234743SAlexei Starovoitov * requested during loader program generation. 2667234743SAlexei Starovoitov */ 2767234743SAlexei Starovoitov struct bpf_map_desc { 2867234743SAlexei Starovoitov union { 2967234743SAlexei Starovoitov /* input for the loader prog */ 3067234743SAlexei Starovoitov struct { 3167234743SAlexei Starovoitov __aligned_u64 initial_value; 3267234743SAlexei Starovoitov __u32 max_entries; 3367234743SAlexei Starovoitov }; 3467234743SAlexei Starovoitov /* output of the loader prog */ 3567234743SAlexei Starovoitov struct { 3667234743SAlexei Starovoitov int map_fd; 3767234743SAlexei Starovoitov }; 3867234743SAlexei Starovoitov }; 3967234743SAlexei Starovoitov }; 4067234743SAlexei Starovoitov struct bpf_prog_desc { 4167234743SAlexei Starovoitov int prog_fd; 4267234743SAlexei Starovoitov }; 4367234743SAlexei Starovoitov 4467234743SAlexei Starovoitov struct bpf_loader_ctx { 4567234743SAlexei Starovoitov size_t sz; 4667234743SAlexei Starovoitov __u32 log_level; 4767234743SAlexei Starovoitov __u32 log_size; 4867234743SAlexei Starovoitov __u64 log_buf; 4967234743SAlexei Starovoitov }; 5067234743SAlexei Starovoitov 5167234743SAlexei Starovoitov struct bpf_load_and_run_opts { 5267234743SAlexei Starovoitov struct bpf_loader_ctx *ctx; 5367234743SAlexei Starovoitov const void *data; 5467234743SAlexei Starovoitov const void *insns; 5567234743SAlexei Starovoitov __u32 data_sz; 5667234743SAlexei Starovoitov __u32 insns_sz; 5767234743SAlexei Starovoitov const char *errstr; 5867234743SAlexei Starovoitov }; 5967234743SAlexei Starovoitov 6067234743SAlexei Starovoitov static inline int skel_sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, 6167234743SAlexei Starovoitov unsigned int size) 6267234743SAlexei Starovoitov { 6367234743SAlexei Starovoitov return syscall(__NR_bpf, cmd, attr, size); 6467234743SAlexei Starovoitov } 6567234743SAlexei Starovoitov 6667234743SAlexei Starovoitov static inline int skel_closenz(int fd) 6767234743SAlexei Starovoitov { 6867234743SAlexei Starovoitov if (fd > 0) 6967234743SAlexei Starovoitov return close(fd); 7067234743SAlexei Starovoitov return -EINVAL; 7167234743SAlexei Starovoitov } 7267234743SAlexei Starovoitov 73e981f41fSAlexei Starovoitov #ifndef offsetofend 74e981f41fSAlexei Starovoitov #define offsetofend(TYPE, MEMBER) \ 75e981f41fSAlexei Starovoitov (offsetof(TYPE, MEMBER) + sizeof((((TYPE *)0)->MEMBER))) 76e981f41fSAlexei Starovoitov #endif 77e981f41fSAlexei Starovoitov 78e981f41fSAlexei Starovoitov static inline int skel_map_create(enum bpf_map_type map_type, 79e981f41fSAlexei Starovoitov const char *map_name, 80e981f41fSAlexei Starovoitov __u32 key_size, 81e981f41fSAlexei Starovoitov __u32 value_size, 82e981f41fSAlexei Starovoitov __u32 max_entries) 83e981f41fSAlexei Starovoitov { 84e981f41fSAlexei Starovoitov const size_t attr_sz = offsetofend(union bpf_attr, map_extra); 85e981f41fSAlexei Starovoitov union bpf_attr attr; 86e981f41fSAlexei Starovoitov 87e981f41fSAlexei Starovoitov memset(&attr, 0, attr_sz); 88e981f41fSAlexei Starovoitov 89e981f41fSAlexei Starovoitov attr.map_type = map_type; 90e981f41fSAlexei Starovoitov strncpy(attr.map_name, map_name, sizeof(attr.map_name)); 91e981f41fSAlexei Starovoitov attr.key_size = key_size; 92e981f41fSAlexei Starovoitov attr.value_size = value_size; 93e981f41fSAlexei Starovoitov attr.max_entries = max_entries; 94e981f41fSAlexei Starovoitov 95e981f41fSAlexei Starovoitov return skel_sys_bpf(BPF_MAP_CREATE, &attr, attr_sz); 96e981f41fSAlexei Starovoitov } 97e981f41fSAlexei Starovoitov 98e981f41fSAlexei Starovoitov static inline int skel_map_update_elem(int fd, const void *key, 99e981f41fSAlexei Starovoitov const void *value, __u64 flags) 100e981f41fSAlexei Starovoitov { 101e981f41fSAlexei Starovoitov const size_t attr_sz = offsetofend(union bpf_attr, flags); 102e981f41fSAlexei Starovoitov union bpf_attr attr; 103e981f41fSAlexei Starovoitov 104e981f41fSAlexei Starovoitov memset(&attr, 0, attr_sz); 105e981f41fSAlexei Starovoitov attr.map_fd = fd; 106e981f41fSAlexei Starovoitov attr.key = (long) key; 107e981f41fSAlexei Starovoitov attr.value = (long) value; 108e981f41fSAlexei Starovoitov attr.flags = flags; 109e981f41fSAlexei Starovoitov 110e981f41fSAlexei Starovoitov return skel_sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, attr_sz); 111e981f41fSAlexei Starovoitov } 112e981f41fSAlexei Starovoitov 113*c69f94a3SAlexei Starovoitov static inline int skel_raw_tracepoint_open(const char *name, int prog_fd) 114*c69f94a3SAlexei Starovoitov { 115*c69f94a3SAlexei Starovoitov const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint.prog_fd); 116*c69f94a3SAlexei Starovoitov union bpf_attr attr; 117*c69f94a3SAlexei Starovoitov 118*c69f94a3SAlexei Starovoitov memset(&attr, 0, attr_sz); 119*c69f94a3SAlexei Starovoitov attr.raw_tracepoint.name = (long) name; 120*c69f94a3SAlexei Starovoitov attr.raw_tracepoint.prog_fd = prog_fd; 121*c69f94a3SAlexei Starovoitov 122*c69f94a3SAlexei Starovoitov return skel_sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz); 123*c69f94a3SAlexei Starovoitov } 124*c69f94a3SAlexei Starovoitov 125*c69f94a3SAlexei Starovoitov static inline int skel_link_create(int prog_fd, int target_fd, 126*c69f94a3SAlexei Starovoitov enum bpf_attach_type attach_type) 127*c69f94a3SAlexei Starovoitov { 128*c69f94a3SAlexei Starovoitov const size_t attr_sz = offsetofend(union bpf_attr, link_create.iter_info_len); 129*c69f94a3SAlexei Starovoitov union bpf_attr attr; 130*c69f94a3SAlexei Starovoitov 131*c69f94a3SAlexei Starovoitov memset(&attr, 0, attr_sz); 132*c69f94a3SAlexei Starovoitov attr.link_create.prog_fd = prog_fd; 133*c69f94a3SAlexei Starovoitov attr.link_create.target_fd = target_fd; 134*c69f94a3SAlexei Starovoitov attr.link_create.attach_type = attach_type; 135*c69f94a3SAlexei Starovoitov 136*c69f94a3SAlexei Starovoitov return skel_sys_bpf(BPF_LINK_CREATE, &attr, attr_sz); 137*c69f94a3SAlexei Starovoitov } 138*c69f94a3SAlexei Starovoitov 13967234743SAlexei Starovoitov static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts) 14067234743SAlexei Starovoitov { 14167234743SAlexei Starovoitov int map_fd = -1, prog_fd = -1, key = 0, err; 14267234743SAlexei Starovoitov union bpf_attr attr; 14367234743SAlexei Starovoitov 144e981f41fSAlexei Starovoitov map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1); 14567234743SAlexei Starovoitov if (map_fd < 0) { 14667234743SAlexei Starovoitov opts->errstr = "failed to create loader map"; 14767234743SAlexei Starovoitov err = -errno; 14867234743SAlexei Starovoitov goto out; 14967234743SAlexei Starovoitov } 15067234743SAlexei Starovoitov 151e981f41fSAlexei Starovoitov err = skel_map_update_elem(map_fd, &key, opts->data, 0); 15267234743SAlexei Starovoitov if (err < 0) { 15367234743SAlexei Starovoitov opts->errstr = "failed to update loader map"; 15467234743SAlexei Starovoitov err = -errno; 15567234743SAlexei Starovoitov goto out; 15667234743SAlexei Starovoitov } 15767234743SAlexei Starovoitov 15867234743SAlexei Starovoitov memset(&attr, 0, sizeof(attr)); 15967234743SAlexei Starovoitov attr.prog_type = BPF_PROG_TYPE_SYSCALL; 16067234743SAlexei Starovoitov attr.insns = (long) opts->insns; 16167234743SAlexei Starovoitov attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn); 16267234743SAlexei Starovoitov attr.license = (long) "Dual BSD/GPL"; 16367234743SAlexei Starovoitov memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog")); 16467234743SAlexei Starovoitov attr.fd_array = (long) &map_fd; 16567234743SAlexei Starovoitov attr.log_level = opts->ctx->log_level; 16667234743SAlexei Starovoitov attr.log_size = opts->ctx->log_size; 16767234743SAlexei Starovoitov attr.log_buf = opts->ctx->log_buf; 16867234743SAlexei Starovoitov attr.prog_flags = BPF_F_SLEEPABLE; 16967234743SAlexei Starovoitov prog_fd = skel_sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 17067234743SAlexei Starovoitov if (prog_fd < 0) { 17167234743SAlexei Starovoitov opts->errstr = "failed to load loader prog"; 17267234743SAlexei Starovoitov err = -errno; 17367234743SAlexei Starovoitov goto out; 17467234743SAlexei Starovoitov } 17567234743SAlexei Starovoitov 17667234743SAlexei Starovoitov memset(&attr, 0, sizeof(attr)); 17767234743SAlexei Starovoitov attr.test.prog_fd = prog_fd; 17867234743SAlexei Starovoitov attr.test.ctx_in = (long) opts->ctx; 17967234743SAlexei Starovoitov attr.test.ctx_size_in = opts->ctx->sz; 1805d67f349SAlexei Starovoitov err = skel_sys_bpf(BPF_PROG_RUN, &attr, sizeof(attr)); 18167234743SAlexei Starovoitov if (err < 0 || (int)attr.test.retval < 0) { 18267234743SAlexei Starovoitov opts->errstr = "failed to execute loader prog"; 183e68ac008SKumar Kartikeya Dwivedi if (err < 0) { 18467234743SAlexei Starovoitov err = -errno; 185e68ac008SKumar Kartikeya Dwivedi } else { 18667234743SAlexei Starovoitov err = (int)attr.test.retval; 187e68ac008SKumar Kartikeya Dwivedi errno = -err; 188e68ac008SKumar Kartikeya Dwivedi } 18967234743SAlexei Starovoitov goto out; 19067234743SAlexei Starovoitov } 19167234743SAlexei Starovoitov err = 0; 19267234743SAlexei Starovoitov out: 19367234743SAlexei Starovoitov if (map_fd >= 0) 19467234743SAlexei Starovoitov close(map_fd); 19567234743SAlexei Starovoitov if (prog_fd >= 0) 19667234743SAlexei Starovoitov close(prog_fd); 19767234743SAlexei Starovoitov return err; 19867234743SAlexei Starovoitov } 19967234743SAlexei Starovoitov 20067234743SAlexei Starovoitov #endif 201