1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Testsuite for eBPF maps
4 *
5 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
6 * Copyright (c) 2016 Facebook
7 */
8
9#include <stdio.h>
10#include <unistd.h>
11#include <errno.h>
12#include <string.h>
13#include <assert.h>
14#include <stdlib.h>
15#include <time.h>
16
17#include <sys/wait.h>
18#include <sys/socket.h>
19#include <netinet/in.h>
20#include <linux/bpf.h>
21
22#include <bpf/bpf.h>
23#include <bpf/libbpf.h>
24
25#include "bpf_util.h"
26#include "bpf_rlimit.h"
27#include "test_maps.h"
28
29#ifndef ENOTSUPP
30#define ENOTSUPP 524
31#endif
32
33static int skips;
34
35static int map_flags;
36
37static void test_hashmap(unsigned int task, void *data)
38{
39	long long key, next_key, first_key, value;
40	int fd;
41
42	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
43			    2, map_flags);
44	if (fd < 0) {
45		printf("Failed to create hashmap '%s'!\n", strerror(errno));
46		exit(1);
47	}
48
49	key = 1;
50	value = 1234;
51	/* Insert key=1 element. */
52	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
53
54	value = 0;
55	/* BPF_NOEXIST means add new element if it doesn't exist. */
56	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
57	       /* key=1 already exists. */
58	       errno == EEXIST);
59
60	/* -1 is an invalid flag. */
61	assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 &&
62	       errno == EINVAL);
63
64	/* Check that key=1 can be found. */
65	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
66
67	key = 2;
68	/* Check that key=2 is not found. */
69	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
70
71	/* BPF_EXIST means update existing element. */
72	assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
73	       /* key=2 is not there. */
74	       errno == ENOENT);
75
76	/* Insert key=2 element. */
77	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
78
79	/* key=1 and key=2 were inserted, check that key=0 cannot be
80	 * inserted due to max_entries limit.
81	 */
82	key = 0;
83	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
84	       errno == E2BIG);
85
86	/* Update existing element, though the map is full. */
87	key = 1;
88	assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
89	key = 2;
90	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
91	key = 3;
92	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
93	       errno == E2BIG);
94
95	/* Check that key = 0 doesn't exist. */
96	key = 0;
97	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
98
99	/* Iterate over two elements. */
100	assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
101	       (first_key == 1 || first_key == 2));
102	assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
103	       (next_key == first_key));
104	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
105	       (next_key == 1 || next_key == 2) &&
106	       (next_key != first_key));
107	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
108	       errno == ENOENT);
109
110	/* Delete both elements. */
111	key = 1;
112	assert(bpf_map_delete_elem(fd, &key) == 0);
113	key = 2;
114	assert(bpf_map_delete_elem(fd, &key) == 0);
115	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
116
117	key = 0;
118	/* Check that map is empty. */
119	assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
120	       errno == ENOENT);
121	assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
122	       errno == ENOENT);
123
124	close(fd);
125}
126
127static void test_hashmap_sizes(unsigned int task, void *data)
128{
129	int fd, i, j;
130
131	for (i = 1; i <= 512; i <<= 1)
132		for (j = 1; j <= 1 << 18; j <<= 1) {
133			fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j,
134					    2, map_flags);
135			if (fd < 0) {
136				if (errno == ENOMEM)
137					return;
138				printf("Failed to create hashmap key=%d value=%d '%s'\n",
139				       i, j, strerror(errno));
140				exit(1);
141			}
142			close(fd);
143			usleep(10); /* give kernel time to destroy */
144		}
145}
146
147static void test_hashmap_percpu(unsigned int task, void *data)
148{
149	unsigned int nr_cpus = bpf_num_possible_cpus();
150	BPF_DECLARE_PERCPU(long, value);
151	long long key, next_key, first_key;
152	int expected_key_mask = 0;
153	int fd, i;
154
155	fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
156			    sizeof(bpf_percpu(value, 0)), 2, map_flags);
157	if (fd < 0) {
158		printf("Failed to create hashmap '%s'!\n", strerror(errno));
159		exit(1);
160	}
161
162	for (i = 0; i < nr_cpus; i++)
163		bpf_percpu(value, i) = i + 100;
164
165	key = 1;
166	/* Insert key=1 element. */
167	assert(!(expected_key_mask & key));
168	assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0);
169	expected_key_mask |= key;
170
171	/* BPF_NOEXIST means add new element if it doesn't exist. */
172	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
173	       /* key=1 already exists. */
174	       errno == EEXIST);
175
176	/* -1 is an invalid flag. */
177	assert(bpf_map_update_elem(fd, &key, value, -1) == -1 &&
178	       errno == EINVAL);
179
180	/* Check that key=1 can be found. Value could be 0 if the lookup
181	 * was run from a different CPU.
182	 */
183	bpf_percpu(value, 0) = 1;
184	assert(bpf_map_lookup_elem(fd, &key, value) == 0 &&
185	       bpf_percpu(value, 0) == 100);
186
187	key = 2;
188	/* Check that key=2 is not found. */
189	assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT);
190
191	/* BPF_EXIST means update existing element. */
192	assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 &&
193	       /* key=2 is not there. */
194	       errno == ENOENT);
195
196	/* Insert key=2 element. */
197	assert(!(expected_key_mask & key));
198	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0);
199	expected_key_mask |= key;
200
201	/* key=1 and key=2 were inserted, check that key=0 cannot be
202	 * inserted due to max_entries limit.
203	 */
204	key = 0;
205	assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
206	       errno == E2BIG);
207
208	/* Check that key = 0 doesn't exist. */
209	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
210
211	/* Iterate over two elements. */
212	assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
213	       ((expected_key_mask & first_key) == first_key));
214	while (!bpf_map_get_next_key(fd, &key, &next_key)) {
215		if (first_key) {
216			assert(next_key == first_key);
217			first_key = 0;
218		}
219		assert((expected_key_mask & next_key) == next_key);
220		expected_key_mask &= ~next_key;
221
222		assert(bpf_map_lookup_elem(fd, &next_key, value) == 0);
223
224		for (i = 0; i < nr_cpus; i++)
225			assert(bpf_percpu(value, i) == i + 100);
226
227		key = next_key;
228	}
229	assert(errno == ENOENT);
230
231	/* Update with BPF_EXIST. */
232	key = 1;
233	assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0);
234
235	/* Delete both elements. */
236	key = 1;
237	assert(bpf_map_delete_elem(fd, &key) == 0);
238	key = 2;
239	assert(bpf_map_delete_elem(fd, &key) == 0);
240	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
241
242	key = 0;
243	/* Check that map is empty. */
244	assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
245	       errno == ENOENT);
246	assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
247	       errno == ENOENT);
248
249	close(fd);
250}
251
252static int helper_fill_hashmap(int max_entries)
253{
254	int i, fd, ret;
255	long long key, value;
256
257	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
258			    max_entries, map_flags);
259	CHECK(fd < 0,
260	      "failed to create hashmap",
261	      "err: %s, flags: 0x%x\n", strerror(errno), map_flags);
262
263	for (i = 0; i < max_entries; i++) {
264		key = i; value = key;
265		ret = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
266		CHECK(ret != 0,
267		      "can't update hashmap",
268		      "err: %s\n", strerror(ret));
269	}
270
271	return fd;
272}
273
274static void test_hashmap_walk(unsigned int task, void *data)
275{
276	int fd, i, max_entries = 1000;
277	long long key, value, next_key;
278	bool next_key_valid = true;
279
280	fd = helper_fill_hashmap(max_entries);
281
282	for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
283					 &next_key) == 0; i++) {
284		key = next_key;
285		assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
286	}
287
288	assert(i == max_entries);
289
290	assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
291	for (i = 0; next_key_valid; i++) {
292		next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0;
293		assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
294		value++;
295		assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
296		key = next_key;
297	}
298
299	assert(i == max_entries);
300
301	for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
302					 &next_key) == 0; i++) {
303		key = next_key;
304		assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
305		assert(value - 1 == key);
306	}
307
308	assert(i == max_entries);
309	close(fd);
310}
311
312static void test_hashmap_zero_seed(void)
313{
314	int i, first, second, old_flags;
315	long long key, next_first, next_second;
316
317	old_flags = map_flags;
318	map_flags |= BPF_F_ZERO_SEED;
319
320	first = helper_fill_hashmap(3);
321	second = helper_fill_hashmap(3);
322
323	for (i = 0; ; i++) {
324		void *key_ptr = !i ? NULL : &key;
325
326		if (bpf_map_get_next_key(first, key_ptr, &next_first) != 0)
327			break;
328
329		CHECK(bpf_map_get_next_key(second, key_ptr, &next_second) != 0,
330		      "next_key for second map must succeed",
331		      "key_ptr: %p", key_ptr);
332		CHECK(next_first != next_second,
333		      "keys must match",
334		      "i: %d first: %lld second: %lld\n", i,
335		      next_first, next_second);
336
337		key = next_first;
338	}
339
340	map_flags = old_flags;
341	close(first);
342	close(second);
343}
344
345static void test_arraymap(unsigned int task, void *data)
346{
347	int key, next_key, fd;
348	long long value;
349
350	fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
351			    2, 0);
352	if (fd < 0) {
353		printf("Failed to create arraymap '%s'!\n", strerror(errno));
354		exit(1);
355	}
356
357	key = 1;
358	value = 1234;
359	/* Insert key=1 element. */
360	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
361
362	value = 0;
363	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
364	       errno == EEXIST);
365
366	/* Check that key=1 can be found. */
367	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
368
369	key = 0;
370	/* Check that key=0 is also found and zero initialized. */
371	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
372
373	/* key=0 and key=1 were inserted, check that key=2 cannot be inserted
374	 * due to max_entries limit.
375	 */
376	key = 2;
377	assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
378	       errno == E2BIG);
379
380	/* Check that key = 2 doesn't exist. */
381	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
382
383	/* Iterate over two elements. */
384	assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
385	       next_key == 0);
386	assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
387	       next_key == 0);
388	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
389	       next_key == 1);
390	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
391	       errno == ENOENT);
392
393	/* Delete shouldn't succeed. */
394	key = 1;
395	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
396
397	close(fd);
398}
399
400static void test_arraymap_percpu(unsigned int task, void *data)
401{
402	unsigned int nr_cpus = bpf_num_possible_cpus();
403	BPF_DECLARE_PERCPU(long, values);
404	int key, next_key, fd, i;
405
406	fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
407			    sizeof(bpf_percpu(values, 0)), 2, 0);
408	if (fd < 0) {
409		printf("Failed to create arraymap '%s'!\n", strerror(errno));
410		exit(1);
411	}
412
413	for (i = 0; i < nr_cpus; i++)
414		bpf_percpu(values, i) = i + 100;
415
416	key = 1;
417	/* Insert key=1 element. */
418	assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
419
420	bpf_percpu(values, 0) = 0;
421	assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 &&
422	       errno == EEXIST);
423
424	/* Check that key=1 can be found. */
425	assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
426	       bpf_percpu(values, 0) == 100);
427
428	key = 0;
429	/* Check that key=0 is also found and zero initialized. */
430	assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
431	       bpf_percpu(values, 0) == 0 &&
432	       bpf_percpu(values, nr_cpus - 1) == 0);
433
434	/* Check that key=2 cannot be inserted due to max_entries limit. */
435	key = 2;
436	assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 &&
437	       errno == E2BIG);
438
439	/* Check that key = 2 doesn't exist. */
440	assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT);
441
442	/* Iterate over two elements. */
443	assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
444	       next_key == 0);
445	assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
446	       next_key == 0);
447	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
448	       next_key == 1);
449	assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
450	       errno == ENOENT);
451
452	/* Delete shouldn't succeed. */
453	key = 1;
454	assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
455
456	close(fd);
457}
458
459static void test_arraymap_percpu_many_keys(void)
460{
461	unsigned int nr_cpus = bpf_num_possible_cpus();
462	BPF_DECLARE_PERCPU(long, values);
463	/* nr_keys is not too large otherwise the test stresses percpu
464	 * allocator more than anything else
465	 */
466	unsigned int nr_keys = 2000;
467	int key, fd, i;
468
469	fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
470			    sizeof(bpf_percpu(values, 0)), nr_keys, 0);
471	if (fd < 0) {
472		printf("Failed to create per-cpu arraymap '%s'!\n",
473		       strerror(errno));
474		exit(1);
475	}
476
477	for (i = 0; i < nr_cpus; i++)
478		bpf_percpu(values, i) = i + 10;
479
480	for (key = 0; key < nr_keys; key++)
481		assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
482
483	for (key = 0; key < nr_keys; key++) {
484		for (i = 0; i < nr_cpus; i++)
485			bpf_percpu(values, i) = 0;
486
487		assert(bpf_map_lookup_elem(fd, &key, values) == 0);
488
489		for (i = 0; i < nr_cpus; i++)
490			assert(bpf_percpu(values, i) == i + 10);
491	}
492
493	close(fd);
494}
495
496static void test_devmap(unsigned int task, void *data)
497{
498	int fd;
499	__u32 key, value;
500
501	fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),
502			    2, 0);
503	if (fd < 0) {
504		printf("Failed to create devmap '%s'!\n", strerror(errno));
505		exit(1);
506	}
507
508	close(fd);
509}
510
511static void test_devmap_hash(unsigned int task, void *data)
512{
513	int fd;
514	__u32 key, value;
515
516	fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP_HASH, sizeof(key), sizeof(value),
517			    2, 0);
518	if (fd < 0) {
519		printf("Failed to create devmap_hash '%s'!\n", strerror(errno));
520		exit(1);
521	}
522
523	close(fd);
524}
525
526static void test_queuemap(unsigned int task, void *data)
527{
528	const int MAP_SIZE = 32;
529	__u32 vals[MAP_SIZE + MAP_SIZE/2], val;
530	int fd, i;
531
532	/* Fill test values to be used */
533	for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++)
534		vals[i] = rand();
535
536	/* Invalid key size */
537	fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 4, sizeof(val), MAP_SIZE,
538			    map_flags);
539	assert(fd < 0 && errno == EINVAL);
540
541	fd = bpf_create_map(BPF_MAP_TYPE_QUEUE, 0, sizeof(val), MAP_SIZE,
542			    map_flags);
543	/* Queue map does not support BPF_F_NO_PREALLOC */
544	if (map_flags & BPF_F_NO_PREALLOC) {
545		assert(fd < 0 && errno == EINVAL);
546		return;
547	}
548	if (fd < 0) {
549		printf("Failed to create queuemap '%s'!\n", strerror(errno));
550		exit(1);
551	}
552
553	/* Push MAP_SIZE elements */
554	for (i = 0; i < MAP_SIZE; i++)
555		assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
556
557	/* Check that element cannot be pushed due to max_entries limit */
558	assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 &&
559	       errno == E2BIG);
560
561	/* Peek element */
562	assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[0]);
563
564	/* Replace half elements */
565	for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++)
566		assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0);
567
568	/* Pop all elements */
569	for (i = MAP_SIZE/2; i < MAP_SIZE + MAP_SIZE/2; i++)
570		assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 &&
571		       val == vals[i]);
572
573	/* Check that there are not elements left */
574	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == -1 &&
575	       errno == ENOENT);
576
577	/* Check that non supported functions set errno to EINVAL */
578	assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
579	assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
580
581	close(fd);
582}
583
584static void test_stackmap(unsigned int task, void *data)
585{
586	const int MAP_SIZE = 32;
587	__u32 vals[MAP_SIZE + MAP_SIZE/2], val;
588	int fd, i;
589
590	/* Fill test values to be used */
591	for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++)
592		vals[i] = rand();
593
594	/* Invalid key size */
595	fd = bpf_create_map(BPF_MAP_TYPE_STACK, 4, sizeof(val), MAP_SIZE,
596			    map_flags);
597	assert(fd < 0 && errno == EINVAL);
598
599	fd = bpf_create_map(BPF_MAP_TYPE_STACK, 0, sizeof(val), MAP_SIZE,
600			    map_flags);
601	/* Stack map does not support BPF_F_NO_PREALLOC */
602	if (map_flags & BPF_F_NO_PREALLOC) {
603		assert(fd < 0 && errno == EINVAL);
604		return;
605	}
606	if (fd < 0) {
607		printf("Failed to create stackmap '%s'!\n", strerror(errno));
608		exit(1);
609	}
610
611	/* Push MAP_SIZE elements */
612	for (i = 0; i < MAP_SIZE; i++)
613		assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0);
614
615	/* Check that element cannot be pushed due to max_entries limit */
616	assert(bpf_map_update_elem(fd, NULL, &val, 0) == -1 &&
617	       errno == E2BIG);
618
619	/* Peek element */
620	assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[i - 1]);
621
622	/* Replace half elements */
623	for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++)
624		assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0);
625
626	/* Pop all elements */
627	for (i = MAP_SIZE + MAP_SIZE/2 - 1; i >= MAP_SIZE/2; i--)
628		assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 &&
629		       val == vals[i]);
630
631	/* Check that there are not elements left */
632	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == -1 &&
633	       errno == ENOENT);
634
635	/* Check that non supported functions set errno to EINVAL */
636	assert(bpf_map_delete_elem(fd, NULL) == -1 && errno == EINVAL);
637	assert(bpf_map_get_next_key(fd, NULL, NULL) == -1 && errno == EINVAL);
638
639	close(fd);
640}
641
642#include <sys/ioctl.h>
643#include <arpa/inet.h>
644#include <sys/select.h>
645#include <linux/err.h>
646#define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
647#define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
648#define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o"
649static void test_sockmap(unsigned int tasks, void *data)
650{
651	struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break;
652	int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break;
653	int ports[] = {50200, 50201, 50202, 50204};
654	int err, i, fd, udp, sfd[6] = {0xdeadbeef};
655	u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
656	int parse_prog, verdict_prog, msg_prog;
657	struct sockaddr_in addr;
658	int one = 1, s, sc, rc;
659	struct bpf_object *obj;
660	struct timeval to;
661	__u32 key, value;
662	pid_t pid[tasks];
663	fd_set w;
664
665	/* Create some sockets to use with sockmap */
666	for (i = 0; i < 2; i++) {
667		sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
668		if (sfd[i] < 0)
669			goto out;
670		err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
671				 (char *)&one, sizeof(one));
672		if (err) {
673			printf("failed to setsockopt\n");
674			goto out;
675		}
676		err = ioctl(sfd[i], FIONBIO, (char *)&one);
677		if (err < 0) {
678			printf("failed to ioctl\n");
679			goto out;
680		}
681		memset(&addr, 0, sizeof(struct sockaddr_in));
682		addr.sin_family = AF_INET;
683		addr.sin_addr.s_addr = inet_addr("127.0.0.1");
684		addr.sin_port = htons(ports[i]);
685		err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
686		if (err < 0) {
687			printf("failed to bind: err %i: %i:%i\n",
688			       err, i, sfd[i]);
689			goto out;
690		}
691		err = listen(sfd[i], 32);
692		if (err < 0) {
693			printf("failed to listen\n");
694			goto out;
695		}
696	}
697
698	for (i = 2; i < 4; i++) {
699		sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
700		if (sfd[i] < 0)
701			goto out;
702		err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
703				 (char *)&one, sizeof(one));
704		if (err) {
705			printf("set sock opt\n");
706			goto out;
707		}
708		memset(&addr, 0, sizeof(struct sockaddr_in));
709		addr.sin_family = AF_INET;
710		addr.sin_addr.s_addr = inet_addr("127.0.0.1");
711		addr.sin_port = htons(ports[i - 2]);
712		err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
713		if (err) {
714			printf("failed to connect\n");
715			goto out;
716		}
717	}
718
719
720	for (i = 4; i < 6; i++) {
721		sfd[i] = accept(sfd[i - 4], NULL, NULL);
722		if (sfd[i] < 0) {
723			printf("accept failed\n");
724			goto out;
725		}
726	}
727
728	/* Test sockmap with connected sockets */
729	fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP,
730			    sizeof(key), sizeof(value),
731			    6, 0);
732	if (fd < 0) {
733		if (!bpf_probe_map_type(BPF_MAP_TYPE_SOCKMAP, 0)) {
734			printf("%s SKIP (unsupported map type BPF_MAP_TYPE_SOCKMAP)\n",
735			       __func__);
736			skips++;
737			for (i = 0; i < 6; i++)
738				close(sfd[i]);
739			return;
740		}
741
742		printf("Failed to create sockmap %i\n", fd);
743		goto out_sockmap;
744	}
745
746	/* Test update with unsupported UDP socket */
747	udp = socket(AF_INET, SOCK_DGRAM, 0);
748	i = 0;
749	err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
750	if (!err) {
751		printf("Failed socket SOCK_DGRAM allowed '%i:%i'\n",
752		       i, udp);
753		goto out_sockmap;
754	}
755
756	/* Test update without programs */
757	for (i = 0; i < 6; i++) {
758		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
759		if (err) {
760			printf("Failed noprog update sockmap '%i:%i'\n",
761			       i, sfd[i]);
762			goto out_sockmap;
763		}
764	}
765
766	/* Test attaching/detaching bad fds */
767	err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
768	if (!err) {
769		printf("Failed invalid parser prog attach\n");
770		goto out_sockmap;
771	}
772
773	err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0);
774	if (!err) {
775		printf("Failed invalid verdict prog attach\n");
776		goto out_sockmap;
777	}
778
779	err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0);
780	if (!err) {
781		printf("Failed invalid msg verdict prog attach\n");
782		goto out_sockmap;
783	}
784
785	err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
786	if (!err) {
787		printf("Failed unknown prog attach\n");
788		goto out_sockmap;
789	}
790
791	err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
792	if (!err) {
793		printf("Failed empty parser prog detach\n");
794		goto out_sockmap;
795	}
796
797	err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
798	if (!err) {
799		printf("Failed empty verdict prog detach\n");
800		goto out_sockmap;
801	}
802
803	err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
804	if (!err) {
805		printf("Failed empty msg verdict prog detach\n");
806		goto out_sockmap;
807	}
808
809	err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
810	if (!err) {
811		printf("Detach invalid prog successful\n");
812		goto out_sockmap;
813	}
814
815	/* Load SK_SKB program and Attach */
816	err = bpf_prog_load(SOCKMAP_PARSE_PROG,
817			    BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
818	if (err) {
819		printf("Failed to load SK_SKB parse prog\n");
820		goto out_sockmap;
821	}
822
823	err = bpf_prog_load(SOCKMAP_TCP_MSG_PROG,
824			    BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog);
825	if (err) {
826		printf("Failed to load SK_SKB msg prog\n");
827		goto out_sockmap;
828	}
829
830	err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
831			    BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
832	if (err) {
833		printf("Failed to load SK_SKB verdict prog\n");
834		goto out_sockmap;
835	}
836
837	bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx");
838	if (IS_ERR(bpf_map_rx)) {
839		printf("Failed to load map rx from verdict prog\n");
840		goto out_sockmap;
841	}
842
843	map_fd_rx = bpf_map__fd(bpf_map_rx);
844	if (map_fd_rx < 0) {
845		printf("Failed to get map rx fd\n");
846		goto out_sockmap;
847	}
848
849	bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx");
850	if (IS_ERR(bpf_map_tx)) {
851		printf("Failed to load map tx from verdict prog\n");
852		goto out_sockmap;
853	}
854
855	map_fd_tx = bpf_map__fd(bpf_map_tx);
856	if (map_fd_tx < 0) {
857		printf("Failed to get map tx fd\n");
858		goto out_sockmap;
859	}
860
861	bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg");
862	if (IS_ERR(bpf_map_msg)) {
863		printf("Failed to load map msg from msg_verdict prog\n");
864		goto out_sockmap;
865	}
866
867	map_fd_msg = bpf_map__fd(bpf_map_msg);
868	if (map_fd_msg < 0) {
869		printf("Failed to get map msg fd\n");
870		goto out_sockmap;
871	}
872
873	bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
874	if (IS_ERR(bpf_map_break)) {
875		printf("Failed to load map tx from verdict prog\n");
876		goto out_sockmap;
877	}
878
879	map_fd_break = bpf_map__fd(bpf_map_break);
880	if (map_fd_break < 0) {
881		printf("Failed to get map tx fd\n");
882		goto out_sockmap;
883	}
884
885	err = bpf_prog_attach(parse_prog, map_fd_break,
886			      BPF_SK_SKB_STREAM_PARSER, 0);
887	if (!err) {
888		printf("Allowed attaching SK_SKB program to invalid map\n");
889		goto out_sockmap;
890	}
891
892	err = bpf_prog_attach(parse_prog, map_fd_rx,
893		      BPF_SK_SKB_STREAM_PARSER, 0);
894	if (err) {
895		printf("Failed stream parser bpf prog attach\n");
896		goto out_sockmap;
897	}
898
899	err = bpf_prog_attach(verdict_prog, map_fd_rx,
900			      BPF_SK_SKB_STREAM_VERDICT, 0);
901	if (err) {
902		printf("Failed stream verdict bpf prog attach\n");
903		goto out_sockmap;
904	}
905
906	err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0);
907	if (err) {
908		printf("Failed msg verdict bpf prog attach\n");
909		goto out_sockmap;
910	}
911
912	err = bpf_prog_attach(verdict_prog, map_fd_rx,
913			      __MAX_BPF_ATTACH_TYPE, 0);
914	if (!err) {
915		printf("Attached unknown bpf prog\n");
916		goto out_sockmap;
917	}
918
919	/* Test map update elem afterwards fd lives in fd and map_fd */
920	for (i = 2; i < 6; i++) {
921		err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
922		if (err) {
923			printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
924			       err, i, sfd[i]);
925			goto out_sockmap;
926		}
927		err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY);
928		if (err) {
929			printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
930			       err, i, sfd[i]);
931			goto out_sockmap;
932		}
933	}
934
935	/* Test map delete elem and remove send/recv sockets */
936	for (i = 2; i < 4; i++) {
937		err = bpf_map_delete_elem(map_fd_rx, &i);
938		if (err) {
939			printf("Failed delete sockmap rx %i '%i:%i'\n",
940			       err, i, sfd[i]);
941			goto out_sockmap;
942		}
943		err = bpf_map_delete_elem(map_fd_tx, &i);
944		if (err) {
945			printf("Failed delete sockmap tx %i '%i:%i'\n",
946			       err, i, sfd[i]);
947			goto out_sockmap;
948		}
949	}
950
951	/* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */
952	i = 0;
953	err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY);
954	if (err) {
955		printf("Failed map_fd_msg update sockmap %i\n", err);
956		goto out_sockmap;
957	}
958
959	/* Test map send/recv */
960	for (i = 0; i < 2; i++) {
961		buf[0] = i;
962		buf[1] = 0x5;
963		sc = send(sfd[2], buf, 20, 0);
964		if (sc < 0) {
965			printf("Failed sockmap send\n");
966			goto out_sockmap;
967		}
968
969		FD_ZERO(&w);
970		FD_SET(sfd[3], &w);
971		to.tv_sec = 30;
972		to.tv_usec = 0;
973		s = select(sfd[3] + 1, &w, NULL, NULL, &to);
974		if (s == -1) {
975			perror("Failed sockmap select()");
976			goto out_sockmap;
977		} else if (!s) {
978			printf("Failed sockmap unexpected timeout\n");
979			goto out_sockmap;
980		}
981
982		if (!FD_ISSET(sfd[3], &w)) {
983			printf("Failed sockmap select/recv\n");
984			goto out_sockmap;
985		}
986
987		rc = recv(sfd[3], buf, sizeof(buf), 0);
988		if (rc < 0) {
989			printf("Failed sockmap recv\n");
990			goto out_sockmap;
991		}
992	}
993
994	/* Negative null entry lookup from datapath should be dropped */
995	buf[0] = 1;
996	buf[1] = 12;
997	sc = send(sfd[2], buf, 20, 0);
998	if (sc < 0) {
999		printf("Failed sockmap send\n");
1000		goto out_sockmap;
1001	}
1002
1003	/* Push fd into same slot */
1004	i = 2;
1005	err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
1006	if (!err) {
1007		printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
1008		goto out_sockmap;
1009	}
1010
1011	err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
1012	if (err) {
1013		printf("Failed sockmap update new slot BPF_ANY\n");
1014		goto out_sockmap;
1015	}
1016
1017	err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
1018	if (err) {
1019		printf("Failed sockmap update new slot BPF_EXIST\n");
1020		goto out_sockmap;
1021	}
1022
1023	/* Delete the elems without programs */
1024	for (i = 2; i < 6; i++) {
1025		err = bpf_map_delete_elem(fd, &i);
1026		if (err) {
1027			printf("Failed delete sockmap %i '%i:%i'\n",
1028			       err, i, sfd[i]);
1029		}
1030	}
1031
1032	/* Test having multiple maps open and set with programs on same fds */
1033	err = bpf_prog_attach(parse_prog, fd,
1034			      BPF_SK_SKB_STREAM_PARSER, 0);
1035	if (err) {
1036		printf("Failed fd bpf parse prog attach\n");
1037		goto out_sockmap;
1038	}
1039	err = bpf_prog_attach(verdict_prog, fd,
1040			      BPF_SK_SKB_STREAM_VERDICT, 0);
1041	if (err) {
1042		printf("Failed fd bpf verdict prog attach\n");
1043		goto out_sockmap;
1044	}
1045
1046	for (i = 4; i < 6; i++) {
1047		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
1048		if (!err) {
1049			printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
1050			       err, i, sfd[i]);
1051			goto out_sockmap;
1052		}
1053		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
1054		if (!err) {
1055			printf("Failed allowed duplicate program in update NOEXIST sockmap  %i '%i:%i'\n",
1056			       err, i, sfd[i]);
1057			goto out_sockmap;
1058		}
1059		err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
1060		if (!err) {
1061			printf("Failed allowed duplicate program in update EXIST sockmap  %i '%i:%i'\n",
1062			       err, i, sfd[i]);
1063			goto out_sockmap;
1064		}
1065	}
1066
1067	/* Test tasks number of forked operations */
1068	for (i = 0; i < tasks; i++) {
1069		pid[i] = fork();
1070		if (pid[i] == 0) {
1071			for (i = 0; i < 6; i++) {
1072				bpf_map_delete_elem(map_fd_tx, &i);
1073				bpf_map_delete_elem(map_fd_rx, &i);
1074				bpf_map_update_elem(map_fd_tx, &i,
1075						    &sfd[i], BPF_ANY);
1076				bpf_map_update_elem(map_fd_rx, &i,
1077						    &sfd[i], BPF_ANY);
1078			}
1079			exit(0);
1080		} else if (pid[i] == -1) {
1081			printf("Couldn't spawn #%d process!\n", i);
1082			exit(1);
1083		}
1084	}
1085
1086	for (i = 0; i < tasks; i++) {
1087		int status;
1088
1089		assert(waitpid(pid[i], &status, 0) == pid[i]);
1090		assert(status == 0);
1091	}
1092
1093	err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE);
1094	if (!err) {
1095		printf("Detached an invalid prog type.\n");
1096		goto out_sockmap;
1097	}
1098
1099	err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
1100	if (err) {
1101		printf("Failed parser prog detach\n");
1102		goto out_sockmap;
1103	}
1104
1105	err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
1106	if (err) {
1107		printf("Failed parser prog detach\n");
1108		goto out_sockmap;
1109	}
1110
1111	/* Test map close sockets and empty maps */
1112	for (i = 0; i < 6; i++) {
1113		bpf_map_delete_elem(map_fd_tx, &i);
1114		bpf_map_delete_elem(map_fd_rx, &i);
1115		close(sfd[i]);
1116	}
1117	close(fd);
1118	close(map_fd_rx);
1119	bpf_object__close(obj);
1120	return;
1121out:
1122	for (i = 0; i < 6; i++)
1123		close(sfd[i]);
1124	printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno));
1125	exit(1);
1126out_sockmap:
1127	for (i = 0; i < 6; i++) {
1128		if (map_fd_tx)
1129			bpf_map_delete_elem(map_fd_tx, &i);
1130		if (map_fd_rx)
1131			bpf_map_delete_elem(map_fd_rx, &i);
1132		close(sfd[i]);
1133	}
1134	close(fd);
1135	exit(1);
1136}
1137
1138#define MAPINMAP_PROG "./test_map_in_map.o"
1139static void test_map_in_map(void)
1140{
1141	struct bpf_object *obj;
1142	struct bpf_map *map;
1143	int mim_fd, fd, err;
1144	int pos = 0;
1145
1146	obj = bpf_object__open(MAPINMAP_PROG);
1147
1148	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int), sizeof(int),
1149			    2, 0);
1150	if (fd < 0) {
1151		printf("Failed to create hashmap '%s'!\n", strerror(errno));
1152		exit(1);
1153	}
1154
1155	map = bpf_object__find_map_by_name(obj, "mim_array");
1156	if (IS_ERR(map)) {
1157		printf("Failed to load array of maps from test prog\n");
1158		goto out_map_in_map;
1159	}
1160	err = bpf_map__set_inner_map_fd(map, fd);
1161	if (err) {
1162		printf("Failed to set inner_map_fd for array of maps\n");
1163		goto out_map_in_map;
1164	}
1165
1166	map = bpf_object__find_map_by_name(obj, "mim_hash");
1167	if (IS_ERR(map)) {
1168		printf("Failed to load hash of maps from test prog\n");
1169		goto out_map_in_map;
1170	}
1171	err = bpf_map__set_inner_map_fd(map, fd);
1172	if (err) {
1173		printf("Failed to set inner_map_fd for hash of maps\n");
1174		goto out_map_in_map;
1175	}
1176
1177	bpf_object__load(obj);
1178
1179	map = bpf_object__find_map_by_name(obj, "mim_array");
1180	if (IS_ERR(map)) {
1181		printf("Failed to load array of maps from test prog\n");
1182		goto out_map_in_map;
1183	}
1184	mim_fd = bpf_map__fd(map);
1185	if (mim_fd < 0) {
1186		printf("Failed to get descriptor for array of maps\n");
1187		goto out_map_in_map;
1188	}
1189
1190	err = bpf_map_update_elem(mim_fd, &pos, &fd, 0);
1191	if (err) {
1192		printf("Failed to update array of maps\n");
1193		goto out_map_in_map;
1194	}
1195
1196	map = bpf_object__find_map_by_name(obj, "mim_hash");
1197	if (IS_ERR(map)) {
1198		printf("Failed to load hash of maps from test prog\n");
1199		goto out_map_in_map;
1200	}
1201	mim_fd = bpf_map__fd(map);
1202	if (mim_fd < 0) {
1203		printf("Failed to get descriptor for hash of maps\n");
1204		goto out_map_in_map;
1205	}
1206
1207	err = bpf_map_update_elem(mim_fd, &pos, &fd, 0);
1208	if (err) {
1209		printf("Failed to update hash of maps\n");
1210		goto out_map_in_map;
1211	}
1212
1213	close(fd);
1214	bpf_object__close(obj);
1215	return;
1216
1217out_map_in_map:
1218	close(fd);
1219	exit(1);
1220}
1221
1222#define MAP_SIZE (32 * 1024)
1223
1224static void test_map_large(void)
1225{
1226	struct bigkey {
1227		int a;
1228		char b[116];
1229		long long c;
1230	} key;
1231	int fd, i, value;
1232
1233	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1234			    MAP_SIZE, map_flags);
1235	if (fd < 0) {
1236		printf("Failed to create large map '%s'!\n", strerror(errno));
1237		exit(1);
1238	}
1239
1240	for (i = 0; i < MAP_SIZE; i++) {
1241		key = (struct bigkey) { .c = i };
1242		value = i;
1243
1244		assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
1245	}
1246
1247	key.c = -1;
1248	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
1249	       errno == E2BIG);
1250
1251	/* Iterate through all elements. */
1252	assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
1253	key.c = -1;
1254	for (i = 0; i < MAP_SIZE; i++)
1255		assert(bpf_map_get_next_key(fd, &key, &key) == 0);
1256	assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
1257
1258	key.c = 0;
1259	assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
1260	key.a = 1;
1261	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
1262
1263	close(fd);
1264}
1265
1266#define run_parallel(N, FN, DATA) \
1267	printf("Fork %u tasks to '" #FN "'\n", N); \
1268	__run_parallel(N, FN, DATA)
1269
1270static void __run_parallel(unsigned int tasks,
1271			   void (*fn)(unsigned int task, void *data),
1272			   void *data)
1273{
1274	pid_t pid[tasks];
1275	int i;
1276
1277	fflush(stdout);
1278
1279	for (i = 0; i < tasks; i++) {
1280		pid[i] = fork();
1281		if (pid[i] == 0) {
1282			fn(i, data);
1283			exit(0);
1284		} else if (pid[i] == -1) {
1285			printf("Couldn't spawn #%d process!\n", i);
1286			exit(1);
1287		}
1288	}
1289
1290	for (i = 0; i < tasks; i++) {
1291		int status;
1292
1293		assert(waitpid(pid[i], &status, 0) == pid[i]);
1294		assert(status == 0);
1295	}
1296}
1297
1298static void test_map_stress(void)
1299{
1300	run_parallel(100, test_hashmap, NULL);
1301	run_parallel(100, test_hashmap_percpu, NULL);
1302	run_parallel(100, test_hashmap_sizes, NULL);
1303	run_parallel(100, test_hashmap_walk, NULL);
1304
1305	run_parallel(100, test_arraymap, NULL);
1306	run_parallel(100, test_arraymap_percpu, NULL);
1307}
1308
1309#define TASKS 1024
1310
1311#define DO_UPDATE 1
1312#define DO_DELETE 0
1313
1314static void test_update_delete(unsigned int fn, void *data)
1315{
1316	int do_update = ((int *)data)[1];
1317	int fd = ((int *)data)[0];
1318	int i, key, value;
1319
1320	for (i = fn; i < MAP_SIZE; i += TASKS) {
1321		key = value = i;
1322
1323		if (do_update) {
1324			assert(bpf_map_update_elem(fd, &key, &value,
1325						   BPF_NOEXIST) == 0);
1326			assert(bpf_map_update_elem(fd, &key, &value,
1327						   BPF_EXIST) == 0);
1328		} else {
1329			assert(bpf_map_delete_elem(fd, &key) == 0);
1330		}
1331	}
1332}
1333
1334static void test_map_parallel(void)
1335{
1336	int i, fd, key = 0, value = 0;
1337	int data[2];
1338
1339	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1340			    MAP_SIZE, map_flags);
1341	if (fd < 0) {
1342		printf("Failed to create map for parallel test '%s'!\n",
1343		       strerror(errno));
1344		exit(1);
1345	}
1346
1347	/* Use the same fd in children to add elements to this map:
1348	 * child_0 adds key=0, key=1024, key=2048, ...
1349	 * child_1 adds key=1, key=1025, key=2049, ...
1350	 * child_1023 adds key=1023, ...
1351	 */
1352	data[0] = fd;
1353	data[1] = DO_UPDATE;
1354	run_parallel(TASKS, test_update_delete, data);
1355
1356	/* Check that key=0 is already there. */
1357	assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
1358	       errno == EEXIST);
1359
1360	/* Check that all elements were inserted. */
1361	assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
1362	key = -1;
1363	for (i = 0; i < MAP_SIZE; i++)
1364		assert(bpf_map_get_next_key(fd, &key, &key) == 0);
1365	assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
1366
1367	/* Another check for all elements */
1368	for (i = 0; i < MAP_SIZE; i++) {
1369		key = MAP_SIZE - i - 1;
1370
1371		assert(bpf_map_lookup_elem(fd, &key, &value) == 0 &&
1372		       value == key);
1373	}
1374
1375	/* Now let's delete all elemenets in parallel. */
1376	data[1] = DO_DELETE;
1377	run_parallel(TASKS, test_update_delete, data);
1378
1379	/* Nothing should be left. */
1380	key = -1;
1381	assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT);
1382	assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
1383}
1384
1385static void test_map_rdonly(void)
1386{
1387	int fd, key = 0, value = 0;
1388
1389	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1390			    MAP_SIZE, map_flags | BPF_F_RDONLY);
1391	if (fd < 0) {
1392		printf("Failed to create map for read only test '%s'!\n",
1393		       strerror(errno));
1394		exit(1);
1395	}
1396
1397	key = 1;
1398	value = 1234;
1399	/* Try to insert key=1 element. */
1400	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 &&
1401	       errno == EPERM);
1402
1403	/* Check that key=1 is not found. */
1404	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
1405	assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT);
1406
1407	close(fd);
1408}
1409
1410static void test_map_wronly_hash(void)
1411{
1412	int fd, key = 0, value = 0;
1413
1414	fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1415			    MAP_SIZE, map_flags | BPF_F_WRONLY);
1416	if (fd < 0) {
1417		printf("Failed to create map for write only test '%s'!\n",
1418		       strerror(errno));
1419		exit(1);
1420	}
1421
1422	key = 1;
1423	value = 1234;
1424	/* Insert key=1 element. */
1425	assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
1426
1427	/* Check that reading elements and keys from the map is not allowed. */
1428	assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM);
1429	assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM);
1430
1431	close(fd);
1432}
1433
1434static void test_map_wronly_stack_or_queue(enum bpf_map_type map_type)
1435{
1436	int fd, value = 0;
1437
1438	assert(map_type == BPF_MAP_TYPE_QUEUE ||
1439	       map_type == BPF_MAP_TYPE_STACK);
1440	fd = bpf_create_map(map_type, 0, sizeof(value), MAP_SIZE,
1441			    map_flags | BPF_F_WRONLY);
1442	/* Stack/Queue maps do not support BPF_F_NO_PREALLOC */
1443	if (map_flags & BPF_F_NO_PREALLOC) {
1444		assert(fd < 0 && errno == EINVAL);
1445		return;
1446	}
1447	if (fd < 0) {
1448		printf("Failed to create map '%s'!\n", strerror(errno));
1449		exit(1);
1450	}
1451
1452	value = 1234;
1453	assert(bpf_map_update_elem(fd, NULL, &value, BPF_ANY) == 0);
1454
1455	/* Peek element should fail */
1456	assert(bpf_map_lookup_elem(fd, NULL, &value) == -1 && errno == EPERM);
1457
1458	/* Pop element should fail */
1459	assert(bpf_map_lookup_and_delete_elem(fd, NULL, &value) == -1 &&
1460	       errno == EPERM);
1461
1462	close(fd);
1463}
1464
1465static void test_map_wronly(void)
1466{
1467	test_map_wronly_hash();
1468	test_map_wronly_stack_or_queue(BPF_MAP_TYPE_STACK);
1469	test_map_wronly_stack_or_queue(BPF_MAP_TYPE_QUEUE);
1470}
1471
1472static void prepare_reuseport_grp(int type, int map_fd, size_t map_elem_size,
1473				  __s64 *fds64, __u64 *sk_cookies,
1474				  unsigned int n)
1475{
1476	socklen_t optlen, addrlen;
1477	struct sockaddr_in6 s6;
1478	const __u32 index0 = 0;
1479	const int optval = 1;
1480	unsigned int i;
1481	u64 sk_cookie;
1482	void *value;
1483	__s32 fd32;
1484	__s64 fd64;
1485	int err;
1486
1487	s6.sin6_family = AF_INET6;
1488	s6.sin6_addr = in6addr_any;
1489	s6.sin6_port = 0;
1490	addrlen = sizeof(s6);
1491	optlen = sizeof(sk_cookie);
1492
1493	for (i = 0; i < n; i++) {
1494		fd64 = socket(AF_INET6, type, 0);
1495		CHECK(fd64 == -1, "socket()",
1496		      "sock_type:%d fd64:%lld errno:%d\n",
1497		      type, fd64, errno);
1498
1499		err = setsockopt(fd64, SOL_SOCKET, SO_REUSEPORT,
1500				 &optval, sizeof(optval));
1501		CHECK(err == -1, "setsockopt(SO_REUSEPORT)",
1502		      "err:%d errno:%d\n", err, errno);
1503
1504		/* reuseport_array does not allow unbound sk */
1505		if (map_elem_size == sizeof(__u64))
1506			value = &fd64;
1507		else {
1508			assert(map_elem_size == sizeof(__u32));
1509			fd32 = (__s32)fd64;
1510			value = &fd32;
1511		}
1512		err = bpf_map_update_elem(map_fd, &index0, value, BPF_ANY);
1513		CHECK(err != -1 || errno != EINVAL,
1514		      "reuseport array update unbound sk",
1515		      "sock_type:%d err:%d errno:%d\n",
1516		      type, err, errno);
1517
1518		err = bind(fd64, (struct sockaddr *)&s6, sizeof(s6));
1519		CHECK(err == -1, "bind()",
1520		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
1521
1522		if (i == 0) {
1523			err = getsockname(fd64, (struct sockaddr *)&s6,
1524					  &addrlen);
1525			CHECK(err == -1, "getsockname()",
1526			      "sock_type:%d err:%d errno:%d\n",
1527			      type, err, errno);
1528		}
1529
1530		err = getsockopt(fd64, SOL_SOCKET, SO_COOKIE, &sk_cookie,
1531				 &optlen);
1532		CHECK(err == -1, "getsockopt(SO_COOKIE)",
1533		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
1534
1535		if (type == SOCK_STREAM) {
1536			/*
1537			 * reuseport_array does not allow
1538			 * non-listening tcp sk.
1539			 */
1540			err = bpf_map_update_elem(map_fd, &index0, value,
1541						  BPF_ANY);
1542			CHECK(err != -1 || errno != EINVAL,
1543			      "reuseport array update non-listening sk",
1544			      "sock_type:%d err:%d errno:%d\n",
1545			      type, err, errno);
1546			err = listen(fd64, 0);
1547			CHECK(err == -1, "listen()",
1548			      "sock_type:%d, err:%d errno:%d\n",
1549			      type, err, errno);
1550		}
1551
1552		fds64[i] = fd64;
1553		sk_cookies[i] = sk_cookie;
1554	}
1555}
1556
1557static void test_reuseport_array(void)
1558{
1559#define REUSEPORT_FD_IDX(err, last) ({ (err) ? last : !last; })
1560
1561	const __u32 array_size = 4, index0 = 0, index3 = 3;
1562	int types[2] = { SOCK_STREAM, SOCK_DGRAM }, type;
1563	__u64 grpa_cookies[2], sk_cookie, map_cookie;
1564	__s64 grpa_fds64[2] = { -1, -1 }, fd64 = -1;
1565	const __u32 bad_index = array_size;
1566	int map_fd, err, t, f;
1567	__u32 fds_idx = 0;
1568	int fd;
1569
1570	map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
1571				sizeof(__u32), sizeof(__u64), array_size, 0);
1572	CHECK(map_fd == -1, "reuseport array create",
1573	      "map_fd:%d, errno:%d\n", map_fd, errno);
1574
1575	/* Test lookup/update/delete with invalid index */
1576	err = bpf_map_delete_elem(map_fd, &bad_index);
1577	CHECK(err != -1 || errno != E2BIG, "reuseport array del >=max_entries",
1578	      "err:%d errno:%d\n", err, errno);
1579
1580	err = bpf_map_update_elem(map_fd, &bad_index, &fd64, BPF_ANY);
1581	CHECK(err != -1 || errno != E2BIG,
1582	      "reuseport array update >=max_entries",
1583	      "err:%d errno:%d\n", err, errno);
1584
1585	err = bpf_map_lookup_elem(map_fd, &bad_index, &map_cookie);
1586	CHECK(err != -1 || errno != ENOENT,
1587	      "reuseport array update >=max_entries",
1588	      "err:%d errno:%d\n", err, errno);
1589
1590	/* Test lookup/delete non existence elem */
1591	err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
1592	CHECK(err != -1 || errno != ENOENT,
1593	      "reuseport array lookup not-exist elem",
1594	      "err:%d errno:%d\n", err, errno);
1595	err = bpf_map_delete_elem(map_fd, &index3);
1596	CHECK(err != -1 || errno != ENOENT,
1597	      "reuseport array del not-exist elem",
1598	      "err:%d errno:%d\n", err, errno);
1599
1600	for (t = 0; t < ARRAY_SIZE(types); t++) {
1601		type = types[t];
1602
1603		prepare_reuseport_grp(type, map_fd, sizeof(__u64), grpa_fds64,
1604				      grpa_cookies, ARRAY_SIZE(grpa_fds64));
1605
1606		/* Test BPF_* update flags */
1607		/* BPF_EXIST failure case */
1608		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
1609					  BPF_EXIST);
1610		CHECK(err != -1 || errno != ENOENT,
1611		      "reuseport array update empty elem BPF_EXIST",
1612		      "sock_type:%d err:%d errno:%d\n",
1613		      type, err, errno);
1614		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
1615
1616		/* BPF_NOEXIST success case */
1617		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
1618					  BPF_NOEXIST);
1619		CHECK(err == -1,
1620		      "reuseport array update empty elem BPF_NOEXIST",
1621		      "sock_type:%d err:%d errno:%d\n",
1622		      type, err, errno);
1623		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
1624
1625		/* BPF_EXIST success case. */
1626		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
1627					  BPF_EXIST);
1628		CHECK(err == -1,
1629		      "reuseport array update same elem BPF_EXIST",
1630		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
1631		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
1632
1633		/* BPF_NOEXIST failure case */
1634		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
1635					  BPF_NOEXIST);
1636		CHECK(err != -1 || errno != EEXIST,
1637		      "reuseport array update non-empty elem BPF_NOEXIST",
1638		      "sock_type:%d err:%d errno:%d\n",
1639		      type, err, errno);
1640		fds_idx = REUSEPORT_FD_IDX(err, fds_idx);
1641
1642		/* BPF_ANY case (always succeed) */
1643		err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx],
1644					  BPF_ANY);
1645		CHECK(err == -1,
1646		      "reuseport array update same sk with BPF_ANY",
1647		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
1648
1649		fd64 = grpa_fds64[fds_idx];
1650		sk_cookie = grpa_cookies[fds_idx];
1651
1652		/* The same sk cannot be added to reuseport_array twice */
1653		err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_ANY);
1654		CHECK(err != -1 || errno != EBUSY,
1655		      "reuseport array update same sk with same index",
1656		      "sock_type:%d err:%d errno:%d\n",
1657		      type, err, errno);
1658
1659		err = bpf_map_update_elem(map_fd, &index0, &fd64, BPF_ANY);
1660		CHECK(err != -1 || errno != EBUSY,
1661		      "reuseport array update same sk with different index",
1662		      "sock_type:%d err:%d errno:%d\n",
1663		      type, err, errno);
1664
1665		/* Test delete elem */
1666		err = bpf_map_delete_elem(map_fd, &index3);
1667		CHECK(err == -1, "reuseport array delete sk",
1668		      "sock_type:%d err:%d errno:%d\n",
1669		      type, err, errno);
1670
1671		/* Add it back with BPF_NOEXIST */
1672		err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST);
1673		CHECK(err == -1,
1674		      "reuseport array re-add with BPF_NOEXIST after del",
1675		      "sock_type:%d err:%d errno:%d\n", type, err, errno);
1676
1677		/* Test cookie */
1678		err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
1679		CHECK(err == -1 || sk_cookie != map_cookie,
1680		      "reuseport array lookup re-added sk",
1681		      "sock_type:%d err:%d errno:%d sk_cookie:0x%llx map_cookie:0x%llxn",
1682		      type, err, errno, sk_cookie, map_cookie);
1683
1684		/* Test elem removed by close() */
1685		for (f = 0; f < ARRAY_SIZE(grpa_fds64); f++)
1686			close(grpa_fds64[f]);
1687		err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
1688		CHECK(err != -1 || errno != ENOENT,
1689		      "reuseport array lookup after close()",
1690		      "sock_type:%d err:%d errno:%d\n",
1691		      type, err, errno);
1692	}
1693
1694	/* Test SOCK_RAW */
1695	fd64 = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP);
1696	CHECK(fd64 == -1, "socket(SOCK_RAW)", "err:%d errno:%d\n",
1697	      err, errno);
1698	err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST);
1699	CHECK(err != -1 || errno != ENOTSUPP, "reuseport array update SOCK_RAW",
1700	      "err:%d errno:%d\n", err, errno);
1701	close(fd64);
1702
1703	/* Close the 64 bit value map */
1704	close(map_fd);
1705
1706	/* Test 32 bit fd */
1707	map_fd = bpf_create_map(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
1708				sizeof(__u32), sizeof(__u32), array_size, 0);
1709	CHECK(map_fd == -1, "reuseport array create",
1710	      "map_fd:%d, errno:%d\n", map_fd, errno);
1711	prepare_reuseport_grp(SOCK_STREAM, map_fd, sizeof(__u32), &fd64,
1712			      &sk_cookie, 1);
1713	fd = fd64;
1714	err = bpf_map_update_elem(map_fd, &index3, &fd, BPF_NOEXIST);
1715	CHECK(err == -1, "reuseport array update 32 bit fd",
1716	      "err:%d errno:%d\n", err, errno);
1717	err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie);
1718	CHECK(err != -1 || errno != ENOSPC,
1719	      "reuseport array lookup 32 bit fd",
1720	      "err:%d errno:%d\n", err, errno);
1721	close(fd);
1722	close(map_fd);
1723}
1724
1725static void run_all_tests(void)
1726{
1727	test_hashmap(0, NULL);
1728	test_hashmap_percpu(0, NULL);
1729	test_hashmap_walk(0, NULL);
1730	test_hashmap_zero_seed();
1731
1732	test_arraymap(0, NULL);
1733	test_arraymap_percpu(0, NULL);
1734
1735	test_arraymap_percpu_many_keys();
1736
1737	test_devmap(0, NULL);
1738	test_devmap_hash(0, NULL);
1739	test_sockmap(0, NULL);
1740
1741	test_map_large();
1742	test_map_parallel();
1743	test_map_stress();
1744
1745	test_map_rdonly();
1746	test_map_wronly();
1747
1748	test_reuseport_array();
1749
1750	test_queuemap(0, NULL);
1751	test_stackmap(0, NULL);
1752
1753	test_map_in_map();
1754}
1755
1756#define DEFINE_TEST(name) extern void test_##name(void);
1757#include <map_tests/tests.h>
1758#undef DEFINE_TEST
1759
1760int main(void)
1761{
1762	srand(time(NULL));
1763
1764	map_flags = 0;
1765	run_all_tests();
1766
1767	map_flags = BPF_F_NO_PREALLOC;
1768	run_all_tests();
1769
1770#define DEFINE_TEST(name) test_##name();
1771#include <map_tests/tests.h>
1772#undef DEFINE_TEST
1773
1774	printf("test_maps: OK, %d SKIPPED\n", skips);
1775	return 0;
1776}
1777