1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2021 Facebook */ 3 4 #include <sys/syscall.h> 5 #include <test_progs.h> 6 #include "bloom_filter_map.skel.h" 7 8 static void test_fail_cases(void) 9 { 10 LIBBPF_OPTS(bpf_map_create_opts, opts); 11 __u32 value; 12 int fd, err; 13 14 /* Invalid key size */ 15 fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 4, sizeof(value), 100, NULL); 16 if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid key size")) 17 close(fd); 18 19 /* Invalid value size */ 20 fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, 0, 100, NULL); 21 if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid value size 0")) 22 close(fd); 23 24 /* Invalid max entries size */ 25 fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 0, NULL); 26 if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid max entries size")) 27 close(fd); 28 29 /* Bloom filter maps do not support BPF_F_NO_PREALLOC */ 30 opts.map_flags = BPF_F_NO_PREALLOC; 31 fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 100, &opts); 32 if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid flags")) 33 close(fd); 34 35 fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 100, NULL); 36 if (!ASSERT_GE(fd, 0, "bpf_map_create bloom filter")) 37 return; 38 39 /* Test invalid flags */ 40 err = bpf_map_update_elem(fd, NULL, &value, -1); 41 ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); 42 43 err = bpf_map_update_elem(fd, NULL, &value, BPF_EXIST); 44 ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); 45 46 err = bpf_map_update_elem(fd, NULL, &value, BPF_F_LOCK); 47 ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); 48 49 err = bpf_map_update_elem(fd, NULL, &value, BPF_NOEXIST); 50 ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); 51 52 err = bpf_map_update_elem(fd, NULL, &value, 10000); 53 ASSERT_EQ(err, -EINVAL, "bpf_map_update_elem bloom filter invalid flags"); 54 55 close(fd); 56 } 57 58 static void test_success_cases(void) 59 { 60 LIBBPF_OPTS(bpf_map_create_opts, opts); 61 char value[11]; 62 int fd, err; 63 64 /* Create a map */ 65 opts.map_flags = BPF_F_ZERO_SEED | BPF_F_NUMA_NODE; 66 fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 100, &opts); 67 if (!ASSERT_GE(fd, 0, "bpf_map_create bloom filter success case")) 68 return; 69 70 /* Add a value to the bloom filter */ 71 err = bpf_map_update_elem(fd, NULL, &value, 0); 72 if (!ASSERT_OK(err, "bpf_map_update_elem bloom filter success case")) 73 goto done; 74 75 /* Lookup a value in the bloom filter */ 76 err = bpf_map_lookup_elem(fd, NULL, &value); 77 ASSERT_OK(err, "bpf_map_update_elem bloom filter success case"); 78 79 done: 80 close(fd); 81 } 82 83 static void check_bloom(struct bloom_filter_map *skel) 84 { 85 struct bpf_link *link; 86 87 link = bpf_program__attach(skel->progs.check_bloom); 88 if (!ASSERT_OK_PTR(link, "link")) 89 return; 90 91 syscall(SYS_getpgid); 92 93 ASSERT_EQ(skel->bss->error, 0, "error"); 94 95 bpf_link__destroy(link); 96 } 97 98 static void test_inner_map(struct bloom_filter_map *skel, const __u32 *rand_vals, 99 __u32 nr_rand_vals) 100 { 101 int outer_map_fd, inner_map_fd, err, i, key = 0; 102 struct bpf_link *link; 103 104 /* Create a bloom filter map that will be used as the inner map */ 105 inner_map_fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(*rand_vals), 106 nr_rand_vals, NULL); 107 if (!ASSERT_GE(inner_map_fd, 0, "bpf_map_create bloom filter inner map")) 108 return; 109 110 for (i = 0; i < nr_rand_vals; i++) { 111 err = bpf_map_update_elem(inner_map_fd, NULL, rand_vals + i, BPF_ANY); 112 if (!ASSERT_OK(err, "Add random value to inner_map_fd")) 113 goto done; 114 } 115 116 /* Add the bloom filter map to the outer map */ 117 outer_map_fd = bpf_map__fd(skel->maps.outer_map); 118 err = bpf_map_update_elem(outer_map_fd, &key, &inner_map_fd, BPF_ANY); 119 if (!ASSERT_OK(err, "Add bloom filter map to outer map")) 120 goto done; 121 122 /* Attach the bloom_filter_inner_map prog */ 123 link = bpf_program__attach(skel->progs.inner_map); 124 if (!ASSERT_OK_PTR(link, "link")) 125 goto delete_inner_map; 126 127 syscall(SYS_getpgid); 128 129 ASSERT_EQ(skel->bss->error, 0, "error"); 130 131 bpf_link__destroy(link); 132 133 delete_inner_map: 134 /* Ensure the inner bloom filter map can be deleted */ 135 err = bpf_map_delete_elem(outer_map_fd, &key); 136 ASSERT_OK(err, "Delete inner bloom filter map"); 137 138 done: 139 close(inner_map_fd); 140 } 141 142 static int setup_progs(struct bloom_filter_map **out_skel, __u32 **out_rand_vals, 143 __u32 *out_nr_rand_vals) 144 { 145 struct bloom_filter_map *skel; 146 int random_data_fd, bloom_fd; 147 __u32 *rand_vals = NULL; 148 __u32 map_size, val; 149 int err, i; 150 151 /* Set up a bloom filter map skeleton */ 152 skel = bloom_filter_map__open_and_load(); 153 if (!ASSERT_OK_PTR(skel, "bloom_filter_map__open_and_load")) 154 return -EINVAL; 155 156 /* Set up rand_vals */ 157 map_size = bpf_map__max_entries(skel->maps.map_random_data); 158 rand_vals = malloc(sizeof(*rand_vals) * map_size); 159 if (!rand_vals) { 160 err = -ENOMEM; 161 goto error; 162 } 163 164 /* Generate random values and populate both skeletons */ 165 random_data_fd = bpf_map__fd(skel->maps.map_random_data); 166 bloom_fd = bpf_map__fd(skel->maps.map_bloom); 167 for (i = 0; i < map_size; i++) { 168 val = rand(); 169 170 err = bpf_map_update_elem(random_data_fd, &i, &val, BPF_ANY); 171 if (!ASSERT_OK(err, "Add random value to map_random_data")) 172 goto error; 173 174 err = bpf_map_update_elem(bloom_fd, NULL, &val, BPF_ANY); 175 if (!ASSERT_OK(err, "Add random value to map_bloom")) 176 goto error; 177 178 rand_vals[i] = val; 179 } 180 181 *out_skel = skel; 182 *out_rand_vals = rand_vals; 183 *out_nr_rand_vals = map_size; 184 185 return 0; 186 187 error: 188 bloom_filter_map__destroy(skel); 189 if (rand_vals) 190 free(rand_vals); 191 return err; 192 } 193 194 void test_bloom_filter_map(void) 195 { 196 __u32 *rand_vals, nr_rand_vals; 197 struct bloom_filter_map *skel; 198 int err; 199 200 test_fail_cases(); 201 test_success_cases(); 202 203 err = setup_progs(&skel, &rand_vals, &nr_rand_vals); 204 if (err) 205 return; 206 207 test_inner_map(skel, rand_vals, nr_rand_vals); 208 free(rand_vals); 209 210 check_bloom(skel); 211 212 bloom_filter_map__destroy(skel); 213 } 214