/*
 * Testsuite for eBPF maps
 *
 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
 * Copyright (c) 2016 Facebook
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 */
#include <stdio.h>
#include <unistd.h>
#include <linux/bpf.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <sys/wait.h>
#include <stdlib.h>
#include "libbpf.h"

static int map_flags;

/* sanity tests for map API */
static void test_hashmap_sanity(int i, void *data)
{
	long long key, next_key, value;
	int map_fd;

	map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
				2, map_flags);
	if (map_fd < 0) {
		printf("failed to create hashmap '%s'\n", strerror(errno));
		exit(1);
	}

	key = 1;
	value = 1234;
	/* insert key=1 element */
	assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);

	value = 0;
	/* BPF_NOEXIST means: add new element if it doesn't exist */
	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
	       /* key=1 already exists */
	       errno == EEXIST);

	assert(bpf_update_elem(map_fd, &key, &value, -1) == -1 && errno == EINVAL);

	/* check that key=1 can be found */
	assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);

	key = 2;
	/* check that key=2 is not found */
	assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);

	/* BPF_EXIST means: update existing element */
	assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
	       /* key=2 is not there */
	       errno == ENOENT);

	/* insert key=2 element */
	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);

	/* key=1 and key=2 were inserted, check that key=0 cannot be inserted
	 * due to max_entries limit
	 */
	key = 0;
	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
	       errno == E2BIG);

	/* update existing element, thought the map is full */
	key = 1;
	assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == 0);
	key = 2;
	assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);
	key = 1;
	assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);

	/* check that key = 0 doesn't exist */
	key = 0;
	assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);

	/* iterate over two elements */
	assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
	       (next_key == 1 || next_key == 2));
	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
	       (next_key == 1 || next_key == 2));
	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
	       errno == ENOENT);

	/* delete both elements */
	key = 1;
	assert(bpf_delete_elem(map_fd, &key) == 0);
	key = 2;
	assert(bpf_delete_elem(map_fd, &key) == 0);
	assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);

	key = 0;
	/* check that map is empty */
	assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 &&
	       errno == ENOENT);
	close(map_fd);
}

/* sanity tests for percpu map API */
static void test_percpu_hashmap_sanity(int task, void *data)
{
	long long key, next_key;
	int expected_key_mask = 0;
	unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
	long long value[nr_cpus];
	int map_fd, i;

	map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
				sizeof(value[0]), 2, map_flags);
	if (map_fd < 0) {
		printf("failed to create hashmap '%s'\n", strerror(errno));
		exit(1);
	}

	for (i = 0; i < nr_cpus; i++)
		value[i] = i + 100;
	key = 1;
	/* insert key=1 element */
	assert(!(expected_key_mask & key));
	assert(bpf_update_elem(map_fd, &key, value, BPF_ANY) == 0);
	expected_key_mask |= key;

	/* BPF_NOEXIST means: add new element if it doesn't exist */
	assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 &&
	       /* key=1 already exists */
	       errno == EEXIST);

	/* -1 is an invalid flag */
	assert(bpf_update_elem(map_fd, &key, value, -1) == -1 &&
	       errno == EINVAL);

	/* check that key=1 can be found. value could be 0 if the lookup
	 * was run from a different cpu.
	 */
	value[0] = 1;
	assert(bpf_lookup_elem(map_fd, &key, value) == 0 && value[0] == 100);

	key = 2;
	/* check that key=2 is not found */
	assert(bpf_lookup_elem(map_fd, &key, value) == -1 && errno == ENOENT);

	/* BPF_EXIST means: update existing element */
	assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == -1 &&
	       /* key=2 is not there */
	       errno == ENOENT);

	/* insert key=2 element */
	assert(!(expected_key_mask & key));
	assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0);
	expected_key_mask |= key;

	/* key=1 and key=2 were inserted, check that key=0 cannot be inserted
	 * due to max_entries limit
	 */
	key = 0;
	assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 &&
	       errno == E2BIG);

	/* check that key = 0 doesn't exist */
	assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);

	/* iterate over two elements */
	while (!bpf_get_next_key(map_fd, &key, &next_key)) {
		assert((expected_key_mask & next_key) == next_key);
		expected_key_mask &= ~next_key;

		assert(bpf_lookup_elem(map_fd, &next_key, value) == 0);
		for (i = 0; i < nr_cpus; i++)
			assert(value[i] == i + 100);

		key = next_key;
	}
	assert(errno == ENOENT);

	/* Update with BPF_EXIST */
	key = 1;
	assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == 0);

	/* delete both elements */
	key = 1;
	assert(bpf_delete_elem(map_fd, &key) == 0);
	key = 2;
	assert(bpf_delete_elem(map_fd, &key) == 0);
	assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT);

	key = 0;
	/* check that map is empty */
	assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 &&
	       errno == ENOENT);
	close(map_fd);
}

