/*
 * Testsuite for eBPF maps
 *
 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
 *
 * 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"

/* 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);
	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);

	/* check that key = 0 doesn't exist */
	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 == 2);
	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 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);
	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);
}

#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);
	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_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);
		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);
	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);
}

int main(void)
{
	test_hashmap_sanity(0, NULL);
	test_arraymap_sanity(0, NULL);
	test_map_large();
	test_map_parallel();
	test_map_stress();
	printf("test_maps: OK\n");
	return 0;
}
