Line data Source code
1 : #ifndef HEADER_fd_src_ballet_ebpf_fd_ebpf_h
2 : #define HEADER_fd_src_ballet_ebpf_fd_ebpf_h
3 :
4 : /* fd_ebpf.h provides APIs for loading Linux eBPF programs. Currently,
5 : only XDP programs are supported.
6 :
7 : The scope of this API is *trusted*: It is assumed that only hardcoded
8 : eBPF programs and symbols are provided.
9 :
10 : ### What are eBPF programs?
11 :
12 : Linux eBPF programs are pieces of bytecode that userland programs can
13 : deploy into the kernel virtual machine. The kernel can interact with
14 : these programs with very low overhead, which makes them particularly
15 : useful for fast packet filtering.
16 :
17 : Userland applications can deploy and interact with eBPF programs via
18 : the bpf(2) syscall. When deploying, the user provides a bytecode blob
19 : (see fd_ebpf_base.h) which is produced by the userland on the fly.
20 : Typically, userland also shares file descriptors while deploying the
21 : program.
22 :
23 : To avoid hardcoding file descriptor numbers into the eBPF programs, eBPF
24 : programs are typically stored as ELF static objects. These are
25 : "relocated" just-in-time to actual bytecode. (The term relocation in
26 : this context has not much to do with offsets. It refers to filling in
27 : symbolic names (such as "xsk_fileno") with an actual value (like 3)).
28 :
29 : This relocation step is provided by fd_ebpf_static_link. Various
30 : wrappers for bpf(2) operations are also provided. */
31 :
32 : #include "../../util/fd_util_base.h"
33 :
34 : /* fd_ebpf_sym_t a key-value pair. name matches the name of an imported
35 : symbol in the ELF object. value is the 'absolute address' to fill in.
36 : (The 'absolute address' is abused as a generic 64-bit value and can
37 : also refer to file descriptors, config parameters, etc.) */
38 :
39 : struct fd_ebpf_sym {
40 : char const * name; /* null-terminated cstr */
41 : ulong value; /* arbitrary 64-bit value */
42 : };
43 : typedef struct fd_ebpf_sym fd_ebpf_sym_t;
44 :
45 : /* fd_ebpf_link_opts_t describe parameters to load an eBPF ELF object into
46 : a bytecode blob that can be loaded into a kernel. section is the name
47 : of the ELF section carrying the bytecode (not necessarily ".text"),
48 : and sym is an array of sym_cnt symbols containing values to fill in.
49 : fd_ebpf_static_link will look for a relocation table for this section,
50 : which identifies where and how to fill in symbol values in the given
51 : section. */
52 :
53 : struct fd_ebpf_link_opts {
54 : /* In params */
55 :
56 : char const * section;
57 : fd_ebpf_sym_t const * sym;
58 : ulong sym_cnt;
59 :
60 : /* Out params */
61 :
62 : ulong * bpf;
63 : ulong bpf_sz;
64 : };
65 : typedef struct fd_ebpf_link_opts fd_ebpf_link_opts_t;
66 :
67 : /* fd_ebpf_static_link relocates an eBPF ELF object as mentioned above.
68 : elf points to a memory region of elf_sz bytes containing the ELF static
69 : object. This memory region will be clobbered during the relocation
70 : process. Returns opts on success, with bpf pointing to the first eBPF
71 : instruction (a subrange of the memory region at elf). bpf_sz is the
72 : size of the eBPF bytecode blob (multiple of 8). On failure, returns
73 : NULL.
74 :
75 : ### Caveats
76 :
77 : The static linking process is fairly slow and quite complex. This
78 : function only implements a small subset of the linking logic needed to
79 : load simple programs. Users of this function should expect bugs and
80 : therefore independently test whether their programs load. See
81 : test_xdp_ebpf on how to do unit testing of the relocated program with
82 : the bpf(2) syscall. */
83 :
84 : fd_ebpf_link_opts_t *
85 : fd_ebpf_static_link( fd_ebpf_link_opts_t * opts,
86 : void * elf,
87 : ulong elf_sz );
88 :
89 : /* bpf syscall wrappers **************************************************/
90 :
91 : #if defined(__linux__) && defined(_DEFAULT_SOURCE) || defined(_BSD_SOURCE)
92 :
93 : #include <sys/syscall.h>
94 : #include <unistd.h>
95 : #include <linux/bpf.h>
96 :
97 : /* bpf Linux syscall */
98 :
99 : static inline long
100 : bpf( int cmd,
101 : union bpf_attr * attr,
102 3 : ulong attr_sz ) {
103 3 : return syscall( SYS_bpf, cmd, attr, attr_sz );
104 3 : }
105 :
106 : /* fd_bpf_map_get_next_key wraps bpf(2) op BPF_MAP_GET_NEXT_KEY.
107 :
108 : Given a BPF map file descriptor and a const ptr to the current key,
109 : finds and stores the next key into `next_key`. key and next_key must
110 : match the key size of the map object. If key does not exist, yields
111 : the first key of the map. When mutating a map while iterating, get
112 : the next key before deleting the current key to avoid iterator from
113 : restarting. Returns 0 on success and -1 on failure (sets errno).
114 : Sets errno to ENOENT if given key is last in map. */
115 :
116 : static inline int
117 : fd_bpf_map_get_next_key( int map_fd,
118 : void const * key,
119 0 : void * next_key ) {
120 0 : union bpf_attr attr = {
121 0 : .map_fd = (uint)map_fd,
122 0 : .key = (ulong)key,
123 0 : .next_key = (ulong)next_key
124 0 : };
125 0 : return (int)bpf( BPF_MAP_GET_NEXT_KEY, &attr, sizeof(union bpf_attr) );
126 0 : }
127 :
128 : /* fd_bpf_map_update_elem wraps bpf(2) op BPF_MAP_UPDATE_ELEM.
129 :
130 : Creates or updates an entry in a BPF map. key and value point to
131 : the tuple to be inserted and must match the key/value size of the map
132 : object. flags is one of BPF_ANY (create or update), BPF_NOEXIST
133 : (create only), BPF_EXIST (update only). Returns 0 on success and -1
134 : on failure (sets errno). Reasons for failure include: E2BIG (max
135 : entry limit reached), EEXIST (BPF_NOEXIST requested but key exists),
136 : ENOENT (BPF_EXIST requested but key not found). */
137 :
138 : static inline int
139 : fd_bpf_map_update_elem( int map_fd,
140 : void const * key,
141 : void const * value,
142 0 : ulong flags ) {
143 0 : union bpf_attr attr = {
144 0 : .map_fd = (uint)map_fd,
145 0 : .key = (ulong)key,
146 0 : .value = (ulong)value,
147 0 : .flags = flags
148 0 : };
149 0 : return (int)bpf( BPF_MAP_UPDATE_ELEM, &attr, sizeof(union bpf_attr) );
150 0 : }
151 :
152 : /* fd_bpf_map_delete_elem wraps bpf(2) op BPF_MAP_DELETE_ELEM.
153 :
154 : Deletes an entry in a BPF map. key points to the key to be deleted
155 : and must match the key size of the map object. Returns 0 on success
156 : and -1 on failure (sets errno). Reasons for failure include: ENOENT
157 : (no such key). */
158 :
159 : static inline int
160 : fd_bpf_map_delete_elem( int map_fd,
161 0 : void const * key ) {
162 0 : union bpf_attr attr = {
163 0 : .map_fd = (uint)map_fd,
164 0 : .key = (ulong)key
165 0 : };
166 0 : return (int)bpf( BPF_MAP_DELETE_ELEM, &attr, sizeof(union bpf_attr) );
167 0 : }
168 :
169 : /* fd_bpf_obj_get wraps bpf(2) op BPF_OBJ_GET.
170 :
171 : Opens a BPF map at given filesystem path. Path must be within a
172 : valid bpffs mount and point to a BPF map pinned via BPF_OBJ_PIN.
173 : Returns fd number on success and negative integer on failure. */
174 :
175 : static inline int
176 0 : fd_bpf_obj_get( char const * pathname ) {
177 0 : union bpf_attr attr = {
178 0 : .pathname = (ulong)pathname
179 0 : };
180 0 : return (int)bpf( BPF_OBJ_GET, &attr, sizeof(union bpf_attr) );
181 0 : }
182 :
183 : /* fd_bpf_obj_pin wraps bpf(2) op BPF_OBJ_PIN.
184 :
185 : Pins a bpf syscall API object at given filesystem path. Types of
186 : objects include: BPF map (BPF_MAP_CREATE), links (BPF_LINK_CREATE),
187 : programs (BPF_PROG_LOAD). Returns 0 on success and -1 on failure. */
188 :
189 : static inline int
190 : fd_bpf_obj_pin( int bpf_fd,
191 0 : char const * pathname ) {
192 0 : union bpf_attr attr = {
193 0 : .bpf_fd = (uint)bpf_fd,
194 0 : .pathname = (ulong)pathname
195 0 : };
196 0 : return (int)bpf( BPF_OBJ_PIN, &attr, sizeof(union bpf_attr) );
197 0 : }
198 :
199 : #endif /* defined (__linux__) */
200 :
201 : #endif /* HEADER_fd_src_ballet_ebpf_fd_ebpf_h */
|