static void test_arraymap_sanity(int i, void *data)
{
	int key, next_key, map_fd;
	long long value;

	map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
				2, 0);
	if (map_fd < 0) {
		printf("failed to create arraymap '%s'\n", strerror(errno));
		exit(1);
	}

	key = 1;
	value = 1234;
	/* insert key=1 element */
	assert(bpf_update_elem(map_fd, &key, &value, BPF_ANY) == 0);

	value = 0;
	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
	       errno == EEXIST);

	/* check that key=1 can be found */
	assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 1234);

	key = 0;
	/* check that key=0 is also found and zero initialized */
	assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0);


	/* key=0 and key=1 were inserted, check that key=2 cannot be inserted
	 * due to max_entries limit
	 */
	key = 2;
	assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == -1 &&
	       errno == E2BIG);

	/* check that key = 2 doesn't exist */
	assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);

	/* iterate over two elements */
	assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
	       next_key == 0);
	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
	       next_key == 1);
	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
	       errno == ENOENT);

	/* delete shouldn't succeed */
	key = 1;
	assert(bpf_delete_elem(map_fd, &key) == -1 && errno == EINVAL);

	close(map_fd);
}

static void test_percpu_arraymap_many_keys(void)
{
	unsigned nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
	unsigned nr_keys = 20000;
	long values[nr_cpus];
	int key, map_fd, i;

	map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
				sizeof(values[0]), nr_keys, 0);
	if (map_fd < 0) {
		printf("failed to create per-cpu arraymap '%s'\n",
		       strerror(errno));
		exit(1);
	}

	for (i = 0; i < nr_cpus; i++)
		values[i] = i + 10;

	for (key = 0; key < nr_keys; key++)
		assert(bpf_update_elem(map_fd, &key, values, BPF_ANY) == 0);

	for (key = 0; key < nr_keys; key++) {
		for (i = 0; i < nr_cpus; i++)
			values[i] = 0;
		assert(bpf_lookup_elem(map_fd, &key, values) == 0);
		for (i = 0; i < nr_cpus; i++)
			assert(values[i] == i + 10);
	}

	close(map_fd);
}

static void test_percpu_arraymap_sanity(int i, void *data)
{
	unsigned nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
	long values[nr_cpus];
	int key, next_key, map_fd;

	map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
				sizeof(values[0]), 2, 0);
	if (map_fd < 0) {
		printf("failed to create arraymap '%s'\n", strerror(errno));
		exit(1);
	}

	for (i = 0; i < nr_cpus; i++)
		values[i] = i + 100;

	key = 1;
	/* insert key=1 element */
	assert(bpf_update_elem(map_fd, &key, values, BPF_ANY) == 0);

	values[0] = 0;
	assert(bpf_update_elem(map_fd, &key, values, BPF_NOEXIST) == -1 &&
	       errno == EEXIST);

	/* check that key=1 can be found */
	assert(bpf_lookup_elem(map_fd, &key, values) == 0 && values[0] == 100);

	key = 0;
	/* check that key=0 is also found and zero initialized */
	assert(bpf_lookup_elem(map_fd, &key, values) == 0 &&
	       values[0] == 0 && values[nr_cpus - 1] == 0);


	/* check that key=2 cannot be inserted due to max_entries limit */
	key = 2;
	assert(bpf_update_elem(map_fd, &key, values, BPF_EXIST) == -1 &&
	       errno == E2BIG);

	/* check that key = 2 doesn't exist */
	assert(bpf_lookup_elem(map_fd, &key, values) == -1 && errno == ENOENT);

	/* iterate over two elements */
	assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
	       next_key == 0);
	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
	       next_key == 1);
	assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
	       errno == ENOENT);

	/* delete shouldn't succeed */
	key = 1;
	assert(bpf_delete_elem(map_fd, &key) == -1 && errno == EINVAL);

	close(map_fd);
}

