18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Testsuite for eBPF maps
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
68c2ecf20Sopenharmony_ci * Copyright (c) 2016 Facebook
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <stdio.h>
108c2ecf20Sopenharmony_ci#include <unistd.h>
118c2ecf20Sopenharmony_ci#include <errno.h>
128c2ecf20Sopenharmony_ci#include <string.h>
138c2ecf20Sopenharmony_ci#include <assert.h>
148c2ecf20Sopenharmony_ci#include <stdlib.h>
158c2ecf20Sopenharmony_ci#include <time.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <sys/wait.h>
188c2ecf20Sopenharmony_ci#include <sys/socket.h>
198c2ecf20Sopenharmony_ci#include <netinet/in.h>
208c2ecf20Sopenharmony_ci#include <linux/bpf.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <bpf/bpf.h>
238c2ecf20Sopenharmony_ci#include <bpf/libbpf.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#include "bpf_util.h"
268c2ecf20Sopenharmony_ci#include "bpf_rlimit.h"
278c2ecf20Sopenharmony_ci#include "test_maps.h"
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#ifndef ENOTSUPP
308c2ecf20Sopenharmony_ci#define ENOTSUPP 524
318c2ecf20Sopenharmony_ci#endif
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic int skips;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic int map_flags;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic void test_hashmap(unsigned int task, void *data)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	long long key, next_key, first_key, value;
408c2ecf20Sopenharmony_ci	int fd;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
438c2ecf20Sopenharmony_ci			    2, map_flags);
448c2ecf20Sopenharmony_ci	if (fd < 0) {
458c2ecf20Sopenharmony_ci		printf("Failed to create hashmap '%s'!\n", strerror(errno));
468c2ecf20Sopenharmony_ci		exit(1);
478c2ecf20Sopenharmony_ci	}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	key = 1;
508c2ecf20Sopenharmony_ci	value = 1234;
518c2ecf20Sopenharmony_ci	/* Insert key=1 element. */
528c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	value = 0;
558c2ecf20Sopenharmony_ci	/* BPF_NOEXIST means add new element if it doesn't exist. */
568c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
578c2ecf20Sopenharmony_ci	       /* key=1 already exists. */
588c2ecf20Sopenharmony_ci	       errno == EEXIST);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	/* -1 is an invalid flag. */
618c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 &&
628c2ecf20Sopenharmony_ci	       errno == EINVAL);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	/* Check that key=1 can be found. */
658c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	key = 2;
688c2ecf20Sopenharmony_ci	/* Check that key=2 is not found. */
698c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	/* BPF_EXIST means update existing element. */
728c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
738c2ecf20Sopenharmony_ci	       /* key=2 is not there. */
748c2ecf20Sopenharmony_ci	       errno == ENOENT);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	/* Insert key=2 element. */
778c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	/* key=1 and key=2 were inserted, check that key=0 cannot be
808c2ecf20Sopenharmony_ci	 * inserted due to max_entries limit.
818c2ecf20Sopenharmony_ci	 */
828c2ecf20Sopenharmony_ci	key = 0;
838c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
848c2ecf20Sopenharmony_ci	       errno == E2BIG);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	/* Update existing element, though the map is full. */
878c2ecf20Sopenharmony_ci	key = 1;
888c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
898c2ecf20Sopenharmony_ci	key = 2;
908c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
918c2ecf20Sopenharmony_ci	key = 3;
928c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
938c2ecf20Sopenharmony_ci	       errno == E2BIG);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	/* Check that key = 0 doesn't exist. */
968c2ecf20Sopenharmony_ci	key = 0;
978c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	/* Iterate over two elements. */
1008c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
1018c2ecf20Sopenharmony_ci	       (first_key == 1 || first_key == 2));
1028c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
1038c2ecf20Sopenharmony_ci	       (next_key == first_key));
1048c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
1058c2ecf20Sopenharmony_ci	       (next_key == 1 || next_key == 2) &&
1068c2ecf20Sopenharmony_ci	       (next_key != first_key));
1078c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
1088c2ecf20Sopenharmony_ci	       errno == ENOENT);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	/* Delete both elements. */
1118c2ecf20Sopenharmony_ci	key = 1;
1128c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == 0);
1138c2ecf20Sopenharmony_ci	key = 2;
1148c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == 0);
1158c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	key = 0;
1188c2ecf20Sopenharmony_ci	/* Check that map is empty. */
1198c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
1208c2ecf20Sopenharmony_ci	       errno == ENOENT);
1218c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
1228c2ecf20Sopenharmony_ci	       errno == ENOENT);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	close(fd);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic void test_hashmap_sizes(unsigned int task, void *data)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	int fd, i, j;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	for (i = 1; i <= 512; i <<= 1)
1328c2ecf20Sopenharmony_ci		for (j = 1; j <= 1 << 18; j <<= 1) {
1338c2ecf20Sopenharmony_ci			fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j,
1348c2ecf20Sopenharmony_ci					    2, map_flags);
1358c2ecf20Sopenharmony_ci			if (fd < 0) {
1368c2ecf20Sopenharmony_ci				if (errno == ENOMEM)
1378c2ecf20Sopenharmony_ci					return;
1388c2ecf20Sopenharmony_ci				printf("Failed to create hashmap key=%d value=%d '%s'\n",
1398c2ecf20Sopenharmony_ci				       i, j, strerror(errno));
1408c2ecf20Sopenharmony_ci				exit(1);
1418c2ecf20Sopenharmony_ci			}
1428c2ecf20Sopenharmony_ci			close(fd);
1438c2ecf20Sopenharmony_ci			usleep(10); /* give kernel time to destroy */
1448c2ecf20Sopenharmony_ci		}
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic void test_hashmap_percpu(unsigned int task, void *data)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	unsigned int nr_cpus = bpf_num_possible_cpus();
1508c2ecf20Sopenharmony_ci	BPF_DECLARE_PERCPU(long, value);
1518c2ecf20Sopenharmony_ci	long long key, next_key, first_key;
1528c2ecf20Sopenharmony_ci	int expected_key_mask = 0;
1538c2ecf20Sopenharmony_ci	int fd, i;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
1568c2ecf20Sopenharmony_ci			    sizeof(bpf_percpu(value, 0)), 2, map_flags);
1578c2ecf20Sopenharmony_ci	if (fd < 0) {
1588c2ecf20Sopenharmony_ci		printf("Failed to create hashmap '%s'!\n", strerror(errno));
1598c2ecf20Sopenharmony_ci		exit(1);
1608c2ecf20Sopenharmony_ci	}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	for (i = 0; i < nr_cpus; i++)
1638c2ecf20Sopenharmony_ci		bpf_percpu(value, i) = i + 100;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	key = 1;
1668c2ecf20Sopenharmony_ci	/* Insert key=1 element. */
1678c2ecf20Sopenharmony_ci	assert(!(expected_key_mask & key));
1688c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0);
1698c2ecf20Sopenharmony_ci	expected_key_mask |= key;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	/* BPF_NOEXIST means add new element if it doesn't exist. */
1728c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
1738c2ecf20Sopenharmony_ci	       /* key=1 already exists. */
1748c2ecf20Sopenharmony_ci	       errno == EEXIST);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	/* -1 is an invalid flag. */
1778c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, value, -1) == -1 &&
1788c2ecf20Sopenharmony_ci	       errno == EINVAL);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	/* Check that key=1 can be found. Value could be 0 if the lookup
1818c2ecf20Sopenharmony_ci	 * was run from a different CPU.
1828c2ecf20Sopenharmony_ci	 */
1838c2ecf20Sopenharmony_ci	bpf_percpu(value, 0) = 1;
1848c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, value) == 0 &&
1858c2ecf20Sopenharmony_ci	       bpf_percpu(value, 0) == 100);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	key = 2;
1888c2ecf20Sopenharmony_ci	/* Check that key=2 is not found. */
1898c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	/* BPF_EXIST means update existing element. */
1928c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 &&
1938c2ecf20Sopenharmony_ci	       /* key=2 is not there. */
1948c2ecf20Sopenharmony_ci	       errno == ENOENT);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	/* Insert key=2 element. */
1978c2ecf20Sopenharmony_ci	assert(!(expected_key_mask & key));
1988c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0);
1998c2ecf20Sopenharmony_ci	expected_key_mask |= key;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	/* key=1 and key=2 were inserted, check that key=0 cannot be
2028c2ecf20Sopenharmony_ci	 * inserted due to max_entries limit.
2038c2ecf20Sopenharmony_ci	 */
2048c2ecf20Sopenharmony_ci	key = 0;
2058c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
2068c2ecf20Sopenharmony_ci	       errno == E2BIG);
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	/* Check that key = 0 doesn't exist. */
2098c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	/* Iterate over two elements. */
2128c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
2138c2ecf20Sopenharmony_ci	       ((expected_key_mask & first_key) == first_key));
2148c2ecf20Sopenharmony_ci	while (!bpf_map_get_next_key(fd, &key, &next_key)) {
2158c2ecf20Sopenharmony_ci		if (first_key) {
2168c2ecf20Sopenharmony_ci			assert(next_key == first_key);
2178c2ecf20Sopenharmony_ci			first_key = 0;
2188c2ecf20Sopenharmony_ci		}
2198c2ecf20Sopenharmony_ci		assert((expected_key_mask & next_key) == next_key);
2208c2ecf20Sopenharmony_ci		expected_key_mask &= ~next_key;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci		assert(bpf_map_lookup_elem(fd, &next_key, value) == 0);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci		for (i = 0; i < nr_cpus; i++)
2258c2ecf20Sopenharmony_ci			assert(bpf_percpu(value, i) == i + 100);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci		key = next_key;
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci	assert(errno == ENOENT);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* Update with BPF_EXIST. */
2328c2ecf20Sopenharmony_ci	key = 1;
2338c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	/* Delete both elements. */
2368c2ecf20Sopenharmony_ci	key = 1;
2378c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == 0);
2388c2ecf20Sopenharmony_ci	key = 2;
2398c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == 0);
2408c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	key = 0;
2438c2ecf20Sopenharmony_ci	/* Check that map is empty. */
2448c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
2458c2ecf20Sopenharmony_ci	       errno == ENOENT);
2468c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
2478c2ecf20Sopenharmony_ci	       errno == ENOENT);
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	close(fd);
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistatic int helper_fill_hashmap(int max_entries)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	int i, fd, ret;
2558c2ecf20Sopenharmony_ci	long long key, value;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
2588c2ecf20Sopenharmony_ci			    max_entries, map_flags);
2598c2ecf20Sopenharmony_ci	CHECK(fd < 0,
2608c2ecf20Sopenharmony_ci	      "failed to create hashmap",
2618c2ecf20Sopenharmony_ci	      "err: %s, flags: 0x%x\n", strerror(errno), map_flags);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	for (i = 0; i < max_entries; i++) {
2648c2ecf20Sopenharmony_ci		key = i; value = key;
2658c2ecf20Sopenharmony_ci		ret = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
2668c2ecf20Sopenharmony_ci		CHECK(ret != 0,
2678c2ecf20Sopenharmony_ci		      "can't update hashmap",
2688c2ecf20Sopenharmony_ci		      "err: %s\n", strerror(ret));
2698c2ecf20Sopenharmony_ci	}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	return fd;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cistatic void test_hashmap_walk(unsigned int task, void *data)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	int fd, i, max_entries = 1000;
2778c2ecf20Sopenharmony_ci	long long key, value, next_key;
2788c2ecf20Sopenharmony_ci	bool next_key_valid = true;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	fd = helper_fill_hashmap(max_entries);
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
2838c2ecf20Sopenharmony_ci					 &next_key) == 0; i++) {
2848c2ecf20Sopenharmony_ci		key = next_key;
2858c2ecf20Sopenharmony_ci		assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
2868c2ecf20Sopenharmony_ci	}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	assert(i == max_entries);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
2918c2ecf20Sopenharmony_ci	for (i = 0; next_key_valid; i++) {
2928c2ecf20Sopenharmony_ci		next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0;
2938c2ecf20Sopenharmony_ci		assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
2948c2ecf20Sopenharmony_ci		value++;
2958c2ecf20Sopenharmony_ci		assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
2968c2ecf20Sopenharmony_ci		key = next_key;
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	assert(i == max_entries);
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
3028c2ecf20Sopenharmony_ci					 &next_key) == 0; i++) {
3038c2ecf20Sopenharmony_ci		key = next_key;
3048c2ecf20Sopenharmony_ci		assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
3058c2ecf20Sopenharmony_ci		assert(value - 1 == key);
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	assert(i == max_entries);
3098c2ecf20Sopenharmony_ci	close(fd);
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic void test_hashmap_zero_seed(void)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	int i, first, second, old_flags;
3158c2ecf20Sopenharmony_ci	long long key, next_first, next_second;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	old_flags = map_flags;
3188c2ecf20Sopenharmony_ci	map_flags |= BPF_F_ZERO_SEED;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	first = helper_fill_hashmap(3);
3218c2ecf20Sopenharmony_ci	second = helper_fill_hashmap(3);
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	for (i = 0; ; i++) {
3248c2ecf20Sopenharmony_ci		void *key_ptr = !i ? NULL : &key;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci		if (bpf_map_get_next_key(first, key_ptr, &next_first) != 0)
3278c2ecf20Sopenharmony_ci			break;
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci		CHECK(bpf_map_get_next_key(second, key_ptr, &next_second) != 0,
3308c2ecf20Sopenharmony_ci		      "next_key for second map must succeed",
3318c2ecf20Sopenharmony_ci		      "key_ptr: %p", key_ptr);
3328c2ecf20Sopenharmony_ci		CHECK(next_first != next_second,
3338c2ecf20Sopenharmony_ci		      "keys must match",
3348c2ecf20Sopenharmony_ci		      "i: %d first: %lld second: %lld\n", i,
3358c2ecf20Sopenharmony_ci		      next_first, next_second);
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci		key = next_first;
3388c2ecf20Sopenharmony_ci	}
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	map_flags = old_flags;
3418c2ecf20Sopenharmony_ci	close(first);
3428c2ecf20Sopenharmony_ci	close(second);
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic void test_arraymap(unsigned int task, void *data)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	int key, next_key, fd;
3488c2ecf20Sopenharmony_ci	long long value;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
3518c2ecf20Sopenharmony_ci			    2, 0);
3528c2ecf20Sopenharmony_ci	if (fd < 0) {
3538c2ecf20Sopenharmony_ci		printf("Failed to create arraymap '%s'!\n", strerror(errno));
3548c2ecf20Sopenharmony_ci		exit(1);
3558c2ecf20Sopenharmony_ci	}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	key = 1;
3588c2ecf20Sopenharmony_ci	value = 1234;
3598c2ecf20Sopenharmony_ci	/* Insert key=1 element. */
3608c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	value = 0;
3638c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
3648c2ecf20Sopenharmony_ci	       errno == EEXIST);
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	/* Check that key=1 can be found. */
3678c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	key = 0;
3708c2ecf20Sopenharmony_ci	/* Check that key=0 is also found and zero initialized. */
3718c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	/* key=0 and key=1 were inserted, check that key=2 cannot be inserted
3748c2ecf20Sopenharmony_ci	 * due to max_entries limit.
3758c2ecf20Sopenharmony_ci	 */
3768c2ecf20Sopenharmony_ci	key = 2;
3778c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
3788c2ecf20Sopenharmony_ci	       errno == E2BIG);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	/* Check that key = 2 doesn't exist. */
3818c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	/* Iterate over two elements. */
3848c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
3858c2ecf20Sopenharmony_ci	       next_key == 0);
3868c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
3878c2ecf20Sopenharmony_ci	       next_key == 0);
3888c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
3898c2ecf20Sopenharmony_ci	       next_key == 1);
3908c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
3918c2ecf20Sopenharmony_ci	       errno == ENOENT);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	/* Delete shouldn't succeed. */
3948c2ecf20Sopenharmony_ci	key = 1;
3958c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	close(fd);
3988c2ecf20Sopenharmony_ci}
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_cistatic void test_arraymap_percpu(unsigned int task, void *data)
4018c2ecf20Sopenharmony_ci{
4028c2ecf20Sopenharmony_ci	unsigned int nr_cpus = bpf_num_possible_cpus();
4038c2ecf20Sopenharmony_ci	BPF_DECLARE_PERCPU(long, values);
4048c2ecf20Sopenharmony_ci	int key, next_key, fd, i;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
4078c2ecf20Sopenharmony_ci			    sizeof(bpf_percpu(values, 0)), 2, 0);
4088c2ecf20Sopenharmony_ci	if (fd < 0) {
4098c2ecf20Sopenharmony_ci		printf("Failed to create arraymap '%s'!\n", strerror(errno));
4108c2ecf20Sopenharmony_ci		exit(1);
4118c2ecf20Sopenharmony_ci	}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	for (i = 0; i < nr_cpus; i++)
4148c2ecf20Sopenharmony_ci		bpf_percpu(values, i) = i + 100;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	key = 1;
4178c2ecf20Sopenharmony_ci	/* Insert key=1 element. */
4188c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	bpf_percpu(values, 0) = 0;
4218c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 &&
4228c2ecf20Sopenharmony_ci	       errno == EEXIST);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	/* Check that key=1 can be found. */
4258c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
4268c2ecf20Sopenharmony_ci	       bpf_percpu(values, 0) == 100);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	key = 0;
4298c2ecf20Sopenharmony_ci	/* Check that key=0 is also found and zero initialized. */
4308c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
4318c2ecf20Sopenharmony_ci	       bpf_percpu(values, 0) == 0 &&
4328c2ecf20Sopenharmony_ci	       bpf_percpu(values, nr_cpus - 1) == 0);
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	/* Check that key=2 cannot be inserted due to max_entries limit. */
4358c2ecf20Sopenharmony_ci	key = 2;
4368c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 &&
4378c2ecf20Sopenharmony_ci	       errno == E2BIG);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	/* Check that key = 2 doesn't exist. */
4408c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	/* Iterate over two elements. */
4438c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
4448c2ecf20Sopenharmony_ci	       next_key == 0);
4458c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
4468c2ecf20Sopenharmony_ci	       next_key == 0);
4478c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
4488c2ecf20Sopenharmony_ci	       next_key == 1);
4498c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
4508c2ecf20Sopenharmony_ci	       errno == ENOENT);
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	/* Delete shouldn't succeed. */
4538c2ecf20Sopenharmony_ci	key = 1;
4548c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	close(fd);
4578c2ecf20Sopenharmony_ci}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_cistatic void test_arraymap_percpu_many_keys(void)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	unsigned int nr_cpus = bpf_num_possible_cpus();
4628c2ecf20Sopenharmony_ci	BPF_DECLARE_PERCPU(long, values);
4638c2ecf20Sopenharmony_ci	/* nr_keys is not too large otherwise the test stresses percpu
4648c2ecf20Sopenharmony_ci	 * allocator more than anything else
4658c2ecf20Sopenharmony_ci	 */
4668c2ecf20Sopenharmony_ci	unsigned int nr_keys = 2000;
4678c2ecf20Sopenharmony_ci	int key, fd, i;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
4708c2ecf20Sopenharmony_ci			    sizeof(bpf_percpu(values, 0)), nr_keys, 0);
4718c2ecf20Sopenharmony_ci	if (fd < 0) {
4728c2ecf20Sopenharmony_ci		printf("Failed to create per-cpu arraymap '%s'!\n",
4738c2ecf20Sopenharmony_ci		       strerror(errno));
4748c2ecf20Sopenharmony_ci		exit(1);
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	for (i = 0; i < nr_cpus; i++)
4788c2ecf20Sopenharmony_ci		bpf_percpu(values, i) = i + 10;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	for (key = 0; key < nr_keys; key++)
4818c2ecf20Sopenharmony_ci		assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	for (key = 0; key < nr_keys; key++) {
4848c2ecf20Sopenharmony_ci		for (i = 0; i < nr_cpus; i++)
4858c2ecf20Sopenharmony_ci			bpf_percpu(values, i) = 0;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci		assert(bpf_map_lookup_elem(fd, &key, values) == 0);
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci		for (i = 0; i < nr_cpus; i++)
4908c2ecf20Sopenharmony_ci			assert(bpf_percpu(values, i) == i + 10);
4918c2ecf20Sopenharmony_ci	}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	close(fd);
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic void test_devmap(unsigned int task, void *data)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	int fd;
4998c2ecf20Sopenharmony_ci	__u32 key, value;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),
5028c2ecf20Sopenharmony_ci			    2, 0);
5038c2ecf20Sopenharmony_ci	if (fd < 0) {
5048c2ecf20Sopenharmony_ci		printf("Failed to create devmap '%s'!\n", strerror(errno));
5058c2ecf20Sopenharmony_ci		exit(1);
5068c2ecf20Sopenharmony_ci	}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	close(fd);
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_cistatic void test_devmap_hash(unsigned int task, void *data)
5128c2ecf20Sopenharmony_ci{
5138c2ecf20Sopenharmony_ci	int fd;
5148c2ecf20Sopenharmony_ci	__u32 key, value;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP_HASH, sizeof(key), sizeof(value),
5178c2ecf20Sopenharmony_ci			    2, 0);
5188c2ecf20Sopenharmony_ci	if (fd < 0) {
5198c2ecf20Sopenharmony_ci		printf("Failed to create devmap_hash '%s'!\n", strerror(errno));
5208c2ecf20Sopenharmony_ci		exit(1);
5218c2ecf20Sopenharmony_ci	}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	close(fd);
5248c2ecf20Sopenharmony_ci}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_cistatic void test_queuemap(unsigned int task, void *data)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	const int MAP_SIZE = 32;
5298c2ecf20Sopenharmony_ci	__u32 vals[MAP_SIZE + MAP_SIZE/2], val;
5308c2ecf20Sopenharmony_ci	int fd, i;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	/* Fill test values to be used */
5338c2ecf20Sopenharmony_ci	for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++)
5348c2ecf20Sopenharmony_ci		vals[i] = rand();
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	/* Invalid key size */
5378c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 4, sizeof(val), MAP_SIZE,
5388c2ecf20Sopenharmony_ci			    map_flags);
5398c2ecf20Sopenharmony_ci	assert(fd < 0 && errno == EINVAL);
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 0, sizeof(val), MAP_SIZE,
5428c2ecf20Sopenharmony_ci			    map_flags);
5438c2ecf20Sopenharmony_ci	/* Queue map does not support BPF_F_NO_PREALLOC */
5448c2ecf20Sopenharmony_ci	if (map_flags & BPF_F_NO_PREALLOC) {
5458c2ecf20Sopenharmony_ci		assert(fd < 0 && errno == EINVAL);
5468c2ecf20Sopenharmony_ci		return;
5478c2ecf20Sopenharmony_ci	}
5488c2ecf20Sopenharmony_ci	if (fd < 0) {
5498c2ecf20Sopenharmony_ci		printf("Failed to create queuemap '%s'!\n", strerror(errno));
5508c2ecf20Sopenharmony_ci		exit(1);
5518c2ecf20Sopenharmony_ci	}
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	/* Push MAP_SIZE elements */
5548c2ecf20Sopenharmony_ci	for (i = 0; i < MAP_SIZE; i++)
5558c2ecf20Sopenharmony_ci		assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	/* Check that element cannot be pushed due to max_entries limit */
5588c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 &&
5598c2ecf20Sopenharmony_ci	       errno == E2BIG);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	/* Peek element */
5628c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[0]);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	/* Replace half elements */
5658c2ecf20Sopenharmony_ci	for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++)
5668c2ecf20Sopenharmony_ci		assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0);
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	/* Pop all elements */
5698c2ecf20Sopenharmony_ci	for (i = MAP_SIZE/2; i < MAP_SIZE + MAP_SIZE/2; i++)
5708c2ecf20Sopenharmony_ci		assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 &&
5718c2ecf20Sopenharmony_ci		       val == vals[i]);
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	/* Check that there are not elements left */
5748c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == -1 &&
5758c2ecf20Sopenharmony_ci	       errno == ENOENT);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	/* Check that non supported functions set errno to EINVAL */
5788c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
5798c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	close(fd);
5828c2ecf20Sopenharmony_ci}
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_cistatic void test_stackmap(unsigned int task, void *data)
5858c2ecf20Sopenharmony_ci{
5868c2ecf20Sopenharmony_ci	const int MAP_SIZE = 32;
5878c2ecf20Sopenharmony_ci	__u32 vals[MAP_SIZE + MAP_SIZE/2], val;
5888c2ecf20Sopenharmony_ci	int fd, i;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	/* Fill test values to be used */
5918c2ecf20Sopenharmony_ci	for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++)
5928c2ecf20Sopenharmony_ci		vals[i] = rand();
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	/* Invalid key size */
5958c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_STACK, 4, sizeof(val), MAP_SIZE,
5968c2ecf20Sopenharmony_ci			    map_flags);
5978c2ecf20Sopenharmony_ci	assert(fd < 0 && errno == EINVAL);
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_STACK, 0, sizeof(val), MAP_SIZE,
6008c2ecf20Sopenharmony_ci			    map_flags);
6018c2ecf20Sopenharmony_ci	/* Stack map does not support BPF_F_NO_PREALLOC */
6028c2ecf20Sopenharmony_ci	if (map_flags & BPF_F_NO_PREALLOC) {
6038c2ecf20Sopenharmony_ci		assert(fd < 0 && errno == EINVAL);
6048c2ecf20Sopenharmony_ci		return;
6058c2ecf20Sopenharmony_ci	}
6068c2ecf20Sopenharmony_ci	if (fd < 0) {
6078c2ecf20Sopenharmony_ci		printf("Failed to create stackmap '%s'!\n", strerror(errno));
6088c2ecf20Sopenharmony_ci		exit(1);
6098c2ecf20Sopenharmony_ci	}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	/* Push MAP_SIZE elements */
6128c2ecf20Sopenharmony_ci	for (i = 0; i < MAP_SIZE; i++)
6138c2ecf20Sopenharmony_ci		assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	/* Check that element cannot be pushed due to max_entries limit */
6168c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 &&
6178c2ecf20Sopenharmony_ci	       errno == E2BIG);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	/* Peek element */
6208c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[i - 1]);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	/* Replace half elements */
6238c2ecf20Sopenharmony_ci	for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++)
6248c2ecf20Sopenharmony_ci		assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	/* Pop all elements */
6278c2ecf20Sopenharmony_ci	for (i = MAP_SIZE + MAP_SIZE/2 - 1; i >= MAP_SIZE/2; i--)
6288c2ecf20Sopenharmony_ci		assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 &&
6298c2ecf20Sopenharmony_ci		       val == vals[i]);
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	/* Check that there are not elements left */
6328c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == -1 &&
6338c2ecf20Sopenharmony_ci	       errno == ENOENT);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	/* Check that non supported functions set errno to EINVAL */
6368c2ecf20Sopenharmony_ci	assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
6378c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci	close(fd);
6408c2ecf20Sopenharmony_ci}
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci#include <sys/ioctl.h>
6438c2ecf20Sopenharmony_ci#include <arpa/inet.h>
6448c2ecf20Sopenharmony_ci#include <sys/select.h>
6458c2ecf20Sopenharmony_ci#include <linux/err.h>
6468c2ecf20Sopenharmony_ci#define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
6478c2ecf20Sopenharmony_ci#define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
6488c2ecf20Sopenharmony_ci#define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o"
6498c2ecf20Sopenharmony_cistatic void test_sockmap(unsigned int tasks, void *data)
6508c2ecf20Sopenharmony_ci{
6518c2ecf20Sopenharmony_ci	struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break;
6528c2ecf20Sopenharmony_ci	int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break;
6538c2ecf20Sopenharmony_ci	int ports[] = {50200, 50201, 50202, 50204};
6548c2ecf20Sopenharmony_ci	int err, i, fd, udp, sfd[6] = {0xdeadbeef};
6558c2ecf20Sopenharmony_ci	u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
6568c2ecf20Sopenharmony_ci	int parse_prog, verdict_prog, msg_prog;
6578c2ecf20Sopenharmony_ci	struct sockaddr_in addr;
6588c2ecf20Sopenharmony_ci	int one = 1, s, sc, rc;
6598c2ecf20Sopenharmony_ci	struct bpf_object *obj;
6608c2ecf20Sopenharmony_ci	struct timeval to;
6618c2ecf20Sopenharmony_ci	__u32 key, value;
6628c2ecf20Sopenharmony_ci	pid_t pid[tasks];
6638c2ecf20Sopenharmony_ci	fd_set w;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	/* Create some sockets to use with sockmap */
6668c2ecf20Sopenharmony_ci	for (i = 0; i < 2; i++) {
6678c2ecf20Sopenharmony_ci		sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
6688c2ecf20Sopenharmony_ci		if (sfd[i] < 0)
6698c2ecf20Sopenharmony_ci			goto out;
6708c2ecf20Sopenharmony_ci		err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
6718c2ecf20Sopenharmony_ci				 (char *)&one, sizeof(one));
6728c2ecf20Sopenharmony_ci		if (err) {
6738c2ecf20Sopenharmony_ci			printf("failed to setsockopt\n");
6748c2ecf20Sopenharmony_ci			goto out;
6758c2ecf20Sopenharmony_ci		}
6768c2ecf20Sopenharmony_ci		err = ioctl(sfd[i], FIONBIO, (char *)&one);
6778c2ecf20Sopenharmony_ci		if (err < 0) {
6788c2ecf20Sopenharmony_ci			printf("failed to ioctl\n");
6798c2ecf20Sopenharmony_ci			goto out;
6808c2ecf20Sopenharmony_ci		}
6818c2ecf20Sopenharmony_ci		memset(&addr, 0, sizeof(struct sockaddr_in));
6828c2ecf20Sopenharmony_ci		addr.sin_family = AF_INET;
6838c2ecf20Sopenharmony_ci		addr.sin_addr.s_addr = inet_addr("127.0.0.1");
6848c2ecf20Sopenharmony_ci		addr.sin_port = htons(ports[i]);
6858c2ecf20Sopenharmony_ci		err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
6868c2ecf20Sopenharmony_ci		if (err < 0) {
6878c2ecf20Sopenharmony_ci			printf("failed to bind: err %i: %i:%i\n",
6888c2ecf20Sopenharmony_ci			       err, i, sfd[i]);
6898c2ecf20Sopenharmony_ci			goto out;
6908c2ecf20Sopenharmony_ci		}
6918c2ecf20Sopenharmony_ci		err = listen(sfd[i], 32);
6928c2ecf20Sopenharmony_ci		if (err < 0) {
6938c2ecf20Sopenharmony_ci			printf("failed to listen\n");
6948c2ecf20Sopenharmony_ci			goto out;
6958c2ecf20Sopenharmony_ci		}
6968c2ecf20Sopenharmony_ci	}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	for (i = 2; i < 4; i++) {
6998c2ecf20Sopenharmony_ci		sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
7008c2ecf20Sopenharmony_ci		if (sfd[i] < 0)
7018c2ecf20Sopenharmony_ci			goto out;
7028c2ecf20Sopenharmony_ci		err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
7038c2ecf20Sopenharmony_ci				 (char *)&one, sizeof(one));
7048c2ecf20Sopenharmony_ci		if (err) {
7058c2ecf20Sopenharmony_ci			printf("set sock opt\n");
7068c2ecf20Sopenharmony_ci			goto out;
7078c2ecf20Sopenharmony_ci		}
7088c2ecf20Sopenharmony_ci		memset(&addr, 0, sizeof(struct sockaddr_in));
7098c2ecf20Sopenharmony_ci		addr.sin_family = AF_INET;
7108c2ecf20Sopenharmony_ci		addr.sin_addr.s_addr = inet_addr("127.0.0.1");
7118c2ecf20Sopenharmony_ci		addr.sin_port = htons(ports[i - 2]);
7128c2ecf20Sopenharmony_ci		err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
7138c2ecf20Sopenharmony_ci		if (err) {
7148c2ecf20Sopenharmony_ci			printf("failed to connect\n");
7158c2ecf20Sopenharmony_ci			goto out;
7168c2ecf20Sopenharmony_ci		}
7178c2ecf20Sopenharmony_ci	}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	for (i = 4; i < 6; i++) {
7218c2ecf20Sopenharmony_ci		sfd[i] = accept(sfd[i - 4], NULL, NULL);
7228c2ecf20Sopenharmony_ci		if (sfd[i] < 0) {
7238c2ecf20Sopenharmony_ci			printf("accept failed\n");
7248c2ecf20Sopenharmony_ci			goto out;
7258c2ecf20Sopenharmony_ci		}
7268c2ecf20Sopenharmony_ci	}
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	/* Test sockmap with connected sockets */
7298c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP,
7308c2ecf20Sopenharmony_ci			    sizeof(key), sizeof(value),
7318c2ecf20Sopenharmony_ci			    6, 0);
7328c2ecf20Sopenharmony_ci	if (fd < 0) {
7338c2ecf20Sopenharmony_ci		if (!bpf_probe_map_type(BPF_MAP_TYPE_SOCKMAP, 0)) {
7348c2ecf20Sopenharmony_ci			printf("%s SKIP (unsupported map type BPF_MAP_TYPE_SOCKMAP)\n",
7358c2ecf20Sopenharmony_ci			       __func__);
7368c2ecf20Sopenharmony_ci			skips++;
7378c2ecf20Sopenharmony_ci			for (i = 0; i < 6; i++)
7388c2ecf20Sopenharmony_ci				close(sfd[i]);
7398c2ecf20Sopenharmony_ci			return;
7408c2ecf20Sopenharmony_ci		}
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci		printf("Failed to create sockmap %i\n", fd);
7438c2ecf20Sopenharmony_ci		goto out_sockmap;
7448c2ecf20Sopenharmony_ci	}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	/* Test update with unsupported UDP socket */
7478c2ecf20Sopenharmony_ci	udp = socket(AF_INET, SOCK_DGRAM, 0);
7488c2ecf20Sopenharmony_ci	i = 0;
7498c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
7508c2ecf20Sopenharmony_ci	if (!err) {
7518c2ecf20Sopenharmony_ci		printf("Failed socket SOCK_DGRAM allowed '%i:%i'\n",
7528c2ecf20Sopenharmony_ci		       i, udp);
7538c2ecf20Sopenharmony_ci		goto out_sockmap;
7548c2ecf20Sopenharmony_ci	}
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	/* Test update without programs */
7578c2ecf20Sopenharmony_ci	for (i = 0; i < 6; i++) {
7588c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
7598c2ecf20Sopenharmony_ci		if (err) {
7608c2ecf20Sopenharmony_ci			printf("Failed noprog update sockmap '%i:%i'\n",
7618c2ecf20Sopenharmony_ci			       i, sfd[i]);
7628c2ecf20Sopenharmony_ci			goto out_sockmap;
7638c2ecf20Sopenharmony_ci		}
7648c2ecf20Sopenharmony_ci	}
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	/* Test attaching/detaching bad fds */
7678c2ecf20Sopenharmony_ci	err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
7688c2ecf20Sopenharmony_ci	if (!err) {
7698c2ecf20Sopenharmony_ci		printf("Failed invalid parser prog attach\n");
7708c2ecf20Sopenharmony_ci		goto out_sockmap;
7718c2ecf20Sopenharmony_ci	}
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0);
7748c2ecf20Sopenharmony_ci	if (!err) {
7758c2ecf20Sopenharmony_ci		printf("Failed invalid verdict prog attach\n");
7768c2ecf20Sopenharmony_ci		goto out_sockmap;
7778c2ecf20Sopenharmony_ci	}
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0);
7808c2ecf20Sopenharmony_ci	if (!err) {
7818c2ecf20Sopenharmony_ci		printf("Failed invalid msg verdict prog attach\n");
7828c2ecf20Sopenharmony_ci		goto out_sockmap;
7838c2ecf20Sopenharmony_ci	}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci	err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
7868c2ecf20Sopenharmony_ci	if (!err) {
7878c2ecf20Sopenharmony_ci		printf("Failed unknown prog attach\n");
7888c2ecf20Sopenharmony_ci		goto out_sockmap;
7898c2ecf20Sopenharmony_ci	}
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
7928c2ecf20Sopenharmony_ci	if (!err) {
7938c2ecf20Sopenharmony_ci		printf("Failed empty parser prog detach\n");
7948c2ecf20Sopenharmony_ci		goto out_sockmap;
7958c2ecf20Sopenharmony_ci	}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
7988c2ecf20Sopenharmony_ci	if (!err) {
7998c2ecf20Sopenharmony_ci		printf("Failed empty verdict prog detach\n");
8008c2ecf20Sopenharmony_ci		goto out_sockmap;
8018c2ecf20Sopenharmony_ci	}
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
8048c2ecf20Sopenharmony_ci	if (!err) {
8058c2ecf20Sopenharmony_ci		printf("Failed empty msg verdict prog detach\n");
8068c2ecf20Sopenharmony_ci		goto out_sockmap;
8078c2ecf20Sopenharmony_ci	}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
8108c2ecf20Sopenharmony_ci	if (!err) {
8118c2ecf20Sopenharmony_ci		printf("Detach invalid prog successful\n");
8128c2ecf20Sopenharmony_ci		goto out_sockmap;
8138c2ecf20Sopenharmony_ci	}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	/* Load SK_SKB program and Attach */
8168c2ecf20Sopenharmony_ci	err = bpf_prog_load(SOCKMAP_PARSE_PROG,
8178c2ecf20Sopenharmony_ci			    BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
8188c2ecf20Sopenharmony_ci	if (err) {
8198c2ecf20Sopenharmony_ci		printf("Failed to load SK_SKB parse prog\n");
8208c2ecf20Sopenharmony_ci		goto out_sockmap;
8218c2ecf20Sopenharmony_ci	}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	err = bpf_prog_load(SOCKMAP_TCP_MSG_PROG,
8248c2ecf20Sopenharmony_ci			    BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog);
8258c2ecf20Sopenharmony_ci	if (err) {
8268c2ecf20Sopenharmony_ci		printf("Failed to load SK_SKB msg prog\n");
8278c2ecf20Sopenharmony_ci		goto out_sockmap;
8288c2ecf20Sopenharmony_ci	}
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
8318c2ecf20Sopenharmony_ci			    BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
8328c2ecf20Sopenharmony_ci	if (err) {
8338c2ecf20Sopenharmony_ci		printf("Failed to load SK_SKB verdict prog\n");
8348c2ecf20Sopenharmony_ci		goto out_sockmap;
8358c2ecf20Sopenharmony_ci	}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx");
8388c2ecf20Sopenharmony_ci	if (IS_ERR(bpf_map_rx)) {
8398c2ecf20Sopenharmony_ci		printf("Failed to load map rx from verdict prog\n");
8408c2ecf20Sopenharmony_ci		goto out_sockmap;
8418c2ecf20Sopenharmony_ci	}
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	map_fd_rx = bpf_map__fd(bpf_map_rx);
8448c2ecf20Sopenharmony_ci	if (map_fd_rx < 0) {
8458c2ecf20Sopenharmony_ci		printf("Failed to get map rx fd\n");
8468c2ecf20Sopenharmony_ci		goto out_sockmap;
8478c2ecf20Sopenharmony_ci	}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx");
8508c2ecf20Sopenharmony_ci	if (IS_ERR(bpf_map_tx)) {
8518c2ecf20Sopenharmony_ci		printf("Failed to load map tx from verdict prog\n");
8528c2ecf20Sopenharmony_ci		goto out_sockmap;
8538c2ecf20Sopenharmony_ci	}
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	map_fd_tx = bpf_map__fd(bpf_map_tx);
8568c2ecf20Sopenharmony_ci	if (map_fd_tx < 0) {
8578c2ecf20Sopenharmony_ci		printf("Failed to get map tx fd\n");
8588c2ecf20Sopenharmony_ci		goto out_sockmap;
8598c2ecf20Sopenharmony_ci	}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg");
8628c2ecf20Sopenharmony_ci	if (IS_ERR(bpf_map_msg)) {
8638c2ecf20Sopenharmony_ci		printf("Failed to load map msg from msg_verdict prog\n");
8648c2ecf20Sopenharmony_ci		goto out_sockmap;
8658c2ecf20Sopenharmony_ci	}
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	map_fd_msg = bpf_map__fd(bpf_map_msg);
8688c2ecf20Sopenharmony_ci	if (map_fd_msg < 0) {
8698c2ecf20Sopenharmony_ci		printf("Failed to get map msg fd\n");
8708c2ecf20Sopenharmony_ci		goto out_sockmap;
8718c2ecf20Sopenharmony_ci	}
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
8748c2ecf20Sopenharmony_ci	if (IS_ERR(bpf_map_break)) {
8758c2ecf20Sopenharmony_ci		printf("Failed to load map tx from verdict prog\n");
8768c2ecf20Sopenharmony_ci		goto out_sockmap;
8778c2ecf20Sopenharmony_ci	}
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	map_fd_break = bpf_map__fd(bpf_map_break);
8808c2ecf20Sopenharmony_ci	if (map_fd_break < 0) {
8818c2ecf20Sopenharmony_ci		printf("Failed to get map tx fd\n");
8828c2ecf20Sopenharmony_ci		goto out_sockmap;
8838c2ecf20Sopenharmony_ci	}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	err = bpf_prog_attach(parse_prog, map_fd_break,
8868c2ecf20Sopenharmony_ci			      BPF_SK_SKB_STREAM_PARSER, 0);
8878c2ecf20Sopenharmony_ci	if (!err) {
8888c2ecf20Sopenharmony_ci		printf("Allowed attaching SK_SKB program to invalid map\n");
8898c2ecf20Sopenharmony_ci		goto out_sockmap;
8908c2ecf20Sopenharmony_ci	}
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	err = bpf_prog_attach(parse_prog, map_fd_rx,
8938c2ecf20Sopenharmony_ci		      BPF_SK_SKB_STREAM_PARSER, 0);
8948c2ecf20Sopenharmony_ci	if (err) {
8958c2ecf20Sopenharmony_ci		printf("Failed stream parser bpf prog attach\n");
8968c2ecf20Sopenharmony_ci		goto out_sockmap;
8978c2ecf20Sopenharmony_ci	}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	err = bpf_prog_attach(verdict_prog, map_fd_rx,
9008c2ecf20Sopenharmony_ci			      BPF_SK_SKB_STREAM_VERDICT, 0);
9018c2ecf20Sopenharmony_ci	if (err) {
9028c2ecf20Sopenharmony_ci		printf("Failed stream verdict bpf prog attach\n");
9038c2ecf20Sopenharmony_ci		goto out_sockmap;
9048c2ecf20Sopenharmony_ci	}
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0);
9078c2ecf20Sopenharmony_ci	if (err) {
9088c2ecf20Sopenharmony_ci		printf("Failed msg verdict bpf prog attach\n");
9098c2ecf20Sopenharmony_ci		goto out_sockmap;
9108c2ecf20Sopenharmony_ci	}
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	err = bpf_prog_attach(verdict_prog, map_fd_rx,
9138c2ecf20Sopenharmony_ci			      __MAX_BPF_ATTACH_TYPE, 0);
9148c2ecf20Sopenharmony_ci	if (!err) {
9158c2ecf20Sopenharmony_ci		printf("Attached unknown bpf prog\n");
9168c2ecf20Sopenharmony_ci		goto out_sockmap;
9178c2ecf20Sopenharmony_ci	}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	/* Test map update elem afterwards fd lives in fd and map_fd */
9208c2ecf20Sopenharmony_ci	for (i = 2; i < 6; i++) {
9218c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
9228c2ecf20Sopenharmony_ci		if (err) {
9238c2ecf20Sopenharmony_ci			printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
9248c2ecf20Sopenharmony_ci			       err, i, sfd[i]);
9258c2ecf20Sopenharmony_ci			goto out_sockmap;
9268c2ecf20Sopenharmony_ci		}
9278c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY);
9288c2ecf20Sopenharmony_ci		if (err) {
9298c2ecf20Sopenharmony_ci			printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
9308c2ecf20Sopenharmony_ci			       err, i, sfd[i]);
9318c2ecf20Sopenharmony_ci			goto out_sockmap;
9328c2ecf20Sopenharmony_ci		}
9338c2ecf20Sopenharmony_ci	}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	/* Test map delete elem and remove send/recv sockets */
9368c2ecf20Sopenharmony_ci	for (i = 2; i < 4; i++) {
9378c2ecf20Sopenharmony_ci		err = bpf_map_delete_elem(map_fd_rx, &i);
9388c2ecf20Sopenharmony_ci		if (err) {
9398c2ecf20Sopenharmony_ci			printf("Failed delete sockmap rx %i '%i:%i'\n",
9408c2ecf20Sopenharmony_ci			       err, i, sfd[i]);
9418c2ecf20Sopenharmony_ci			goto out_sockmap;
9428c2ecf20Sopenharmony_ci		}
9438c2ecf20Sopenharmony_ci		err = bpf_map_delete_elem(map_fd_tx, &i);
9448c2ecf20Sopenharmony_ci		if (err) {
9458c2ecf20Sopenharmony_ci			printf("Failed delete sockmap tx %i '%i:%i'\n",
9468c2ecf20Sopenharmony_ci			       err, i, sfd[i]);
9478c2ecf20Sopenharmony_ci			goto out_sockmap;
9488c2ecf20Sopenharmony_ci		}
9498c2ecf20Sopenharmony_ci	}
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	/* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */
9528c2ecf20Sopenharmony_ci	i = 0;
9538c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY);
9548c2ecf20Sopenharmony_ci	if (err) {
9558c2ecf20Sopenharmony_ci		printf("Failed map_fd_msg update sockmap %i\n", err);
9568c2ecf20Sopenharmony_ci		goto out_sockmap;
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	/* Test map send/recv */
9608c2ecf20Sopenharmony_ci	for (i = 0; i < 2; i++) {
9618c2ecf20Sopenharmony_ci		buf[0] = i;
9628c2ecf20Sopenharmony_ci		buf[1] = 0x5;
9638c2ecf20Sopenharmony_ci		sc = send(sfd[2], buf, 20, 0);
9648c2ecf20Sopenharmony_ci		if (sc < 0) {
9658c2ecf20Sopenharmony_ci			printf("Failed sockmap send\n");
9668c2ecf20Sopenharmony_ci			goto out_sockmap;
9678c2ecf20Sopenharmony_ci		}
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci		FD_ZERO(&w);
9708c2ecf20Sopenharmony_ci		FD_SET(sfd[3], &w);
9718c2ecf20Sopenharmony_ci		to.tv_sec = 30;
9728c2ecf20Sopenharmony_ci		to.tv_usec = 0;
9738c2ecf20Sopenharmony_ci		s = select(sfd[3] + 1, &w, NULL, NULL, &to);
9748c2ecf20Sopenharmony_ci		if (s == -1) {
9758c2ecf20Sopenharmony_ci			perror("Failed sockmap select()");
9768c2ecf20Sopenharmony_ci			goto out_sockmap;
9778c2ecf20Sopenharmony_ci		} else if (!s) {
9788c2ecf20Sopenharmony_ci			printf("Failed sockmap unexpected timeout\n");
9798c2ecf20Sopenharmony_ci			goto out_sockmap;
9808c2ecf20Sopenharmony_ci		}
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci		if (!FD_ISSET(sfd[3], &w)) {
9838c2ecf20Sopenharmony_ci			printf("Failed sockmap select/recv\n");
9848c2ecf20Sopenharmony_ci			goto out_sockmap;
9858c2ecf20Sopenharmony_ci		}
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci		rc = recv(sfd[3], buf, sizeof(buf), 0);
9888c2ecf20Sopenharmony_ci		if (rc < 0) {
9898c2ecf20Sopenharmony_ci			printf("Failed sockmap recv\n");
9908c2ecf20Sopenharmony_ci			goto out_sockmap;
9918c2ecf20Sopenharmony_ci		}
9928c2ecf20Sopenharmony_ci	}
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	/* Negative null entry lookup from datapath should be dropped */
9958c2ecf20Sopenharmony_ci	buf[0] = 1;
9968c2ecf20Sopenharmony_ci	buf[1] = 12;
9978c2ecf20Sopenharmony_ci	sc = send(sfd[2], buf, 20, 0);
9988c2ecf20Sopenharmony_ci	if (sc < 0) {
9998c2ecf20Sopenharmony_ci		printf("Failed sockmap send\n");
10008c2ecf20Sopenharmony_ci		goto out_sockmap;
10018c2ecf20Sopenharmony_ci	}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci	/* Push fd into same slot */
10048c2ecf20Sopenharmony_ci	i = 2;
10058c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
10068c2ecf20Sopenharmony_ci	if (!err) {
10078c2ecf20Sopenharmony_ci		printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
10088c2ecf20Sopenharmony_ci		goto out_sockmap;
10098c2ecf20Sopenharmony_ci	}
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
10128c2ecf20Sopenharmony_ci	if (err) {
10138c2ecf20Sopenharmony_ci		printf("Failed sockmap update new slot BPF_ANY\n");
10148c2ecf20Sopenharmony_ci		goto out_sockmap;
10158c2ecf20Sopenharmony_ci	}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
10188c2ecf20Sopenharmony_ci	if (err) {
10198c2ecf20Sopenharmony_ci		printf("Failed sockmap update new slot BPF_EXIST\n");
10208c2ecf20Sopenharmony_ci		goto out_sockmap;
10218c2ecf20Sopenharmony_ci	}
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	/* Delete the elems without programs */
10248c2ecf20Sopenharmony_ci	for (i = 2; i < 6; i++) {
10258c2ecf20Sopenharmony_ci		err = bpf_map_delete_elem(fd, &i);
10268c2ecf20Sopenharmony_ci		if (err) {
10278c2ecf20Sopenharmony_ci			printf("Failed delete sockmap %i '%i:%i'\n",
10288c2ecf20Sopenharmony_ci			       err, i, sfd[i]);
10298c2ecf20Sopenharmony_ci		}
10308c2ecf20Sopenharmony_ci	}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	/* Test having multiple maps open and set with programs on same fds */
10338c2ecf20Sopenharmony_ci	err = bpf_prog_attach(parse_prog, fd,
10348c2ecf20Sopenharmony_ci			      BPF_SK_SKB_STREAM_PARSER, 0);
10358c2ecf20Sopenharmony_ci	if (err) {
10368c2ecf20Sopenharmony_ci		printf("Failed fd bpf parse prog attach\n");
10378c2ecf20Sopenharmony_ci		goto out_sockmap;
10388c2ecf20Sopenharmony_ci	}
10398c2ecf20Sopenharmony_ci	err = bpf_prog_attach(verdict_prog, fd,
10408c2ecf20Sopenharmony_ci			      BPF_SK_SKB_STREAM_VERDICT, 0);
10418c2ecf20Sopenharmony_ci	if (err) {
10428c2ecf20Sopenharmony_ci		printf("Failed fd bpf verdict prog attach\n");
10438c2ecf20Sopenharmony_ci		goto out_sockmap;
10448c2ecf20Sopenharmony_ci	}
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	for (i = 4; i < 6; i++) {
10478c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
10488c2ecf20Sopenharmony_ci		if (!err) {
10498c2ecf20Sopenharmony_ci			printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
10508c2ecf20Sopenharmony_ci			       err, i, sfd[i]);
10518c2ecf20Sopenharmony_ci			goto out_sockmap;
10528c2ecf20Sopenharmony_ci		}
10538c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
10548c2ecf20Sopenharmony_ci		if (!err) {
10558c2ecf20Sopenharmony_ci			printf("Failed allowed duplicate program in update NOEXIST sockmap  %i '%i:%i'\n",
10568c2ecf20Sopenharmony_ci			       err, i, sfd[i]);
10578c2ecf20Sopenharmony_ci			goto out_sockmap;
10588c2ecf20Sopenharmony_ci		}
10598c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
10608c2ecf20Sopenharmony_ci		if (!err) {
10618c2ecf20Sopenharmony_ci			printf("Failed allowed duplicate program in update EXIST sockmap  %i '%i:%i'\n",
10628c2ecf20Sopenharmony_ci			       err, i, sfd[i]);
10638c2ecf20Sopenharmony_ci			goto out_sockmap;
10648c2ecf20Sopenharmony_ci		}
10658c2ecf20Sopenharmony_ci	}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	/* Test tasks number of forked operations */
10688c2ecf20Sopenharmony_ci	for (i = 0; i < tasks; i++) {
10698c2ecf20Sopenharmony_ci		pid[i] = fork();
10708c2ecf20Sopenharmony_ci		if (pid[i] == 0) {
10718c2ecf20Sopenharmony_ci			for (i = 0; i < 6; i++) {
10728c2ecf20Sopenharmony_ci				bpf_map_delete_elem(map_fd_tx, &i);
10738c2ecf20Sopenharmony_ci				bpf_map_delete_elem(map_fd_rx, &i);
10748c2ecf20Sopenharmony_ci				bpf_map_update_elem(map_fd_tx, &i,
10758c2ecf20Sopenharmony_ci						    &sfd[i], BPF_ANY);
10768c2ecf20Sopenharmony_ci				bpf_map_update_elem(map_fd_rx, &i,
10778c2ecf20Sopenharmony_ci						    &sfd[i], BPF_ANY);
10788c2ecf20Sopenharmony_ci			}
10798c2ecf20Sopenharmony_ci			exit(0);
10808c2ecf20Sopenharmony_ci		} else if (pid[i] == -1) {
10818c2ecf20Sopenharmony_ci			printf("Couldn't spawn #%d process!\n", i);
10828c2ecf20Sopenharmony_ci			exit(1);
10838c2ecf20Sopenharmony_ci		}
10848c2ecf20Sopenharmony_ci	}
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	for (i = 0; i < tasks; i++) {
10878c2ecf20Sopenharmony_ci		int status;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci		assert(waitpid(pid[i], &status, 0) == pid[i]);
10908c2ecf20Sopenharmony_ci		assert(status == 0);
10918c2ecf20Sopenharmony_ci	}
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE);
10948c2ecf20Sopenharmony_ci	if (!err) {
10958c2ecf20Sopenharmony_ci		printf("Detached an invalid prog type.\n");
10968c2ecf20Sopenharmony_ci		goto out_sockmap;
10978c2ecf20Sopenharmony_ci	}
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci	err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
11008c2ecf20Sopenharmony_ci	if (err) {
11018c2ecf20Sopenharmony_ci		printf("Failed parser prog detach\n");
11028c2ecf20Sopenharmony_ci		goto out_sockmap;
11038c2ecf20Sopenharmony_ci	}
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
11068c2ecf20Sopenharmony_ci	if (err) {
11078c2ecf20Sopenharmony_ci		printf("Failed parser prog detach\n");
11088c2ecf20Sopenharmony_ci		goto out_sockmap;
11098c2ecf20Sopenharmony_ci	}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	/* Test map close sockets and empty maps */
11128c2ecf20Sopenharmony_ci	for (i = 0; i < 6; i++) {
11138c2ecf20Sopenharmony_ci		bpf_map_delete_elem(map_fd_tx, &i);
11148c2ecf20Sopenharmony_ci		bpf_map_delete_elem(map_fd_rx, &i);
11158c2ecf20Sopenharmony_ci		close(sfd[i]);
11168c2ecf20Sopenharmony_ci	}
11178c2ecf20Sopenharmony_ci	close(fd);
11188c2ecf20Sopenharmony_ci	close(map_fd_rx);
11198c2ecf20Sopenharmony_ci	bpf_object__close(obj);
11208c2ecf20Sopenharmony_ci	return;
11218c2ecf20Sopenharmony_ciout:
11228c2ecf20Sopenharmony_ci	for (i = 0; i < 6; i++)
11238c2ecf20Sopenharmony_ci		close(sfd[i]);
11248c2ecf20Sopenharmony_ci	printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno));
11258c2ecf20Sopenharmony_ci	exit(1);
11268c2ecf20Sopenharmony_ciout_sockmap:
11278c2ecf20Sopenharmony_ci	for (i = 0; i < 6; i++) {
11288c2ecf20Sopenharmony_ci		if (map_fd_tx)
11298c2ecf20Sopenharmony_ci			bpf_map_delete_elem(map_fd_tx, &i);
11308c2ecf20Sopenharmony_ci		if (map_fd_rx)
11318c2ecf20Sopenharmony_ci			bpf_map_delete_elem(map_fd_rx, &i);
11328c2ecf20Sopenharmony_ci		close(sfd[i]);
11338c2ecf20Sopenharmony_ci	}
11348c2ecf20Sopenharmony_ci	close(fd);
11358c2ecf20Sopenharmony_ci	exit(1);
11368c2ecf20Sopenharmony_ci}
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci#define MAPINMAP_PROG "./test_map_in_map.o"
11398c2ecf20Sopenharmony_cistatic void test_map_in_map(void)
11408c2ecf20Sopenharmony_ci{
11418c2ecf20Sopenharmony_ci	struct bpf_object *obj;
11428c2ecf20Sopenharmony_ci	struct bpf_map *map;
11438c2ecf20Sopenharmony_ci	int mim_fd, fd, err;
11448c2ecf20Sopenharmony_ci	int pos = 0;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	obj = bpf_object__open(MAPINMAP_PROG);
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int), sizeof(int),
11498c2ecf20Sopenharmony_ci			    2, 0);
11508c2ecf20Sopenharmony_ci	if (fd < 0) {
11518c2ecf20Sopenharmony_ci		printf("Failed to create hashmap '%s'!\n", strerror(errno));
11528c2ecf20Sopenharmony_ci		exit(1);
11538c2ecf20Sopenharmony_ci	}
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	map = bpf_object__find_map_by_name(obj, "mim_array");
11568c2ecf20Sopenharmony_ci	if (IS_ERR(map)) {
11578c2ecf20Sopenharmony_ci		printf("Failed to load array of maps from test prog\n");
11588c2ecf20Sopenharmony_ci		goto out_map_in_map;
11598c2ecf20Sopenharmony_ci	}
11608c2ecf20Sopenharmony_ci	err = bpf_map__set_inner_map_fd(map, fd);
11618c2ecf20Sopenharmony_ci	if (err) {
11628c2ecf20Sopenharmony_ci		printf("Failed to set inner_map_fd for array of maps\n");
11638c2ecf20Sopenharmony_ci		goto out_map_in_map;
11648c2ecf20Sopenharmony_ci	}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	map = bpf_object__find_map_by_name(obj, "mim_hash");
11678c2ecf20Sopenharmony_ci	if (IS_ERR(map)) {
11688c2ecf20Sopenharmony_ci		printf("Failed to load hash of maps from test prog\n");
11698c2ecf20Sopenharmony_ci		goto out_map_in_map;
11708c2ecf20Sopenharmony_ci	}
11718c2ecf20Sopenharmony_ci	err = bpf_map__set_inner_map_fd(map, fd);
11728c2ecf20Sopenharmony_ci	if (err) {
11738c2ecf20Sopenharmony_ci		printf("Failed to set inner_map_fd for hash of maps\n");
11748c2ecf20Sopenharmony_ci		goto out_map_in_map;
11758c2ecf20Sopenharmony_ci	}
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci	bpf_object__load(obj);
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	map = bpf_object__find_map_by_name(obj, "mim_array");
11808c2ecf20Sopenharmony_ci	if (IS_ERR(map)) {
11818c2ecf20Sopenharmony_ci		printf("Failed to load array of maps from test prog\n");
11828c2ecf20Sopenharmony_ci		goto out_map_in_map;
11838c2ecf20Sopenharmony_ci	}
11848c2ecf20Sopenharmony_ci	mim_fd = bpf_map__fd(map);
11858c2ecf20Sopenharmony_ci	if (mim_fd < 0) {
11868c2ecf20Sopenharmony_ci		printf("Failed to get descriptor for array of maps\n");
11878c2ecf20Sopenharmony_ci		goto out_map_in_map;
11888c2ecf20Sopenharmony_ci	}
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(mim_fd, &pos, &fd, 0);
11918c2ecf20Sopenharmony_ci	if (err) {
11928c2ecf20Sopenharmony_ci		printf("Failed to update array of maps\n");
11938c2ecf20Sopenharmony_ci		goto out_map_in_map;
11948c2ecf20Sopenharmony_ci	}
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	map = bpf_object__find_map_by_name(obj, "mim_hash");
11978c2ecf20Sopenharmony_ci	if (IS_ERR(map)) {
11988c2ecf20Sopenharmony_ci		printf("Failed to load hash of maps from test prog\n");
11998c2ecf20Sopenharmony_ci		goto out_map_in_map;
12008c2ecf20Sopenharmony_ci	}
12018c2ecf20Sopenharmony_ci	mim_fd = bpf_map__fd(map);
12028c2ecf20Sopenharmony_ci	if (mim_fd < 0) {
12038c2ecf20Sopenharmony_ci		printf("Failed to get descriptor for hash of maps\n");
12048c2ecf20Sopenharmony_ci		goto out_map_in_map;
12058c2ecf20Sopenharmony_ci	}
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(mim_fd, &pos, &fd, 0);
12088c2ecf20Sopenharmony_ci	if (err) {
12098c2ecf20Sopenharmony_ci		printf("Failed to update hash of maps\n");
12108c2ecf20Sopenharmony_ci		goto out_map_in_map;
12118c2ecf20Sopenharmony_ci	}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	close(fd);
12148c2ecf20Sopenharmony_ci	bpf_object__close(obj);
12158c2ecf20Sopenharmony_ci	return;
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ciout_map_in_map:
12188c2ecf20Sopenharmony_ci	close(fd);
12198c2ecf20Sopenharmony_ci	exit(1);
12208c2ecf20Sopenharmony_ci}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci#define MAP_SIZE (32 * 1024)
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_cistatic void test_map_large(void)
12258c2ecf20Sopenharmony_ci{
12268c2ecf20Sopenharmony_ci	struct bigkey {
12278c2ecf20Sopenharmony_ci		int a;
12288c2ecf20Sopenharmony_ci		char b[116];
12298c2ecf20Sopenharmony_ci		long long c;
12308c2ecf20Sopenharmony_ci	} key;
12318c2ecf20Sopenharmony_ci	int fd, i, value;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
12348c2ecf20Sopenharmony_ci			    MAP_SIZE, map_flags);
12358c2ecf20Sopenharmony_ci	if (fd < 0) {
12368c2ecf20Sopenharmony_ci		printf("Failed to create large map '%s'!\n", strerror(errno));
12378c2ecf20Sopenharmony_ci		exit(1);
12388c2ecf20Sopenharmony_ci	}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci	for (i = 0; i < MAP_SIZE; i++) {
12418c2ecf20Sopenharmony_ci		key = (struct bigkey) { .c = i };
12428c2ecf20Sopenharmony_ci		value = i;
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci		assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
12458c2ecf20Sopenharmony_ci	}
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	key.c = -1;
12488c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
12498c2ecf20Sopenharmony_ci	       errno == E2BIG);
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	/* Iterate through all elements. */
12528c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
12538c2ecf20Sopenharmony_ci	key.c = -1;
12548c2ecf20Sopenharmony_ci	for (i = 0; i < MAP_SIZE; i++)
12558c2ecf20Sopenharmony_ci		assert(bpf_map_get_next_key(fd, &key, &key) == 0);
12568c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	key.c = 0;
12598c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
12608c2ecf20Sopenharmony_ci	key.a = 1;
12618c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	close(fd);
12648c2ecf20Sopenharmony_ci}
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci#define run_parallel(N, FN, DATA) \
12678c2ecf20Sopenharmony_ci	printf("Fork %u tasks to '" #FN "'\n", N); \
12688c2ecf20Sopenharmony_ci	__run_parallel(N, FN, DATA)
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_cistatic void __run_parallel(unsigned int tasks,
12718c2ecf20Sopenharmony_ci			   void (*fn)(unsigned int task, void *data),
12728c2ecf20Sopenharmony_ci			   void *data)
12738c2ecf20Sopenharmony_ci{
12748c2ecf20Sopenharmony_ci	pid_t pid[tasks];
12758c2ecf20Sopenharmony_ci	int i;
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	fflush(stdout);
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci	for (i = 0; i < tasks; i++) {
12808c2ecf20Sopenharmony_ci		pid[i] = fork();
12818c2ecf20Sopenharmony_ci		if (pid[i] == 0) {
12828c2ecf20Sopenharmony_ci			fn(i, data);
12838c2ecf20Sopenharmony_ci			exit(0);
12848c2ecf20Sopenharmony_ci		} else if (pid[i] == -1) {
12858c2ecf20Sopenharmony_ci			printf("Couldn't spawn #%d process!\n", i);
12868c2ecf20Sopenharmony_ci			exit(1);
12878c2ecf20Sopenharmony_ci		}
12888c2ecf20Sopenharmony_ci	}
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	for (i = 0; i < tasks; i++) {
12918c2ecf20Sopenharmony_ci		int status;
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci		assert(waitpid(pid[i], &status, 0) == pid[i]);
12948c2ecf20Sopenharmony_ci		assert(status == 0);
12958c2ecf20Sopenharmony_ci	}
12968c2ecf20Sopenharmony_ci}
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_cistatic void test_map_stress(void)
12998c2ecf20Sopenharmony_ci{
13008c2ecf20Sopenharmony_ci	run_parallel(100, test_hashmap, NULL);
13018c2ecf20Sopenharmony_ci	run_parallel(100, test_hashmap_percpu, NULL);
13028c2ecf20Sopenharmony_ci	run_parallel(100, test_hashmap_sizes, NULL);
13038c2ecf20Sopenharmony_ci	run_parallel(100, test_hashmap_walk, NULL);
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci	run_parallel(100, test_arraymap, NULL);
13068c2ecf20Sopenharmony_ci	run_parallel(100, test_arraymap_percpu, NULL);
13078c2ecf20Sopenharmony_ci}
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ci#define TASKS 1024
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci#define DO_UPDATE 1
13128c2ecf20Sopenharmony_ci#define DO_DELETE 0
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_cistatic void test_update_delete(unsigned int fn, void *data)
13158c2ecf20Sopenharmony_ci{
13168c2ecf20Sopenharmony_ci	int do_update = ((int *)data)[1];
13178c2ecf20Sopenharmony_ci	int fd = ((int *)data)[0];
13188c2ecf20Sopenharmony_ci	int i, key, value;
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci	for (i = fn; i < MAP_SIZE; i += TASKS) {
13218c2ecf20Sopenharmony_ci		key = value = i;
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci		if (do_update) {
13248c2ecf20Sopenharmony_ci			assert(bpf_map_update_elem(fd, &key, &value,
13258c2ecf20Sopenharmony_ci						   BPF_NOEXIST) == 0);
13268c2ecf20Sopenharmony_ci			assert(bpf_map_update_elem(fd, &key, &value,
13278c2ecf20Sopenharmony_ci						   BPF_EXIST) == 0);
13288c2ecf20Sopenharmony_ci		} else {
13298c2ecf20Sopenharmony_ci			assert(bpf_map_delete_elem(fd, &key) == 0);
13308c2ecf20Sopenharmony_ci		}
13318c2ecf20Sopenharmony_ci	}
13328c2ecf20Sopenharmony_ci}
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_cistatic void test_map_parallel(void)
13358c2ecf20Sopenharmony_ci{
13368c2ecf20Sopenharmony_ci	int i, fd, key = 0, value = 0;
13378c2ecf20Sopenharmony_ci	int data[2];
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
13408c2ecf20Sopenharmony_ci			    MAP_SIZE, map_flags);
13418c2ecf20Sopenharmony_ci	if (fd < 0) {
13428c2ecf20Sopenharmony_ci		printf("Failed to create map for parallel test '%s'!\n",
13438c2ecf20Sopenharmony_ci		       strerror(errno));
13448c2ecf20Sopenharmony_ci		exit(1);
13458c2ecf20Sopenharmony_ci	}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	/* Use the same fd in children to add elements to this map:
13488c2ecf20Sopenharmony_ci	 * child_0 adds key=0, key=1024, key=2048, ...
13498c2ecf20Sopenharmony_ci	 * child_1 adds key=1, key=1025, key=2049, ...
13508c2ecf20Sopenharmony_ci	 * child_1023 adds key=1023, ...
13518c2ecf20Sopenharmony_ci	 */
13528c2ecf20Sopenharmony_ci	data[0] = fd;
13538c2ecf20Sopenharmony_ci	data[1] = DO_UPDATE;
13548c2ecf20Sopenharmony_ci	run_parallel(TASKS, test_update_delete, data);
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	/* Check that key=0 is already there. */
13578c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
13588c2ecf20Sopenharmony_ci	       errno == EEXIST);
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	/* Check that all elements were inserted. */
13618c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
13628c2ecf20Sopenharmony_ci	key = -1;
13638c2ecf20Sopenharmony_ci	for (i = 0; i < MAP_SIZE; i++)
13648c2ecf20Sopenharmony_ci		assert(bpf_map_get_next_key(fd, &key, &key) == 0);
13658c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
13668c2ecf20Sopenharmony_ci
13678c2ecf20Sopenharmony_ci	/* Another check for all elements */
13688c2ecf20Sopenharmony_ci	for (i = 0; i < MAP_SIZE; i++) {
13698c2ecf20Sopenharmony_ci		key = MAP_SIZE - i - 1;
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci		assert(bpf_map_lookup_elem(fd, &key, &value) == 0 &&
13728c2ecf20Sopenharmony_ci		       value == key);
13738c2ecf20Sopenharmony_ci	}
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	/* Now let's delete all elemenets in parallel. */
13768c2ecf20Sopenharmony_ci	data[1] = DO_DELETE;
13778c2ecf20Sopenharmony_ci	run_parallel(TASKS, test_update_delete, data);
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	/* Nothing should be left. */
13808c2ecf20Sopenharmony_ci	key = -1;
13818c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT);
13828c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
13838c2ecf20Sopenharmony_ci}
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_cistatic void test_map_rdonly(void)
13868c2ecf20Sopenharmony_ci{
13878c2ecf20Sopenharmony_ci	int fd, key = 0, value = 0;
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
13908c2ecf20Sopenharmony_ci			    MAP_SIZE, map_flags | BPF_F_RDONLY);
13918c2ecf20Sopenharmony_ci	if (fd < 0) {
13928c2ecf20Sopenharmony_ci		printf("Failed to create map for read only test '%s'!\n",
13938c2ecf20Sopenharmony_ci		       strerror(errno));
13948c2ecf20Sopenharmony_ci		exit(1);
13958c2ecf20Sopenharmony_ci	}
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci	key = 1;
13988c2ecf20Sopenharmony_ci	value = 1234;
13998c2ecf20Sopenharmony_ci	/* Try to insert key=1 element. */
14008c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 &&
14018c2ecf20Sopenharmony_ci	       errno == EPERM);
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci	/* Check that key=1 is not found. */
14048c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
14058c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT);
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	close(fd);
14088c2ecf20Sopenharmony_ci}
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_cistatic void test_map_wronly_hash(void)
14118c2ecf20Sopenharmony_ci{
14128c2ecf20Sopenharmony_ci	int fd, key = 0, value = 0;
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
14158c2ecf20Sopenharmony_ci			    MAP_SIZE, map_flags | BPF_F_WRONLY);
14168c2ecf20Sopenharmony_ci	if (fd < 0) {
14178c2ecf20Sopenharmony_ci		printf("Failed to create map for write only test '%s'!\n",
14188c2ecf20Sopenharmony_ci		       strerror(errno));
14198c2ecf20Sopenharmony_ci		exit(1);
14208c2ecf20Sopenharmony_ci	}
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_ci	key = 1;
14238c2ecf20Sopenharmony_ci	value = 1234;
14248c2ecf20Sopenharmony_ci	/* Insert key=1 element. */
14258c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci	/* Check that reading elements and keys from the map is not allowed. */
14288c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM);
14298c2ecf20Sopenharmony_ci	assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM);
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci	close(fd);
14328c2ecf20Sopenharmony_ci}
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_cistatic void test_map_wronly_stack_or_queue(enum bpf_map_type map_type)
14358c2ecf20Sopenharmony_ci{
14368c2ecf20Sopenharmony_ci	int fd, value = 0;
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	assert(map_type == BPF_MAP_TYPE_QUEUE ||
14398c2ecf20Sopenharmony_ci	       map_type == BPF_MAP_TYPE_STACK);
14408c2ecf20Sopenharmony_ci	fd = bpf_create_map(map_type, 0, sizeof(value), MAP_SIZE,
14418c2ecf20Sopenharmony_ci			    map_flags | BPF_F_WRONLY);
14428c2ecf20Sopenharmony_ci	/* Stack/Queue maps do not support BPF_F_NO_PREALLOC */
14438c2ecf20Sopenharmony_ci	if (map_flags & BPF_F_NO_PREALLOC) {
14448c2ecf20Sopenharmony_ci		assert(fd < 0 && errno == EINVAL);
14458c2ecf20Sopenharmony_ci		return;
14468c2ecf20Sopenharmony_ci	}
14478c2ecf20Sopenharmony_ci	if (fd < 0) {
14488c2ecf20Sopenharmony_ci		printf("Failed to create map '%s'!\n", strerror(errno));
14498c2ecf20Sopenharmony_ci		exit(1);
14508c2ecf20Sopenharmony_ci	}
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	value = 1234;
14538c2ecf20Sopenharmony_ci	assert(bpf_map_update_elem(fd, NULL, &value, BPF_ANY) == 0);
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci	/* Peek element should fail */
14568c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_elem(fd, NULL, &value) == -1 && errno == EPERM);
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_ci	/* Pop element should fail */
14598c2ecf20Sopenharmony_ci	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &value) == -1 &&
14608c2ecf20Sopenharmony_ci	       errno == EPERM);
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_ci	close(fd);
14638c2ecf20Sopenharmony_ci}
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_cistatic void test_map_wronly(void)
14668c2ecf20Sopenharmony_ci{
14678c2ecf20Sopenharmony_ci	test_map_wronly_hash();
14688c2ecf20Sopenharmony_ci	test_map_wronly_stack_or_queue(BPF_MAP_TYPE_STACK);
14698c2ecf20Sopenharmony_ci	test_map_wronly_stack_or_queue(BPF_MAP_TYPE_QUEUE);
14708c2ecf20Sopenharmony_ci}
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_cistatic void prepare_reuseport_grp(int type, int map_fd, size_t map_elem_size,
14738c2ecf20Sopenharmony_ci				  __s64 *fds64, __u64 *sk_cookies,
14748c2ecf20Sopenharmony_ci				  unsigned int n)
14758c2ecf20Sopenharmony_ci{
14768c2ecf20Sopenharmony_ci	socklen_t optlen, addrlen;
14778c2ecf20Sopenharmony_ci	struct sockaddr_in6 s6;
14788c2ecf20Sopenharmony_ci	const __u32 index0 = 0;
14798c2ecf20Sopenharmony_ci	const int optval = 1;
14808c2ecf20Sopenharmony_ci	unsigned int i;
14818c2ecf20Sopenharmony_ci	u64 sk_cookie;
14828c2ecf20Sopenharmony_ci	void *value;
14838c2ecf20Sopenharmony_ci	__s32 fd32;
14848c2ecf20Sopenharmony_ci	__s64 fd64;
14858c2ecf20Sopenharmony_ci	int err;
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	s6.sin6_family = AF_INET6;
14888c2ecf20Sopenharmony_ci	s6.sin6_addr = in6addr_any;
14898c2ecf20Sopenharmony_ci	s6.sin6_port = 0;
14908c2ecf20Sopenharmony_ci	addrlen = sizeof(s6);
14918c2ecf20Sopenharmony_ci	optlen = sizeof(sk_cookie);
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_ci	for (i = 0; i < n; i++) {
14948c2ecf20Sopenharmony_ci		fd64 = socket(AF_INET6, type, 0);
14958c2ecf20Sopenharmony_ci		CHECK(fd64 == -1, "socket()",
14968c2ecf20Sopenharmony_ci		      "sock_type:%d fd64:%lld errno:%d\n",
14978c2ecf20Sopenharmony_ci		      type, fd64, errno);
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci		err = setsockopt(fd64, SOL_SOCKET, SO_REUSEPORT,
15008c2ecf20Sopenharmony_ci				 &optval, sizeof(optval));
15018c2ecf20Sopenharmony_ci		CHECK(err == -1, "setsockopt(SO_REUSEPORT)",
15028c2ecf20Sopenharmony_ci		      "err:%d errno:%d\n", err, errno);
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci		/* reuseport_array does not allow unbound sk */
15058c2ecf20Sopenharmony_ci		if (map_elem_size == sizeof(__u64))
15068c2ecf20Sopenharmony_ci			value = &fd64;
15078c2ecf20Sopenharmony_ci		else {
15088c2ecf20Sopenharmony_ci			assert(map_elem_size == sizeof(__u32));
15098c2ecf20Sopenharmony_ci			fd32 = (__s32)fd64;
15108c2ecf20Sopenharmony_ci			value = &fd32;
15118c2ecf20Sopenharmony_ci		}
15128c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd, &index0, value, BPF_ANY);
15138c2ecf20Sopenharmony_ci		CHECK(err != -1 || errno != EINVAL,
15148c2ecf20Sopenharmony_ci		      "reuseport array update unbound sk",
15158c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n",
15168c2ecf20Sopenharmony_ci		      type, err, errno);
15178c2ecf20Sopenharmony_ci
15188c2ecf20Sopenharmony_ci		err = bind(fd64, (struct sockaddr *)&s6, sizeof(s6));
15198c2ecf20Sopenharmony_ci		CHECK(err == -1, "bind()",
15208c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
15218c2ecf20Sopenharmony_ci
15228c2ecf20Sopenharmony_ci		if (i == 0) {
15238c2ecf20Sopenharmony_ci			err = getsockname(fd64, (struct sockaddr *)&s6,
15248c2ecf20Sopenharmony_ci					  &addrlen);
15258c2ecf20Sopenharmony_ci			CHECK(err == -1, "getsockname()",
15268c2ecf20Sopenharmony_ci			      "sock_type:%d err:%d errno:%d\n",
15278c2ecf20Sopenharmony_ci			      type, err, errno);
15288c2ecf20Sopenharmony_ci		}
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci		err = getsockopt(fd64, SOL_SOCKET, SO_COOKIE, &sk_cookie,
15318c2ecf20Sopenharmony_ci				 &optlen);
15328c2ecf20Sopenharmony_ci		CHECK(err == -1, "getsockopt(SO_COOKIE)",
15338c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci		if (type == SOCK_STREAM) {
15368c2ecf20Sopenharmony_ci			/*
15378c2ecf20Sopenharmony_ci			 * reuseport_array does not allow
15388c2ecf20Sopenharmony_ci			 * non-listening tcp sk.
15398c2ecf20Sopenharmony_ci			 */
15408c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd, &index0, value,
15418c2ecf20Sopenharmony_ci						  BPF_ANY);
15428c2ecf20Sopenharmony_ci			CHECK(err != -1 || errno != EINVAL,
15438c2ecf20Sopenharmony_ci			      "reuseport array update non-listening sk",
15448c2ecf20Sopenharmony_ci			      "sock_type:%d err:%d errno:%d\n",
15458c2ecf20Sopenharmony_ci			      type, err, errno);
15468c2ecf20Sopenharmony_ci			err = listen(fd64, 0);
15478c2ecf20Sopenharmony_ci			CHECK(err == -1, "listen()",
15488c2ecf20Sopenharmony_ci			      "sock_type:%d, err:%d errno:%d\n",
15498c2ecf20Sopenharmony_ci			      type, err, errno);
15508c2ecf20Sopenharmony_ci		}
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci		fds64[i] = fd64;
15538c2ecf20Sopenharmony_ci		sk_cookies[i] = sk_cookie;
15548c2ecf20Sopenharmony_ci	}
15558c2ecf20Sopenharmony_ci}
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_cistatic void test_reuseport_array(void)
15588c2ecf20Sopenharmony_ci{
15598c2ecf20Sopenharmony_ci#define REUSEPORT_FD_IDX(err, last) ({ (err) ? last : !last; })
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	const __u32 array_size = 4, index0 = 0, index3 = 3;
15628c2ecf20Sopenharmony_ci	int types[2] = { SOCK_STREAM, SOCK_DGRAM }, type;
15638c2ecf20Sopenharmony_ci	__u64 grpa_cookies[2], sk_cookie, map_cookie;
15648c2ecf20Sopenharmony_ci	__s64 grpa_fds64[2] = { -1, -1 }, fd64 = -1;
15658c2ecf20Sopenharmony_ci	const __u32 bad_index = array_size;
15668c2ecf20Sopenharmony_ci	int map_fd, err, t, f;
15678c2ecf20Sopenharmony_ci	__u32 fds_idx = 0;
15688c2ecf20Sopenharmony_ci	int fd;
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci	map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
15718c2ecf20Sopenharmony_ci				sizeof(__u32), sizeof(__u64), array_size, 0);
15728c2ecf20Sopenharmony_ci	CHECK(map_fd == -1, "reuseport array create",
15738c2ecf20Sopenharmony_ci	      "map_fd:%d, errno:%d\n", map_fd, errno);
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	/* Test lookup/update/delete with invalid index */
15768c2ecf20Sopenharmony_ci	err = bpf_map_delete_elem(map_fd, &bad_index);
15778c2ecf20Sopenharmony_ci	CHECK(err != -1 || errno != E2BIG, "reuseport array del >=max_entries",
15788c2ecf20Sopenharmony_ci	      "err:%d errno:%d\n", err, errno);
15798c2ecf20Sopenharmony_ci
15808c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(map_fd, &bad_index, &fd64, BPF_ANY);
15818c2ecf20Sopenharmony_ci	CHECK(err != -1 || errno != E2BIG,
15828c2ecf20Sopenharmony_ci	      "reuseport array update >=max_entries",
15838c2ecf20Sopenharmony_ci	      "err:%d errno:%d\n", err, errno);
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci	err = bpf_map_lookup_elem(map_fd, &bad_index, &map_cookie);
15868c2ecf20Sopenharmony_ci	CHECK(err != -1 || errno != ENOENT,
15878c2ecf20Sopenharmony_ci	      "reuseport array update >=max_entries",
15888c2ecf20Sopenharmony_ci	      "err:%d errno:%d\n", err, errno);
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	/* Test lookup/delete non existence elem */
15918c2ecf20Sopenharmony_ci	err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
15928c2ecf20Sopenharmony_ci	CHECK(err != -1 || errno != ENOENT,
15938c2ecf20Sopenharmony_ci	      "reuseport array lookup not-exist elem",
15948c2ecf20Sopenharmony_ci	      "err:%d errno:%d\n", err, errno);
15958c2ecf20Sopenharmony_ci	err = bpf_map_delete_elem(map_fd, &index3);
15968c2ecf20Sopenharmony_ci	CHECK(err != -1 || errno != ENOENT,
15978c2ecf20Sopenharmony_ci	      "reuseport array del not-exist elem",
15988c2ecf20Sopenharmony_ci	      "err:%d errno:%d\n", err, errno);
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci	for (t = 0; t < ARRAY_SIZE(types); t++) {
16018c2ecf20Sopenharmony_ci		type = types[t];
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci		prepare_reuseport_grp(type, map_fd, sizeof(__u64), grpa_fds64,
16048c2ecf20Sopenharmony_ci				      grpa_cookies, ARRAY_SIZE(grpa_fds64));
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci		/* Test BPF_* update flags */
16078c2ecf20Sopenharmony_ci		/* BPF_EXIST failure case */
16088c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
16098c2ecf20Sopenharmony_ci					  BPF_EXIST);
16108c2ecf20Sopenharmony_ci		CHECK(err != -1 || errno != ENOENT,
16118c2ecf20Sopenharmony_ci		      "reuseport array update empty elem BPF_EXIST",
16128c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n",
16138c2ecf20Sopenharmony_ci		      type, err, errno);
16148c2ecf20Sopenharmony_ci		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_ci		/* BPF_NOEXIST success case */
16178c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
16188c2ecf20Sopenharmony_ci					  BPF_NOEXIST);
16198c2ecf20Sopenharmony_ci		CHECK(err == -1,
16208c2ecf20Sopenharmony_ci		      "reuseport array update empty elem BPF_NOEXIST",
16218c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n",
16228c2ecf20Sopenharmony_ci		      type, err, errno);
16238c2ecf20Sopenharmony_ci		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci		/* BPF_EXIST success case. */
16268c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
16278c2ecf20Sopenharmony_ci					  BPF_EXIST);
16288c2ecf20Sopenharmony_ci		CHECK(err == -1,
16298c2ecf20Sopenharmony_ci		      "reuseport array update same elem BPF_EXIST",
16308c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
16318c2ecf20Sopenharmony_ci		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
16328c2ecf20Sopenharmony_ci
16338c2ecf20Sopenharmony_ci		/* BPF_NOEXIST failure case */
16348c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
16358c2ecf20Sopenharmony_ci					  BPF_NOEXIST);
16368c2ecf20Sopenharmony_ci		CHECK(err != -1 || errno != EEXIST,
16378c2ecf20Sopenharmony_ci		      "reuseport array update non-empty elem BPF_NOEXIST",
16388c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n",
16398c2ecf20Sopenharmony_ci		      type, err, errno);
16408c2ecf20Sopenharmony_ci		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci		/* BPF_ANY case (always succeed) */
16438c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
16448c2ecf20Sopenharmony_ci					  BPF_ANY);
16458c2ecf20Sopenharmony_ci		CHECK(err == -1,
16468c2ecf20Sopenharmony_ci		      "reuseport array update same sk with BPF_ANY",
16478c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci		fd64 = grpa_fds64[fds_idx];
16508c2ecf20Sopenharmony_ci		sk_cookie = grpa_cookies[fds_idx];
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci		/* The same sk cannot be added to reuseport_array twice */
16538c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_ANY);
16548c2ecf20Sopenharmony_ci		CHECK(err != -1 || errno != EBUSY,
16558c2ecf20Sopenharmony_ci		      "reuseport array update same sk with same index",
16568c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n",
16578c2ecf20Sopenharmony_ci		      type, err, errno);
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd, &index0, &fd64, BPF_ANY);
16608c2ecf20Sopenharmony_ci		CHECK(err != -1 || errno != EBUSY,
16618c2ecf20Sopenharmony_ci		      "reuseport array update same sk with different index",
16628c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n",
16638c2ecf20Sopenharmony_ci		      type, err, errno);
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_ci		/* Test delete elem */
16668c2ecf20Sopenharmony_ci		err = bpf_map_delete_elem(map_fd, &index3);
16678c2ecf20Sopenharmony_ci		CHECK(err == -1, "reuseport array delete sk",
16688c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n",
16698c2ecf20Sopenharmony_ci		      type, err, errno);
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci		/* Add it back with BPF_NOEXIST */
16728c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST);
16738c2ecf20Sopenharmony_ci		CHECK(err == -1,
16748c2ecf20Sopenharmony_ci		      "reuseport array re-add with BPF_NOEXIST after del",
16758c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci		/* Test cookie */
16788c2ecf20Sopenharmony_ci		err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
16798c2ecf20Sopenharmony_ci		CHECK(err == -1 || sk_cookie != map_cookie,
16808c2ecf20Sopenharmony_ci		      "reuseport array lookup re-added sk",
16818c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d sk_cookie:0x%llx map_cookie:0x%llxn",
16828c2ecf20Sopenharmony_ci		      type, err, errno, sk_cookie, map_cookie);
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci		/* Test elem removed by close() */
16858c2ecf20Sopenharmony_ci		for (f = 0; f < ARRAY_SIZE(grpa_fds64); f++)
16868c2ecf20Sopenharmony_ci			close(grpa_fds64[f]);
16878c2ecf20Sopenharmony_ci		err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
16888c2ecf20Sopenharmony_ci		CHECK(err != -1 || errno != ENOENT,
16898c2ecf20Sopenharmony_ci		      "reuseport array lookup after close()",
16908c2ecf20Sopenharmony_ci		      "sock_type:%d err:%d errno:%d\n",
16918c2ecf20Sopenharmony_ci		      type, err, errno);
16928c2ecf20Sopenharmony_ci	}
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	/* Test SOCK_RAW */
16958c2ecf20Sopenharmony_ci	fd64 = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP);
16968c2ecf20Sopenharmony_ci	CHECK(fd64 == -1, "socket(SOCK_RAW)", "err:%d errno:%d\n",
16978c2ecf20Sopenharmony_ci	      err, errno);
16988c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST);
16998c2ecf20Sopenharmony_ci	CHECK(err != -1 || errno != ENOTSUPP, "reuseport array update SOCK_RAW",
17008c2ecf20Sopenharmony_ci	      "err:%d errno:%d\n", err, errno);
17018c2ecf20Sopenharmony_ci	close(fd64);
17028c2ecf20Sopenharmony_ci
17038c2ecf20Sopenharmony_ci	/* Close the 64 bit value map */
17048c2ecf20Sopenharmony_ci	close(map_fd);
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	/* Test 32 bit fd */
17078c2ecf20Sopenharmony_ci	map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
17088c2ecf20Sopenharmony_ci				sizeof(__u32), sizeof(__u32), array_size, 0);
17098c2ecf20Sopenharmony_ci	CHECK(map_fd == -1, "reuseport array create",
17108c2ecf20Sopenharmony_ci	      "map_fd:%d, errno:%d\n", map_fd, errno);
17118c2ecf20Sopenharmony_ci	prepare_reuseport_grp(SOCK_STREAM, map_fd, sizeof(__u32), &fd64,
17128c2ecf20Sopenharmony_ci			      &sk_cookie, 1);
17138c2ecf20Sopenharmony_ci	fd = fd64;
17148c2ecf20Sopenharmony_ci	err = bpf_map_update_elem(map_fd, &index3, &fd, BPF_NOEXIST);
17158c2ecf20Sopenharmony_ci	CHECK(err == -1, "reuseport array update 32 bit fd",
17168c2ecf20Sopenharmony_ci	      "err:%d errno:%d\n", err, errno);
17178c2ecf20Sopenharmony_ci	err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
17188c2ecf20Sopenharmony_ci	CHECK(err != -1 || errno != ENOSPC,
17198c2ecf20Sopenharmony_ci	      "reuseport array lookup 32 bit fd",
17208c2ecf20Sopenharmony_ci	      "err:%d errno:%d\n", err, errno);
17218c2ecf20Sopenharmony_ci	close(fd);
17228c2ecf20Sopenharmony_ci	close(map_fd);
17238c2ecf20Sopenharmony_ci}
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_cistatic void run_all_tests(void)
17268c2ecf20Sopenharmony_ci{
17278c2ecf20Sopenharmony_ci	test_hashmap(0, NULL);
17288c2ecf20Sopenharmony_ci	test_hashmap_percpu(0, NULL);
17298c2ecf20Sopenharmony_ci	test_hashmap_walk(0, NULL);
17308c2ecf20Sopenharmony_ci	test_hashmap_zero_seed();
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_ci	test_arraymap(0, NULL);
17338c2ecf20Sopenharmony_ci	test_arraymap_percpu(0, NULL);
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci	test_arraymap_percpu_many_keys();
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_ci	test_devmap(0, NULL);
17388c2ecf20Sopenharmony_ci	test_devmap_hash(0, NULL);
17398c2ecf20Sopenharmony_ci	test_sockmap(0, NULL);
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	test_map_large();
17428c2ecf20Sopenharmony_ci	test_map_parallel();
17438c2ecf20Sopenharmony_ci	test_map_stress();
17448c2ecf20Sopenharmony_ci
17458c2ecf20Sopenharmony_ci	test_map_rdonly();
17468c2ecf20Sopenharmony_ci	test_map_wronly();
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	test_reuseport_array();
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_ci	test_queuemap(0, NULL);
17518c2ecf20Sopenharmony_ci	test_stackmap(0, NULL);
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci	test_map_in_map();
17548c2ecf20Sopenharmony_ci}
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci#define DEFINE_TEST(name) extern void test_##name(void);
17578c2ecf20Sopenharmony_ci#include <map_tests/tests.h>
17588c2ecf20Sopenharmony_ci#undef DEFINE_TEST
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ciint main(void)
17618c2ecf20Sopenharmony_ci{
17628c2ecf20Sopenharmony_ci	srand(time(NULL));
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci	map_flags = 0;
17658c2ecf20Sopenharmony_ci	run_all_tests();
17668c2ecf20Sopenharmony_ci
17678c2ecf20Sopenharmony_ci	map_flags = BPF_F_NO_PREALLOC;
17688c2ecf20Sopenharmony_ci	run_all_tests();
17698c2ecf20Sopenharmony_ci
17708c2ecf20Sopenharmony_ci#define DEFINE_TEST(name) test_##name();
17718c2ecf20Sopenharmony_ci#include <map_tests/tests.h>
17728c2ecf20Sopenharmony_ci#undef DEFINE_TEST
17738c2ecf20Sopenharmony_ci
17748c2ecf20Sopenharmony_ci	printf("test_maps: OK, %d SKIPPED\n", skips);
17758c2ecf20Sopenharmony_ci	return 0;
17768c2ecf20Sopenharmony_ci}
1777