// 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();
}
