diff options
author | Martin KaFai Lau <kafai@fb.com> | 2016-02-02 01:39:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-02-06 03:34:36 -0500 |
commit | e15596717948c95587a0b15363030283c126c23a (patch) | |
tree | 14e130e94d3576dfdf5d940541cf867e765fc6a6 /samples | |
parent | 15a07b33814d14ca817887dbea8530728dc0fbe4 (diff) |
samples/bpf: unit test for BPF_MAP_TYPE_PERCPU_HASH
A sanity test for BPF_MAP_TYPE_PERCPU_HASH.
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples')
-rw-r--r-- | samples/bpf/test_maps.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c index 6299ee95cd11..5f5fe5332148 100644 --- a/samples/bpf/test_maps.c +++ b/samples/bpf/test_maps.c | |||
@@ -89,6 +89,100 @@ static void test_hashmap_sanity(int i, void *data) | |||
89 | close(map_fd); | 89 | close(map_fd); |
90 | } | 90 | } |
91 | 91 | ||
92 | /* sanity tests for percpu map API */ | ||
93 | static void test_percpu_hashmap_sanity(int task, void *data) | ||
94 | { | ||
95 | long long key, next_key; | ||
96 | int expected_key_mask = 0; | ||
97 | unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); | ||
98 | long long value[nr_cpus]; | ||
99 | int map_fd, i; | ||
100 | |||
101 | map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key), | ||
102 | sizeof(value[0]), 2); | ||
103 | if (map_fd < 0) { | ||
104 | printf("failed to create hashmap '%s'\n", strerror(errno)); | ||
105 | exit(1); | ||
106 | } | ||
107 | |||
108 | for (i = 0; i < nr_cpus; i++) | ||
109 | value[i] = i + 100; | ||
110 | key = 1; | ||
111 | /* insert key=1 element */ | ||
112 | assert(!(expected_key_mask & key)); | ||
113 | assert(bpf_update_elem(map_fd, &key, value, BPF_ANY) == 0); | ||
114 | expected_key_mask |= key; | ||
115 | |||
116 | /* BPF_NOEXIST means: add new element if it doesn't exist */ | ||
117 | assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 && | ||
118 | /* key=1 already exists */ | ||
119 | errno == EEXIST); | ||
120 | |||
121 | /* -1 is an invalid flag */ | ||
122 | assert(bpf_update_elem(map_fd, &key, value, -1) == -1 && | ||
123 | errno == EINVAL); | ||
124 | |||
125 | /* check that key=1 can be found. value could be 0 if the lookup | ||
126 | * was run from a different cpu. | ||
127 | */ | ||
128 | value[0] = 1; | ||
129 | assert(bpf_lookup_elem(map_fd, &key, value) == 0 && value[0] == 100); | ||
130 | |||
131 | key = 2; | ||
132 | /* check that key=2 is not found */ | ||
133 | assert(bpf_lookup_elem(map_fd, &key, value) == -1 && errno == ENOENT); | ||
134 | |||
135 | /* BPF_EXIST means: update existing element */ | ||
136 | assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == -1 && | ||
137 | /* key=2 is not there */ | ||
138 | errno == ENOENT); | ||
139 | |||
140 | /* insert key=2 element */ | ||
141 | assert(!(expected_key_mask & key)); | ||
142 | assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0); | ||
143 | expected_key_mask |= key; | ||
144 | |||
145 | /* key=1 and key=2 were inserted, check that key=0 cannot be inserted | ||
146 | * due to max_entries limit | ||
147 | */ | ||
148 | key = 0; | ||
149 | assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 && | ||
150 | errno == E2BIG); | ||
151 | |||
152 | /* check that key = 0 doesn't exist */ | ||
153 | assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT); | ||
154 | |||
155 | /* iterate over two elements */ | ||
156 | while (!bpf_get_next_key(map_fd, &key, &next_key)) { | ||
157 | assert((expected_key_mask & next_key) == next_key); | ||
158 | expected_key_mask &= ~next_key; | ||
159 | |||
160 | assert(bpf_lookup_elem(map_fd, &next_key, value) == 0); | ||
161 | for (i = 0; i < nr_cpus; i++) | ||
162 | assert(value[i] == i + 100); | ||
163 | |||
164 | key = next_key; | ||
165 | } | ||
166 | assert(errno == ENOENT); | ||
167 | |||
168 | /* Update with BPF_EXIST */ | ||
169 | key = 1; | ||
170 | assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == 0); | ||
171 | |||
172 | /* delete both elements */ | ||
173 | key = 1; | ||
174 | assert(bpf_delete_elem(map_fd, &key) == 0); | ||
175 | key = 2; | ||
176 | assert(bpf_delete_elem(map_fd, &key) == 0); | ||
177 | assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT); | ||
178 | |||
179 | key = 0; | ||
180 | /* check that map is empty */ | ||
181 | assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 && | ||
182 | errno == ENOENT); | ||
183 | close(map_fd); | ||
184 | } | ||
185 | |||
92 | static void test_arraymap_sanity(int i, void *data) | 186 | static void test_arraymap_sanity(int i, void *data) |
93 | { | 187 | { |
94 | int key, next_key, map_fd; | 188 | int key, next_key, map_fd; |
@@ -209,6 +303,7 @@ static void run_parallel(int tasks, void (*fn)(int i, void *data), void *data) | |||
209 | static void test_map_stress(void) | 303 | static void test_map_stress(void) |
210 | { | 304 | { |
211 | run_parallel(100, test_hashmap_sanity, NULL); | 305 | run_parallel(100, test_hashmap_sanity, NULL); |
306 | run_parallel(100, test_percpu_hashmap_sanity, NULL); | ||
212 | run_parallel(100, test_arraymap_sanity, NULL); | 307 | run_parallel(100, test_arraymap_sanity, NULL); |
213 | } | 308 | } |
214 | 309 | ||
@@ -282,6 +377,7 @@ static void test_map_parallel(void) | |||
282 | int main(void) | 377 | int main(void) |
283 | { | 378 | { |
284 | test_hashmap_sanity(0, NULL); | 379 | test_hashmap_sanity(0, NULL); |
380 | test_percpu_hashmap_sanity(0, NULL); | ||
285 | test_arraymap_sanity(0, NULL); | 381 | test_arraymap_sanity(0, NULL); |
286 | test_map_large(); | 382 | test_map_large(); |
287 | test_map_parallel(); | 383 | test_map_parallel(); |