1 // SPDX-License-Identifier: GPL-2.0 2 #include <test_progs.h> 3 #include <network_helpers.h> 4 5 static void *spin_lock_thread(void *arg) 6 { 7 int err, prog_fd = *(u32 *) arg; 8 LIBBPF_OPTS(bpf_test_run_opts, topts, 9 .data_in = &pkt_v4, 10 .data_size_in = sizeof(pkt_v4), 11 .repeat = 10000, 12 ); 13 14 err = bpf_prog_test_run_opts(prog_fd, &topts); 15 ASSERT_OK(err, "test_run_opts err"); 16 ASSERT_OK(topts.retval, "test_run_opts retval"); 17 18 pthread_exit(arg); 19 } 20 21 static void *parallel_map_access(void *arg) 22 { 23 int err, map_fd = *(u32 *) arg; 24 int vars[17], i, j, rnd, key = 0; 25 26 for (i = 0; i < 10000; i++) { 27 err = bpf_map_lookup_elem_flags(map_fd, &key, vars, BPF_F_LOCK); 28 if (CHECK_FAIL(err)) { 29 printf("lookup failed\n"); 30 goto out; 31 } 32 if (CHECK_FAIL(vars[0] != 0)) { 33 printf("lookup #%d var[0]=%d\n", i, vars[0]); 34 goto out; 35 } 36 rnd = vars[1]; 37 for (j = 2; j < 17; j++) { 38 if (vars[j] == rnd) 39 continue; 40 printf("lookup #%d var[1]=%d var[%d]=%d\n", 41 i, rnd, j, vars[j]); 42 CHECK_FAIL(vars[j] != rnd); 43 goto out; 44 } 45 } 46 out: 47 pthread_exit(arg); 48 } 49 50 void test_map_lock(void) 51 { 52 const char *file = "./test_map_lock.bpf.o"; 53 int prog_fd, map_fd[2], vars[17] = {}; 54 pthread_t thread_id[6]; 55 struct bpf_object *obj = NULL; 56 int err = 0, key = 0, i; 57 void *ret; 58 59 err = bpf_prog_test_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd); 60 if (CHECK_FAIL(err)) { 61 printf("test_map_lock:bpf_prog_test_load errno %d\n", errno); 62 goto close_prog; 63 } 64 map_fd[0] = bpf_find_map(__func__, obj, "hash_map"); 65 if (CHECK_FAIL(map_fd[0] < 0)) 66 goto close_prog; 67 map_fd[1] = bpf_find_map(__func__, obj, "array_map"); 68 if (CHECK_FAIL(map_fd[1] < 0)) 69 goto close_prog; 70 71 bpf_map_update_elem(map_fd[0], &key, vars, BPF_F_LOCK); 72 73 for (i = 0; i < 4; i++) 74 if (CHECK_FAIL(pthread_create(&thread_id[i], NULL, 75 &spin_lock_thread, &prog_fd))) 76 goto close_prog; 77 for (i = 4; i < 6; i++) 78 if (CHECK_FAIL(pthread_create(&thread_id[i], NULL, 79 ¶llel_map_access, 80 &map_fd[i - 4]))) 81 goto close_prog; 82 for (i = 0; i < 4; i++) 83 if (CHECK_FAIL(pthread_join(thread_id[i], &ret) || 84 ret != (void *)&prog_fd)) 85 goto close_prog; 86 for (i = 4; i < 6; i++) 87 if (CHECK_FAIL(pthread_join(thread_id[i], &ret) || 88 ret != (void *)&map_fd[i - 4])) 89 goto close_prog; 90 close_prog: 91 bpf_object__close(obj); 92 } 93