1 /* SPDX-License-Identifier: GPL-2.0 */
3 * bpf_libbpf.c BPF code relay on libbpf
4 * Authors: Hangbin Liu <haliu@redhat.com>
20 #include <bpf/libbpf.h>
25 static int verbose_print(enum libbpf_print_level level
, const char *format
, va_list args
)
27 return vfprintf(stderr
, format
, args
);
30 static int silent_print(enum libbpf_print_level level
, const char *format
, va_list args
)
32 if (level
> LIBBPF_WARN
)
35 /* Skip warning from bpf_object__init_user_maps() for legacy maps */
36 if (strstr(format
, "has unrecognized, non-zero options"))
39 return vfprintf(stderr
, format
, args
);
42 static const char *get_bpf_program__section_name(const struct bpf_program
*prog
)
44 #ifdef HAVE_LIBBPF_SECTION_NAME
45 return bpf_program__section_name(prog
);
47 return bpf_program__title(prog
, false);
51 static int create_map(const char *name
, struct bpf_elf_map
*map
,
52 __u32 ifindex
, int inner_fd
)
54 struct bpf_create_map_attr map_attr
= {};
57 map_attr
.map_type
= map
->type
;
58 map_attr
.map_flags
= map
->flags
;
59 map_attr
.key_size
= map
->size_key
;
60 map_attr
.value_size
= map
->size_value
;
61 map_attr
.max_entries
= map
->max_elem
;
62 map_attr
.map_ifindex
= ifindex
;
63 map_attr
.inner_map_fd
= inner_fd
;
65 return bpf_create_map_xattr(&map_attr
);
68 static int create_map_in_map(struct bpf_object
*obj
, struct bpf_map
*map
,
69 struct bpf_elf_map
*elf_map
, int inner_fd
,
72 char pathname
[PATH_MAX
];
77 map_name
= bpf_map__name(map
);
79 if (iproute2_is_pin_map(map_name
, pathname
)) {
82 /* Check if there already has a pinned map */
83 map_fd
= bpf_obj_get(pathname
);
86 *reuse_pin_map
= true;
88 return bpf_map__set_pin_path(map
, pathname
);
92 map_fd
= create_map(map_name
, elf_map
, bpf_map__ifindex(map
), inner_fd
);
94 fprintf(stderr
, "create map %s failed\n", map_name
);
98 ret
= bpf_map__reuse_fd(map
, map_fd
);
100 fprintf(stderr
, "map %s reuse fd failed\n", map_name
);
105 ret
= bpf_map__set_pin_path(map
, pathname
);
117 handle_legacy_map_in_map(struct bpf_object
*obj
, struct bpf_map
*inner_map
,
118 const char *inner_map_name
)
120 int inner_fd
, outer_fd
, inner_idx
, ret
= 0;
121 struct bpf_elf_map imap
, omap
;
122 struct bpf_map
*outer_map
;
123 /* What's the size limit of map name? */
124 char outer_map_name
[128];
125 bool reuse_pin_map
= false;
127 /* Deal with map-in-map */
128 if (iproute2_is_map_in_map(inner_map_name
, &imap
, &omap
, outer_map_name
)) {
129 ret
= create_map_in_map(obj
, inner_map
, &imap
, -1, NULL
);
133 inner_fd
= bpf_map__fd(inner_map
);
134 outer_map
= bpf_object__find_map_by_name(obj
, outer_map_name
);
135 ret
= create_map_in_map(obj
, outer_map
, &omap
, inner_fd
, &reuse_pin_map
);
139 if (!reuse_pin_map
) {
140 inner_idx
= imap
.inner_idx
;
141 outer_fd
= bpf_map__fd(outer_map
);
142 ret
= bpf_map_update_elem(outer_fd
, &inner_idx
, &inner_fd
, 0);
144 fprintf(stderr
, "Cannot update inner_idx into outer_map\n");
151 static int find_legacy_tail_calls(struct bpf_program
*prog
, struct bpf_object
*obj
)
153 unsigned int map_id
, key_id
;
154 const char *sec_name
;
159 /* Handle iproute2 tail call */
160 sec_name
= get_bpf_program__section_name(prog
);
161 ret
= sscanf(sec_name
, "%i/%i", &map_id
, &key_id
);
165 ret
= iproute2_find_map_name_by_id(map_id
, map_name
);
167 fprintf(stderr
, "unable to find map id %u for tail call\n", map_id
);
171 map
= bpf_object__find_map_by_name(obj
, map_name
);
175 /* Save the map here for later updating */
176 bpf_program__set_priv(prog
, map
, NULL
);
181 static int update_legacy_tail_call_maps(struct bpf_object
*obj
)
183 int prog_fd
, map_fd
, ret
= 0;
184 unsigned int map_id
, key_id
;
185 struct bpf_program
*prog
;
186 const char *sec_name
;
189 bpf_object__for_each_program(prog
, obj
) {
190 map
= bpf_program__priv(prog
);
194 prog_fd
= bpf_program__fd(prog
);
198 sec_name
= get_bpf_program__section_name(prog
);
199 ret
= sscanf(sec_name
, "%i/%i", &map_id
, &key_id
);
203 map_fd
= bpf_map__fd(map
);
204 ret
= bpf_map_update_elem(map_fd
, &key_id
, &prog_fd
, 0);
206 fprintf(stderr
, "Cannot update map key for tail call!\n");
214 static int handle_legacy_maps(struct bpf_object
*obj
)
216 char pathname
[PATH_MAX
];
218 const char *map_name
;
221 bpf_object__for_each_map(map
, obj
) {
222 map_name
= bpf_map__name(map
);
224 ret
= handle_legacy_map_in_map(obj
, map
, map_name
);
228 /* If it is a iproute2 legacy pin maps, just set pin path
229 * and let bpf_object__load() to deal with the map creation.
230 * We need to ignore map-in-maps which have pinned maps manually
232 map_fd
= bpf_map__fd(map
);
233 if (map_fd
< 0 && iproute2_is_pin_map(map_name
, pathname
)) {
234 ret
= bpf_map__set_pin_path(map
, pathname
);
236 fprintf(stderr
, "map '%s': couldn't set pin path.\n", map_name
);
246 static int load_bpf_object(struct bpf_cfg_in
*cfg
)
248 struct bpf_program
*p
, *prog
= NULL
;
249 struct bpf_object
*obj
;
250 char root_path
[PATH_MAX
];
252 int prog_fd
, ret
= 0;
254 ret
= iproute2_get_root_path(root_path
, PATH_MAX
);
258 DECLARE_LIBBPF_OPTS(bpf_object_open_opts
, open_opts
,
259 .relaxed_maps
= true,
260 .pin_root_path
= root_path
,
263 obj
= bpf_object__open_file(cfg
->object
, &open_opts
);
264 if (libbpf_get_error(obj
)) {
265 fprintf(stderr
, "ERROR: opening BPF object file failed\n");
269 bpf_object__for_each_program(p
, obj
) {
270 /* Only load the programs that will either be subsequently
271 * attached or inserted into a tail call map */
272 if (find_legacy_tail_calls(p
, obj
) < 0 && cfg
->section
&&
273 strcmp(get_bpf_program__section_name(p
), cfg
->section
)) {
274 ret
= bpf_program__set_autoload(p
, false);
280 bpf_program__set_type(p
, cfg
->type
);
281 bpf_program__set_ifindex(p
, cfg
->ifindex
);
286 bpf_object__for_each_map(map
, obj
) {
287 if (!bpf_map__is_offload_neutral(map
))
288 bpf_map__set_ifindex(map
, cfg
->ifindex
);
292 fprintf(stderr
, "object file doesn't contain sec %s\n", cfg
->section
);
296 /* Handle iproute2 legacy pin maps and map-in-maps */
297 ret
= handle_legacy_maps(obj
);
301 ret
= bpf_object__load(obj
);
305 ret
= update_legacy_tail_call_maps(obj
);
309 prog_fd
= fcntl(bpf_program__fd(prog
), F_DUPFD_CLOEXEC
, 1);
313 cfg
->prog_fd
= prog_fd
;
316 /* Close obj as we don't need it */
317 bpf_object__close(obj
);
321 /* Load ebpf and return prog fd */
322 int iproute2_load_libbpf(struct bpf_cfg_in
*cfg
)
327 libbpf_set_print(verbose_print
);
329 libbpf_set_print(silent_print
);
331 ret
= iproute2_bpf_elf_ctx_init(cfg
);
333 fprintf(stderr
, "Cannot initialize ELF context!\n");
337 ret
= iproute2_bpf_fetch_ancillary();
339 fprintf(stderr
, "Error fetching ELF ancillary data!\n");
343 ret
= load_bpf_object(cfg
);