xref: /openbmc/linux/tools/testing/selftests/bpf/test_maps.c (revision 5ee9cd065836e5934710ca35653bce7905add20b)
125763b3cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
25aa5bd14SDaniel Borkmann /*
35aa5bd14SDaniel Borkmann  * Testsuite for eBPF maps
45aa5bd14SDaniel Borkmann  *
55aa5bd14SDaniel Borkmann  * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
65aa5bd14SDaniel Borkmann  * Copyright (c) 2016 Facebook
75aa5bd14SDaniel Borkmann  */
85aa5bd14SDaniel Borkmann 
95aa5bd14SDaniel Borkmann #include <stdio.h>
105aa5bd14SDaniel Borkmann #include <unistd.h>
115aa5bd14SDaniel Borkmann #include <errno.h>
125aa5bd14SDaniel Borkmann #include <string.h>
135aa5bd14SDaniel Borkmann #include <assert.h>
145aa5bd14SDaniel Borkmann #include <stdlib.h>
1543b987d2SMauricio Vasquez B #include <time.h>
165aa5bd14SDaniel Borkmann 
175aa5bd14SDaniel Borkmann #include <sys/wait.h>
186bc8529cSMartin KaFai Lau #include <sys/socket.h>
196bc8529cSMartin KaFai Lau #include <netinet/in.h>
205aa5bd14SDaniel Borkmann #include <linux/bpf.h>
215aa5bd14SDaniel Borkmann 
2210ecc728SMickaël Salaün #include <bpf/bpf.h>
236f6d33f3SJohn Fastabend #include <bpf/libbpf.h>
24fe8d662aSDaniel Borkmann 
25e00c7b21SDaniel Borkmann #include "bpf_util.h"
2651a0e301SMartin KaFai Lau #include "test_maps.h"
27cbdb1461SAndrii Nakryiko #include "testing_helpers.h"
285aa5bd14SDaniel Borkmann 
296bc8529cSMartin KaFai Lau #ifndef ENOTSUPP
306bc8529cSMartin KaFai Lau #define ENOTSUPP 524
316bc8529cSMartin KaFai Lau #endif
326bc8529cSMartin KaFai Lau 
33a7e85406SHou Tao int skips;
34e8ddbfb4SStanislav Fomichev 
352fe256a4SAndrii Nakryiko static struct bpf_map_create_opts map_opts = { .sz = sizeof(map_opts) };
365aa5bd14SDaniel Borkmann 
test_hashmap(unsigned int task,void * data)37dd9cef43SBreno Leitao static void test_hashmap(unsigned int task, void *data)
385aa5bd14SDaniel Borkmann {
398fe45924STeng Qin 	long long key, next_key, first_key, value;
405aa5bd14SDaniel Borkmann 	int fd;
415aa5bd14SDaniel Borkmann 
422fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value), 2, &map_opts);
435aa5bd14SDaniel Borkmann 	if (fd < 0) {
445aa5bd14SDaniel Borkmann 		printf("Failed to create hashmap '%s'!\n", strerror(errno));
455aa5bd14SDaniel Borkmann 		exit(1);
465aa5bd14SDaniel Borkmann 	}
475aa5bd14SDaniel Borkmann 
485aa5bd14SDaniel Borkmann 	key = 1;
495aa5bd14SDaniel Borkmann 	value = 1234;
505aa5bd14SDaniel Borkmann 	/* Insert key=1 element. */
5110ecc728SMickaël Salaün 	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
525aa5bd14SDaniel Borkmann 
535aa5bd14SDaniel Borkmann 	value = 0;
545aa5bd14SDaniel Borkmann 	/* BPF_NOEXIST means add new element if it doesn't exist. */
55bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 &&
565aa5bd14SDaniel Borkmann 	       /* key=1 already exists. */
575aa5bd14SDaniel Borkmann 	       errno == EEXIST);
585aa5bd14SDaniel Borkmann 
595aa5bd14SDaniel Borkmann 	/* -1 is an invalid flag. */
60bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, -1) < 0 &&
6110ecc728SMickaël Salaün 	       errno == EINVAL);
625aa5bd14SDaniel Borkmann 
635aa5bd14SDaniel Borkmann 	/* Check that key=1 can be found. */
64e5ff7c40SMickaël Salaün 	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
655aa5bd14SDaniel Borkmann 
665aa5bd14SDaniel Borkmann 	key = 2;
6749c299b6SDenis Salopek 	value = 1234;
6849c299b6SDenis Salopek 	/* Insert key=2 element. */
6949c299b6SDenis Salopek 	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
7049c299b6SDenis Salopek 
7149c299b6SDenis Salopek 	/* Check that key=2 matches the value and delete it */
7249c299b6SDenis Salopek 	assert(bpf_map_lookup_and_delete_elem(fd, &key, &value) == 0 && value == 1234);
7349c299b6SDenis Salopek 
745aa5bd14SDaniel Borkmann 	/* Check that key=2 is not found. */
75bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == ENOENT);
765aa5bd14SDaniel Borkmann 
775aa5bd14SDaniel Borkmann 	/* BPF_EXIST means update existing element. */
78bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) < 0 &&
795aa5bd14SDaniel Borkmann 	       /* key=2 is not there. */
805aa5bd14SDaniel Borkmann 	       errno == ENOENT);
815aa5bd14SDaniel Borkmann 
825aa5bd14SDaniel Borkmann 	/* Insert key=2 element. */
8310ecc728SMickaël Salaün 	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
845aa5bd14SDaniel Borkmann 
855aa5bd14SDaniel Borkmann 	/* key=1 and key=2 were inserted, check that key=0 cannot be
865aa5bd14SDaniel Borkmann 	 * inserted due to max_entries limit.
875aa5bd14SDaniel Borkmann 	 */
885aa5bd14SDaniel Borkmann 	key = 0;
89bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 &&
905aa5bd14SDaniel Borkmann 	       errno == E2BIG);
915aa5bd14SDaniel Borkmann 
925aa5bd14SDaniel Borkmann 	/* Update existing element, though the map is full. */
935aa5bd14SDaniel Borkmann 	key = 1;
9410ecc728SMickaël Salaün 	assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
955aa5bd14SDaniel Borkmann 	key = 2;
9610ecc728SMickaël Salaün 	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
978c290e60SAlexei Starovoitov 	key = 3;
98bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 &&
998c290e60SAlexei Starovoitov 	       errno == E2BIG);
1005aa5bd14SDaniel Borkmann 
1015aa5bd14SDaniel Borkmann 	/* Check that key = 0 doesn't exist. */
1025aa5bd14SDaniel Borkmann 	key = 0;
103bad2e478SAndrii Nakryiko 	assert(bpf_map_delete_elem(fd, &key) < 0 && errno == ENOENT);
1045aa5bd14SDaniel Borkmann 
1055aa5bd14SDaniel Borkmann 	/* Iterate over two elements. */
1068fe45924STeng Qin 	assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
1078fe45924STeng Qin 	       (first_key == 1 || first_key == 2));
1085f155c25SMickaël Salaün 	assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
1098fe45924STeng Qin 	       (next_key == first_key));
1105f155c25SMickaël Salaün 	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
1118fe45924STeng Qin 	       (next_key == 1 || next_key == 2) &&
1128fe45924STeng Qin 	       (next_key != first_key));
113bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &next_key, &next_key) < 0 &&
1145aa5bd14SDaniel Borkmann 	       errno == ENOENT);
1155aa5bd14SDaniel Borkmann 
1165aa5bd14SDaniel Borkmann 	/* Delete both elements. */
1175aa5bd14SDaniel Borkmann 	key = 1;
118e58383b8SMickaël Salaün 	assert(bpf_map_delete_elem(fd, &key) == 0);
1195aa5bd14SDaniel Borkmann 	key = 2;
120e58383b8SMickaël Salaün 	assert(bpf_map_delete_elem(fd, &key) == 0);
121bad2e478SAndrii Nakryiko 	assert(bpf_map_delete_elem(fd, &key) < 0 && errno == ENOENT);
1225aa5bd14SDaniel Borkmann 
1235aa5bd14SDaniel Borkmann 	key = 0;
1245aa5bd14SDaniel Borkmann 	/* Check that map is empty. */
125bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, NULL, &next_key) < 0 &&
1268fe45924STeng Qin 	       errno == ENOENT);
127bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &key, &next_key) < 0 &&
1285aa5bd14SDaniel Borkmann 	       errno == ENOENT);
1295aa5bd14SDaniel Borkmann 
1305aa5bd14SDaniel Borkmann 	close(fd);
1315aa5bd14SDaniel Borkmann }
1325aa5bd14SDaniel Borkmann 
test_hashmap_sizes(unsigned int task,void * data)133dd9cef43SBreno Leitao static void test_hashmap_sizes(unsigned int task, void *data)
1348c290e60SAlexei Starovoitov {
1358c290e60SAlexei Starovoitov 	int fd, i, j;
1368c290e60SAlexei Starovoitov 
1378c290e60SAlexei Starovoitov 	for (i = 1; i <= 512; i <<= 1)
1388c290e60SAlexei Starovoitov 		for (j = 1; j <= 1 << 18; j <<= 1) {
1392fe256a4SAndrii Nakryiko 			fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, i, j, 2, &map_opts);
1408c290e60SAlexei Starovoitov 			if (fd < 0) {
14180475c48SLi Zhijian 				if (errno == ENOMEM)
14280475c48SLi Zhijian 					return;
1438c290e60SAlexei Starovoitov 				printf("Failed to create hashmap key=%d value=%d '%s'\n",
1448c290e60SAlexei Starovoitov 				       i, j, strerror(errno));
1458c290e60SAlexei Starovoitov 				exit(1);
1468c290e60SAlexei Starovoitov 			}
1478c290e60SAlexei Starovoitov 			close(fd);
1488c290e60SAlexei Starovoitov 			usleep(10); /* give kernel time to destroy */
1498c290e60SAlexei Starovoitov 		}
1508c290e60SAlexei Starovoitov }
1518c290e60SAlexei Starovoitov 
test_hashmap_percpu(unsigned int task,void * data)152dd9cef43SBreno Leitao static void test_hashmap_percpu(unsigned int task, void *data)
1535aa5bd14SDaniel Borkmann {
154e00c7b21SDaniel Borkmann 	unsigned int nr_cpus = bpf_num_possible_cpus();
155f3515b5dSDaniel Borkmann 	BPF_DECLARE_PERCPU(long, value);
1568fe45924STeng Qin 	long long key, next_key, first_key;
1575aa5bd14SDaniel Borkmann 	int expected_key_mask = 0;
1585aa5bd14SDaniel Borkmann 	int fd, i;
1595aa5bd14SDaniel Borkmann 
1602fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, NULL, sizeof(key),
1612fe256a4SAndrii Nakryiko 			    sizeof(bpf_percpu(value, 0)), 2, &map_opts);
1625aa5bd14SDaniel Borkmann 	if (fd < 0) {
1635aa5bd14SDaniel Borkmann 		printf("Failed to create hashmap '%s'!\n", strerror(errno));
1645aa5bd14SDaniel Borkmann 		exit(1);
1655aa5bd14SDaniel Borkmann 	}
1665aa5bd14SDaniel Borkmann 
1675aa5bd14SDaniel Borkmann 	for (i = 0; i < nr_cpus; i++)
168f3515b5dSDaniel Borkmann 		bpf_percpu(value, i) = i + 100;
1695aa5bd14SDaniel Borkmann 
1705aa5bd14SDaniel Borkmann 	key = 1;
1715aa5bd14SDaniel Borkmann 	/* Insert key=1 element. */
1725aa5bd14SDaniel Borkmann 	assert(!(expected_key_mask & key));
17310ecc728SMickaël Salaün 	assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0);
17449c299b6SDenis Salopek 
17549c299b6SDenis Salopek 	/* Lookup and delete elem key=1 and check value. */
17649c299b6SDenis Salopek 	assert(bpf_map_lookup_and_delete_elem(fd, &key, value) == 0 &&
17749c299b6SDenis Salopek 	       bpf_percpu(value,0) == 100);
17849c299b6SDenis Salopek 
17949c299b6SDenis Salopek 	for (i = 0; i < nr_cpus; i++)
18049c299b6SDenis Salopek 		bpf_percpu(value,i) = i + 100;
18149c299b6SDenis Salopek 
18249c299b6SDenis Salopek 	/* Insert key=1 element which should not exist. */
18349c299b6SDenis Salopek 	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0);
1845aa5bd14SDaniel Borkmann 	expected_key_mask |= key;
1855aa5bd14SDaniel Borkmann 
1865aa5bd14SDaniel Borkmann 	/* BPF_NOEXIST means add new element if it doesn't exist. */
187bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) < 0 &&
1885aa5bd14SDaniel Borkmann 	       /* key=1 already exists. */
1895aa5bd14SDaniel Borkmann 	       errno == EEXIST);
1905aa5bd14SDaniel Borkmann 
1915aa5bd14SDaniel Borkmann 	/* -1 is an invalid flag. */
192bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, value, -1) < 0 &&
19310ecc728SMickaël Salaün 	       errno == EINVAL);
1945aa5bd14SDaniel Borkmann 
1955aa5bd14SDaniel Borkmann 	/* Check that key=1 can be found. Value could be 0 if the lookup
1965aa5bd14SDaniel Borkmann 	 * was run from a different CPU.
1975aa5bd14SDaniel Borkmann 	 */
198f3515b5dSDaniel Borkmann 	bpf_percpu(value, 0) = 1;
199f3515b5dSDaniel Borkmann 	assert(bpf_map_lookup_elem(fd, &key, value) == 0 &&
200f3515b5dSDaniel Borkmann 	       bpf_percpu(value, 0) == 100);
2015aa5bd14SDaniel Borkmann 
2025aa5bd14SDaniel Borkmann 	key = 2;
2035aa5bd14SDaniel Borkmann 	/* Check that key=2 is not found. */
204bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_elem(fd, &key, value) < 0 && errno == ENOENT);
2055aa5bd14SDaniel Borkmann 
2065aa5bd14SDaniel Borkmann 	/* BPF_EXIST means update existing element. */
207bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) < 0 &&
2085aa5bd14SDaniel Borkmann 	       /* key=2 is not there. */
2095aa5bd14SDaniel Borkmann 	       errno == ENOENT);
2105aa5bd14SDaniel Borkmann 
2115aa5bd14SDaniel Borkmann 	/* Insert key=2 element. */
2125aa5bd14SDaniel Borkmann 	assert(!(expected_key_mask & key));
21310ecc728SMickaël Salaün 	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0);
2145aa5bd14SDaniel Borkmann 	expected_key_mask |= key;
2155aa5bd14SDaniel Borkmann 
2165aa5bd14SDaniel Borkmann 	/* key=1 and key=2 were inserted, check that key=0 cannot be
2175aa5bd14SDaniel Borkmann 	 * inserted due to max_entries limit.
2185aa5bd14SDaniel Borkmann 	 */
2195aa5bd14SDaniel Borkmann 	key = 0;
220bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) < 0 &&
2215aa5bd14SDaniel Borkmann 	       errno == E2BIG);
2225aa5bd14SDaniel Borkmann 
2235aa5bd14SDaniel Borkmann 	/* Check that key = 0 doesn't exist. */
224bad2e478SAndrii Nakryiko 	assert(bpf_map_delete_elem(fd, &key) < 0 && errno == ENOENT);
2255aa5bd14SDaniel Borkmann 
2265aa5bd14SDaniel Borkmann 	/* Iterate over two elements. */
2278fe45924STeng Qin 	assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
2288fe45924STeng Qin 	       ((expected_key_mask & first_key) == first_key));
2295f155c25SMickaël Salaün 	while (!bpf_map_get_next_key(fd, &key, &next_key)) {
2308fe45924STeng Qin 		if (first_key) {
2318fe45924STeng Qin 			assert(next_key == first_key);
2328fe45924STeng Qin 			first_key = 0;
2338fe45924STeng Qin 		}
2345aa5bd14SDaniel Borkmann 		assert((expected_key_mask & next_key) == next_key);
2355aa5bd14SDaniel Borkmann 		expected_key_mask &= ~next_key;
2365aa5bd14SDaniel Borkmann 
237e5ff7c40SMickaël Salaün 		assert(bpf_map_lookup_elem(fd, &next_key, value) == 0);
2385aa5bd14SDaniel Borkmann 
2395aa5bd14SDaniel Borkmann 		for (i = 0; i < nr_cpus; i++)
240f3515b5dSDaniel Borkmann 			assert(bpf_percpu(value, i) == i + 100);
2415aa5bd14SDaniel Borkmann 
2425aa5bd14SDaniel Borkmann 		key = next_key;
2435aa5bd14SDaniel Borkmann 	}
2445aa5bd14SDaniel Borkmann 	assert(errno == ENOENT);
2455aa5bd14SDaniel Borkmann 
2465aa5bd14SDaniel Borkmann 	/* Update with BPF_EXIST. */
2475aa5bd14SDaniel Borkmann 	key = 1;
24810ecc728SMickaël Salaün 	assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0);
2495aa5bd14SDaniel Borkmann 
2505aa5bd14SDaniel Borkmann 	/* Delete both elements. */
2515aa5bd14SDaniel Borkmann 	key = 1;
252e58383b8SMickaël Salaün 	assert(bpf_map_delete_elem(fd, &key) == 0);
2535aa5bd14SDaniel Borkmann 	key = 2;
254e58383b8SMickaël Salaün 	assert(bpf_map_delete_elem(fd, &key) == 0);
255bad2e478SAndrii Nakryiko 	assert(bpf_map_delete_elem(fd, &key) < 0 && errno == ENOENT);
2565aa5bd14SDaniel Borkmann 
2575aa5bd14SDaniel Borkmann 	key = 0;
2585aa5bd14SDaniel Borkmann 	/* Check that map is empty. */
259bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, NULL, &next_key) < 0 &&
2608fe45924STeng Qin 	       errno == ENOENT);
261bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &key, &next_key) < 0 &&
2625aa5bd14SDaniel Borkmann 	       errno == ENOENT);
2635aa5bd14SDaniel Borkmann 
2645aa5bd14SDaniel Borkmann 	close(fd);
2655aa5bd14SDaniel Borkmann }
2665aa5bd14SDaniel Borkmann 
26737521bffSAlexei Starovoitov #define VALUE_SIZE 3
helper_fill_hashmap(int max_entries)268bf5d68c7SLorenz Bauer static int helper_fill_hashmap(int max_entries)
269bf5d68c7SLorenz Bauer {
270bf5d68c7SLorenz Bauer 	int i, fd, ret;
27137521bffSAlexei Starovoitov 	long long key, value[VALUE_SIZE] = {};
272bf5d68c7SLorenz Bauer 
2732fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value),
2742fe256a4SAndrii Nakryiko 			    max_entries, &map_opts);
275bf5d68c7SLorenz Bauer 	CHECK(fd < 0,
276bf5d68c7SLorenz Bauer 	      "failed to create hashmap",
2772fe256a4SAndrii Nakryiko 	      "err: %s, flags: 0x%x\n", strerror(errno), map_opts.map_flags);
278bf5d68c7SLorenz Bauer 
279bf5d68c7SLorenz Bauer 	for (i = 0; i < max_entries; i++) {
28037521bffSAlexei Starovoitov 		key = i; value[0] = key;
28137521bffSAlexei Starovoitov 		ret = bpf_map_update_elem(fd, &key, value, BPF_NOEXIST);
282bf5d68c7SLorenz Bauer 		CHECK(ret != 0,
283bf5d68c7SLorenz Bauer 		      "can't update hashmap",
284bf5d68c7SLorenz Bauer 		      "err: %s\n", strerror(ret));
285bf5d68c7SLorenz Bauer 	}
286bf5d68c7SLorenz Bauer 
287bf5d68c7SLorenz Bauer 	return fd;
288bf5d68c7SLorenz Bauer }
289bf5d68c7SLorenz Bauer 
test_hashmap_walk(unsigned int task,void * data)290dd9cef43SBreno Leitao static void test_hashmap_walk(unsigned int task, void *data)
2915ecf51fdSDaniel Borkmann {
29237521bffSAlexei Starovoitov 	int fd, i, max_entries = 10000;
29337521bffSAlexei Starovoitov 	long long key, value[VALUE_SIZE], next_key;
2945ecf51fdSDaniel Borkmann 	bool next_key_valid = true;
2955ecf51fdSDaniel Borkmann 
296bf5d68c7SLorenz Bauer 	fd = helper_fill_hashmap(max_entries);
2975ecf51fdSDaniel Borkmann 
2985ecf51fdSDaniel Borkmann 	for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
2995ecf51fdSDaniel Borkmann 					 &next_key) == 0; i++) {
3005ecf51fdSDaniel Borkmann 		key = next_key;
30137521bffSAlexei Starovoitov 		assert(bpf_map_lookup_elem(fd, &key, value) == 0);
3025ecf51fdSDaniel Borkmann 	}
3035ecf51fdSDaniel Borkmann 
3045ecf51fdSDaniel Borkmann 	assert(i == max_entries);
3055ecf51fdSDaniel Borkmann 
3065ecf51fdSDaniel Borkmann 	assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
3075ecf51fdSDaniel Borkmann 	for (i = 0; next_key_valid; i++) {
3085ecf51fdSDaniel Borkmann 		next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0;
30937521bffSAlexei Starovoitov 		assert(bpf_map_lookup_elem(fd, &key, value) == 0);
31037521bffSAlexei Starovoitov 		value[0]++;
31137521bffSAlexei Starovoitov 		assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0);
3125ecf51fdSDaniel Borkmann 		key = next_key;
3135ecf51fdSDaniel Borkmann 	}
3145ecf51fdSDaniel Borkmann 
3155ecf51fdSDaniel Borkmann 	assert(i == max_entries);
3165ecf51fdSDaniel Borkmann 
3175ecf51fdSDaniel Borkmann 	for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
3185ecf51fdSDaniel Borkmann 					 &next_key) == 0; i++) {
3195ecf51fdSDaniel Borkmann 		key = next_key;
32037521bffSAlexei Starovoitov 		assert(bpf_map_lookup_elem(fd, &key, value) == 0);
32137521bffSAlexei Starovoitov 		assert(value[0] - 1 == key);
3225ecf51fdSDaniel Borkmann 	}
3235ecf51fdSDaniel Borkmann 
3245ecf51fdSDaniel Borkmann 	assert(i == max_entries);
3255ecf51fdSDaniel Borkmann 	close(fd);
3265ecf51fdSDaniel Borkmann }
3275ecf51fdSDaniel Borkmann 
test_hashmap_zero_seed(void)328bf5d68c7SLorenz Bauer static void test_hashmap_zero_seed(void)
329bf5d68c7SLorenz Bauer {
330bf5d68c7SLorenz Bauer 	int i, first, second, old_flags;
331bf5d68c7SLorenz Bauer 	long long key, next_first, next_second;
332bf5d68c7SLorenz Bauer 
3332fe256a4SAndrii Nakryiko 	old_flags = map_opts.map_flags;
3342fe256a4SAndrii Nakryiko 	map_opts.map_flags |= BPF_F_ZERO_SEED;
335bf5d68c7SLorenz Bauer 
336bf5d68c7SLorenz Bauer 	first = helper_fill_hashmap(3);
337bf5d68c7SLorenz Bauer 	second = helper_fill_hashmap(3);
338bf5d68c7SLorenz Bauer 
339bf5d68c7SLorenz Bauer 	for (i = 0; ; i++) {
340bf5d68c7SLorenz Bauer 		void *key_ptr = !i ? NULL : &key;
341bf5d68c7SLorenz Bauer 
342bf5d68c7SLorenz Bauer 		if (bpf_map_get_next_key(first, key_ptr, &next_first) != 0)
343bf5d68c7SLorenz Bauer 			break;
344bf5d68c7SLorenz Bauer 
345bf5d68c7SLorenz Bauer 		CHECK(bpf_map_get_next_key(second, key_ptr, &next_second) != 0,
346bf5d68c7SLorenz Bauer 		      "next_key for second map must succeed",
347bf5d68c7SLorenz Bauer 		      "key_ptr: %p", key_ptr);
348bf5d68c7SLorenz Bauer 		CHECK(next_first != next_second,
349bf5d68c7SLorenz Bauer 		      "keys must match",
350bf5d68c7SLorenz Bauer 		      "i: %d first: %lld second: %lld\n", i,
351bf5d68c7SLorenz Bauer 		      next_first, next_second);
352bf5d68c7SLorenz Bauer 
353bf5d68c7SLorenz Bauer 		key = next_first;
354bf5d68c7SLorenz Bauer 	}
355bf5d68c7SLorenz Bauer 
3562fe256a4SAndrii Nakryiko 	map_opts.map_flags = old_flags;
357bf5d68c7SLorenz Bauer 	close(first);
358bf5d68c7SLorenz Bauer 	close(second);
359bf5d68c7SLorenz Bauer }
360bf5d68c7SLorenz Bauer 
test_arraymap(unsigned int task,void * data)361dd9cef43SBreno Leitao static void test_arraymap(unsigned int task, void *data)
3625aa5bd14SDaniel Borkmann {
3635aa5bd14SDaniel Borkmann 	int key, next_key, fd;
3645aa5bd14SDaniel Borkmann 	long long value;
3655aa5bd14SDaniel Borkmann 
3662fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(key), sizeof(value), 2, NULL);
3675aa5bd14SDaniel Borkmann 	if (fd < 0) {
3685aa5bd14SDaniel Borkmann 		printf("Failed to create arraymap '%s'!\n", strerror(errno));
3695aa5bd14SDaniel Borkmann 		exit(1);
3705aa5bd14SDaniel Borkmann 	}
3715aa5bd14SDaniel Borkmann 
3725aa5bd14SDaniel Borkmann 	key = 1;
3735aa5bd14SDaniel Borkmann 	value = 1234;
3745aa5bd14SDaniel Borkmann 	/* Insert key=1 element. */
37510ecc728SMickaël Salaün 	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
3765aa5bd14SDaniel Borkmann 
3775aa5bd14SDaniel Borkmann 	value = 0;
378bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 &&
3795aa5bd14SDaniel Borkmann 	       errno == EEXIST);
3805aa5bd14SDaniel Borkmann 
3815aa5bd14SDaniel Borkmann 	/* Check that key=1 can be found. */
382e5ff7c40SMickaël Salaün 	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
3835aa5bd14SDaniel Borkmann 
3845aa5bd14SDaniel Borkmann 	key = 0;
3855aa5bd14SDaniel Borkmann 	/* Check that key=0 is also found and zero initialized. */
386e5ff7c40SMickaël Salaün 	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
3875aa5bd14SDaniel Borkmann 
3885aa5bd14SDaniel Borkmann 	/* key=0 and key=1 were inserted, check that key=2 cannot be inserted
3895aa5bd14SDaniel Borkmann 	 * due to max_entries limit.
3905aa5bd14SDaniel Borkmann 	 */
3915aa5bd14SDaniel Borkmann 	key = 2;
392bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) < 0 &&
3935aa5bd14SDaniel Borkmann 	       errno == E2BIG);
3945aa5bd14SDaniel Borkmann 
3955aa5bd14SDaniel Borkmann 	/* Check that key = 2 doesn't exist. */
396bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == ENOENT);
3975aa5bd14SDaniel Borkmann 
3985aa5bd14SDaniel Borkmann 	/* Iterate over two elements. */
3998fe45924STeng Qin 	assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
4008fe45924STeng Qin 	       next_key == 0);
4015f155c25SMickaël Salaün 	assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
4025aa5bd14SDaniel Borkmann 	       next_key == 0);
4035f155c25SMickaël Salaün 	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
4045aa5bd14SDaniel Borkmann 	       next_key == 1);
405bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &next_key, &next_key) < 0 &&
4065aa5bd14SDaniel Borkmann 	       errno == ENOENT);
4075aa5bd14SDaniel Borkmann 
4085aa5bd14SDaniel Borkmann 	/* Delete shouldn't succeed. */
4095aa5bd14SDaniel Borkmann 	key = 1;
410bad2e478SAndrii Nakryiko 	assert(bpf_map_delete_elem(fd, &key) < 0 && errno == EINVAL);
4115aa5bd14SDaniel Borkmann 
4125aa5bd14SDaniel Borkmann 	close(fd);
4135aa5bd14SDaniel Borkmann }
4145aa5bd14SDaniel Borkmann 
test_arraymap_percpu(unsigned int task,void * data)415dd9cef43SBreno Leitao static void test_arraymap_percpu(unsigned int task, void *data)
4165aa5bd14SDaniel Borkmann {
417e00c7b21SDaniel Borkmann 	unsigned int nr_cpus = bpf_num_possible_cpus();
418f3515b5dSDaniel Borkmann 	BPF_DECLARE_PERCPU(long, values);
4195aa5bd14SDaniel Borkmann 	int key, next_key, fd, i;
4205aa5bd14SDaniel Borkmann 
4212fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, NULL, sizeof(key),
4222fe256a4SAndrii Nakryiko 			    sizeof(bpf_percpu(values, 0)), 2, NULL);
4235aa5bd14SDaniel Borkmann 	if (fd < 0) {
4245aa5bd14SDaniel Borkmann 		printf("Failed to create arraymap '%s'!\n", strerror(errno));
4255aa5bd14SDaniel Borkmann 		exit(1);
4265aa5bd14SDaniel Borkmann 	}
4275aa5bd14SDaniel Borkmann 
4285aa5bd14SDaniel Borkmann 	for (i = 0; i < nr_cpus; i++)
429f3515b5dSDaniel Borkmann 		bpf_percpu(values, i) = i + 100;
4305aa5bd14SDaniel Borkmann 
4315aa5bd14SDaniel Borkmann 	key = 1;
4325aa5bd14SDaniel Borkmann 	/* Insert key=1 element. */
43310ecc728SMickaël Salaün 	assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
4345aa5bd14SDaniel Borkmann 
435f3515b5dSDaniel Borkmann 	bpf_percpu(values, 0) = 0;
436bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) < 0 &&
4375aa5bd14SDaniel Borkmann 	       errno == EEXIST);
4385aa5bd14SDaniel Borkmann 
4395aa5bd14SDaniel Borkmann 	/* Check that key=1 can be found. */
440f3515b5dSDaniel Borkmann 	assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
441f3515b5dSDaniel Borkmann 	       bpf_percpu(values, 0) == 100);
4425aa5bd14SDaniel Borkmann 
4435aa5bd14SDaniel Borkmann 	key = 0;
4445aa5bd14SDaniel Borkmann 	/* Check that key=0 is also found and zero initialized. */
445e5ff7c40SMickaël Salaün 	assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
446f3515b5dSDaniel Borkmann 	       bpf_percpu(values, 0) == 0 &&
447f3515b5dSDaniel Borkmann 	       bpf_percpu(values, nr_cpus - 1) == 0);
4485aa5bd14SDaniel Borkmann 
4495aa5bd14SDaniel Borkmann 	/* Check that key=2 cannot be inserted due to max_entries limit. */
4505aa5bd14SDaniel Borkmann 	key = 2;
451bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) < 0 &&
4525aa5bd14SDaniel Borkmann 	       errno == E2BIG);
4535aa5bd14SDaniel Borkmann 
4545aa5bd14SDaniel Borkmann 	/* Check that key = 2 doesn't exist. */
455bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_elem(fd, &key, values) < 0 && errno == ENOENT);
4565aa5bd14SDaniel Borkmann 
4575aa5bd14SDaniel Borkmann 	/* Iterate over two elements. */
4588fe45924STeng Qin 	assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
4598fe45924STeng Qin 	       next_key == 0);
4605f155c25SMickaël Salaün 	assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
4615aa5bd14SDaniel Borkmann 	       next_key == 0);
4625f155c25SMickaël Salaün 	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
4635aa5bd14SDaniel Borkmann 	       next_key == 1);
464bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &next_key, &next_key) < 0 &&
4655aa5bd14SDaniel Borkmann 	       errno == ENOENT);
4665aa5bd14SDaniel Borkmann 
4675aa5bd14SDaniel Borkmann 	/* Delete shouldn't succeed. */
4685aa5bd14SDaniel Borkmann 	key = 1;
469bad2e478SAndrii Nakryiko 	assert(bpf_map_delete_elem(fd, &key) < 0 && errno == EINVAL);
4705aa5bd14SDaniel Borkmann 
4715aa5bd14SDaniel Borkmann 	close(fd);
4725aa5bd14SDaniel Borkmann }
4735aa5bd14SDaniel Borkmann 
test_arraymap_percpu_many_keys(void)4745aa5bd14SDaniel Borkmann static void test_arraymap_percpu_many_keys(void)
4755aa5bd14SDaniel Borkmann {
476e00c7b21SDaniel Borkmann 	unsigned int nr_cpus = bpf_num_possible_cpus();
477f3515b5dSDaniel Borkmann 	BPF_DECLARE_PERCPU(long, values);
4788c290e60SAlexei Starovoitov 	/* nr_keys is not too large otherwise the test stresses percpu
4798c290e60SAlexei Starovoitov 	 * allocator more than anything else
4808c290e60SAlexei Starovoitov 	 */
4818c290e60SAlexei Starovoitov 	unsigned int nr_keys = 2000;
4825aa5bd14SDaniel Borkmann 	int key, fd, i;
4835aa5bd14SDaniel Borkmann 
4842fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, NULL, sizeof(key),
4852fe256a4SAndrii Nakryiko 			    sizeof(bpf_percpu(values, 0)), nr_keys, NULL);
4865aa5bd14SDaniel Borkmann 	if (fd < 0) {
4875aa5bd14SDaniel Borkmann 		printf("Failed to create per-cpu arraymap '%s'!\n",
4885aa5bd14SDaniel Borkmann 		       strerror(errno));
4895aa5bd14SDaniel Borkmann 		exit(1);
4905aa5bd14SDaniel Borkmann 	}
4915aa5bd14SDaniel Borkmann 
4925aa5bd14SDaniel Borkmann 	for (i = 0; i < nr_cpus; i++)
493f3515b5dSDaniel Borkmann 		bpf_percpu(values, i) = i + 10;
4945aa5bd14SDaniel Borkmann 
4955aa5bd14SDaniel Borkmann 	for (key = 0; key < nr_keys; key++)
49610ecc728SMickaël Salaün 		assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
4975aa5bd14SDaniel Borkmann 
4985aa5bd14SDaniel Borkmann 	for (key = 0; key < nr_keys; key++) {
4995aa5bd14SDaniel Borkmann 		for (i = 0; i < nr_cpus; i++)
500f3515b5dSDaniel Borkmann 			bpf_percpu(values, i) = 0;
5015aa5bd14SDaniel Borkmann 
502e5ff7c40SMickaël Salaün 		assert(bpf_map_lookup_elem(fd, &key, values) == 0);
5035aa5bd14SDaniel Borkmann 
5045aa5bd14SDaniel Borkmann 		for (i = 0; i < nr_cpus; i++)
505f3515b5dSDaniel Borkmann 			assert(bpf_percpu(values, i) == i + 10);
5065aa5bd14SDaniel Borkmann 	}
5075aa5bd14SDaniel Borkmann 
5085aa5bd14SDaniel Borkmann 	close(fd);
5095aa5bd14SDaniel Borkmann }
5105aa5bd14SDaniel Borkmann 
test_devmap(unsigned int task,void * data)511dd9cef43SBreno Leitao static void test_devmap(unsigned int task, void *data)
512546ac1ffSJohn Fastabend {
51381f6bf81SJohn Fastabend 	int fd;
514546ac1ffSJohn Fastabend 	__u32 key, value;
515546ac1ffSJohn Fastabend 
5162fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, NULL, sizeof(key), sizeof(value), 2, NULL);
517546ac1ffSJohn Fastabend 	if (fd < 0) {
5188b6b25cfSXiaozhou Liu 		printf("Failed to create devmap '%s'!\n", strerror(errno));
519546ac1ffSJohn Fastabend 		exit(1);
520546ac1ffSJohn Fastabend 	}
521546ac1ffSJohn Fastabend 
522546ac1ffSJohn Fastabend 	close(fd);
523546ac1ffSJohn Fastabend }
524546ac1ffSJohn Fastabend 
test_devmap_hash(unsigned int task,void * data)5251375dc4aSToke Høiland-Jørgensen static void test_devmap_hash(unsigned int task, void *data)
5261375dc4aSToke Høiland-Jørgensen {
5271375dc4aSToke Høiland-Jørgensen 	int fd;
5281375dc4aSToke Høiland-Jørgensen 	__u32 key, value;
5291375dc4aSToke Høiland-Jørgensen 
5302fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP_HASH, NULL, sizeof(key), sizeof(value), 2, NULL);
5311375dc4aSToke Høiland-Jørgensen 	if (fd < 0) {
5321375dc4aSToke Høiland-Jørgensen 		printf("Failed to create devmap_hash '%s'!\n", strerror(errno));
5331375dc4aSToke Høiland-Jørgensen 		exit(1);
5341375dc4aSToke Høiland-Jørgensen 	}
5351375dc4aSToke Høiland-Jørgensen 
5361375dc4aSToke Høiland-Jørgensen 	close(fd);
5371375dc4aSToke Høiland-Jørgensen }
5381375dc4aSToke Høiland-Jørgensen 
test_queuemap(unsigned int task,void * data)539dd9cef43SBreno Leitao static void test_queuemap(unsigned int task, void *data)
54043b987d2SMauricio Vasquez B {
54143b987d2SMauricio Vasquez B 	const int MAP_SIZE = 32;
54243b987d2SMauricio Vasquez B 	__u32 vals[MAP_SIZE + MAP_SIZE/2], val;
54343b987d2SMauricio Vasquez B 	int fd, i;
54443b987d2SMauricio Vasquez B 
54543b987d2SMauricio Vasquez B 	/* Fill test values to be used */
54643b987d2SMauricio Vasquez B 	for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++)
54743b987d2SMauricio Vasquez B 		vals[i] = rand();
54843b987d2SMauricio Vasquez B 
54943b987d2SMauricio Vasquez B 	/* Invalid key size */
5502fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_QUEUE, NULL, 4, sizeof(val), MAP_SIZE, &map_opts);
55143b987d2SMauricio Vasquez B 	assert(fd < 0 && errno == EINVAL);
55243b987d2SMauricio Vasquez B 
5532fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_QUEUE, NULL, 0, sizeof(val), MAP_SIZE, &map_opts);
55443b987d2SMauricio Vasquez B 	/* Queue map does not support BPF_F_NO_PREALLOC */
5552fe256a4SAndrii Nakryiko 	if (map_opts.map_flags & BPF_F_NO_PREALLOC) {
55643b987d2SMauricio Vasquez B 		assert(fd < 0 && errno == EINVAL);
55743b987d2SMauricio Vasquez B 		return;
55843b987d2SMauricio Vasquez B 	}
55943b987d2SMauricio Vasquez B 	if (fd < 0) {
56043b987d2SMauricio Vasquez B 		printf("Failed to create queuemap '%s'!\n", strerror(errno));
56143b987d2SMauricio Vasquez B 		exit(1);
56243b987d2SMauricio Vasquez B 	}
56343b987d2SMauricio Vasquez B 
56443b987d2SMauricio Vasquez B 	/* Push MAP_SIZE elements */
56543b987d2SMauricio Vasquez B 	for (i = 0; i < MAP_SIZE; i++)
56643b987d2SMauricio Vasquez B 		assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
56743b987d2SMauricio Vasquez B 
56843b987d2SMauricio Vasquez B 	/* Check that element cannot be pushed due to max_entries limit */
569bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, NULL, &val, 0) < 0 &&
57043b987d2SMauricio Vasquez B 	       errno == E2BIG);
57143b987d2SMauricio Vasquez B 
57243b987d2SMauricio Vasquez B 	/* Peek element */
57343b987d2SMauricio Vasquez B 	assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[0]);
57443b987d2SMauricio Vasquez B 
57543b987d2SMauricio Vasquez B 	/* Replace half elements */
57643b987d2SMauricio Vasquez B 	for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++)
57743b987d2SMauricio Vasquez B 		assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0);
57843b987d2SMauricio Vasquez B 
57943b987d2SMauricio Vasquez B 	/* Pop all elements */
58043b987d2SMauricio Vasquez B 	for (i = MAP_SIZE/2; i < MAP_SIZE + MAP_SIZE/2; i++)
58143b987d2SMauricio Vasquez B 		assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 &&
58243b987d2SMauricio Vasquez B 		       val == vals[i]);
58343b987d2SMauricio Vasquez B 
58443b987d2SMauricio Vasquez B 	/* Check that there are not elements left */
585bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) < 0 &&
58643b987d2SMauricio Vasquez B 	       errno == ENOENT);
58743b987d2SMauricio Vasquez B 
58843b987d2SMauricio Vasquez B 	/* Check that non supported functions set errno to EINVAL */
589bad2e478SAndrii Nakryiko 	assert(bpf_map_delete_elem(fd, NULL) < 0 && errno == EINVAL);
590bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, NULL, NULL) < 0 && errno == EINVAL);
59143b987d2SMauricio Vasquez B 
59243b987d2SMauricio Vasquez B 	close(fd);
59343b987d2SMauricio Vasquez B }
59443b987d2SMauricio Vasquez B 
test_stackmap(unsigned int task,void * data)595dd9cef43SBreno Leitao static void test_stackmap(unsigned int task, void *data)
59643b987d2SMauricio Vasquez B {
59743b987d2SMauricio Vasquez B 	const int MAP_SIZE = 32;
59843b987d2SMauricio Vasquez B 	__u32 vals[MAP_SIZE + MAP_SIZE/2], val;
59943b987d2SMauricio Vasquez B 	int fd, i;
60043b987d2SMauricio Vasquez B 
60143b987d2SMauricio Vasquez B 	/* Fill test values to be used */
60243b987d2SMauricio Vasquez B 	for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++)
60343b987d2SMauricio Vasquez B 		vals[i] = rand();
60443b987d2SMauricio Vasquez B 
60543b987d2SMauricio Vasquez B 	/* Invalid key size */
6062fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_STACK, NULL, 4, sizeof(val), MAP_SIZE, &map_opts);
60743b987d2SMauricio Vasquez B 	assert(fd < 0 && errno == EINVAL);
60843b987d2SMauricio Vasquez B 
6092fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_STACK, NULL, 0, sizeof(val), MAP_SIZE, &map_opts);
61043b987d2SMauricio Vasquez B 	/* Stack map does not support BPF_F_NO_PREALLOC */
6112fe256a4SAndrii Nakryiko 	if (map_opts.map_flags & BPF_F_NO_PREALLOC) {
61243b987d2SMauricio Vasquez B 		assert(fd < 0 && errno == EINVAL);
61343b987d2SMauricio Vasquez B 		return;
61443b987d2SMauricio Vasquez B 	}
61543b987d2SMauricio Vasquez B 	if (fd < 0) {
61643b987d2SMauricio Vasquez B 		printf("Failed to create stackmap '%s'!\n", strerror(errno));
61743b987d2SMauricio Vasquez B 		exit(1);
61843b987d2SMauricio Vasquez B 	}
61943b987d2SMauricio Vasquez B 
62043b987d2SMauricio Vasquez B 	/* Push MAP_SIZE elements */
62143b987d2SMauricio Vasquez B 	for (i = 0; i < MAP_SIZE; i++)
62243b987d2SMauricio Vasquez B 		assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
62343b987d2SMauricio Vasquez B 
62443b987d2SMauricio Vasquez B 	/* Check that element cannot be pushed due to max_entries limit */
625bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, NULL, &val, 0) < 0 &&
62643b987d2SMauricio Vasquez B 	       errno == E2BIG);
62743b987d2SMauricio Vasquez B 
62843b987d2SMauricio Vasquez B 	/* Peek element */
62943b987d2SMauricio Vasquez B 	assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[i - 1]);
63043b987d2SMauricio Vasquez B 
63143b987d2SMauricio Vasquez B 	/* Replace half elements */
63243b987d2SMauricio Vasquez B 	for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++)
63343b987d2SMauricio Vasquez B 		assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0);
63443b987d2SMauricio Vasquez B 
63543b987d2SMauricio Vasquez B 	/* Pop all elements */
63643b987d2SMauricio Vasquez B 	for (i = MAP_SIZE + MAP_SIZE/2 - 1; i >= MAP_SIZE/2; i--)
63743b987d2SMauricio Vasquez B 		assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 &&
63843b987d2SMauricio Vasquez B 		       val == vals[i]);
63943b987d2SMauricio Vasquez B 
64043b987d2SMauricio Vasquez B 	/* Check that there are not elements left */
641bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) < 0 &&
64243b987d2SMauricio Vasquez B 	       errno == ENOENT);
64343b987d2SMauricio Vasquez B 
64443b987d2SMauricio Vasquez B 	/* Check that non supported functions set errno to EINVAL */
645bad2e478SAndrii Nakryiko 	assert(bpf_map_delete_elem(fd, NULL) < 0 && errno == EINVAL);
646bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, NULL, NULL) < 0 && errno == EINVAL);
64743b987d2SMauricio Vasquez B 
64843b987d2SMauricio Vasquez B 	close(fd);
64943b987d2SMauricio Vasquez B }
65043b987d2SMauricio Vasquez B 
6516f6d33f3SJohn Fastabend #include <sys/ioctl.h>
6526f6d33f3SJohn Fastabend #include <arpa/inet.h>
6536f6d33f3SJohn Fastabend #include <sys/select.h>
6546f6d33f3SJohn Fastabend #include <linux/err.h>
655afef88e6SDaniel Müller #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.bpf.o"
656afef88e6SDaniel Müller #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.bpf.o"
657afef88e6SDaniel Müller #define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.bpf.o"
test_sockmap(unsigned int tasks,void * data)658dd9cef43SBreno Leitao static void test_sockmap(unsigned int tasks, void *data)
6596f6d33f3SJohn Fastabend {
66082a86168SJohn Fastabend 	struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break;
66182a86168SJohn Fastabend 	int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break;
662103d002fSHou Tao 	struct bpf_object *parse_obj, *verdict_obj, *msg_obj;
6636f6d33f3SJohn Fastabend 	int ports[] = {50200, 50201, 50202, 50204};
664435bf0d3SJohn Fastabend 	int err, i, fd, udp, sfd[6] = {0xdeadbeef};
6656fd28865SJohn Fastabend 	u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
66682a86168SJohn Fastabend 	int parse_prog, verdict_prog, msg_prog;
6676f6d33f3SJohn Fastabend 	struct sockaddr_in addr;
66882a86168SJohn Fastabend 	int one = 1, s, sc, rc;
6696f6d33f3SJohn Fastabend 	struct timeval to;
6706f6d33f3SJohn Fastabend 	__u32 key, value;
6713f0d6a16SJohn Fastabend 	pid_t pid[tasks];
6726f6d33f3SJohn Fastabend 	fd_set w;
6736f6d33f3SJohn Fastabend 
6746f6d33f3SJohn Fastabend 	/* Create some sockets to use with sockmap */
6756f6d33f3SJohn Fastabend 	for (i = 0; i < 2; i++) {
6766f6d33f3SJohn Fastabend 		sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
6776f6d33f3SJohn Fastabend 		if (sfd[i] < 0)
6786f6d33f3SJohn Fastabend 			goto out;
6796f6d33f3SJohn Fastabend 		err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
6806f6d33f3SJohn Fastabend 				 (char *)&one, sizeof(one));
6816f6d33f3SJohn Fastabend 		if (err) {
6826f6d33f3SJohn Fastabend 			printf("failed to setsockopt\n");
6836f6d33f3SJohn Fastabend 			goto out;
6846f6d33f3SJohn Fastabend 		}
6856f6d33f3SJohn Fastabend 		err = ioctl(sfd[i], FIONBIO, (char *)&one);
6866f6d33f3SJohn Fastabend 		if (err < 0) {
6876f6d33f3SJohn Fastabend 			printf("failed to ioctl\n");
6886f6d33f3SJohn Fastabend 			goto out;
6896f6d33f3SJohn Fastabend 		}
6906f6d33f3SJohn Fastabend 		memset(&addr, 0, sizeof(struct sockaddr_in));
6916f6d33f3SJohn Fastabend 		addr.sin_family = AF_INET;
6926f6d33f3SJohn Fastabend 		addr.sin_addr.s_addr = inet_addr("127.0.0.1");
6936f6d33f3SJohn Fastabend 		addr.sin_port = htons(ports[i]);
6946f6d33f3SJohn Fastabend 		err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
6956f6d33f3SJohn Fastabend 		if (err < 0) {
6966f6d33f3SJohn Fastabend 			printf("failed to bind: err %i: %i:%i\n",
6976f6d33f3SJohn Fastabend 			       err, i, sfd[i]);
6986f6d33f3SJohn Fastabend 			goto out;
6996f6d33f3SJohn Fastabend 		}
7006f6d33f3SJohn Fastabend 		err = listen(sfd[i], 32);
7016f6d33f3SJohn Fastabend 		if (err < 0) {
70290774a93SColin Ian King 			printf("failed to listen\n");
7036f6d33f3SJohn Fastabend 			goto out;
7046f6d33f3SJohn Fastabend 		}
7056f6d33f3SJohn Fastabend 	}
7066f6d33f3SJohn Fastabend 
7076f6d33f3SJohn Fastabend 	for (i = 2; i < 4; i++) {
7086f6d33f3SJohn Fastabend 		sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
7096f6d33f3SJohn Fastabend 		if (sfd[i] < 0)
7106f6d33f3SJohn Fastabend 			goto out;
7116f6d33f3SJohn Fastabend 		err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
7126f6d33f3SJohn Fastabend 				 (char *)&one, sizeof(one));
7136f6d33f3SJohn Fastabend 		if (err) {
7146f6d33f3SJohn Fastabend 			printf("set sock opt\n");
7156f6d33f3SJohn Fastabend 			goto out;
7166f6d33f3SJohn Fastabend 		}
7176f6d33f3SJohn Fastabend 		memset(&addr, 0, sizeof(struct sockaddr_in));
7186f6d33f3SJohn Fastabend 		addr.sin_family = AF_INET;
7196f6d33f3SJohn Fastabend 		addr.sin_addr.s_addr = inet_addr("127.0.0.1");
7206f6d33f3SJohn Fastabend 		addr.sin_port = htons(ports[i - 2]);
7216f6d33f3SJohn Fastabend 		err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
7226f6d33f3SJohn Fastabend 		if (err) {
72390774a93SColin Ian King 			printf("failed to connect\n");
7246f6d33f3SJohn Fastabend 			goto out;
7256f6d33f3SJohn Fastabend 		}
7266f6d33f3SJohn Fastabend 	}
7276f6d33f3SJohn Fastabend 
7286f6d33f3SJohn Fastabend 
7296f6d33f3SJohn Fastabend 	for (i = 4; i < 6; i++) {
7306f6d33f3SJohn Fastabend 		sfd[i] = accept(sfd[i - 4], NULL, NULL);
7316f6d33f3SJohn Fastabend 		if (sfd[i] < 0) {
7326f6d33f3SJohn Fastabend 			printf("accept failed\n");
7336f6d33f3SJohn Fastabend 			goto out;
7346f6d33f3SJohn Fastabend 		}
7356f6d33f3SJohn Fastabend 	}
7366f6d33f3SJohn Fastabend 
7376f6d33f3SJohn Fastabend 	/* Test sockmap with connected sockets */
7382fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_SOCKMAP, NULL,
7396f6d33f3SJohn Fastabend 			    sizeof(key), sizeof(value),
7402fe256a4SAndrii Nakryiko 			    6, NULL);
7416f6d33f3SJohn Fastabend 	if (fd < 0) {
74232e608f8SAndrii Nakryiko 		if (!libbpf_probe_bpf_map_type(BPF_MAP_TYPE_SOCKMAP, NULL)) {
743e8ddbfb4SStanislav Fomichev 			printf("%s SKIP (unsupported map type BPF_MAP_TYPE_SOCKMAP)\n",
744e8ddbfb4SStanislav Fomichev 			       __func__);
745e8ddbfb4SStanislav Fomichev 			skips++;
746e8ddbfb4SStanislav Fomichev 			for (i = 0; i < 6; i++)
747e8ddbfb4SStanislav Fomichev 				close(sfd[i]);
748e8ddbfb4SStanislav Fomichev 			return;
749e8ddbfb4SStanislav Fomichev 		}
750e8ddbfb4SStanislav Fomichev 
7516f6d33f3SJohn Fastabend 		printf("Failed to create sockmap %i\n", fd);
7526f6d33f3SJohn Fastabend 		goto out_sockmap;
7536f6d33f3SJohn Fastabend 	}
7546f6d33f3SJohn Fastabend 
755435bf0d3SJohn Fastabend 	/* Test update with unsupported UDP socket */
756435bf0d3SJohn Fastabend 	udp = socket(AF_INET, SOCK_DGRAM, 0);
757435bf0d3SJohn Fastabend 	i = 0;
758435bf0d3SJohn Fastabend 	err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
759c39aa215SJohn Fastabend 	if (err) {
760c39aa215SJohn Fastabend 		printf("Failed socket update SOCK_DGRAM '%i:%i'\n",
761435bf0d3SJohn Fastabend 		       i, udp);
762435bf0d3SJohn Fastabend 		goto out_sockmap;
763435bf0d3SJohn Fastabend 	}
764103d002fSHou Tao 	close(udp);
765435bf0d3SJohn Fastabend 
766464bc0fdSJohn Fastabend 	/* Test update without programs */
7676f6d33f3SJohn Fastabend 	for (i = 0; i < 6; i++) {
7686f6d33f3SJohn Fastabend 		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
7698ca30379SJakub Sitnicki 		if (err) {
770464bc0fdSJohn Fastabend 			printf("Failed noprog update sockmap '%i:%i'\n",
7716f6d33f3SJohn Fastabend 			       i, sfd[i]);
7726f6d33f3SJohn Fastabend 			goto out_sockmap;
7736f6d33f3SJohn Fastabend 		}
7746f6d33f3SJohn Fastabend 	}
7756f6d33f3SJohn Fastabend 
7765a67da2aSJohn Fastabend 	/* Test attaching/detaching bad fds */
777464bc0fdSJohn Fastabend 	err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
7786f6d33f3SJohn Fastabend 	if (!err) {
779464bc0fdSJohn Fastabend 		printf("Failed invalid parser prog attach\n");
780464bc0fdSJohn Fastabend 		goto out_sockmap;
781464bc0fdSJohn Fastabend 	}
782464bc0fdSJohn Fastabend 
783464bc0fdSJohn Fastabend 	err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0);
784464bc0fdSJohn Fastabend 	if (!err) {
785464bc0fdSJohn Fastabend 		printf("Failed invalid verdict prog attach\n");
7866f6d33f3SJohn Fastabend 		goto out_sockmap;
7876f6d33f3SJohn Fastabend 	}
7886f6d33f3SJohn Fastabend 
78982a86168SJohn Fastabend 	err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0);
79082a86168SJohn Fastabend 	if (!err) {
79182a86168SJohn Fastabend 		printf("Failed invalid msg verdict prog attach\n");
79282a86168SJohn Fastabend 		goto out_sockmap;
79382a86168SJohn Fastabend 	}
79482a86168SJohn Fastabend 
7955a67da2aSJohn Fastabend 	err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
7965a67da2aSJohn Fastabend 	if (!err) {
7975a67da2aSJohn Fastabend 		printf("Failed unknown prog attach\n");
7985a67da2aSJohn Fastabend 		goto out_sockmap;
7995a67da2aSJohn Fastabend 	}
8005a67da2aSJohn Fastabend 
8015a67da2aSJohn Fastabend 	err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
802f43cb0d6SLorenz Bauer 	if (!err) {
8035a67da2aSJohn Fastabend 		printf("Failed empty parser prog detach\n");
8045a67da2aSJohn Fastabend 		goto out_sockmap;
8055a67da2aSJohn Fastabend 	}
8065a67da2aSJohn Fastabend 
8075a67da2aSJohn Fastabend 	err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
808f43cb0d6SLorenz Bauer 	if (!err) {
8095a67da2aSJohn Fastabend 		printf("Failed empty verdict prog detach\n");
8105a67da2aSJohn Fastabend 		goto out_sockmap;
8115a67da2aSJohn Fastabend 	}
8125a67da2aSJohn Fastabend 
81382a86168SJohn Fastabend 	err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
814f43cb0d6SLorenz Bauer 	if (!err) {
81582a86168SJohn Fastabend 		printf("Failed empty msg verdict prog detach\n");
81682a86168SJohn Fastabend 		goto out_sockmap;
81782a86168SJohn Fastabend 	}
81882a86168SJohn Fastabend 
8195a67da2aSJohn Fastabend 	err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
8205a67da2aSJohn Fastabend 	if (!err) {
8215a67da2aSJohn Fastabend 		printf("Detach invalid prog successful\n");
8225a67da2aSJohn Fastabend 		goto out_sockmap;
8235a67da2aSJohn Fastabend 	}
8245a67da2aSJohn Fastabend 
8256f6d33f3SJohn Fastabend 	/* Load SK_SKB program and Attach */
826cbdb1461SAndrii Nakryiko 	err = bpf_prog_test_load(SOCKMAP_PARSE_PROG,
827103d002fSHou Tao 			    BPF_PROG_TYPE_SK_SKB, &parse_obj, &parse_prog);
8286f6d33f3SJohn Fastabend 	if (err) {
8296f6d33f3SJohn Fastabend 		printf("Failed to load SK_SKB parse prog\n");
8306f6d33f3SJohn Fastabend 		goto out_sockmap;
8316f6d33f3SJohn Fastabend 	}
8326f6d33f3SJohn Fastabend 
833cbdb1461SAndrii Nakryiko 	err = bpf_prog_test_load(SOCKMAP_TCP_MSG_PROG,
834103d002fSHou Tao 			    BPF_PROG_TYPE_SK_MSG, &msg_obj, &msg_prog);
83582a86168SJohn Fastabend 	if (err) {
83682a86168SJohn Fastabend 		printf("Failed to load SK_SKB msg prog\n");
83782a86168SJohn Fastabend 		goto out_sockmap;
83882a86168SJohn Fastabend 	}
83982a86168SJohn Fastabend 
840cbdb1461SAndrii Nakryiko 	err = bpf_prog_test_load(SOCKMAP_VERDICT_PROG,
841103d002fSHou Tao 			    BPF_PROG_TYPE_SK_SKB, &verdict_obj, &verdict_prog);
8426f6d33f3SJohn Fastabend 	if (err) {
8436f6d33f3SJohn Fastabend 		printf("Failed to load SK_SKB verdict prog\n");
8446f6d33f3SJohn Fastabend 		goto out_sockmap;
8456f6d33f3SJohn Fastabend 	}
8466f6d33f3SJohn Fastabend 
847103d002fSHou Tao 	bpf_map_rx = bpf_object__find_map_by_name(verdict_obj, "sock_map_rx");
848bad2e478SAndrii Nakryiko 	if (!bpf_map_rx) {
8496fd28865SJohn Fastabend 		printf("Failed to load map rx from verdict prog\n");
8506f6d33f3SJohn Fastabend 		goto out_sockmap;
8516f6d33f3SJohn Fastabend 	}
8526f6d33f3SJohn Fastabend 
8536fd28865SJohn Fastabend 	map_fd_rx = bpf_map__fd(bpf_map_rx);
8546fd28865SJohn Fastabend 	if (map_fd_rx < 0) {
85582a86168SJohn Fastabend 		printf("Failed to get map rx fd\n");
8566f6d33f3SJohn Fastabend 		goto out_sockmap;
8576f6d33f3SJohn Fastabend 	}
8586f6d33f3SJohn Fastabend 
859103d002fSHou Tao 	bpf_map_tx = bpf_object__find_map_by_name(verdict_obj, "sock_map_tx");
860bad2e478SAndrii Nakryiko 	if (!bpf_map_tx) {
8616fd28865SJohn Fastabend 		printf("Failed to load map tx from verdict prog\n");
8626fd28865SJohn Fastabend 		goto out_sockmap;
8636fd28865SJohn Fastabend 	}
8646fd28865SJohn Fastabend 
8656fd28865SJohn Fastabend 	map_fd_tx = bpf_map__fd(bpf_map_tx);
8666fd28865SJohn Fastabend 	if (map_fd_tx < 0) {
8676fd28865SJohn Fastabend 		printf("Failed to get map tx fd\n");
8686fd28865SJohn Fastabend 		goto out_sockmap;
8696fd28865SJohn Fastabend 	}
8706fd28865SJohn Fastabend 
871103d002fSHou Tao 	bpf_map_msg = bpf_object__find_map_by_name(verdict_obj, "sock_map_msg");
872bad2e478SAndrii Nakryiko 	if (!bpf_map_msg) {
87382a86168SJohn Fastabend 		printf("Failed to load map msg from msg_verdict prog\n");
87482a86168SJohn Fastabend 		goto out_sockmap;
87582a86168SJohn Fastabend 	}
87682a86168SJohn Fastabend 
87782a86168SJohn Fastabend 	map_fd_msg = bpf_map__fd(bpf_map_msg);
87882a86168SJohn Fastabend 	if (map_fd_msg < 0) {
87982a86168SJohn Fastabend 		printf("Failed to get map msg fd\n");
88082a86168SJohn Fastabend 		goto out_sockmap;
88182a86168SJohn Fastabend 	}
88282a86168SJohn Fastabend 
883103d002fSHou Tao 	bpf_map_break = bpf_object__find_map_by_name(verdict_obj, "sock_map_break");
884bad2e478SAndrii Nakryiko 	if (!bpf_map_break) {
88581374aaaSJohn Fastabend 		printf("Failed to load map tx from verdict prog\n");
88681374aaaSJohn Fastabend 		goto out_sockmap;
88781374aaaSJohn Fastabend 	}
88881374aaaSJohn Fastabend 
88981374aaaSJohn Fastabend 	map_fd_break = bpf_map__fd(bpf_map_break);
89081374aaaSJohn Fastabend 	if (map_fd_break < 0) {
89181374aaaSJohn Fastabend 		printf("Failed to get map tx fd\n");
89281374aaaSJohn Fastabend 		goto out_sockmap;
89381374aaaSJohn Fastabend 	}
89481374aaaSJohn Fastabend 
89581374aaaSJohn Fastabend 	err = bpf_prog_attach(parse_prog, map_fd_break,
89681374aaaSJohn Fastabend 			      BPF_SK_SKB_STREAM_PARSER, 0);
89781374aaaSJohn Fastabend 	if (!err) {
89881374aaaSJohn Fastabend 		printf("Allowed attaching SK_SKB program to invalid map\n");
89981374aaaSJohn Fastabend 		goto out_sockmap;
90081374aaaSJohn Fastabend 	}
90181374aaaSJohn Fastabend 
9026fd28865SJohn Fastabend 	err = bpf_prog_attach(parse_prog, map_fd_rx,
903464bc0fdSJohn Fastabend 		      BPF_SK_SKB_STREAM_PARSER, 0);
9046f6d33f3SJohn Fastabend 	if (err) {
90581374aaaSJohn Fastabend 		printf("Failed stream parser bpf prog attach\n");
9066f6d33f3SJohn Fastabend 		goto out_sockmap;
9076f6d33f3SJohn Fastabend 	}
9086f6d33f3SJohn Fastabend 
9096fd28865SJohn Fastabend 	err = bpf_prog_attach(verdict_prog, map_fd_rx,
910464bc0fdSJohn Fastabend 			      BPF_SK_SKB_STREAM_VERDICT, 0);
911464bc0fdSJohn Fastabend 	if (err) {
91281374aaaSJohn Fastabend 		printf("Failed stream verdict bpf prog attach\n");
913464bc0fdSJohn Fastabend 		goto out_sockmap;
914464bc0fdSJohn Fastabend 	}
915464bc0fdSJohn Fastabend 
91682a86168SJohn Fastabend 	err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0);
91782a86168SJohn Fastabend 	if (err) {
91882a86168SJohn Fastabend 		printf("Failed msg verdict bpf prog attach\n");
91982a86168SJohn Fastabend 		goto out_sockmap;
92082a86168SJohn Fastabend 	}
92182a86168SJohn Fastabend 
9225a67da2aSJohn Fastabend 	err = bpf_prog_attach(verdict_prog, map_fd_rx,
9235a67da2aSJohn Fastabend 			      __MAX_BPF_ATTACH_TYPE, 0);
9245a67da2aSJohn Fastabend 	if (!err) {
9255a67da2aSJohn Fastabend 		printf("Attached unknown bpf prog\n");
9265a67da2aSJohn Fastabend 		goto out_sockmap;
9275a67da2aSJohn Fastabend 	}
9285a67da2aSJohn Fastabend 
929464bc0fdSJohn Fastabend 	/* Test map update elem afterwards fd lives in fd and map_fd */
93050280278SJohn Fastabend 	for (i = 2; i < 6; i++) {
9316fd28865SJohn Fastabend 		err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
9326f6d33f3SJohn Fastabend 		if (err) {
9336fd28865SJohn Fastabend 			printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
9346fd28865SJohn Fastabend 			       err, i, sfd[i]);
9356fd28865SJohn Fastabend 			goto out_sockmap;
9366fd28865SJohn Fastabend 		}
9376fd28865SJohn Fastabend 		err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY);
9386fd28865SJohn Fastabend 		if (err) {
9396fd28865SJohn Fastabend 			printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
9406f6d33f3SJohn Fastabend 			       err, i, sfd[i]);
9416f6d33f3SJohn Fastabend 			goto out_sockmap;
9426f6d33f3SJohn Fastabend 		}
9436f6d33f3SJohn Fastabend 	}
9446f6d33f3SJohn Fastabend 
9456f6d33f3SJohn Fastabend 	/* Test map delete elem and remove send/recv sockets */
9466f6d33f3SJohn Fastabend 	for (i = 2; i < 4; i++) {
9476fd28865SJohn Fastabend 		err = bpf_map_delete_elem(map_fd_rx, &i);
9486f6d33f3SJohn Fastabend 		if (err) {
9496fd28865SJohn Fastabend 			printf("Failed delete sockmap rx %i '%i:%i'\n",
9506fd28865SJohn Fastabend 			       err, i, sfd[i]);
9516fd28865SJohn Fastabend 			goto out_sockmap;
9526fd28865SJohn Fastabend 		}
9536fd28865SJohn Fastabend 		err = bpf_map_delete_elem(map_fd_tx, &i);
9546fd28865SJohn Fastabend 		if (err) {
9556fd28865SJohn Fastabend 			printf("Failed delete sockmap tx %i '%i:%i'\n",
9566f6d33f3SJohn Fastabend 			       err, i, sfd[i]);
9576f6d33f3SJohn Fastabend 			goto out_sockmap;
9586f6d33f3SJohn Fastabend 		}
9596f6d33f3SJohn Fastabend 	}
9606f6d33f3SJohn Fastabend 
96182a86168SJohn Fastabend 	/* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */
96282a86168SJohn Fastabend 	i = 0;
96382a86168SJohn Fastabend 	err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY);
96482a86168SJohn Fastabend 	if (err) {
96582a86168SJohn Fastabend 		printf("Failed map_fd_msg update sockmap %i\n", err);
96682a86168SJohn Fastabend 		goto out_sockmap;
96782a86168SJohn Fastabend 	}
96882a86168SJohn Fastabend 
9696f6d33f3SJohn Fastabend 	/* Test map send/recv */
9706fd28865SJohn Fastabend 	for (i = 0; i < 2; i++) {
9716fd28865SJohn Fastabend 		buf[0] = i;
9726fd28865SJohn Fastabend 		buf[1] = 0x5;
9736fd28865SJohn Fastabend 		sc = send(sfd[2], buf, 20, 0);
9746f6d33f3SJohn Fastabend 		if (sc < 0) {
9756f6d33f3SJohn Fastabend 			printf("Failed sockmap send\n");
9766f6d33f3SJohn Fastabend 			goto out_sockmap;
9776f6d33f3SJohn Fastabend 		}
9786f6d33f3SJohn Fastabend 
9796f6d33f3SJohn Fastabend 		FD_ZERO(&w);
9806f6d33f3SJohn Fastabend 		FD_SET(sfd[3], &w);
9812d82d73dSLi Zhijian 		to.tv_sec = 30;
9826f6d33f3SJohn Fastabend 		to.tv_usec = 0;
9836f6d33f3SJohn Fastabend 		s = select(sfd[3] + 1, &w, NULL, NULL, &to);
9846f6d33f3SJohn Fastabend 		if (s == -1) {
9856f6d33f3SJohn Fastabend 			perror("Failed sockmap select()");
9866f6d33f3SJohn Fastabend 			goto out_sockmap;
9876f6d33f3SJohn Fastabend 		} else if (!s) {
9886f6d33f3SJohn Fastabend 			printf("Failed sockmap unexpected timeout\n");
9896f6d33f3SJohn Fastabend 			goto out_sockmap;
9906f6d33f3SJohn Fastabend 		}
9916f6d33f3SJohn Fastabend 
9926f6d33f3SJohn Fastabend 		if (!FD_ISSET(sfd[3], &w)) {
9936f6d33f3SJohn Fastabend 			printf("Failed sockmap select/recv\n");
9946f6d33f3SJohn Fastabend 			goto out_sockmap;
9956f6d33f3SJohn Fastabend 		}
9966f6d33f3SJohn Fastabend 
9976f6d33f3SJohn Fastabend 		rc = recv(sfd[3], buf, sizeof(buf), 0);
9986f6d33f3SJohn Fastabend 		if (rc < 0) {
9996f6d33f3SJohn Fastabend 			printf("Failed sockmap recv\n");
10006f6d33f3SJohn Fastabend 			goto out_sockmap;
10016f6d33f3SJohn Fastabend 		}
10026fd28865SJohn Fastabend 	}
10036fd28865SJohn Fastabend 
10046fd28865SJohn Fastabend 	/* Negative null entry lookup from datapath should be dropped */
10056fd28865SJohn Fastabend 	buf[0] = 1;
10066fd28865SJohn Fastabend 	buf[1] = 12;
10076fd28865SJohn Fastabend 	sc = send(sfd[2], buf, 20, 0);
10086fd28865SJohn Fastabend 	if (sc < 0) {
10096fd28865SJohn Fastabend 		printf("Failed sockmap send\n");
10106fd28865SJohn Fastabend 		goto out_sockmap;
10116fd28865SJohn Fastabend 	}
10126f6d33f3SJohn Fastabend 
1013464bc0fdSJohn Fastabend 	/* Push fd into same slot */
10146f6d33f3SJohn Fastabend 	i = 2;
10156f6d33f3SJohn Fastabend 	err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
10166f6d33f3SJohn Fastabend 	if (!err) {
1017464bc0fdSJohn Fastabend 		printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
10186f6d33f3SJohn Fastabend 		goto out_sockmap;
10196f6d33f3SJohn Fastabend 	}
10206f6d33f3SJohn Fastabend 
10216f6d33f3SJohn Fastabend 	err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
10226f6d33f3SJohn Fastabend 	if (err) {
1023464bc0fdSJohn Fastabend 		printf("Failed sockmap update new slot BPF_ANY\n");
10246f6d33f3SJohn Fastabend 		goto out_sockmap;
10256f6d33f3SJohn Fastabend 	}
10266f6d33f3SJohn Fastabend 
10276f6d33f3SJohn Fastabend 	err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
10286f6d33f3SJohn Fastabend 	if (err) {
1029464bc0fdSJohn Fastabend 		printf("Failed sockmap update new slot BPF_EXIST\n");
10306f6d33f3SJohn Fastabend 		goto out_sockmap;
10316f6d33f3SJohn Fastabend 	}
10326f6d33f3SJohn Fastabend 
1033464bc0fdSJohn Fastabend 	/* Delete the elems without programs */
103450280278SJohn Fastabend 	for (i = 2; i < 6; i++) {
1035464bc0fdSJohn Fastabend 		err = bpf_map_delete_elem(fd, &i);
1036464bc0fdSJohn Fastabend 		if (err) {
1037464bc0fdSJohn Fastabend 			printf("Failed delete sockmap %i '%i:%i'\n",
1038464bc0fdSJohn Fastabend 			       err, i, sfd[i]);
1039464bc0fdSJohn Fastabend 		}
1040464bc0fdSJohn Fastabend 	}
1041464bc0fdSJohn Fastabend 
1042464bc0fdSJohn Fastabend 	/* Test having multiple maps open and set with programs on same fds */
1043464bc0fdSJohn Fastabend 	err = bpf_prog_attach(parse_prog, fd,
1044464bc0fdSJohn Fastabend 			      BPF_SK_SKB_STREAM_PARSER, 0);
1045464bc0fdSJohn Fastabend 	if (err) {
1046464bc0fdSJohn Fastabend 		printf("Failed fd bpf parse prog attach\n");
1047464bc0fdSJohn Fastabend 		goto out_sockmap;
1048464bc0fdSJohn Fastabend 	}
1049464bc0fdSJohn Fastabend 	err = bpf_prog_attach(verdict_prog, fd,
1050464bc0fdSJohn Fastabend 			      BPF_SK_SKB_STREAM_VERDICT, 0);
1051464bc0fdSJohn Fastabend 	if (err) {
1052464bc0fdSJohn Fastabend 		printf("Failed fd bpf verdict prog attach\n");
10536f6d33f3SJohn Fastabend 		goto out_sockmap;
10546f6d33f3SJohn Fastabend 	}
10556f6d33f3SJohn Fastabend 
1056464bc0fdSJohn Fastabend 	for (i = 4; i < 6; i++) {
1057464bc0fdSJohn Fastabend 		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
10586f6d33f3SJohn Fastabend 		if (!err) {
1059464bc0fdSJohn Fastabend 			printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
1060464bc0fdSJohn Fastabend 			       err, i, sfd[i]);
10616f6d33f3SJohn Fastabend 			goto out_sockmap;
10626f6d33f3SJohn Fastabend 		}
1063464bc0fdSJohn Fastabend 		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
10646f6d33f3SJohn Fastabend 		if (!err) {
1065464bc0fdSJohn Fastabend 			printf("Failed allowed duplicate program in update NOEXIST sockmap  %i '%i:%i'\n",
1066464bc0fdSJohn Fastabend 			       err, i, sfd[i]);
10676f6d33f3SJohn Fastabend 			goto out_sockmap;
10686f6d33f3SJohn Fastabend 		}
1069464bc0fdSJohn Fastabend 		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
1070464bc0fdSJohn Fastabend 		if (!err) {
1071464bc0fdSJohn Fastabend 			printf("Failed allowed duplicate program in update EXIST sockmap  %i '%i:%i'\n",
1072464bc0fdSJohn Fastabend 			       err, i, sfd[i]);
1073464bc0fdSJohn Fastabend 			goto out_sockmap;
1074464bc0fdSJohn Fastabend 		}
1075464bc0fdSJohn Fastabend 	}
10766f6d33f3SJohn Fastabend 
10773f0d6a16SJohn Fastabend 	/* Test tasks number of forked operations */
10783f0d6a16SJohn Fastabend 	for (i = 0; i < tasks; i++) {
10793f0d6a16SJohn Fastabend 		pid[i] = fork();
10803f0d6a16SJohn Fastabend 		if (pid[i] == 0) {
10813f0d6a16SJohn Fastabend 			for (i = 0; i < 6; i++) {
10823f0d6a16SJohn Fastabend 				bpf_map_delete_elem(map_fd_tx, &i);
10833f0d6a16SJohn Fastabend 				bpf_map_delete_elem(map_fd_rx, &i);
10843f0d6a16SJohn Fastabend 				bpf_map_update_elem(map_fd_tx, &i,
10853f0d6a16SJohn Fastabend 						    &sfd[i], BPF_ANY);
10863f0d6a16SJohn Fastabend 				bpf_map_update_elem(map_fd_rx, &i,
10873f0d6a16SJohn Fastabend 						    &sfd[i], BPF_ANY);
10883f0d6a16SJohn Fastabend 			}
10893f0d6a16SJohn Fastabend 			exit(0);
10903f0d6a16SJohn Fastabend 		} else if (pid[i] == -1) {
10913f0d6a16SJohn Fastabend 			printf("Couldn't spawn #%d process!\n", i);
10923f0d6a16SJohn Fastabend 			exit(1);
10933f0d6a16SJohn Fastabend 		}
10943f0d6a16SJohn Fastabend 	}
10953f0d6a16SJohn Fastabend 
10963f0d6a16SJohn Fastabend 	for (i = 0; i < tasks; i++) {
10973f0d6a16SJohn Fastabend 		int status;
10983f0d6a16SJohn Fastabend 
10993f0d6a16SJohn Fastabend 		assert(waitpid(pid[i], &status, 0) == pid[i]);
11003f0d6a16SJohn Fastabend 		assert(status == 0);
11013f0d6a16SJohn Fastabend 	}
11023f0d6a16SJohn Fastabend 
1103f43cb0d6SLorenz Bauer 	err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE);
11045a67da2aSJohn Fastabend 	if (!err) {
11055a67da2aSJohn Fastabend 		printf("Detached an invalid prog type.\n");
11065a67da2aSJohn Fastabend 		goto out_sockmap;
11075a67da2aSJohn Fastabend 	}
11085a67da2aSJohn Fastabend 
1109f43cb0d6SLorenz Bauer 	err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
11105a67da2aSJohn Fastabend 	if (err) {
11115a67da2aSJohn Fastabend 		printf("Failed parser prog detach\n");
11125a67da2aSJohn Fastabend 		goto out_sockmap;
11135a67da2aSJohn Fastabend 	}
11145a67da2aSJohn Fastabend 
1115f43cb0d6SLorenz Bauer 	err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
11165a67da2aSJohn Fastabend 	if (err) {
11175a67da2aSJohn Fastabend 		printf("Failed parser prog detach\n");
11185a67da2aSJohn Fastabend 		goto out_sockmap;
11195a67da2aSJohn Fastabend 	}
11205a67da2aSJohn Fastabend 
112178368781SPrashant Bhole 	/* Test map close sockets and empty maps */
112278368781SPrashant Bhole 	for (i = 0; i < 6; i++) {
112378368781SPrashant Bhole 		bpf_map_delete_elem(map_fd_tx, &i);
112478368781SPrashant Bhole 		bpf_map_delete_elem(map_fd_rx, &i);
11256f6d33f3SJohn Fastabend 		close(sfd[i]);
112678368781SPrashant Bhole 	}
11276f6d33f3SJohn Fastabend 	close(fd);
11286fd28865SJohn Fastabend 	close(map_fd_rx);
1129103d002fSHou Tao 	bpf_object__close(parse_obj);
1130103d002fSHou Tao 	bpf_object__close(msg_obj);
1131103d002fSHou Tao 	bpf_object__close(verdict_obj);
11326f6d33f3SJohn Fastabend 	return;
11336f6d33f3SJohn Fastabend out:
11346f6d33f3SJohn Fastabend 	for (i = 0; i < 6; i++)
11356f6d33f3SJohn Fastabend 		close(sfd[i]);
11366f6d33f3SJohn Fastabend 	printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno));
11376f6d33f3SJohn Fastabend 	exit(1);
11386f6d33f3SJohn Fastabend out_sockmap:
113978368781SPrashant Bhole 	for (i = 0; i < 6; i++) {
114078368781SPrashant Bhole 		if (map_fd_tx)
114178368781SPrashant Bhole 			bpf_map_delete_elem(map_fd_tx, &i);
114278368781SPrashant Bhole 		if (map_fd_rx)
114378368781SPrashant Bhole 			bpf_map_delete_elem(map_fd_rx, &i);
11446f6d33f3SJohn Fastabend 		close(sfd[i]);
114578368781SPrashant Bhole 	}
11466f6d33f3SJohn Fastabend 	close(fd);
11476f6d33f3SJohn Fastabend 	exit(1);
11486f6d33f3SJohn Fastabend }
11496f6d33f3SJohn Fastabend 
1150afef88e6SDaniel Müller #define MAPINMAP_PROG "./test_map_in_map.bpf.o"
1151afef88e6SDaniel Müller #define MAPINMAP_INVALID_PROG "./test_map_in_map_invalid.bpf.o"
test_map_in_map(void)1152b1957c92SNikita V. Shirokov static void test_map_in_map(void)
1153b1957c92SNikita V. Shirokov {
1154b1957c92SNikita V. Shirokov 	struct bpf_object *obj;
1155b1957c92SNikita V. Shirokov 	struct bpf_map *map;
1156b1957c92SNikita V. Shirokov 	int mim_fd, fd, err;
1157b1957c92SNikita V. Shirokov 	int pos = 0;
115808f71a1eSMartynas Pumputis 	struct bpf_map_info info = {};
115908f71a1eSMartynas Pumputis 	__u32 len = sizeof(info);
116008f71a1eSMartynas Pumputis 	__u32 id = 0;
11619907442fSMartynas Pumputis 	libbpf_print_fn_t old_print_fn;
1162b1957c92SNikita V. Shirokov 
1163b1957c92SNikita V. Shirokov 	obj = bpf_object__open(MAPINMAP_PROG);
1164b1957c92SNikita V. Shirokov 
11652fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(int), sizeof(int), 2, NULL);
1166b1957c92SNikita V. Shirokov 	if (fd < 0) {
1167b1957c92SNikita V. Shirokov 		printf("Failed to create hashmap '%s'!\n", strerror(errno));
1168b1957c92SNikita V. Shirokov 		exit(1);
1169b1957c92SNikita V. Shirokov 	}
1170b1957c92SNikita V. Shirokov 
1171b1957c92SNikita V. Shirokov 	map = bpf_object__find_map_by_name(obj, "mim_array");
1172bad2e478SAndrii Nakryiko 	if (!map) {
1173b1957c92SNikita V. Shirokov 		printf("Failed to load array of maps from test prog\n");
1174b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1175b1957c92SNikita V. Shirokov 	}
1176b1957c92SNikita V. Shirokov 	err = bpf_map__set_inner_map_fd(map, fd);
1177b1957c92SNikita V. Shirokov 	if (err) {
1178b1957c92SNikita V. Shirokov 		printf("Failed to set inner_map_fd for array of maps\n");
1179b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1180b1957c92SNikita V. Shirokov 	}
1181b1957c92SNikita V. Shirokov 
1182b1957c92SNikita V. Shirokov 	map = bpf_object__find_map_by_name(obj, "mim_hash");
1183bad2e478SAndrii Nakryiko 	if (!map) {
1184b1957c92SNikita V. Shirokov 		printf("Failed to load hash of maps from test prog\n");
1185b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1186b1957c92SNikita V. Shirokov 	}
1187b1957c92SNikita V. Shirokov 	err = bpf_map__set_inner_map_fd(map, fd);
1188b1957c92SNikita V. Shirokov 	if (err) {
1189b1957c92SNikita V. Shirokov 		printf("Failed to set inner_map_fd for hash of maps\n");
1190b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1191b1957c92SNikita V. Shirokov 	}
1192b1957c92SNikita V. Shirokov 
1193*fb9f3f36SAndrey Grafin 	err = bpf_object__load(obj);
1194*fb9f3f36SAndrey Grafin 	if (err) {
1195*fb9f3f36SAndrey Grafin 		printf("Failed to load test prog\n");
1196*fb9f3f36SAndrey Grafin 		goto out_map_in_map;
1197*fb9f3f36SAndrey Grafin 	}
1198b1957c92SNikita V. Shirokov 
1199b1957c92SNikita V. Shirokov 	map = bpf_object__find_map_by_name(obj, "mim_array");
1200bad2e478SAndrii Nakryiko 	if (!map) {
1201b1957c92SNikita V. Shirokov 		printf("Failed to load array of maps from test prog\n");
1202b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1203b1957c92SNikita V. Shirokov 	}
1204b1957c92SNikita V. Shirokov 	mim_fd = bpf_map__fd(map);
1205b1957c92SNikita V. Shirokov 	if (mim_fd < 0) {
1206b1957c92SNikita V. Shirokov 		printf("Failed to get descriptor for array of maps\n");
1207b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1208b1957c92SNikita V. Shirokov 	}
1209b1957c92SNikita V. Shirokov 
1210b1957c92SNikita V. Shirokov 	err = bpf_map_update_elem(mim_fd, &pos, &fd, 0);
1211b1957c92SNikita V. Shirokov 	if (err) {
1212b1957c92SNikita V. Shirokov 		printf("Failed to update array of maps\n");
1213b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1214b1957c92SNikita V. Shirokov 	}
1215b1957c92SNikita V. Shirokov 
1216b1957c92SNikita V. Shirokov 	map = bpf_object__find_map_by_name(obj, "mim_hash");
1217bad2e478SAndrii Nakryiko 	if (!map) {
1218b1957c92SNikita V. Shirokov 		printf("Failed to load hash of maps from test prog\n");
1219b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1220b1957c92SNikita V. Shirokov 	}
1221b1957c92SNikita V. Shirokov 	mim_fd = bpf_map__fd(map);
1222b1957c92SNikita V. Shirokov 	if (mim_fd < 0) {
1223b1957c92SNikita V. Shirokov 		printf("Failed to get descriptor for hash of maps\n");
1224b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1225b1957c92SNikita V. Shirokov 	}
1226b1957c92SNikita V. Shirokov 
1227b1957c92SNikita V. Shirokov 	err = bpf_map_update_elem(mim_fd, &pos, &fd, 0);
1228b1957c92SNikita V. Shirokov 	if (err) {
1229b1957c92SNikita V. Shirokov 		printf("Failed to update hash of maps\n");
1230b1957c92SNikita V. Shirokov 		goto out_map_in_map;
1231b1957c92SNikita V. Shirokov 	}
1232b1957c92SNikita V. Shirokov 
1233b1957c92SNikita V. Shirokov 	close(fd);
123408f71a1eSMartynas Pumputis 	fd = -1;
1235b1957c92SNikita V. Shirokov 	bpf_object__close(obj);
123608f71a1eSMartynas Pumputis 
123708f71a1eSMartynas Pumputis 	/* Test that failing bpf_object__create_map() destroys the inner map */
123808f71a1eSMartynas Pumputis 	obj = bpf_object__open(MAPINMAP_INVALID_PROG);
123908f71a1eSMartynas Pumputis 	err = libbpf_get_error(obj);
124008f71a1eSMartynas Pumputis 	if (err) {
124108f71a1eSMartynas Pumputis 		printf("Failed to load %s program: %d %d",
124208f71a1eSMartynas Pumputis 		       MAPINMAP_INVALID_PROG, err, errno);
124308f71a1eSMartynas Pumputis 		goto out_map_in_map;
124408f71a1eSMartynas Pumputis 	}
124508f71a1eSMartynas Pumputis 
124608f71a1eSMartynas Pumputis 	map = bpf_object__find_map_by_name(obj, "mim");
124708f71a1eSMartynas Pumputis 	if (!map) {
124808f71a1eSMartynas Pumputis 		printf("Failed to load array of maps from test prog\n");
124908f71a1eSMartynas Pumputis 		goto out_map_in_map;
125008f71a1eSMartynas Pumputis 	}
125108f71a1eSMartynas Pumputis 
12529907442fSMartynas Pumputis 	old_print_fn = libbpf_set_print(NULL);
12539907442fSMartynas Pumputis 
125408f71a1eSMartynas Pumputis 	err = bpf_object__load(obj);
125508f71a1eSMartynas Pumputis 	if (!err) {
125608f71a1eSMartynas Pumputis 		printf("Loading obj supposed to fail\n");
125708f71a1eSMartynas Pumputis 		goto out_map_in_map;
125808f71a1eSMartynas Pumputis 	}
125908f71a1eSMartynas Pumputis 
12609907442fSMartynas Pumputis 	libbpf_set_print(old_print_fn);
12619907442fSMartynas Pumputis 
126208f71a1eSMartynas Pumputis 	/* Iterate over all maps to check whether the internal map
126308f71a1eSMartynas Pumputis 	 * ("mim.internal") has been destroyed.
126408f71a1eSMartynas Pumputis 	 */
126508f71a1eSMartynas Pumputis 	while (true) {
126608f71a1eSMartynas Pumputis 		err = bpf_map_get_next_id(id, &id);
126708f71a1eSMartynas Pumputis 		if (err) {
126808f71a1eSMartynas Pumputis 			if (errno == ENOENT)
126908f71a1eSMartynas Pumputis 				break;
127008f71a1eSMartynas Pumputis 			printf("Failed to get next map: %d", errno);
127108f71a1eSMartynas Pumputis 			goto out_map_in_map;
127208f71a1eSMartynas Pumputis 		}
127308f71a1eSMartynas Pumputis 
127408f71a1eSMartynas Pumputis 		fd = bpf_map_get_fd_by_id(id);
127508f71a1eSMartynas Pumputis 		if (fd < 0) {
127608f71a1eSMartynas Pumputis 			if (errno == ENOENT)
127708f71a1eSMartynas Pumputis 				continue;
127808f71a1eSMartynas Pumputis 			printf("Failed to get map by id %u: %d", id, errno);
127908f71a1eSMartynas Pumputis 			goto out_map_in_map;
128008f71a1eSMartynas Pumputis 		}
128108f71a1eSMartynas Pumputis 
1282c5a237a4SIlya Leoshkevich 		err = bpf_map_get_info_by_fd(fd, &info, &len);
128308f71a1eSMartynas Pumputis 		if (err) {
128408f71a1eSMartynas Pumputis 			printf("Failed to get map info by fd %d: %d", fd,
128508f71a1eSMartynas Pumputis 			       errno);
128608f71a1eSMartynas Pumputis 			goto out_map_in_map;
128708f71a1eSMartynas Pumputis 		}
128808f71a1eSMartynas Pumputis 
128908f71a1eSMartynas Pumputis 		if (!strcmp(info.name, "mim.inner")) {
129008f71a1eSMartynas Pumputis 			printf("Inner map mim.inner was not destroyed\n");
129108f71a1eSMartynas Pumputis 			goto out_map_in_map;
129208f71a1eSMartynas Pumputis 		}
1293103d002fSHou Tao 
1294103d002fSHou Tao 		close(fd);
129508f71a1eSMartynas Pumputis 	}
129608f71a1eSMartynas Pumputis 
1297103d002fSHou Tao 	bpf_object__close(obj);
1298b1957c92SNikita V. Shirokov 	return;
1299b1957c92SNikita V. Shirokov 
1300b1957c92SNikita V. Shirokov out_map_in_map:
130108f71a1eSMartynas Pumputis 	if (fd >= 0)
1302b1957c92SNikita V. Shirokov 		close(fd);
1303b1957c92SNikita V. Shirokov 	exit(1);
1304b1957c92SNikita V. Shirokov }
1305b1957c92SNikita V. Shirokov 
13065aa5bd14SDaniel Borkmann #define MAP_SIZE (32 * 1024)
13075aa5bd14SDaniel Borkmann 
test_map_large(void)13085aa5bd14SDaniel Borkmann static void test_map_large(void)
13095aa5bd14SDaniel Borkmann {
1310c6bde958SFlorian Lehner 
13115aa5bd14SDaniel Borkmann 	struct bigkey {
13125aa5bd14SDaniel Borkmann 		int a;
1313c6bde958SFlorian Lehner 		char b[4096];
13145aa5bd14SDaniel Borkmann 		long long c;
13155aa5bd14SDaniel Borkmann 	} key;
13165aa5bd14SDaniel Borkmann 	int fd, i, value;
13175aa5bd14SDaniel Borkmann 
13182fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value),
13192fe256a4SAndrii Nakryiko 			    MAP_SIZE, &map_opts);
13205aa5bd14SDaniel Borkmann 	if (fd < 0) {
13215aa5bd14SDaniel Borkmann 		printf("Failed to create large map '%s'!\n", strerror(errno));
13225aa5bd14SDaniel Borkmann 		exit(1);
13235aa5bd14SDaniel Borkmann 	}
13245aa5bd14SDaniel Borkmann 
13255aa5bd14SDaniel Borkmann 	for (i = 0; i < MAP_SIZE; i++) {
13265aa5bd14SDaniel Borkmann 		key = (struct bigkey) { .c = i };
13275aa5bd14SDaniel Borkmann 		value = i;
13285aa5bd14SDaniel Borkmann 
132910ecc728SMickaël Salaün 		assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
13305aa5bd14SDaniel Borkmann 	}
13315aa5bd14SDaniel Borkmann 
13325aa5bd14SDaniel Borkmann 	key.c = -1;
1333bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 &&
13345aa5bd14SDaniel Borkmann 	       errno == E2BIG);
13355aa5bd14SDaniel Borkmann 
13365aa5bd14SDaniel Borkmann 	/* Iterate through all elements. */
13378fe45924STeng Qin 	assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
13388fe45924STeng Qin 	key.c = -1;
13395aa5bd14SDaniel Borkmann 	for (i = 0; i < MAP_SIZE; i++)
13405f155c25SMickaël Salaün 		assert(bpf_map_get_next_key(fd, &key, &key) == 0);
1341bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &key, &key) < 0 && errno == ENOENT);
13425aa5bd14SDaniel Borkmann 
13435aa5bd14SDaniel Borkmann 	key.c = 0;
1344e5ff7c40SMickaël Salaün 	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
13455aa5bd14SDaniel Borkmann 	key.a = 1;
1346bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == ENOENT);
13475aa5bd14SDaniel Borkmann 
13485aa5bd14SDaniel Borkmann 	close(fd);
13495aa5bd14SDaniel Borkmann }
13505aa5bd14SDaniel Borkmann 
13511a97cf1fSAlexei Starovoitov #define run_parallel(N, FN, DATA) \
1352dd9cef43SBreno Leitao 	printf("Fork %u tasks to '" #FN "'\n", N); \
13531a97cf1fSAlexei Starovoitov 	__run_parallel(N, FN, DATA)
13541a97cf1fSAlexei Starovoitov 
__run_parallel(unsigned int tasks,void (* fn)(unsigned int task,void * data),void * data)1355dd9cef43SBreno Leitao static void __run_parallel(unsigned int tasks,
1356dd9cef43SBreno Leitao 			   void (*fn)(unsigned int task, void *data),
13575aa5bd14SDaniel Borkmann 			   void *data)
13585aa5bd14SDaniel Borkmann {
13595aa5bd14SDaniel Borkmann 	pid_t pid[tasks];
13605aa5bd14SDaniel Borkmann 	int i;
13615aa5bd14SDaniel Borkmann 
1362fa450567SJesper Dangaard Brouer 	fflush(stdout);
1363fa450567SJesper Dangaard Brouer 
13645aa5bd14SDaniel Borkmann 	for (i = 0; i < tasks; i++) {
13655aa5bd14SDaniel Borkmann 		pid[i] = fork();
13665aa5bd14SDaniel Borkmann 		if (pid[i] == 0) {
13675aa5bd14SDaniel Borkmann 			fn(i, data);
13685aa5bd14SDaniel Borkmann 			exit(0);
13695aa5bd14SDaniel Borkmann 		} else if (pid[i] == -1) {
13705aa5bd14SDaniel Borkmann 			printf("Couldn't spawn #%d process!\n", i);
13715aa5bd14SDaniel Borkmann 			exit(1);
13725aa5bd14SDaniel Borkmann 		}
13735aa5bd14SDaniel Borkmann 	}
13745aa5bd14SDaniel Borkmann 
13755aa5bd14SDaniel Borkmann 	for (i = 0; i < tasks; i++) {
13765aa5bd14SDaniel Borkmann 		int status;
13775aa5bd14SDaniel Borkmann 
13785aa5bd14SDaniel Borkmann 		assert(waitpid(pid[i], &status, 0) == pid[i]);
13795aa5bd14SDaniel Borkmann 		assert(status == 0);
13805aa5bd14SDaniel Borkmann 	}
13815aa5bd14SDaniel Borkmann }
13825aa5bd14SDaniel Borkmann 
test_map_stress(void)13835aa5bd14SDaniel Borkmann static void test_map_stress(void)
13845aa5bd14SDaniel Borkmann {
138537521bffSAlexei Starovoitov 	run_parallel(100, test_hashmap_walk, NULL);
13865aa5bd14SDaniel Borkmann 	run_parallel(100, test_hashmap, NULL);
13875aa5bd14SDaniel Borkmann 	run_parallel(100, test_hashmap_percpu, NULL);
13888c290e60SAlexei Starovoitov 	run_parallel(100, test_hashmap_sizes, NULL);
13895aa5bd14SDaniel Borkmann 
13905aa5bd14SDaniel Borkmann 	run_parallel(100, test_arraymap, NULL);
13915aa5bd14SDaniel Borkmann 	run_parallel(100, test_arraymap_percpu, NULL);
13925aa5bd14SDaniel Borkmann }
13935aa5bd14SDaniel Borkmann 
139437521bffSAlexei Starovoitov #define TASKS 100
13955aa5bd14SDaniel Borkmann 
13965aa5bd14SDaniel Borkmann #define DO_UPDATE 1
13975aa5bd14SDaniel Borkmann #define DO_DELETE 0
13985aa5bd14SDaniel Borkmann 
139911b844b0SAndrii Nakryiko #define MAP_RETRIES 20
14003c3bd542SYucong Sun #define MAX_DELAY_US 50000
14013c3bd542SYucong Sun #define MIN_DELAY_RANGE_US 5000
140211b844b0SAndrii Nakryiko 
map_update_retriable(int map_fd,const void * key,const void * value,int flags,int attempts)140311b844b0SAndrii Nakryiko static int map_update_retriable(int map_fd, const void *key, const void *value,
140411b844b0SAndrii Nakryiko 				int flags, int attempts)
140511b844b0SAndrii Nakryiko {
14063c3bd542SYucong Sun 	int delay = rand() % MIN_DELAY_RANGE_US;
14073c3bd542SYucong Sun 
140811b844b0SAndrii Nakryiko 	while (bpf_map_update_elem(map_fd, key, value, flags)) {
140911b844b0SAndrii Nakryiko 		if (!attempts || (errno != EAGAIN && errno != EBUSY))
141011b844b0SAndrii Nakryiko 			return -errno;
141111b844b0SAndrii Nakryiko 
14123c3bd542SYucong Sun 		if (delay <= MAX_DELAY_US / 2)
14133c3bd542SYucong Sun 			delay *= 2;
14143c3bd542SYucong Sun 
14153c3bd542SYucong Sun 		usleep(delay);
141611b844b0SAndrii Nakryiko 		attempts--;
141711b844b0SAndrii Nakryiko 	}
141811b844b0SAndrii Nakryiko 
141911b844b0SAndrii Nakryiko 	return 0;
142011b844b0SAndrii Nakryiko }
142111b844b0SAndrii Nakryiko 
map_delete_retriable(int map_fd,const void * key,int attempts)142211b844b0SAndrii Nakryiko static int map_delete_retriable(int map_fd, const void *key, int attempts)
142311b844b0SAndrii Nakryiko {
1424857f75eaSYucong Sun 	int delay = rand() % MIN_DELAY_RANGE_US;
1425857f75eaSYucong Sun 
142611b844b0SAndrii Nakryiko 	while (bpf_map_delete_elem(map_fd, key)) {
142711b844b0SAndrii Nakryiko 		if (!attempts || (errno != EAGAIN && errno != EBUSY))
142811b844b0SAndrii Nakryiko 			return -errno;
142911b844b0SAndrii Nakryiko 
1430857f75eaSYucong Sun 		if (delay <= MAX_DELAY_US / 2)
1431857f75eaSYucong Sun 			delay *= 2;
1432857f75eaSYucong Sun 
1433857f75eaSYucong Sun 		usleep(delay);
143411b844b0SAndrii Nakryiko 		attempts--;
143511b844b0SAndrii Nakryiko 	}
143611b844b0SAndrii Nakryiko 
143711b844b0SAndrii Nakryiko 	return 0;
143811b844b0SAndrii Nakryiko }
143911b844b0SAndrii Nakryiko 
test_update_delete(unsigned int fn,void * data)1440dd9cef43SBreno Leitao static void test_update_delete(unsigned int fn, void *data)
14415aa5bd14SDaniel Borkmann {
14425aa5bd14SDaniel Borkmann 	int do_update = ((int *)data)[1];
14435aa5bd14SDaniel Borkmann 	int fd = ((int *)data)[0];
144411b844b0SAndrii Nakryiko 	int i, key, value, err;
14455aa5bd14SDaniel Borkmann 
144637521bffSAlexei Starovoitov 	if (fn & 1)
144737521bffSAlexei Starovoitov 		test_hashmap_walk(fn, NULL);
14485aa5bd14SDaniel Borkmann 	for (i = fn; i < MAP_SIZE; i += TASKS) {
14495aa5bd14SDaniel Borkmann 		key = value = i;
14505aa5bd14SDaniel Borkmann 
14515aa5bd14SDaniel Borkmann 		if (do_update) {
145211b844b0SAndrii Nakryiko 			err = map_update_retriable(fd, &key, &value, BPF_NOEXIST, MAP_RETRIES);
145311b844b0SAndrii Nakryiko 			if (err)
145411b844b0SAndrii Nakryiko 				printf("error %d %d\n", err, errno);
145511b844b0SAndrii Nakryiko 			assert(err == 0);
145611b844b0SAndrii Nakryiko 			err = map_update_retriable(fd, &key, &value, BPF_EXIST, MAP_RETRIES);
145711b844b0SAndrii Nakryiko 			if (err)
145811b844b0SAndrii Nakryiko 				printf("error %d %d\n", err, errno);
145911b844b0SAndrii Nakryiko 			assert(err == 0);
14605aa5bd14SDaniel Borkmann 		} else {
146111b844b0SAndrii Nakryiko 			err = map_delete_retriable(fd, &key, MAP_RETRIES);
146211b844b0SAndrii Nakryiko 			if (err)
146311b844b0SAndrii Nakryiko 				printf("error %d %d\n", err, errno);
146411b844b0SAndrii Nakryiko 			assert(err == 0);
14655aa5bd14SDaniel Borkmann 		}
14665aa5bd14SDaniel Borkmann 	}
14675aa5bd14SDaniel Borkmann }
14685aa5bd14SDaniel Borkmann 
test_map_parallel(void)14695aa5bd14SDaniel Borkmann static void test_map_parallel(void)
14705aa5bd14SDaniel Borkmann {
147137521bffSAlexei Starovoitov 	int i, fd, key = 0, value = 0, j = 0;
14725aa5bd14SDaniel Borkmann 	int data[2];
14735aa5bd14SDaniel Borkmann 
14742fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value),
14752fe256a4SAndrii Nakryiko 			    MAP_SIZE, &map_opts);
14765aa5bd14SDaniel Borkmann 	if (fd < 0) {
14775aa5bd14SDaniel Borkmann 		printf("Failed to create map for parallel test '%s'!\n",
14785aa5bd14SDaniel Borkmann 		       strerror(errno));
14795aa5bd14SDaniel Borkmann 		exit(1);
14805aa5bd14SDaniel Borkmann 	}
14815aa5bd14SDaniel Borkmann 
148237521bffSAlexei Starovoitov again:
14835aa5bd14SDaniel Borkmann 	/* Use the same fd in children to add elements to this map:
14845aa5bd14SDaniel Borkmann 	 * child_0 adds key=0, key=1024, key=2048, ...
14855aa5bd14SDaniel Borkmann 	 * child_1 adds key=1, key=1025, key=2049, ...
14865aa5bd14SDaniel Borkmann 	 * child_1023 adds key=1023, ...
14875aa5bd14SDaniel Borkmann 	 */
14885aa5bd14SDaniel Borkmann 	data[0] = fd;
14895aa5bd14SDaniel Borkmann 	data[1] = DO_UPDATE;
14901a97cf1fSAlexei Starovoitov 	run_parallel(TASKS, test_update_delete, data);
14915aa5bd14SDaniel Borkmann 
14925aa5bd14SDaniel Borkmann 	/* Check that key=0 is already there. */
1493bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 &&
14945aa5bd14SDaniel Borkmann 	       errno == EEXIST);
14955aa5bd14SDaniel Borkmann 
14965aa5bd14SDaniel Borkmann 	/* Check that all elements were inserted. */
14978fe45924STeng Qin 	assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
14985aa5bd14SDaniel Borkmann 	key = -1;
14995aa5bd14SDaniel Borkmann 	for (i = 0; i < MAP_SIZE; i++)
15005f155c25SMickaël Salaün 		assert(bpf_map_get_next_key(fd, &key, &key) == 0);
1501bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &key, &key) < 0 && errno == ENOENT);
15025aa5bd14SDaniel Borkmann 
15035aa5bd14SDaniel Borkmann 	/* Another check for all elements */
15045aa5bd14SDaniel Borkmann 	for (i = 0; i < MAP_SIZE; i++) {
15055aa5bd14SDaniel Borkmann 		key = MAP_SIZE - i - 1;
15065aa5bd14SDaniel Borkmann 
1507e5ff7c40SMickaël Salaün 		assert(bpf_map_lookup_elem(fd, &key, &value) == 0 &&
15085aa5bd14SDaniel Borkmann 		       value == key);
15095aa5bd14SDaniel Borkmann 	}
15105aa5bd14SDaniel Borkmann 
15115aa5bd14SDaniel Borkmann 	/* Now let's delete all elemenets in parallel. */
15125aa5bd14SDaniel Borkmann 	data[1] = DO_DELETE;
15131a97cf1fSAlexei Starovoitov 	run_parallel(TASKS, test_update_delete, data);
15145aa5bd14SDaniel Borkmann 
15155aa5bd14SDaniel Borkmann 	/* Nothing should be left. */
15165aa5bd14SDaniel Borkmann 	key = -1;
1517bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, NULL, &key) < 0 && errno == ENOENT);
1518bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &key, &key) < 0 && errno == ENOENT);
151937521bffSAlexei Starovoitov 
152037521bffSAlexei Starovoitov 	key = 0;
152137521bffSAlexei Starovoitov 	bpf_map_delete_elem(fd, &key);
152237521bffSAlexei Starovoitov 	if (j++ < 5)
152337521bffSAlexei Starovoitov 		goto again;
152437521bffSAlexei Starovoitov 	close(fd);
15255aa5bd14SDaniel Borkmann }
15265aa5bd14SDaniel Borkmann 
test_map_rdonly(void)1527e043325bSChenbo Feng static void test_map_rdonly(void)
1528e043325bSChenbo Feng {
1529e27afb84SAlexei Starovoitov 	int fd, key = 0, value = 0;
15302fe256a4SAndrii Nakryiko 	__u32 old_flags;
1531e043325bSChenbo Feng 
15322fe256a4SAndrii Nakryiko 	old_flags = map_opts.map_flags;
15332fe256a4SAndrii Nakryiko 	map_opts.map_flags |= BPF_F_RDONLY;
15342fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value),
15352fe256a4SAndrii Nakryiko 			    MAP_SIZE, &map_opts);
15362fe256a4SAndrii Nakryiko 	map_opts.map_flags = old_flags;
1537e043325bSChenbo Feng 	if (fd < 0) {
1538e043325bSChenbo Feng 		printf("Failed to create map for read only test '%s'!\n",
1539e043325bSChenbo Feng 		       strerror(errno));
1540e043325bSChenbo Feng 		exit(1);
1541e043325bSChenbo Feng 	}
1542e043325bSChenbo Feng 
1543e043325bSChenbo Feng 	key = 1;
1544e043325bSChenbo Feng 	value = 1234;
1545efbc3b8fSAnton Protopopov 	/* Try to insert key=1 element. */
1546bad2e478SAndrii Nakryiko 	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) < 0 &&
1547e043325bSChenbo Feng 	       errno == EPERM);
1548e043325bSChenbo Feng 
1549efbc3b8fSAnton Protopopov 	/* Check that key=1 is not found. */
1550bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == ENOENT);
1551bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &key, &value) < 0 && errno == ENOENT);
155236ef9a2dSAnton Protopopov 
155336ef9a2dSAnton Protopopov 	close(fd);
1554e043325bSChenbo Feng }
1555e043325bSChenbo Feng 
test_map_wronly_hash(void)155643dd115bSAnton Protopopov static void test_map_wronly_hash(void)
1557e043325bSChenbo Feng {
1558e27afb84SAlexei Starovoitov 	int fd, key = 0, value = 0;
15592fe256a4SAndrii Nakryiko 	__u32 old_flags;
1560e043325bSChenbo Feng 
15612fe256a4SAndrii Nakryiko 	old_flags = map_opts.map_flags;
15622fe256a4SAndrii Nakryiko 	map_opts.map_flags |= BPF_F_WRONLY;
15632fe256a4SAndrii Nakryiko 	fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value),
15642fe256a4SAndrii Nakryiko 			    MAP_SIZE, &map_opts);
15652fe256a4SAndrii Nakryiko 	map_opts.map_flags = old_flags;
1566e043325bSChenbo Feng 	if (fd < 0) {
1567204fb041SAnton Protopopov 		printf("Failed to create map for write only test '%s'!\n",
1568e043325bSChenbo Feng 		       strerror(errno));
1569e043325bSChenbo Feng 		exit(1);
1570e043325bSChenbo Feng 	}
1571e043325bSChenbo Feng 
1572e043325bSChenbo Feng 	key = 1;
1573e043325bSChenbo Feng 	value = 1234;
1574e043325bSChenbo Feng 	/* Insert key=1 element. */
1575e27afb84SAlexei Starovoitov 	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
1576e043325bSChenbo Feng 
1577efbc3b8fSAnton Protopopov 	/* Check that reading elements and keys from the map is not allowed. */
1578bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == EPERM);
1579bad2e478SAndrii Nakryiko 	assert(bpf_map_get_next_key(fd, &key, &value) < 0 && errno == EPERM);
158036ef9a2dSAnton Protopopov 
158136ef9a2dSAnton Protopopov 	close(fd);
1582e043325bSChenbo Feng }
1583e043325bSChenbo Feng 
test_map_wronly_stack_or_queue(enum bpf_map_type map_type)158443dd115bSAnton Protopopov static void test_map_wronly_stack_or_queue(enum bpf_map_type map_type)
158543dd115bSAnton Protopopov {
158643dd115bSAnton Protopopov 	int fd, value = 0;
15872fe256a4SAndrii Nakryiko 	__u32 old_flags;
15882fe256a4SAndrii Nakryiko 
158943dd115bSAnton Protopopov 
159043dd115bSAnton Protopopov 	assert(map_type == BPF_MAP_TYPE_QUEUE ||
159143dd115bSAnton Protopopov 	       map_type == BPF_MAP_TYPE_STACK);
15922fe256a4SAndrii Nakryiko 	old_flags = map_opts.map_flags;
15932fe256a4SAndrii Nakryiko 	map_opts.map_flags |= BPF_F_WRONLY;
15942fe256a4SAndrii Nakryiko 	fd = bpf_map_create(map_type, NULL, 0, sizeof(value), MAP_SIZE, &map_opts);
15952fe256a4SAndrii Nakryiko 	map_opts.map_flags = old_flags;
159643dd115bSAnton Protopopov 	/* Stack/Queue maps do not support BPF_F_NO_PREALLOC */
15972fe256a4SAndrii Nakryiko 	if (map_opts.map_flags & BPF_F_NO_PREALLOC) {
159843dd115bSAnton Protopopov 		assert(fd < 0 && errno == EINVAL);
159943dd115bSAnton Protopopov 		return;
160043dd115bSAnton Protopopov 	}
160143dd115bSAnton Protopopov 	if (fd < 0) {
160243dd115bSAnton Protopopov 		printf("Failed to create map '%s'!\n", strerror(errno));
160343dd115bSAnton Protopopov 		exit(1);
160443dd115bSAnton Protopopov 	}
160543dd115bSAnton Protopopov 
160643dd115bSAnton Protopopov 	value = 1234;
160743dd115bSAnton Protopopov 	assert(bpf_map_update_elem(fd, NULL, &value, BPF_ANY) == 0);
160843dd115bSAnton Protopopov 
160943dd115bSAnton Protopopov 	/* Peek element should fail */
1610bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_elem(fd, NULL, &value) < 0 && errno == EPERM);
161143dd115bSAnton Protopopov 
161243dd115bSAnton Protopopov 	/* Pop element should fail */
1613bad2e478SAndrii Nakryiko 	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &value) < 0 &&
161443dd115bSAnton Protopopov 	       errno == EPERM);
161543dd115bSAnton Protopopov 
161643dd115bSAnton Protopopov 	close(fd);
161743dd115bSAnton Protopopov }
161843dd115bSAnton Protopopov 
test_map_wronly(void)161943dd115bSAnton Protopopov static void test_map_wronly(void)
162043dd115bSAnton Protopopov {
162143dd115bSAnton Protopopov 	test_map_wronly_hash();
162243dd115bSAnton Protopopov 	test_map_wronly_stack_or_queue(BPF_MAP_TYPE_STACK);
162343dd115bSAnton Protopopov 	test_map_wronly_stack_or_queue(BPF_MAP_TYPE_QUEUE);
162443dd115bSAnton Protopopov }
162543dd115bSAnton Protopopov 
prepare_reuseport_grp(int type,int map_fd,size_t map_elem_size,__s64 * fds64,__u64 * sk_cookies,unsigned int n)1626bc2d8afeSIlya Leoshkevich static void prepare_reuseport_grp(int type, int map_fd, size_t map_elem_size,
16276bc8529cSMartin KaFai Lau 				  __s64 *fds64, __u64 *sk_cookies,
16286bc8529cSMartin KaFai Lau 				  unsigned int n)
16296bc8529cSMartin KaFai Lau {
16306bc8529cSMartin KaFai Lau 	socklen_t optlen, addrlen;
16316bc8529cSMartin KaFai Lau 	struct sockaddr_in6 s6;
16326bc8529cSMartin KaFai Lau 	const __u32 index0 = 0;
16336bc8529cSMartin KaFai Lau 	const int optval = 1;
16346bc8529cSMartin KaFai Lau 	unsigned int i;
16356bc8529cSMartin KaFai Lau 	u64 sk_cookie;
1636bc2d8afeSIlya Leoshkevich 	void *value;
1637bc2d8afeSIlya Leoshkevich 	__s32 fd32;
16386bc8529cSMartin KaFai Lau 	__s64 fd64;
16396bc8529cSMartin KaFai Lau 	int err;
16406bc8529cSMartin KaFai Lau 
16416bc8529cSMartin KaFai Lau 	s6.sin6_family = AF_INET6;
16426bc8529cSMartin KaFai Lau 	s6.sin6_addr = in6addr_any;
16436bc8529cSMartin KaFai Lau 	s6.sin6_port = 0;
16446bc8529cSMartin KaFai Lau 	addrlen = sizeof(s6);
16456bc8529cSMartin KaFai Lau 	optlen = sizeof(sk_cookie);
16466bc8529cSMartin KaFai Lau 
16476bc8529cSMartin KaFai Lau 	for (i = 0; i < n; i++) {
16486bc8529cSMartin KaFai Lau 		fd64 = socket(AF_INET6, type, 0);
16496bc8529cSMartin KaFai Lau 		CHECK(fd64 == -1, "socket()",
16506bc8529cSMartin KaFai Lau 		      "sock_type:%d fd64:%lld errno:%d\n",
16516bc8529cSMartin KaFai Lau 		      type, fd64, errno);
16526bc8529cSMartin KaFai Lau 
16536bc8529cSMartin KaFai Lau 		err = setsockopt(fd64, SOL_SOCKET, SO_REUSEPORT,
16546bc8529cSMartin KaFai Lau 				 &optval, sizeof(optval));
165526a1ccc6SColin Ian King 		CHECK(err == -1, "setsockopt(SO_REUSEPORT)",
16566bc8529cSMartin KaFai Lau 		      "err:%d errno:%d\n", err, errno);
16576bc8529cSMartin KaFai Lau 
16586bc8529cSMartin KaFai Lau 		/* reuseport_array does not allow unbound sk */
1659bc2d8afeSIlya Leoshkevich 		if (map_elem_size == sizeof(__u64))
1660bc2d8afeSIlya Leoshkevich 			value = &fd64;
1661bc2d8afeSIlya Leoshkevich 		else {
1662bc2d8afeSIlya Leoshkevich 			assert(map_elem_size == sizeof(__u32));
1663bc2d8afeSIlya Leoshkevich 			fd32 = (__s32)fd64;
1664bc2d8afeSIlya Leoshkevich 			value = &fd32;
1665bc2d8afeSIlya Leoshkevich 		}
1666bc2d8afeSIlya Leoshkevich 		err = bpf_map_update_elem(map_fd, &index0, value, BPF_ANY);
1667bad2e478SAndrii Nakryiko 		CHECK(err >= 0 || errno != EINVAL,
16686bc8529cSMartin KaFai Lau 		      "reuseport array update unbound sk",
16696bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n",
16706bc8529cSMartin KaFai Lau 		      type, err, errno);
16716bc8529cSMartin KaFai Lau 
16726bc8529cSMartin KaFai Lau 		err = bind(fd64, (struct sockaddr *)&s6, sizeof(s6));
16736bc8529cSMartin KaFai Lau 		CHECK(err == -1, "bind()",
16746bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
16756bc8529cSMartin KaFai Lau 
16766bc8529cSMartin KaFai Lau 		if (i == 0) {
16776bc8529cSMartin KaFai Lau 			err = getsockname(fd64, (struct sockaddr *)&s6,
16786bc8529cSMartin KaFai Lau 					  &addrlen);
16796bc8529cSMartin KaFai Lau 			CHECK(err == -1, "getsockname()",
16806bc8529cSMartin KaFai Lau 			      "sock_type:%d err:%d errno:%d\n",
16816bc8529cSMartin KaFai Lau 			      type, err, errno);
16826bc8529cSMartin KaFai Lau 		}
16836bc8529cSMartin KaFai Lau 
16846bc8529cSMartin KaFai Lau 		err = getsockopt(fd64, SOL_SOCKET, SO_COOKIE, &sk_cookie,
16856bc8529cSMartin KaFai Lau 				 &optlen);
16866bc8529cSMartin KaFai Lau 		CHECK(err == -1, "getsockopt(SO_COOKIE)",
16876bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
16886bc8529cSMartin KaFai Lau 
16896bc8529cSMartin KaFai Lau 		if (type == SOCK_STREAM) {
16906bc8529cSMartin KaFai Lau 			/*
16916bc8529cSMartin KaFai Lau 			 * reuseport_array does not allow
16926bc8529cSMartin KaFai Lau 			 * non-listening tcp sk.
16936bc8529cSMartin KaFai Lau 			 */
1694bc2d8afeSIlya Leoshkevich 			err = bpf_map_update_elem(map_fd, &index0, value,
16956bc8529cSMartin KaFai Lau 						  BPF_ANY);
1696bad2e478SAndrii Nakryiko 			CHECK(err >= 0 || errno != EINVAL,
16976bc8529cSMartin KaFai Lau 			      "reuseport array update non-listening sk",
16986bc8529cSMartin KaFai Lau 			      "sock_type:%d err:%d errno:%d\n",
16996bc8529cSMartin KaFai Lau 			      type, err, errno);
17006bc8529cSMartin KaFai Lau 			err = listen(fd64, 0);
17016bc8529cSMartin KaFai Lau 			CHECK(err == -1, "listen()",
17026bc8529cSMartin KaFai Lau 			      "sock_type:%d, err:%d errno:%d\n",
17036bc8529cSMartin KaFai Lau 			      type, err, errno);
17046bc8529cSMartin KaFai Lau 		}
17056bc8529cSMartin KaFai Lau 
17066bc8529cSMartin KaFai Lau 		fds64[i] = fd64;
17076bc8529cSMartin KaFai Lau 		sk_cookies[i] = sk_cookie;
17086bc8529cSMartin KaFai Lau 	}
17096bc8529cSMartin KaFai Lau }
17106bc8529cSMartin KaFai Lau 
test_reuseport_array(void)17116bc8529cSMartin KaFai Lau static void test_reuseport_array(void)
17126bc8529cSMartin KaFai Lau {
17136bc8529cSMartin KaFai Lau #define REUSEPORT_FD_IDX(err, last) ({ (err) ? last : !last; })
17146bc8529cSMartin KaFai Lau 
17156bc8529cSMartin KaFai Lau 	const __u32 array_size = 4, index0 = 0, index3 = 3;
17166bc8529cSMartin KaFai Lau 	int types[2] = { SOCK_STREAM, SOCK_DGRAM }, type;
17176bc8529cSMartin KaFai Lau 	__u64 grpa_cookies[2], sk_cookie, map_cookie;
17186bc8529cSMartin KaFai Lau 	__s64 grpa_fds64[2] = { -1, -1 }, fd64 = -1;
17196bc8529cSMartin KaFai Lau 	const __u32 bad_index = array_size;
17206bc8529cSMartin KaFai Lau 	int map_fd, err, t, f;
17216bc8529cSMartin KaFai Lau 	__u32 fds_idx = 0;
17226bc8529cSMartin KaFai Lau 	int fd;
17236bc8529cSMartin KaFai Lau 
17242fe256a4SAndrii Nakryiko 	map_fd = bpf_map_create(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, NULL,
17252fe256a4SAndrii Nakryiko 				sizeof(__u32), sizeof(__u64), array_size, NULL);
1726bad2e478SAndrii Nakryiko 	CHECK(map_fd < 0, "reuseport array create",
17276bc8529cSMartin KaFai Lau 	      "map_fd:%d, errno:%d\n", map_fd, errno);
17286bc8529cSMartin KaFai Lau 
17296bc8529cSMartin KaFai Lau 	/* Test lookup/update/delete with invalid index */
17306bc8529cSMartin KaFai Lau 	err = bpf_map_delete_elem(map_fd, &bad_index);
1731bad2e478SAndrii Nakryiko 	CHECK(err >= 0 || errno != E2BIG, "reuseport array del >=max_entries",
17326bc8529cSMartin KaFai Lau 	      "err:%d errno:%d\n", err, errno);
17336bc8529cSMartin KaFai Lau 
17346bc8529cSMartin KaFai Lau 	err = bpf_map_update_elem(map_fd, &bad_index, &fd64, BPF_ANY);
1735bad2e478SAndrii Nakryiko 	CHECK(err >= 0 || errno != E2BIG,
17366bc8529cSMartin KaFai Lau 	      "reuseport array update >=max_entries",
17376bc8529cSMartin KaFai Lau 	      "err:%d errno:%d\n", err, errno);
17386bc8529cSMartin KaFai Lau 
17396bc8529cSMartin KaFai Lau 	err = bpf_map_lookup_elem(map_fd, &bad_index, &map_cookie);
1740bad2e478SAndrii Nakryiko 	CHECK(err >= 0 || errno != ENOENT,
17416bc8529cSMartin KaFai Lau 	      "reuseport array update >=max_entries",
17426bc8529cSMartin KaFai Lau 	      "err:%d errno:%d\n", err, errno);
17436bc8529cSMartin KaFai Lau 
17446bc8529cSMartin KaFai Lau 	/* Test lookup/delete non existence elem */
17456bc8529cSMartin KaFai Lau 	err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
1746bad2e478SAndrii Nakryiko 	CHECK(err >= 0 || errno != ENOENT,
17476bc8529cSMartin KaFai Lau 	      "reuseport array lookup not-exist elem",
17486bc8529cSMartin KaFai Lau 	      "err:%d errno:%d\n", err, errno);
17496bc8529cSMartin KaFai Lau 	err = bpf_map_delete_elem(map_fd, &index3);
1750bad2e478SAndrii Nakryiko 	CHECK(err >= 0 || errno != ENOENT,
17516bc8529cSMartin KaFai Lau 	      "reuseport array del not-exist elem",
17526bc8529cSMartin KaFai Lau 	      "err:%d errno:%d\n", err, errno);
17536bc8529cSMartin KaFai Lau 
17546bc8529cSMartin KaFai Lau 	for (t = 0; t < ARRAY_SIZE(types); t++) {
17556bc8529cSMartin KaFai Lau 		type = types[t];
17566bc8529cSMartin KaFai Lau 
1757bc2d8afeSIlya Leoshkevich 		prepare_reuseport_grp(type, map_fd, sizeof(__u64), grpa_fds64,
17586bc8529cSMartin KaFai Lau 				      grpa_cookies, ARRAY_SIZE(grpa_fds64));
17596bc8529cSMartin KaFai Lau 
17606bc8529cSMartin KaFai Lau 		/* Test BPF_* update flags */
17616bc8529cSMartin KaFai Lau 		/* BPF_EXIST failure case */
17626bc8529cSMartin KaFai Lau 		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
17636bc8529cSMartin KaFai Lau 					  BPF_EXIST);
1764bad2e478SAndrii Nakryiko 		CHECK(err >= 0 || errno != ENOENT,
17656bc8529cSMartin KaFai Lau 		      "reuseport array update empty elem BPF_EXIST",
17666bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n",
17676bc8529cSMartin KaFai Lau 		      type, err, errno);
17686bc8529cSMartin KaFai Lau 		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
17696bc8529cSMartin KaFai Lau 
17706bc8529cSMartin KaFai Lau 		/* BPF_NOEXIST success case */
17716bc8529cSMartin KaFai Lau 		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
17726bc8529cSMartin KaFai Lau 					  BPF_NOEXIST);
1773bad2e478SAndrii Nakryiko 		CHECK(err < 0,
17746bc8529cSMartin KaFai Lau 		      "reuseport array update empty elem BPF_NOEXIST",
17756bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n",
17766bc8529cSMartin KaFai Lau 		      type, err, errno);
17776bc8529cSMartin KaFai Lau 		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
17786bc8529cSMartin KaFai Lau 
17796bc8529cSMartin KaFai Lau 		/* BPF_EXIST success case. */
17806bc8529cSMartin KaFai Lau 		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
17816bc8529cSMartin KaFai Lau 					  BPF_EXIST);
1782bad2e478SAndrii Nakryiko 		CHECK(err < 0,
17836bc8529cSMartin KaFai Lau 		      "reuseport array update same elem BPF_EXIST",
17846bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
17856bc8529cSMartin KaFai Lau 		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
17866bc8529cSMartin KaFai Lau 
17876bc8529cSMartin KaFai Lau 		/* BPF_NOEXIST failure case */
17886bc8529cSMartin KaFai Lau 		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
17896bc8529cSMartin KaFai Lau 					  BPF_NOEXIST);
1790bad2e478SAndrii Nakryiko 		CHECK(err >= 0 || errno != EEXIST,
17916bc8529cSMartin KaFai Lau 		      "reuseport array update non-empty elem BPF_NOEXIST",
17926bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n",
17936bc8529cSMartin KaFai Lau 		      type, err, errno);
17946bc8529cSMartin KaFai Lau 		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
17956bc8529cSMartin KaFai Lau 
17966bc8529cSMartin KaFai Lau 		/* BPF_ANY case (always succeed) */
17976bc8529cSMartin KaFai Lau 		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
17986bc8529cSMartin KaFai Lau 					  BPF_ANY);
1799bad2e478SAndrii Nakryiko 		CHECK(err < 0,
18006bc8529cSMartin KaFai Lau 		      "reuseport array update same sk with BPF_ANY",
18016bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
18026bc8529cSMartin KaFai Lau 
18036bc8529cSMartin KaFai Lau 		fd64 = grpa_fds64[fds_idx];
18046bc8529cSMartin KaFai Lau 		sk_cookie = grpa_cookies[fds_idx];
18056bc8529cSMartin KaFai Lau 
18066bc8529cSMartin KaFai Lau 		/* The same sk cannot be added to reuseport_array twice */
18076bc8529cSMartin KaFai Lau 		err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_ANY);
1808bad2e478SAndrii Nakryiko 		CHECK(err >= 0 || errno != EBUSY,
18096bc8529cSMartin KaFai Lau 		      "reuseport array update same sk with same index",
18106bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n",
18116bc8529cSMartin KaFai Lau 		      type, err, errno);
18126bc8529cSMartin KaFai Lau 
18136bc8529cSMartin KaFai Lau 		err = bpf_map_update_elem(map_fd, &index0, &fd64, BPF_ANY);
1814bad2e478SAndrii Nakryiko 		CHECK(err >= 0 || errno != EBUSY,
18156bc8529cSMartin KaFai Lau 		      "reuseport array update same sk with different index",
18166bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n",
18176bc8529cSMartin KaFai Lau 		      type, err, errno);
18186bc8529cSMartin KaFai Lau 
18196bc8529cSMartin KaFai Lau 		/* Test delete elem */
18206bc8529cSMartin KaFai Lau 		err = bpf_map_delete_elem(map_fd, &index3);
1821bad2e478SAndrii Nakryiko 		CHECK(err < 0, "reuseport array delete sk",
18226bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n",
18236bc8529cSMartin KaFai Lau 		      type, err, errno);
18246bc8529cSMartin KaFai Lau 
18256bc8529cSMartin KaFai Lau 		/* Add it back with BPF_NOEXIST */
18266bc8529cSMartin KaFai Lau 		err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST);
1827bad2e478SAndrii Nakryiko 		CHECK(err < 0,
18286bc8529cSMartin KaFai Lau 		      "reuseport array re-add with BPF_NOEXIST after del",
18296bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
18306bc8529cSMartin KaFai Lau 
18316bc8529cSMartin KaFai Lau 		/* Test cookie */
18326bc8529cSMartin KaFai Lau 		err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
1833bad2e478SAndrii Nakryiko 		CHECK(err < 0 || sk_cookie != map_cookie,
18346bc8529cSMartin KaFai Lau 		      "reuseport array lookup re-added sk",
18356bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d sk_cookie:0x%llx map_cookie:0x%llxn",
18366bc8529cSMartin KaFai Lau 		      type, err, errno, sk_cookie, map_cookie);
18376bc8529cSMartin KaFai Lau 
18386bc8529cSMartin KaFai Lau 		/* Test elem removed by close() */
18396bc8529cSMartin KaFai Lau 		for (f = 0; f < ARRAY_SIZE(grpa_fds64); f++)
18406bc8529cSMartin KaFai Lau 			close(grpa_fds64[f]);
18416bc8529cSMartin KaFai Lau 		err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
1842bad2e478SAndrii Nakryiko 		CHECK(err >= 0 || errno != ENOENT,
18436bc8529cSMartin KaFai Lau 		      "reuseport array lookup after close()",
18446bc8529cSMartin KaFai Lau 		      "sock_type:%d err:%d errno:%d\n",
18456bc8529cSMartin KaFai Lau 		      type, err, errno);
18466bc8529cSMartin KaFai Lau 	}
18476bc8529cSMartin KaFai Lau 
18486bc8529cSMartin KaFai Lau 	/* Test SOCK_RAW */
18496bc8529cSMartin KaFai Lau 	fd64 = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP);
18506bc8529cSMartin KaFai Lau 	CHECK(fd64 == -1, "socket(SOCK_RAW)", "err:%d errno:%d\n",
18516bc8529cSMartin KaFai Lau 	      err, errno);
18526bc8529cSMartin KaFai Lau 	err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST);
1853bad2e478SAndrii Nakryiko 	CHECK(err >= 0 || errno != ENOTSUPP, "reuseport array update SOCK_RAW",
18546bc8529cSMartin KaFai Lau 	      "err:%d errno:%d\n", err, errno);
18556bc8529cSMartin KaFai Lau 	close(fd64);
18566bc8529cSMartin KaFai Lau 
18576bc8529cSMartin KaFai Lau 	/* Close the 64 bit value map */
18586bc8529cSMartin KaFai Lau 	close(map_fd);
18596bc8529cSMartin KaFai Lau 
18606bc8529cSMartin KaFai Lau 	/* Test 32 bit fd */
18612fe256a4SAndrii Nakryiko 	map_fd = bpf_map_create(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, NULL,
18622fe256a4SAndrii Nakryiko 				sizeof(__u32), sizeof(__u32), array_size, NULL);
1863bad2e478SAndrii Nakryiko 	CHECK(map_fd < 0, "reuseport array create",
18646bc8529cSMartin KaFai Lau 	      "map_fd:%d, errno:%d\n", map_fd, errno);
1865bc2d8afeSIlya Leoshkevich 	prepare_reuseport_grp(SOCK_STREAM, map_fd, sizeof(__u32), &fd64,
1866bc2d8afeSIlya Leoshkevich 			      &sk_cookie, 1);
18676bc8529cSMartin KaFai Lau 	fd = fd64;
18686bc8529cSMartin KaFai Lau 	err = bpf_map_update_elem(map_fd, &index3, &fd, BPF_NOEXIST);
1869bad2e478SAndrii Nakryiko 	CHECK(err < 0, "reuseport array update 32 bit fd",
18706bc8529cSMartin KaFai Lau 	      "err:%d errno:%d\n", err, errno);
18716bc8529cSMartin KaFai Lau 	err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
1872bad2e478SAndrii Nakryiko 	CHECK(err >= 0 || errno != ENOSPC,
18736bc8529cSMartin KaFai Lau 	      "reuseport array lookup 32 bit fd",
18746bc8529cSMartin KaFai Lau 	      "err:%d errno:%d\n", err, errno);
18756bc8529cSMartin KaFai Lau 	close(fd);
18766bc8529cSMartin KaFai Lau 	close(map_fd);
18776bc8529cSMartin KaFai Lau }
18786bc8529cSMartin KaFai Lau 
run_all_tests(void)18795aa5bd14SDaniel Borkmann static void run_all_tests(void)
18805aa5bd14SDaniel Borkmann {
18815aa5bd14SDaniel Borkmann 	test_hashmap(0, NULL);
18825aa5bd14SDaniel Borkmann 	test_hashmap_percpu(0, NULL);
18835ecf51fdSDaniel Borkmann 	test_hashmap_walk(0, NULL);
1884bf5d68c7SLorenz Bauer 	test_hashmap_zero_seed();
18855aa5bd14SDaniel Borkmann 
18865aa5bd14SDaniel Borkmann 	test_arraymap(0, NULL);
18875aa5bd14SDaniel Borkmann 	test_arraymap_percpu(0, NULL);
18885aa5bd14SDaniel Borkmann 
18895aa5bd14SDaniel Borkmann 	test_arraymap_percpu_many_keys();
18905aa5bd14SDaniel Borkmann 
189181f6bf81SJohn Fastabend 	test_devmap(0, NULL);
18921375dc4aSToke Høiland-Jørgensen 	test_devmap_hash(0, NULL);
18936f6d33f3SJohn Fastabend 	test_sockmap(0, NULL);
189481f6bf81SJohn Fastabend 
18955aa5bd14SDaniel Borkmann 	test_map_large();
18965aa5bd14SDaniel Borkmann 	test_map_parallel();
18975aa5bd14SDaniel Borkmann 	test_map_stress();
1898e043325bSChenbo Feng 
1899e043325bSChenbo Feng 	test_map_rdonly();
1900e043325bSChenbo Feng 	test_map_wronly();
19016bc8529cSMartin KaFai Lau 
19026bc8529cSMartin KaFai Lau 	test_reuseport_array();
190343b987d2SMauricio Vasquez B 
190443b987d2SMauricio Vasquez B 	test_queuemap(0, NULL);
190543b987d2SMauricio Vasquez B 	test_stackmap(0, NULL);
1906b1957c92SNikita V. Shirokov 
1907b1957c92SNikita V. Shirokov 	test_map_in_map();
19085aa5bd14SDaniel Borkmann }
19095aa5bd14SDaniel Borkmann 
1910ee6c52e9SAndrii Nakryiko #define DEFINE_TEST(name) extern void test_##name(void);
191151a0e301SMartin KaFai Lau #include <map_tests/tests.h>
1912ee6c52e9SAndrii Nakryiko #undef DEFINE_TEST
191351a0e301SMartin KaFai Lau 
main(void)19145aa5bd14SDaniel Borkmann int main(void)
19155aa5bd14SDaniel Borkmann {
191643b987d2SMauricio Vasquez B 	srand(time(NULL));
191743b987d2SMauricio Vasquez B 
1918bad2e478SAndrii Nakryiko 	libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
1919bad2e478SAndrii Nakryiko 
19202fe256a4SAndrii Nakryiko 	map_opts.map_flags = 0;
19215aa5bd14SDaniel Borkmann 	run_all_tests();
19225aa5bd14SDaniel Borkmann 
19232fe256a4SAndrii Nakryiko 	map_opts.map_flags = BPF_F_NO_PREALLOC;
19245aa5bd14SDaniel Borkmann 	run_all_tests();
19255aa5bd14SDaniel Borkmann 
1926ee6c52e9SAndrii Nakryiko #define DEFINE_TEST(name) test_##name();
192751a0e301SMartin KaFai Lau #include <map_tests/tests.h>
1928ee6c52e9SAndrii Nakryiko #undef DEFINE_TEST
192951a0e301SMartin KaFai Lau 
1930e8ddbfb4SStanislav Fomichev 	printf("test_maps: OK, %d SKIPPED\n", skips);
19315aa5bd14SDaniel Borkmann 	return 0;
19325aa5bd14SDaniel Borkmann }
1933