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