hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/tools/testing/selftests/bpf/test_maps.c
....@@ -1,12 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Testsuite for eBPF maps
34 *
45 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
56 * Copyright (c) 2016 Facebook
6
- *
7
- * This program is free software; you can redistribute it and/or
8
- * modify it under the terms of version 2 of the GNU General Public
9
- * License as published by the Free Software Foundation.
107 */
118
129 #include <stdio.h>
....@@ -15,6 +12,7 @@
1512 #include <string.h>
1613 #include <assert.h>
1714 #include <stdlib.h>
15
+#include <time.h>
1816
1917 #include <sys/wait.h>
2018 #include <sys/socket.h>
....@@ -26,23 +24,17 @@
2624
2725 #include "bpf_util.h"
2826 #include "bpf_rlimit.h"
27
+#include "test_maps.h"
2928
3029 #ifndef ENOTSUPP
3130 #define ENOTSUPP 524
3231 #endif
3332
33
+static int skips;
34
+
3435 static int map_flags;
3536
36
-#define CHECK(condition, tag, format...) ({ \
37
- int __ret = !!(condition); \
38
- if (__ret) { \
39
- printf("%s(%d):FAIL:%s ", __func__, __LINE__, tag); \
40
- printf(format); \
41
- exit(-1); \
42
- } \
43
-})
44
-
45
-static void test_hashmap(int task, void *data)
37
+static void test_hashmap(unsigned int task, void *data)
4638 {
4739 long long key, next_key, first_key, value;
4840 int fd;
....@@ -132,7 +124,7 @@
132124 close(fd);
133125 }
134126
135
-static void test_hashmap_sizes(int task, void *data)
127
+static void test_hashmap_sizes(unsigned int task, void *data)
136128 {
137129 int fd, i, j;
138130
....@@ -152,7 +144,7 @@
152144 }
153145 }
154146
155
-static void test_hashmap_percpu(int task, void *data)
147
+static void test_hashmap_percpu(unsigned int task, void *data)
156148 {
157149 unsigned int nr_cpus = bpf_num_possible_cpus();
158150 BPF_DECLARE_PERCPU(long, value);
....@@ -257,23 +249,35 @@
257249 close(fd);
258250 }
259251
260
-static void test_hashmap_walk(int task, void *data)
252
+static 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
+
274
+static void test_hashmap_walk(unsigned int task, void *data)
261275 {
262276 int fd, i, max_entries = 1000;
263277 long long key, value, next_key;
264278 bool next_key_valid = true;
265279
266
- fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
267
- max_entries, map_flags);
268
- if (fd < 0) {
269
- printf("Failed to create hashmap '%s'!\n", strerror(errno));
270
- exit(1);
271
- }
272
-
273
- for (i = 0; i < max_entries; i++) {
274
- key = i; value = key;
275
- assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
276
- }
280
+ fd = helper_fill_hashmap(max_entries);
277281
278282 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
279283 &next_key) == 0; i++) {
....@@ -305,7 +309,40 @@
305309 close(fd);
306310 }
307311
308
-static void test_arraymap(int task, void *data)
312
+static 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
+
345
+static void test_arraymap(unsigned int task, void *data)
309346 {
310347 int key, next_key, fd;
311348 long long value;
....@@ -360,7 +397,7 @@
360397 close(fd);
361398 }
362399
363
-static void test_arraymap_percpu(int task, void *data)
400
+static void test_arraymap_percpu(unsigned int task, void *data)
364401 {
365402 unsigned int nr_cpus = bpf_num_possible_cpus();
366403 BPF_DECLARE_PERCPU(long, values);
....@@ -456,7 +493,7 @@
456493 close(fd);
457494 }
458495
459
-static void test_devmap(int task, void *data)
496
+static void test_devmap(unsigned int task, void *data)
460497 {
461498 int fd;
462499 __u32 key, value;
....@@ -464,14 +501,144 @@
464501 fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),
465502 2, 0);
466503 if (fd < 0) {
467
- printf("Failed to create arraymap '%s'!\n", strerror(errno));
504
+ printf("Failed to create devmap '%s'!\n", strerror(errno));
468505 exit(1);
469506 }
470507
471508 close(fd);
472509 }
473510
474
-#include <sys/socket.h>
511
+static 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
+
526
+static 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
+
584
+static 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
+
475642 #include <sys/ioctl.h>
476643 #include <arpa/inet.h>
477644 #include <sys/select.h>
....@@ -479,7 +646,7 @@
479646 #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
480647 #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
481648 #define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.o"
482
-static void test_sockmap(int tasks, void *data)
649
+static void test_sockmap(unsigned int tasks, void *data)
483650 {
484651 struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break;
485652 int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break;
....@@ -563,6 +730,15 @@
563730 sizeof(key), sizeof(value),
564731 6, 0);
565732 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
+
566742 printf("Failed to create sockmap %i\n", fd);
567743 goto out_sockmap;
568744 }
....@@ -580,11 +756,7 @@
580756 /* Test update without programs */
581757 for (i = 0; i < 6; i++) {
582758 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
583
- if (i < 2 && !err) {
584
- printf("Allowed update sockmap '%i:%i' not in ESTABLISHED\n",
585
- i, sfd[i]);
586
- goto out_sockmap;
587
- } else if (i >= 2 && err) {
759
+ if (err) {
588760 printf("Failed noprog update sockmap '%i:%i'\n",
589761 i, sfd[i]);
590762 goto out_sockmap;
....@@ -617,19 +789,19 @@
617789 }
618790
619791 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
620
- if (err) {
792
+ if (!err) {
621793 printf("Failed empty parser prog detach\n");
622794 goto out_sockmap;
623795 }
624796
625797 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
626
- if (err) {
798
+ if (!err) {
627799 printf("Failed empty verdict prog detach\n");
628800 goto out_sockmap;
629801 }
630802
631803 err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
632
- if (err) {
804
+ if (!err) {
633805 printf("Failed empty msg verdict prog detach\n");
634806 goto out_sockmap;
635807 }
....@@ -918,19 +1090,19 @@
9181090 assert(status == 0);
9191091 }
9201092
921
- err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
1093
+ err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE);
9221094 if (!err) {
9231095 printf("Detached an invalid prog type.\n");
9241096 goto out_sockmap;
9251097 }
9261098
927
- err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
1099
+ err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
9281100 if (err) {
9291101 printf("Failed parser prog detach\n");
9301102 goto out_sockmap;
9311103 }
9321104
933
- err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
1105
+ err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
9341106 if (err) {
9351107 printf("Failed parser prog detach\n");
9361108 goto out_sockmap;
....@@ -959,6 +1131,90 @@
9591131 bpf_map_delete_elem(map_fd_rx, &i);
9601132 close(sfd[i]);
9611133 }
1134
+ close(fd);
1135
+ exit(1);
1136
+}
1137
+
1138
+#define MAPINMAP_PROG "./test_map_in_map.o"
1139
+static 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
+
1217
+out_map_in_map:
9621218 close(fd);
9631219 exit(1);
9641220 }
....@@ -1008,10 +1264,11 @@
10081264 }
10091265
10101266 #define run_parallel(N, FN, DATA) \
1011
- printf("Fork %d tasks to '" #FN "'\n", N); \
1267
+ printf("Fork %u tasks to '" #FN "'\n", N); \
10121268 __run_parallel(N, FN, DATA)
10131269
1014
-static void __run_parallel(int tasks, void (*fn)(int task, void *data),
1270
+static void __run_parallel(unsigned int tasks,
1271
+ void (*fn)(unsigned int task, void *data),
10151272 void *data)
10161273 {
10171274 pid_t pid[tasks];
....@@ -1054,7 +1311,7 @@
10541311 #define DO_UPDATE 1
10551312 #define DO_DELETE 0
10561313
1057
-static void test_update_delete(int fn, void *data)
1314
+static void test_update_delete(unsigned int fn, void *data)
10581315 {
10591316 int do_update = ((int *)data)[1];
10601317 int fd = ((int *)data)[0];
....@@ -1139,23 +1396,25 @@
11391396
11401397 key = 1;
11411398 value = 1234;
1142
- /* Insert key=1 element. */
1399
+ /* Try to insert key=1 element. */
11431400 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 &&
11441401 errno == EPERM);
11451402
1146
- /* Check that key=2 is not found. */
1403
+ /* Check that key=1 is not found. */
11471404 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
11481405 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT);
1406
+
1407
+ close(fd);
11491408 }
11501409
1151
-static void test_map_wronly(void)
1410
+static void test_map_wronly_hash(void)
11521411 {
11531412 int fd, key = 0, value = 0;
11541413
11551414 fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
11561415 MAP_SIZE, map_flags | BPF_F_WRONLY);
11571416 if (fd < 0) {
1158
- printf("Failed to create map for read only test '%s'!\n",
1417
+ printf("Failed to create map for write only test '%s'!\n",
11591418 strerror(errno));
11601419 exit(1);
11611420 }
....@@ -1165,12 +1424,52 @@
11651424 /* Insert key=1 element. */
11661425 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
11671426
1168
- /* Check that key=2 is not found. */
1427
+ /* Check that reading elements and keys from the map is not allowed. */
11691428 assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM);
11701429 assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM);
1430
+
1431
+ close(fd);
11711432 }
11721433
1173
-static void prepare_reuseport_grp(int type, int map_fd,
1434
+static 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
+
1465
+static 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
+
1472
+static void prepare_reuseport_grp(int type, int map_fd, size_t map_elem_size,
11741473 __s64 *fds64, __u64 *sk_cookies,
11751474 unsigned int n)
11761475 {
....@@ -1180,6 +1479,8 @@
11801479 const int optval = 1;
11811480 unsigned int i;
11821481 u64 sk_cookie;
1482
+ void *value;
1483
+ __s32 fd32;
11831484 __s64 fd64;
11841485 int err;
11851486
....@@ -1201,8 +1502,14 @@
12011502 "err:%d errno:%d\n", err, errno);
12021503
12031504 /* reuseport_array does not allow unbound sk */
1204
- err = bpf_map_update_elem(map_fd, &index0, &fd64,
1205
- BPF_ANY);
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);
12061513 CHECK(err != -1 || errno != EINVAL,
12071514 "reuseport array update unbound sk",
12081515 "sock_type:%d err:%d errno:%d\n",
....@@ -1230,7 +1537,7 @@
12301537 * reuseport_array does not allow
12311538 * non-listening tcp sk.
12321539 */
1233
- err = bpf_map_update_elem(map_fd, &index0, &fd64,
1540
+ err = bpf_map_update_elem(map_fd, &index0, value,
12341541 BPF_ANY);
12351542 CHECK(err != -1 || errno != EINVAL,
12361543 "reuseport array update non-listening sk",
....@@ -1293,7 +1600,7 @@
12931600 for (t = 0; t < ARRAY_SIZE(types); t++) {
12941601 type = types[t];
12951602
1296
- prepare_reuseport_grp(type, map_fd, grpa_fds64,
1603
+ prepare_reuseport_grp(type, map_fd, sizeof(__u64), grpa_fds64,
12971604 grpa_cookies, ARRAY_SIZE(grpa_fds64));
12981605
12991606 /* Test BPF_* update flags */
....@@ -1401,7 +1708,8 @@
14011708 sizeof(__u32), sizeof(__u32), array_size, 0);
14021709 CHECK(map_fd == -1, "reuseport array create",
14031710 "map_fd:%d, errno:%d\n", map_fd, errno);
1404
- prepare_reuseport_grp(SOCK_STREAM, map_fd, &fd64, &sk_cookie, 1);
1711
+ prepare_reuseport_grp(SOCK_STREAM, map_fd, sizeof(__u32), &fd64,
1712
+ &sk_cookie, 1);
14051713 fd = fd64;
14061714 err = bpf_map_update_elem(map_fd, &index3, &fd, BPF_NOEXIST);
14071715 CHECK(err == -1, "reuseport array update 32 bit fd",
....@@ -1419,6 +1727,7 @@
14191727 test_hashmap(0, NULL);
14201728 test_hashmap_percpu(0, NULL);
14211729 test_hashmap_walk(0, NULL);
1730
+ test_hashmap_zero_seed();
14221731
14231732 test_arraymap(0, NULL);
14241733 test_arraymap_percpu(0, NULL);
....@@ -1426,6 +1735,7 @@
14261735 test_arraymap_percpu_many_keys();
14271736
14281737 test_devmap(0, NULL);
1738
+ test_devmap_hash(0, NULL);
14291739 test_sockmap(0, NULL);
14301740
14311741 test_map_large();
....@@ -1436,16 +1746,31 @@
14361746 test_map_wronly();
14371747
14381748 test_reuseport_array();
1749
+
1750
+ test_queuemap(0, NULL);
1751
+ test_stackmap(0, NULL);
1752
+
1753
+ test_map_in_map();
14391754 }
1755
+
1756
+#define DEFINE_TEST(name) extern void test_##name(void);
1757
+#include <map_tests/tests.h>
1758
+#undef DEFINE_TEST
14401759
14411760 int main(void)
14421761 {
1762
+ srand(time(NULL));
1763
+
14431764 map_flags = 0;
14441765 run_all_tests();
14451766
14461767 map_flags = BPF_F_NO_PREALLOC;
14471768 run_all_tests();
14481769
1449
- printf("test_maps: OK\n");
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);
14501775 return 0;
14511776 }