2 * Copyright (c) 2016 Facebook
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
21 #include <bpf/libbpf.h>
24 #include "bpf_rlimit.h"
25 #include "../../../include/linux/filter.h"
27 #define LOCAL_FREE_TARGET (128)
28 #define PERCPU_FREE_TARGET (4)
32 static int create_map(int map_type, int map_flags, unsigned int size)
36 map_fd = bpf_create_map(map_type, sizeof(unsigned long long),
37 sizeof(unsigned long long), size, map_flags);
40 perror("bpf_create_map");
45 static int bpf_map_lookup_elem_with_ref_bit(int fd, unsigned long long key,
48 struct bpf_load_program_attr prog;
49 struct bpf_create_map_attr map;
50 struct bpf_insn insns[] = {
51 BPF_LD_MAP_VALUE(BPF_REG_9, 0, 0),
52 BPF_LD_MAP_FD(BPF_REG_1, fd),
53 BPF_LD_IMM64(BPF_REG_3, key),
54 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
55 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
56 BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0),
57 BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
58 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
59 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
60 BPF_STX_MEM(BPF_DW, BPF_REG_9, BPF_REG_1, 0),
61 BPF_MOV64_IMM(BPF_REG_0, 42),
62 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
63 BPF_MOV64_IMM(BPF_REG_0, 1),
67 int mfd, pfd, ret, zero = 0;
70 memset(&map, 0, sizeof(map));
71 map.map_type = BPF_MAP_TYPE_ARRAY;
72 map.key_size = sizeof(int);
73 map.value_size = sizeof(unsigned long long);
76 mfd = bpf_create_map_xattr(&map);
82 memset(&prog, 0, sizeof(prog));
83 prog.prog_type = BPF_PROG_TYPE_SCHED_CLS;
85 prog.insns_cnt = ARRAY_SIZE(insns);
88 pfd = bpf_load_program_xattr(&prog, NULL, 0);
94 ret = bpf_prog_test_run(pfd, 1, data, sizeof(data),
95 NULL, NULL, &retval, NULL);
96 if (ret < 0 || retval != 42) {
99 assert(!bpf_map_lookup_elem(mfd, &zero, value));
107 static int map_subset(int map0, int map1)
109 unsigned long long next_key = 0;
110 unsigned long long value0[nr_cpus], value1[nr_cpus];
113 while (!bpf_map_get_next_key(map1, &next_key, &next_key)) {
114 assert(!bpf_map_lookup_elem(map1, &next_key, value1));
115 ret = bpf_map_lookup_elem(map0, &next_key, value0);
117 printf("key:%llu not found from map. %s(%d)\n",
118 next_key, strerror(errno), errno);
121 if (value0[0] != value1[0]) {
122 printf("key:%llu value0:%llu != value1:%llu\n",
123 next_key, value0[0], value1[0]);
130 static int map_equal(int lru_map, int expected)
132 return map_subset(lru_map, expected) && map_subset(expected, lru_map);
135 static int sched_next_online(int pid, int *next_to_try)
138 int next = *next_to_try;
141 while (next < nr_cpus) {
143 CPU_SET(next++, &cpuset);
144 if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset)) {
154 /* Size of the LRU map is 2
159 * => Key=2 will be removed by LRU
160 * Iterate map. Only found key=1 and key=3
162 static void test_lru_sanity0(int map_type, int map_flags)
164 unsigned long long key, value[nr_cpus];
165 int lru_map_fd, expected_map_fd;
168 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
171 assert(sched_next_online(0, &next_cpu) != -1);
173 if (map_flags & BPF_F_NO_COMMON_LRU)
174 lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus);
176 lru_map_fd = create_map(map_type, map_flags, 2);
177 assert(lru_map_fd != -1);
179 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, 2);
180 assert(expected_map_fd != -1);
184 /* insert key=1 element */
187 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
188 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
191 /* BPF_NOEXIST means: add new element if it doesn't exist */
192 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST) == -1
193 /* key=1 already exists */
196 assert(bpf_map_update_elem(lru_map_fd, &key, value, -1) == -1 &&
199 /* insert key=2 element */
201 /* check that key=2 is not found */
203 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
206 /* BPF_EXIST means: update existing element */
207 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_EXIST) == -1 &&
208 /* key=2 is not there */
211 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
213 /* insert key=3 element */
215 /* check that key=3 is not found */
217 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
220 /* check that key=1 can be found and mark the ref bit to
221 * stop LRU from removing key=1
224 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
225 assert(value[0] == 1234);
228 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
229 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
232 /* key=2 has been removed from the LRU */
234 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
237 assert(map_equal(lru_map_fd, expected_map_fd));
239 close(expected_map_fd);
245 /* Size of the LRU map is 1.5*tgt_free
246 * Insert 1 to tgt_free (+tgt_free keys)
247 * Lookup 1 to tgt_free/2
248 * Insert 1+tgt_free to 2*tgt_free (+tgt_free keys)
249 * => 1+tgt_free/2 to LOCALFREE_TARGET will be removed by LRU
251 static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free)
253 unsigned long long key, end_key, value[nr_cpus];
254 int lru_map_fd, expected_map_fd;
255 unsigned int batch_size;
256 unsigned int map_size;
259 if (map_flags & BPF_F_NO_COMMON_LRU)
260 /* This test is only applicable to common LRU list */
263 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
266 assert(sched_next_online(0, &next_cpu) != -1);
268 batch_size = tgt_free / 2;
269 assert(batch_size * 2 == tgt_free);
271 map_size = tgt_free + batch_size;
272 lru_map_fd = create_map(map_type, map_flags, map_size);
273 assert(lru_map_fd != -1);
275 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, map_size);
276 assert(expected_map_fd != -1);
280 /* Insert 1 to tgt_free (+tgt_free keys) */
281 end_key = 1 + tgt_free;
282 for (key = 1; key < end_key; key++)
283 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
286 /* Lookup 1 to tgt_free/2 */
287 end_key = 1 + batch_size;
288 for (key = 1; key < end_key; key++) {
289 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
290 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
294 /* Insert 1+tgt_free to 2*tgt_free
295 * => 1+tgt_free/2 to LOCALFREE_TARGET will be
299 end_key = key + tgt_free;
300 for (; key < end_key; key++) {
301 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
303 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
307 assert(map_equal(lru_map_fd, expected_map_fd));
309 close(expected_map_fd);
315 /* Size of the LRU map 1.5 * tgt_free
316 * Insert 1 to tgt_free (+tgt_free keys)
317 * Update 1 to tgt_free/2
318 * => The original 1 to tgt_free/2 will be removed due to
319 * the LRU shrink process
320 * Re-insert 1 to tgt_free/2 again and do a lookup immeidately
321 * Insert 1+tgt_free to tgt_free*3/2
322 * Insert 1+tgt_free*3/2 to tgt_free*5/2
323 * => Key 1+tgt_free to tgt_free*3/2
324 * will be removed from LRU because it has never
325 * been lookup and ref bit is not set
327 static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free)
329 unsigned long long key, value[nr_cpus];
330 unsigned long long end_key;
331 int lru_map_fd, expected_map_fd;
332 unsigned int batch_size;
333 unsigned int map_size;
336 if (map_flags & BPF_F_NO_COMMON_LRU)
337 /* This test is only applicable to common LRU list */
340 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
343 assert(sched_next_online(0, &next_cpu) != -1);
345 batch_size = tgt_free / 2;
346 assert(batch_size * 2 == tgt_free);
348 map_size = tgt_free + batch_size;
349 lru_map_fd = create_map(map_type, map_flags, map_size);
350 assert(lru_map_fd != -1);
352 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, map_size);
353 assert(expected_map_fd != -1);
357 /* Insert 1 to tgt_free (+tgt_free keys) */
358 end_key = 1 + tgt_free;
359 for (key = 1; key < end_key; key++)
360 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
363 /* Any bpf_map_update_elem will require to acquire a new node
366 * The local list is running out of free nodes.
367 * It gets from the global LRU list which tries to
368 * shrink the inactive list to get tgt_free
369 * number of free nodes.
371 * Hence, the oldest key 1 to tgt_free/2
372 * are removed from the LRU list.
375 if (map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
376 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
378 assert(!bpf_map_delete_elem(lru_map_fd, &key));
380 assert(bpf_map_update_elem(lru_map_fd, &key, value,
384 /* Re-insert 1 to tgt_free/2 again and do a lookup
387 end_key = 1 + batch_size;
389 for (key = 1; key < end_key; key++) {
390 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
392 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
394 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
395 assert(value[0] == 4321);
396 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
402 /* Insert 1+tgt_free to tgt_free*3/2 */
403 end_key = 1 + tgt_free + batch_size;
404 for (key = 1 + tgt_free; key < end_key; key++)
405 /* These newly added but not referenced keys will be
406 * gone during the next LRU shrink.
408 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
411 /* Insert 1+tgt_free*3/2 to tgt_free*5/2 */
412 end_key = key + tgt_free;
413 for (; key < end_key; key++) {
414 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
416 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
420 assert(map_equal(lru_map_fd, expected_map_fd));
422 close(expected_map_fd);
428 /* Size of the LRU map is 2*tgt_free
429 * It is to test the active/inactive list rotation
430 * Insert 1 to 2*tgt_free (+2*tgt_free keys)
431 * Lookup key 1 to tgt_free*3/2
432 * Add 1+2*tgt_free to tgt_free*5/2 (+tgt_free/2 keys)
433 * => key 1+tgt_free*3/2 to 2*tgt_free are removed from LRU
435 static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free)
437 unsigned long long key, end_key, value[nr_cpus];
438 int lru_map_fd, expected_map_fd;
439 unsigned int batch_size;
440 unsigned int map_size;
443 if (map_flags & BPF_F_NO_COMMON_LRU)
444 /* This test is only applicable to common LRU list */
447 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
450 assert(sched_next_online(0, &next_cpu) != -1);
452 batch_size = tgt_free / 2;
453 assert(batch_size * 2 == tgt_free);
455 map_size = tgt_free * 2;
456 lru_map_fd = create_map(map_type, map_flags, map_size);
457 assert(lru_map_fd != -1);
459 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, map_size);
460 assert(expected_map_fd != -1);
464 /* Insert 1 to 2*tgt_free (+2*tgt_free keys) */
465 end_key = 1 + (2 * tgt_free);
466 for (key = 1; key < end_key; key++)
467 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
470 /* Lookup key 1 to tgt_free*3/2 */
471 end_key = tgt_free + batch_size;
472 for (key = 1; key < end_key; key++) {
473 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
474 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
478 /* Add 1+2*tgt_free to tgt_free*5/2
481 key = 2 * tgt_free + 1;
482 end_key = key + batch_size;
483 for (; key < end_key; key++) {
484 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
486 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
490 assert(map_equal(lru_map_fd, expected_map_fd));
492 close(expected_map_fd);
499 static void test_lru_sanity4(int map_type, int map_flags, unsigned int tgt_free)
501 int lru_map_fd, expected_map_fd;
502 unsigned long long key, value[nr_cpus];
503 unsigned long long end_key;
506 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
509 assert(sched_next_online(0, &next_cpu) != -1);
511 if (map_flags & BPF_F_NO_COMMON_LRU)
512 lru_map_fd = create_map(map_type, map_flags,
513 3 * tgt_free * nr_cpus);
515 lru_map_fd = create_map(map_type, map_flags, 3 * tgt_free);
516 assert(lru_map_fd != -1);
518 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0,
520 assert(expected_map_fd != -1);
524 for (key = 1; key <= 2 * tgt_free; key++)
525 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
529 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
531 for (key = 1; key <= tgt_free; key++) {
532 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
533 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
537 for (; key <= 2 * tgt_free; key++) {
538 assert(!bpf_map_delete_elem(lru_map_fd, &key));
539 assert(bpf_map_delete_elem(lru_map_fd, &key));
542 end_key = key + 2 * tgt_free;
543 for (; key < end_key; key++) {
544 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
546 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
550 assert(map_equal(lru_map_fd, expected_map_fd));
552 close(expected_map_fd);
558 static void do_test_lru_sanity5(unsigned long long last_key, int map_fd)
560 unsigned long long key, value[nr_cpus];
562 /* Ensure the last key inserted by previous CPU can be found */
563 assert(!bpf_map_lookup_elem_with_ref_bit(map_fd, last_key, value));
567 assert(!bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST));
568 assert(!bpf_map_lookup_elem_with_ref_bit(map_fd, key, value));
570 /* Cannot find the last key because it was removed by LRU */
571 assert(bpf_map_lookup_elem(map_fd, &last_key, value) == -1 &&
575 /* Test map with only one element */
576 static void test_lru_sanity5(int map_type, int map_flags)
578 unsigned long long key, value[nr_cpus];
582 if (map_flags & BPF_F_NO_COMMON_LRU)
585 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
588 map_fd = create_map(map_type, map_flags, 1);
589 assert(map_fd != -1);
593 assert(!bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST));
595 while (sched_next_online(0, &next_cpu) != -1) {
600 do_test_lru_sanity5(key, map_fd);
602 } else if (pid == -1) {
603 printf("couldn't spawn process to test key:%llu\n",
609 assert(waitpid(pid, &status, 0) == pid);
616 /* At least one key should be tested */
622 /* Test list rotation for BPF_F_NO_COMMON_LRU map */
623 static void test_lru_sanity6(int map_type, int map_flags, int tgt_free)
625 int lru_map_fd, expected_map_fd;
626 unsigned long long key, value[nr_cpus];
627 unsigned int map_size = tgt_free * 2;
630 if (!(map_flags & BPF_F_NO_COMMON_LRU))
633 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
636 assert(sched_next_online(0, &next_cpu) != -1);
638 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, map_size);
639 assert(expected_map_fd != -1);
641 lru_map_fd = create_map(map_type, map_flags, map_size * nr_cpus);
642 assert(lru_map_fd != -1);
646 for (key = 1; key <= tgt_free; key++) {
647 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
649 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
653 for (; key <= tgt_free * 2; key++) {
654 unsigned long long stable_key;
656 /* Make ref bit sticky for key: [1, tgt_free] */
657 for (stable_key = 1; stable_key <= tgt_free; stable_key++) {
658 /* Mark the ref bit */
659 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd,
662 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
666 for (; key <= tgt_free * 3; key++) {
667 assert(!bpf_map_update_elem(lru_map_fd, &key, value,
669 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
673 assert(map_equal(lru_map_fd, expected_map_fd));
675 close(expected_map_fd);
681 /* Size of the LRU map is 2
684 * Lookup Key=1 (datapath)
685 * Lookup Key=2 (syscall)
687 * => Key=2 will be removed by LRU
688 * Iterate map. Only found key=1 and key=3
690 static void test_lru_sanity7(int map_type, int map_flags)
692 unsigned long long key, value[nr_cpus];
693 int lru_map_fd, expected_map_fd;
696 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
699 assert(sched_next_online(0, &next_cpu) != -1);
701 if (map_flags & BPF_F_NO_COMMON_LRU)
702 lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus);
704 lru_map_fd = create_map(map_type, map_flags, 2);
705 assert(lru_map_fd != -1);
707 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, 2);
708 assert(expected_map_fd != -1);
712 /* insert key=1 element */
715 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
716 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
719 /* BPF_NOEXIST means: add new element if it doesn't exist */
720 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST) == -1
721 /* key=1 already exists */
724 /* insert key=2 element */
726 /* check that key=2 is not found */
728 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
731 /* BPF_EXIST means: update existing element */
732 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_EXIST) == -1 &&
733 /* key=2 is not there */
736 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
738 /* insert key=3 element */
740 /* check that key=3 is not found */
742 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
745 /* check that key=1 can be found and mark the ref bit to
746 * stop LRU from removing key=1
749 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
750 assert(value[0] == 1234);
752 /* check that key=2 can be found and do _not_ mark ref bit.
753 * this will be evicted on next update.
756 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
757 assert(value[0] == 1234);
760 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
761 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
764 /* key=2 has been removed from the LRU */
766 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
769 assert(map_equal(lru_map_fd, expected_map_fd));
771 close(expected_map_fd);
777 /* Size of the LRU map is 2
780 * Lookup Key=1 (syscall)
781 * Lookup Key=2 (datapath)
783 * => Key=1 will be removed by LRU
784 * Iterate map. Only found key=2 and key=3
786 static void test_lru_sanity8(int map_type, int map_flags)
788 unsigned long long key, value[nr_cpus];
789 int lru_map_fd, expected_map_fd;
792 printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
795 assert(sched_next_online(0, &next_cpu) != -1);
797 if (map_flags & BPF_F_NO_COMMON_LRU)
798 lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus);
800 lru_map_fd = create_map(map_type, map_flags, 2);
801 assert(lru_map_fd != -1);
803 expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, 2);
804 assert(expected_map_fd != -1);
808 /* insert key=1 element */
811 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
813 /* BPF_NOEXIST means: add new element if it doesn't exist */
814 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST) == -1
815 /* key=1 already exists */
818 /* insert key=2 element */
820 /* check that key=2 is not found */
822 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
825 /* BPF_EXIST means: update existing element */
826 assert(bpf_map_update_elem(lru_map_fd, &key, value, BPF_EXIST) == -1 &&
827 /* key=2 is not there */
830 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
831 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
834 /* insert key=3 element */
836 /* check that key=3 is not found */
838 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
841 /* check that key=1 can be found and do _not_ mark ref bit.
842 * this will be evicted on next update.
845 assert(!bpf_map_lookup_elem(lru_map_fd, &key, value));
846 assert(value[0] == 1234);
848 /* check that key=2 can be found and mark the ref bit to
849 * stop LRU from removing key=2
852 assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value));
853 assert(value[0] == 1234);
856 assert(!bpf_map_update_elem(lru_map_fd, &key, value, BPF_NOEXIST));
857 assert(!bpf_map_update_elem(expected_map_fd, &key, value,
860 /* key=1 has been removed from the LRU */
862 assert(bpf_map_lookup_elem(lru_map_fd, &key, value) == -1 &&
865 assert(map_equal(lru_map_fd, expected_map_fd));
867 close(expected_map_fd);
873 int main(int argc, char **argv)
875 int map_types[] = {BPF_MAP_TYPE_LRU_HASH,
876 BPF_MAP_TYPE_LRU_PERCPU_HASH};
877 int map_flags[] = {0, BPF_F_NO_COMMON_LRU};
880 setbuf(stdout, NULL);
882 nr_cpus = bpf_num_possible_cpus();
883 assert(nr_cpus != -1);
884 printf("nr_cpus:%d\n\n", nr_cpus);
886 for (f = 0; f < sizeof(map_flags) / sizeof(*map_flags); f++) {
887 unsigned int tgt_free = (map_flags[f] & BPF_F_NO_COMMON_LRU) ?
888 PERCPU_FREE_TARGET : LOCAL_FREE_TARGET;
890 for (t = 0; t < sizeof(map_types) / sizeof(*map_types); t++) {
891 test_lru_sanity0(map_types[t], map_flags[f]);
892 test_lru_sanity1(map_types[t], map_flags[f], tgt_free);
893 test_lru_sanity2(map_types[t], map_flags[f], tgt_free);
894 test_lru_sanity3(map_types[t], map_flags[f], tgt_free);
895 test_lru_sanity4(map_types[t], map_flags[f], tgt_free);
896 test_lru_sanity5(map_types[t], map_flags[f]);
897 test_lru_sanity6(map_types[t], map_flags[f], tgt_free);
898 test_lru_sanity7(map_types[t], map_flags[f]);
899 test_lru_sanity8(map_types[t], map_flags[f]);