1*67234743SAlexei Starovoitov /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2*67234743SAlexei Starovoitov /* Copyright (c) 2021 Facebook */ 3*67234743SAlexei Starovoitov #ifndef __SKEL_INTERNAL_H 4*67234743SAlexei Starovoitov #define __SKEL_INTERNAL_H 5*67234743SAlexei Starovoitov 6*67234743SAlexei Starovoitov #include <unistd.h> 7*67234743SAlexei Starovoitov #include <sys/syscall.h> 8*67234743SAlexei Starovoitov #include <sys/mman.h> 9*67234743SAlexei Starovoitov 10*67234743SAlexei Starovoitov /* This file is a base header for auto-generated *.lskel.h files. 11*67234743SAlexei Starovoitov * Its contents will change and may become part of auto-generation in the future. 12*67234743SAlexei Starovoitov * 13*67234743SAlexei Starovoitov * The layout of bpf_[map|prog]_desc and bpf_loader_ctx is feature dependent 14*67234743SAlexei Starovoitov * and will change from one version of libbpf to another and features 15*67234743SAlexei Starovoitov * requested during loader program generation. 16*67234743SAlexei Starovoitov */ 17*67234743SAlexei Starovoitov struct bpf_map_desc { 18*67234743SAlexei Starovoitov union { 19*67234743SAlexei Starovoitov /* input for the loader prog */ 20*67234743SAlexei Starovoitov struct { 21*67234743SAlexei Starovoitov __aligned_u64 initial_value; 22*67234743SAlexei Starovoitov __u32 max_entries; 23*67234743SAlexei Starovoitov }; 24*67234743SAlexei Starovoitov /* output of the loader prog */ 25*67234743SAlexei Starovoitov struct { 26*67234743SAlexei Starovoitov int map_fd; 27*67234743SAlexei Starovoitov }; 28*67234743SAlexei Starovoitov }; 29*67234743SAlexei Starovoitov }; 30*67234743SAlexei Starovoitov struct bpf_prog_desc { 31*67234743SAlexei Starovoitov int prog_fd; 32*67234743SAlexei Starovoitov }; 33*67234743SAlexei Starovoitov 34*67234743SAlexei Starovoitov struct bpf_loader_ctx { 35*67234743SAlexei Starovoitov size_t sz; 36*67234743SAlexei Starovoitov __u32 log_level; 37*67234743SAlexei Starovoitov __u32 log_size; 38*67234743SAlexei Starovoitov __u64 log_buf; 39*67234743SAlexei Starovoitov }; 40*67234743SAlexei Starovoitov 41*67234743SAlexei Starovoitov struct bpf_load_and_run_opts { 42*67234743SAlexei Starovoitov struct bpf_loader_ctx *ctx; 43*67234743SAlexei Starovoitov const void *data; 44*67234743SAlexei Starovoitov const void *insns; 45*67234743SAlexei Starovoitov __u32 data_sz; 46*67234743SAlexei Starovoitov __u32 insns_sz; 47*67234743SAlexei Starovoitov const char *errstr; 48*67234743SAlexei Starovoitov }; 49*67234743SAlexei Starovoitov 50*67234743SAlexei Starovoitov static inline int skel_sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, 51*67234743SAlexei Starovoitov unsigned int size) 52*67234743SAlexei Starovoitov { 53*67234743SAlexei Starovoitov return syscall(__NR_bpf, cmd, attr, size); 54*67234743SAlexei Starovoitov } 55*67234743SAlexei Starovoitov 56*67234743SAlexei Starovoitov static inline int skel_closenz(int fd) 57*67234743SAlexei Starovoitov { 58*67234743SAlexei Starovoitov if (fd > 0) 59*67234743SAlexei Starovoitov return close(fd); 60*67234743SAlexei Starovoitov return -EINVAL; 61*67234743SAlexei Starovoitov } 62*67234743SAlexei Starovoitov 63*67234743SAlexei Starovoitov static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts) 64*67234743SAlexei Starovoitov { 65*67234743SAlexei Starovoitov int map_fd = -1, prog_fd = -1, key = 0, err; 66*67234743SAlexei Starovoitov union bpf_attr attr; 67*67234743SAlexei Starovoitov 68*67234743SAlexei Starovoitov map_fd = bpf_create_map_name(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, 69*67234743SAlexei Starovoitov opts->data_sz, 1, 0); 70*67234743SAlexei Starovoitov if (map_fd < 0) { 71*67234743SAlexei Starovoitov opts->errstr = "failed to create loader map"; 72*67234743SAlexei Starovoitov err = -errno; 73*67234743SAlexei Starovoitov goto out; 74*67234743SAlexei Starovoitov } 75*67234743SAlexei Starovoitov 76*67234743SAlexei Starovoitov err = bpf_map_update_elem(map_fd, &key, opts->data, 0); 77*67234743SAlexei Starovoitov if (err < 0) { 78*67234743SAlexei Starovoitov opts->errstr = "failed to update loader map"; 79*67234743SAlexei Starovoitov err = -errno; 80*67234743SAlexei Starovoitov goto out; 81*67234743SAlexei Starovoitov } 82*67234743SAlexei Starovoitov 83*67234743SAlexei Starovoitov memset(&attr, 0, sizeof(attr)); 84*67234743SAlexei Starovoitov attr.prog_type = BPF_PROG_TYPE_SYSCALL; 85*67234743SAlexei Starovoitov attr.insns = (long) opts->insns; 86*67234743SAlexei Starovoitov attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn); 87*67234743SAlexei Starovoitov attr.license = (long) "Dual BSD/GPL"; 88*67234743SAlexei Starovoitov memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog")); 89*67234743SAlexei Starovoitov attr.fd_array = (long) &map_fd; 90*67234743SAlexei Starovoitov attr.log_level = opts->ctx->log_level; 91*67234743SAlexei Starovoitov attr.log_size = opts->ctx->log_size; 92*67234743SAlexei Starovoitov attr.log_buf = opts->ctx->log_buf; 93*67234743SAlexei Starovoitov attr.prog_flags = BPF_F_SLEEPABLE; 94*67234743SAlexei Starovoitov prog_fd = skel_sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 95*67234743SAlexei Starovoitov if (prog_fd < 0) { 96*67234743SAlexei Starovoitov opts->errstr = "failed to load loader prog"; 97*67234743SAlexei Starovoitov err = -errno; 98*67234743SAlexei Starovoitov goto out; 99*67234743SAlexei Starovoitov } 100*67234743SAlexei Starovoitov 101*67234743SAlexei Starovoitov memset(&attr, 0, sizeof(attr)); 102*67234743SAlexei Starovoitov attr.test.prog_fd = prog_fd; 103*67234743SAlexei Starovoitov attr.test.ctx_in = (long) opts->ctx; 104*67234743SAlexei Starovoitov attr.test.ctx_size_in = opts->ctx->sz; 105*67234743SAlexei Starovoitov err = skel_sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); 106*67234743SAlexei Starovoitov if (err < 0 || (int)attr.test.retval < 0) { 107*67234743SAlexei Starovoitov opts->errstr = "failed to execute loader prog"; 108*67234743SAlexei Starovoitov if (err < 0) 109*67234743SAlexei Starovoitov err = -errno; 110*67234743SAlexei Starovoitov else 111*67234743SAlexei Starovoitov err = (int)attr.test.retval; 112*67234743SAlexei Starovoitov goto out; 113*67234743SAlexei Starovoitov } 114*67234743SAlexei Starovoitov err = 0; 115*67234743SAlexei Starovoitov out: 116*67234743SAlexei Starovoitov if (map_fd >= 0) 117*67234743SAlexei Starovoitov close(map_fd); 118*67234743SAlexei Starovoitov if (prog_fd >= 0) 119*67234743SAlexei Starovoitov close(prog_fd); 120*67234743SAlexei Starovoitov return err; 121*67234743SAlexei Starovoitov } 122*67234743SAlexei Starovoitov 123*67234743SAlexei Starovoitov #endif 124