| // SPDX-License-Identifier: GPL-2.0-only | |
| /* | |
| * Copyright 2020 Google LLC. | |
| */ | |
| #include <test_progs.h> | |
| #include <cgroup_helpers.h> | |
| #include <network_helpers.h> | |
| #include "metadata_unused.skel.h" | |
| #include "metadata_used.skel.h" | |
| static int duration; | |
| static int prog_holds_map(int prog_fd, int map_fd) | |
| { | |
| struct bpf_prog_info prog_info = {}; | |
| struct bpf_prog_info map_info = {}; | |
| __u32 prog_info_len; | |
| __u32 map_info_len; | |
| __u32 *map_ids; | |
| int nr_maps; | |
| int ret; | |
| int i; | |
| map_info_len = sizeof(map_info); | |
| ret = bpf_obj_get_info_by_fd(map_fd, &map_info, &map_info_len); | |
| if (ret) | |
| return -errno; | |
| prog_info_len = sizeof(prog_info); | |
| ret = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &prog_info_len); | |
| if (ret) | |
| return -errno; | |
| map_ids = calloc(prog_info.nr_map_ids, sizeof(__u32)); | |
| if (!map_ids) | |
| return -ENOMEM; | |
| nr_maps = prog_info.nr_map_ids; | |
| memset(&prog_info, 0, sizeof(prog_info)); | |
| prog_info.nr_map_ids = nr_maps; | |
| prog_info.map_ids = ptr_to_u64(map_ids); | |
| prog_info_len = sizeof(prog_info); | |
| ret = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &prog_info_len); | |
| if (ret) { | |
| ret = -errno; | |
| goto free_map_ids; | |
| } | |
| ret = -ENOENT; | |
| for (i = 0; i < prog_info.nr_map_ids; i++) { | |
| if (map_ids[i] == map_info.id) { | |
| ret = 0; | |
| break; | |
| } | |
| } | |
| free_map_ids: | |
| free(map_ids); | |
| return ret; | |
| } | |
| static void test_metadata_unused(void) | |
| { | |
| struct metadata_unused *obj; | |
| int err; | |
| obj = metadata_unused__open_and_load(); | |
| if (CHECK(!obj, "skel-load", "errno %d", errno)) | |
| return; | |
| err = prog_holds_map(bpf_program__fd(obj->progs.prog), | |
| bpf_map__fd(obj->maps.rodata)); | |
| if (CHECK(err, "prog-holds-rodata", "errno: %d", err)) | |
| return; | |
| /* Assert that we can access the metadata in skel and the values are | |
| * what we expect. | |
| */ | |
| if (CHECK(strncmp(obj->rodata->bpf_metadata_a, "foo", | |
| sizeof(obj->rodata->bpf_metadata_a)), | |
| "bpf_metadata_a", "expected \"foo\", value differ")) | |
| goto close_bpf_object; | |
| if (CHECK(obj->rodata->bpf_metadata_b != 1, "bpf_metadata_b", | |
| "expected 1, got %d", obj->rodata->bpf_metadata_b)) | |
| goto close_bpf_object; | |
| /* Assert that binding metadata map to prog again succeeds. */ | |
| err = bpf_prog_bind_map(bpf_program__fd(obj->progs.prog), | |
| bpf_map__fd(obj->maps.rodata), NULL); | |
| CHECK(err, "rebind_map", "errno %d, expected 0", errno); | |
| close_bpf_object: | |
| metadata_unused__destroy(obj); | |
| } | |
| static void test_metadata_used(void) | |
| { | |
| struct metadata_used *obj; | |
| int err; | |
| obj = metadata_used__open_and_load(); | |
| if (CHECK(!obj, "skel-load", "errno %d", errno)) | |
| return; | |
| err = prog_holds_map(bpf_program__fd(obj->progs.prog), | |
| bpf_map__fd(obj->maps.rodata)); | |
| if (CHECK(err, "prog-holds-rodata", "errno: %d", err)) | |
| return; | |
| /* Assert that we can access the metadata in skel and the values are | |
| * what we expect. | |
| */ | |
| if (CHECK(strncmp(obj->rodata->bpf_metadata_a, "bar", | |
| sizeof(obj->rodata->bpf_metadata_a)), | |
| "metadata_a", "expected \"bar\", value differ")) | |
| goto close_bpf_object; | |
| if (CHECK(obj->rodata->bpf_metadata_b != 2, "metadata_b", | |
| "expected 2, got %d", obj->rodata->bpf_metadata_b)) | |
| goto close_bpf_object; | |
| /* Assert that binding metadata map to prog again succeeds. */ | |
| err = bpf_prog_bind_map(bpf_program__fd(obj->progs.prog), | |
| bpf_map__fd(obj->maps.rodata), NULL); | |
| CHECK(err, "rebind_map", "errno %d, expected 0", errno); | |
| close_bpf_object: | |
| metadata_used__destroy(obj); | |
| } | |
| void test_metadata(void) | |
| { | |
| if (test__start_subtest("unused")) | |
| test_metadata_unused(); | |
| if (test__start_subtest("used")) | |
| test_metadata_used(); | |
| } |