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