#define MAP_SIZE (32 * 1024)
static void test_map_large(void)
{
	struct bigkey {
		int a;
		char b[116];
		long long c;
	} key;
	int map_fd, i, value;

	/* allocate 4Mbyte of memory */
	map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
				MAP_SIZE, map_flags);
	if (map_fd < 0) {
		printf("failed to create large map '%s'\n", strerror(errno));
		exit(1);
	}

	for (i = 0; i < MAP_SIZE; i++) {
		key = (struct bigkey) {.c = i};
		value = i;
		assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
	}
	key.c = -1;
	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
	       errno == E2BIG);

	/* iterate through all elements */
	for (i = 0; i < MAP_SIZE; i++)
		assert(bpf_get_next_key(map_fd, &key, &key) == 0);
	assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);

	key.c = 0;
	assert(bpf_lookup_elem(map_fd, &key, &value) == 0 && value == 0);
	key.a = 1;
	assert(bpf_lookup_elem(map_fd, &key, &value) == -1 && errno == ENOENT);

	close(map_fd);
}

/* fork N children and wait for them to complete */
static void run_parallel(int tasks, void (*fn)(int i, void *data), void *data)
{
	pid_t pid[tasks];
	int i;

	for (i = 0; i < tasks; i++) {
		pid[i] = fork();
		if (pid[i] == 0) {
			fn(i, data);
			exit(0);
		} else if (pid[i] == -1) {
			printf("couldn't spawn #%d process\n", i);
			exit(1);
		}
	}
	for (i = 0; i < tasks; i++) {
		int status;

		assert(waitpid(pid[i], &status, 0) == pid[i]);
		assert(status == 0);
	}
}

static void test_map_stress(void)
{
	run_parallel(100, test_hashmap_sanity, NULL);
	run_parallel(100, test_percpu_hashmap_sanity, NULL);
	run_parallel(100, test_arraymap_sanity, NULL);
	run_parallel(100, test_percpu_arraymap_sanity, NULL);
}

#define TASKS 1024
#define DO_UPDATE 1
#define DO_DELETE 0
static void do_work(int fn, void *data)
{
	int map_fd = ((int *)data)[0];
	int do_update = ((int *)data)[1];
	int i;
	int key, value;

	for (i = fn; i < MAP_SIZE; i += TASKS) {
		key = value = i;
		if (do_update) {
			assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == 0);
			assert(bpf_update_elem(map_fd, &key, &value, BPF_EXIST) == 0);
		} else {
			assert(bpf_delete_elem(map_fd, &key) == 0);
		}
	}
}

static void test_map_parallel(void)
{
	int i, map_fd, key = 0, value = 0;
	int data[2];

	map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
				MAP_SIZE, map_flags);
	if (map_fd < 0) {
		printf("failed to create map for parallel test '%s'\n",
		       strerror(errno));
		exit(1);
	}

	data[0] = map_fd;
	data[1] = DO_UPDATE;
	/* use the same map_fd in children to add elements to this map
	 * child_0 adds key=0, key=1024, key=2048, ...
	 * child_1 adds key=1, key=1025, key=2049, ...
	 * child_1023 adds key=1023, ...
	 */
	run_parallel(TASKS, do_work, data);

	/* check that key=0 is already there */
	assert(bpf_update_elem(map_fd, &key, &value, BPF_NOEXIST) == -1 &&
	       errno == EEXIST);

	/* check that all elements were inserted */
	key = -1;
	for (i = 0; i < MAP_SIZE; i++)
		assert(bpf_get_next_key(map_fd, &key, &key) == 0);
	assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);

	/* another check for all elements */
	for (i = 0; i < MAP_SIZE; i++) {
		key = MAP_SIZE - i - 1;
		assert(bpf_lookup_elem(map_fd, &key, &value) == 0 &&
		       value == key);
	}

	/* now let's delete all elemenets in parallel */
	data[1] = DO_DELETE;
	run_parallel(TASKS, do_work, data);

	/* nothing should be left */
	key = -1;
	assert(bpf_get_next_key(map_fd, &key, &key) == -1 && errno == ENOENT);
}

static void run_all_tests(void)
{
	test_hashmap_sanity(0, NULL);
	test_percpu_hashmap_sanity(0, NULL);
	test_arraymap_sanity(0, NULL);
	test_percpu_arraymap_sanity(0, NULL);
	test_percpu_arraymap_many_keys();

	test_map_large();
	test_map_parallel();
	test_map_stress();
}

int main(void)
{
	map_flags = 0;
	run_all_tests();
	map_flags = BPF_F_NO_PREALLOC;
	run_all_tests();
	printf("test_maps: OK\n");
	return 0;
}
