xref: /linux/tools/lib/bpf/skel_internal.h (revision 67234743736a6ac31e3e74f6ec5e6d7bb3073676)
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