blob: 9120f502c912166b775c5694722b123d5bc3f4a5 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 Copyright (c) 2010 Eliot Dresselhaus
17
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
25
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
28
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36*/
37
38#include <vppinfra/vhash.h>
39
40#ifdef CLIB_HAVE_VEC128
41
42/* Overflow search buckets have an extra u32x4 for saving key_hash data.
43 This makes it easier to refill main search bucket from overflow vector. */
Dave Barachc3799992016-08-15 11:12:27 -040044typedef struct
45{
Ed Warnickecb9cada2015-12-08 15:45:58 -070046 /* 4 results for this bucket. */
47 u32x4_union_t result;
48
49 /* 4 hash codes for this bucket. These are used to refill main
50 search buckets from overflow buckets when space becomes available. */
51 u32x4_union_t key_hash;
52
53 /* n_key_u32s u32x4s of key data follow. */
54 u32x4_union_t key[0];
55} vhash_overflow_search_bucket_t;
56
57always_inline void
58set_overflow_result (vhash_overflow_search_bucket_t * b,
Dave Barachc3799992016-08-15 11:12:27 -040059 u32 i, u32 result, u32 key_hash)
Ed Warnickecb9cada2015-12-08 15:45:58 -070060{
61 b->result.as_u32[i] = result;
62 b->key_hash.as_u32[i] = key_hash;
63}
64
65always_inline void
66free_overflow_bucket (vhash_overflow_buckets_t * ob,
Dave Barachc3799992016-08-15 11:12:27 -040067 vhash_overflow_search_bucket_t * b, u32 i)
Ed Warnickecb9cada2015-12-08 15:45:58 -070068{
69 u32 o = (u32x4_union_t *) b - ob->search_buckets;
70 ASSERT (o < vec_len (ob->search_buckets));
71 vec_add1 (ob->free_indices, 4 * o + i);
72}
73
74always_inline vhash_overflow_search_bucket_t *
Dave Barachc3799992016-08-15 11:12:27 -040075get_overflow_search_bucket (vhash_overflow_buckets_t * obs, u32 i,
76 u32 n_key_u32s)
Ed Warnickecb9cada2015-12-08 15:45:58 -070077{
78 return ((vhash_overflow_search_bucket_t *)
79 vec_elt_at_index (obs->search_buckets, i));
80}
81
82always_inline vhash_overflow_search_bucket_t *
83next_overflow_bucket (vhash_overflow_search_bucket_t * b, u32 n_key_u32s)
Dave Barachc3799992016-08-15 11:12:27 -040084{
85 return (vhash_overflow_search_bucket_t *) & b->key[n_key_u32s];
86}
Ed Warnickecb9cada2015-12-08 15:45:58 -070087
88#define foreach_vhash_overflow_bucket(b,ob,n_key_u32s) \
89 for ((b) = (vhash_overflow_search_bucket_t *) ob->search_buckets; \
90 (u32x4_union_t *) (b) < vec_end (ob->search_buckets); \
91 b = next_overflow_bucket (b, n_key_u32s))
92
93u32
Dave Barachc3799992016-08-15 11:12:27 -040094vhash_get_overflow (vhash_t * h, u32 key_hash, u32 vi, u32 n_key_u32s)
Ed Warnickecb9cada2015-12-08 15:45:58 -070095{
Dave Barachc3799992016-08-15 11:12:27 -040096 vhash_overflow_buckets_t *ob = vhash_get_overflow_buckets (h, key_hash);
97 vhash_overflow_search_bucket_t *b;
Ed Warnickecb9cada2015-12-08 15:45:58 -070098 u32 i, result = 0;
99
100 foreach_vhash_overflow_bucket (b, ob, n_key_u32s)
Dave Barachc3799992016-08-15 11:12:27 -0400101 {
102 u32x4 r = b->result.as_u32x4;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700103
Dave Barachc3799992016-08-15 11:12:27 -0400104 for (i = 0; i < n_key_u32s; i++)
105 r &= vhash_bucket_compare (h, &b->key[0], i, vi);
106
107 result = vhash_merge_results (r);
108 if (result)
109 break;
110 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700111
112 return result;
113}
114
115u32
116vhash_set_overflow (vhash_t * h,
Dave Barachc3799992016-08-15 11:12:27 -0400117 u32 key_hash, u32 vi, u32 new_result, u32 n_key_u32s)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700118{
Dave Barachc3799992016-08-15 11:12:27 -0400119 vhash_overflow_buckets_t *ob = vhash_get_overflow_buckets (h, key_hash);
120 vhash_overflow_search_bucket_t *b;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700121 u32 i_set, i, old_result;
122
123 foreach_vhash_overflow_bucket (b, ob, n_key_u32s)
Dave Barachc3799992016-08-15 11:12:27 -0400124 {
125 u32x4 r;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126
Dave Barachc3799992016-08-15 11:12:27 -0400127 r = b->result.as_u32x4;
128 for (i = 0; i < n_key_u32s; i++)
129 r &= vhash_bucket_compare (h, &b->key[0], i, vi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130
Dave Barachc3799992016-08-15 11:12:27 -0400131 old_result = vhash_merge_results (r);
132 if (old_result)
133 {
134 i_set = vhash_non_empty_result_index (r);
135 set_overflow_result (b, i_set, new_result, key_hash);
136 return old_result;
137 }
138 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700139
140 /* Check free list. */
141 if (vec_len (ob->free_indices) == 0)
142 {
143 /* Out of free overflow buckets. Resize. */
Dave Barachc3799992016-08-15 11:12:27 -0400144 u32 j, *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700145 i = vec_len (ob->search_buckets);
146 vec_resize_aligned (ob->search_buckets,
147 sizeof (b[0]) / sizeof (u32x4) + n_key_u32s,
148 CLIB_CACHE_LINE_BYTES);
149 vec_add2 (ob->free_indices, p, 4);
150 for (j = 0; j < 4; j++)
151 p[j] = 4 * i + j;
152 }
153
154 i = vec_pop (ob->free_indices);
155
156 i_set = i & 3;
157 b = ((vhash_overflow_search_bucket_t *)
158 vec_elt_at_index (ob->search_buckets, i / 4));
159
160 /* Insert result. */
161 set_overflow_result (b, i_set, new_result, key_hash);
162
163 /* Insert key. */
164 for (i = 0; i < n_key_u32s; i++)
165 b->key[i].as_u32[i_set] = vhash_get_key_word (h, i, vi);
166
167 ob->n_overflow++;
168 h->n_elts++;
169
170 return /* old result was invalid */ 0;
171}
172
173u32
Dave Barachc3799992016-08-15 11:12:27 -0400174vhash_unset_overflow (vhash_t * h, u32 key_hash, u32 vi, u32 n_key_u32s)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700175{
Dave Barachc3799992016-08-15 11:12:27 -0400176 vhash_overflow_buckets_t *ob = vhash_get_overflow_buckets (h, key_hash);
177 vhash_overflow_search_bucket_t *b;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700178 u32 i_set, i, old_result;
179
180 foreach_vhash_overflow_bucket (b, ob, n_key_u32s)
Dave Barachc3799992016-08-15 11:12:27 -0400181 {
182 u32x4 r;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700183
Dave Barachc3799992016-08-15 11:12:27 -0400184 r = b->result.as_u32x4;
185 for (i = 0; i < n_key_u32s; i++)
186 r &= vhash_bucket_compare (h, &b->key[0], i, vi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700187
Dave Barachc3799992016-08-15 11:12:27 -0400188 old_result = vhash_merge_results (r);
189 if (old_result)
190 {
191 i_set = vhash_non_empty_result_index (r);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700192
Dave Barachc3799992016-08-15 11:12:27 -0400193 /* Invalidate result and invert key hash so that this will
194 never match since all keys in this overflow bucket have
195 matching key hashs. */
196 set_overflow_result (b, i_set, 0, ~key_hash);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700197
Dave Barachc3799992016-08-15 11:12:27 -0400198 free_overflow_bucket (ob, b, i_set);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700199
Dave Barachc3799992016-08-15 11:12:27 -0400200 ASSERT (ob->n_overflow > 0);
201 ob->n_overflow--;
202 h->n_elts--;
203 return old_result;
204 }
205 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700206
207 /* Could not find key. */
208 return 0;
209}
210
211void
212vhash_unset_refill_from_overflow (vhash_t * h,
213 vhash_search_bucket_t * sb,
Dave Barachc3799992016-08-15 11:12:27 -0400214 u32 key_hash, u32 n_key_u32s)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700215{
Dave Barachc3799992016-08-15 11:12:27 -0400216 vhash_overflow_buckets_t *obs = vhash_get_overflow_buckets (h, key_hash);
217 vhash_overflow_search_bucket_t *ob;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700218 u32 i, j, i_refill, bucket_mask = h->bucket_mask.as_u32[0];
219
220 /* Find overflow element with matching key hash. */
221 foreach_vhash_overflow_bucket (ob, obs, n_key_u32s)
Dave Barachc3799992016-08-15 11:12:27 -0400222 {
223 for (i = 0; i < 4; i++)
224 {
225 if (!ob->result.as_u32[i])
226 continue;
227 if ((ob->key_hash.as_u32[i] & bucket_mask)
228 != (key_hash & bucket_mask))
229 continue;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700230
Dave Barachc3799992016-08-15 11:12:27 -0400231 i_refill = vhash_empty_result_index (sb->result.as_u32x4);
232 sb->result.as_u32[i_refill] = ob->result.as_u32[i];
233 for (j = 0; j < n_key_u32s; j++)
234 sb->key[j].as_u32[i_refill] = ob->key[j].as_u32[i];
235 set_overflow_result (ob, i, 0, ~key_hash);
236 free_overflow_bucket (obs, ob, i);
237 return;
238 }
239 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700240}
241
Dave Barachc3799992016-08-15 11:12:27 -0400242void
243vhash_init (vhash_t * h, u32 log2_n_keys, u32 n_key_u32, u32 * hash_seeds)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700244{
245 uword i, j, m;
Dave Barachc3799992016-08-15 11:12:27 -0400246 vhash_search_bucket_t *b;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700247
Dave Barachb7b92992018-10-17 10:38:51 -0400248 clib_memset (h, 0, sizeof (h[0]));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700249
250 /* Must have at least 4 keys (e.g. one search bucket). */
251 log2_n_keys = clib_max (log2_n_keys, 2);
252
253 h->log2_n_keys = log2_n_keys;
254 h->n_key_u32 = n_key_u32;
Dave Barachc3799992016-08-15 11:12:27 -0400255 m = pow2_mask (h->log2_n_keys) & ~3;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700256 for (i = 0; i < VECTOR_WORD_TYPE_LEN (u32); i++)
257 h->bucket_mask.as_u32[i] = m;
258
259 /* Allocate and zero search buckets. */
260 i = (sizeof (b[0]) / sizeof (u32x4) + n_key_u32) << (log2_n_keys - 2);
261 vec_validate_aligned (h->search_buckets, i - 1, CLIB_CACHE_LINE_BYTES);
262
263 for (i = 0; i < ARRAY_LEN (h->find_first_zero_table); i++)
264 h->find_first_zero_table[i] = min_log2 (first_set (~i));
265
266 for (i = 0; i < ARRAY_LEN (h->hash_seeds); i++)
267 for (j = 0; j < VECTOR_WORD_TYPE_LEN (u32); j++)
268 h->hash_seeds[i].as_u32[j] = hash_seeds[i];
269}
270
271static_always_inline u32
Dave Barachc3799992016-08-15 11:12:27 -0400272vhash_main_key_gather (void *_vm, u32 vi, u32 wi, u32 n_key_u32)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700273{
Dave Barachc3799992016-08-15 11:12:27 -0400274 vhash_main_t *vm = _vm;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700275 return vec_elt (vm->keys, vi * n_key_u32 + wi);
276}
277
278static_always_inline u32x4
Dave Barachc3799992016-08-15 11:12:27 -0400279vhash_main_4key_gather (void *_vm, u32 vi, u32 wi, u32 n_key_u32s)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700280{
Dave Barachc3799992016-08-15 11:12:27 -0400281 vhash_main_t *vm = _vm;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700282 u32x4_union_t x;
283
284 ASSERT (n_key_u32s == vm->n_key_u32);
285 ASSERT (wi < n_key_u32s);
286
287 x.as_u32[0] = vec_elt (vm->keys, (vi + 0) * n_key_u32s + wi);
288 x.as_u32[1] = vec_elt (vm->keys, (vi + 1) * n_key_u32s + wi);
289 x.as_u32[2] = vec_elt (vm->keys, (vi + 2) * n_key_u32s + wi);
290 x.as_u32[3] = vec_elt (vm->keys, (vi + 3) * n_key_u32s + wi);
291 return x.as_u32x4;
292}
293
294static_always_inline u32
Dave Barachc3799992016-08-15 11:12:27 -0400295vhash_main_set_result (void *_vm, u32 vi, u32 old_result, u32 n_key_u32)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700296{
Dave Barachc3799992016-08-15 11:12:27 -0400297 vhash_main_t *vm = _vm;
298 u32 *p = vec_elt_at_index (vm->results, vi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700299 u32 new_result = p[0];
300 p[0] = old_result;
301 return new_result;
302}
303
304static_always_inline u32
Dave Barachc3799992016-08-15 11:12:27 -0400305vhash_main_get_result (void *_vm, u32 vi, u32 old_result, u32 n_key_u32)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700306{
Dave Barachc3799992016-08-15 11:12:27 -0400307 vhash_main_t *vm = _vm;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700308 vec_elt (vm->results, vi) = old_result;
309 return old_result;
310}
311
312static_always_inline u32x4
Dave Barachc3799992016-08-15 11:12:27 -0400313vhash_main_get_4result (void *_vm, u32 vi, u32x4 old_result, u32 n_key_u32)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700314{
Dave Barachc3799992016-08-15 11:12:27 -0400315 vhash_main_t *vm = _vm;
316 u32x4 *p = (u32x4 *) vec_elt_at_index (vm->results, vi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700317 p[0] = old_result;
318 return old_result;
319}
320
321#define _(N_KEY_U32) \
322 static_always_inline u32 \
323 vhash_main_key_gather_##N_KEY_U32 (void * _vm, u32 vi, u32 i) \
324 { return vhash_main_key_gather (_vm, vi, i, N_KEY_U32); } \
325 \
326 static_always_inline u32x4 \
327 vhash_main_4key_gather_##N_KEY_U32 (void * _vm, u32 vi, u32 i) \
328 { return vhash_main_4key_gather (_vm, vi, i, N_KEY_U32); } \
329 \
330 clib_pipeline_stage_static \
331 (vhash_main_gather_keys_stage_##N_KEY_U32, \
332 vhash_main_t *, vm, i, \
333 { \
334 vhash_gather_4key_stage \
335 (vm->vhash, \
336 /* vector_index */ i, \
337 vhash_main_4key_gather_##N_KEY_U32, \
338 vm, \
339 N_KEY_U32); \
340 }) \
341 \
342 clib_pipeline_stage_no_inline \
343 (vhash_main_gather_keys_mod_stage_##N_KEY_U32, \
344 vhash_main_t *, vm, i, \
345 { \
346 vhash_gather_key_stage \
347 (vm->vhash, \
348 /* vector_index */ vm->n_vectors_div_4, \
349 /* n_vectors */ vm->n_vectors_mod_4, \
350 vhash_main_key_gather_##N_KEY_U32, \
351 vm, \
352 N_KEY_U32); \
353 }) \
354 \
355 clib_pipeline_stage \
356 (vhash_main_hash_finalize_stage_##N_KEY_U32, \
357 vhash_main_t *, vm, i, \
358 { \
359 vhash_finalize_stage (vm->vhash, i, N_KEY_U32); \
360 }) \
361 \
362 clib_pipeline_stage_no_inline \
363 (vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \
364 vhash_main_t *, vm, i, \
365 { \
366 vhash_finalize_stage (vm->vhash, vm->n_vectors_div_4, N_KEY_U32); \
367 }) \
368 \
369 clib_pipeline_stage_static \
370 (vhash_main_get_stage_##N_KEY_U32, \
371 vhash_main_t *, vm, i, \
372 { \
373 vhash_get_4_stage (vm->vhash, \
374 /* vector_index */ i, \
375 vhash_main_get_4result, \
376 vm, N_KEY_U32); \
377 }) \
378 \
379 clib_pipeline_stage_no_inline \
380 (vhash_main_get_mod_stage_##N_KEY_U32, \
381 vhash_main_t *, vm, i, \
382 { \
383 vhash_get_stage (vm->vhash, \
384 /* vector_index */ vm->n_vectors_div_4, \
385 /* n_vectors */ vm->n_vectors_mod_4, \
386 vhash_main_get_result, \
387 vm, N_KEY_U32); \
388 }) \
389 \
390 clib_pipeline_stage_static \
391 (vhash_main_set_stage_##N_KEY_U32, \
392 vhash_main_t *, vm, i, \
393 { \
394 vhash_set_stage (vm->vhash, \
395 /* vector_index */ i, \
396 /* n_vectors */ VECTOR_WORD_TYPE_LEN (u32), \
397 vhash_main_set_result, \
398 vm, N_KEY_U32); \
399 }) \
400 \
401 clib_pipeline_stage_no_inline \
402 (vhash_main_set_mod_stage_##N_KEY_U32, \
403 vhash_main_t *, vm, i, \
404 { \
405 vhash_set_stage (vm->vhash, \
406 /* vector_index */ vm->n_vectors_div_4, \
407 /* n_vectors */ vm->n_vectors_mod_4, \
408 vhash_main_set_result, \
409 vm, N_KEY_U32); \
410 }) \
411 \
412 clib_pipeline_stage_static \
413 (vhash_main_unset_stage_##N_KEY_U32, \
414 vhash_main_t *, vm, i, \
415 { \
416 vhash_unset_stage (vm->vhash, \
417 /* vector_index */ i, \
418 /* n_vectors */ VECTOR_WORD_TYPE_LEN (u32), \
419 vhash_main_get_result, \
420 vm, N_KEY_U32); \
421 }) \
422 \
423 clib_pipeline_stage_no_inline \
424 (vhash_main_unset_mod_stage_##N_KEY_U32, \
425 vhash_main_t *, vm, i, \
426 { \
427 vhash_unset_stage (vm->vhash, \
428 /* vector_index */ vm->n_vectors_div_4, \
429 /* n_vectors */ vm->n_vectors_mod_4, \
430 vhash_main_get_result, \
431 vm, N_KEY_U32); \
432 })
433
Dave Barachc3799992016-08-15 11:12:27 -0400434_(1);
435_(2);
436_(3);
437_(4);
438_(5);
439_(6);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700440
441#undef _
442
443#define _(N_KEY_U32) \
444 clib_pipeline_stage \
445 (vhash_main_hash_mix_stage_##N_KEY_U32, \
446 vhash_main_t *, vm, i, \
447 { \
448 vhash_mix_stage (vm->vhash, i, N_KEY_U32); \
449 }) \
450 \
451 clib_pipeline_stage_no_inline \
452 (vhash_main_hash_mix_mod_stage_##N_KEY_U32, \
453 vhash_main_t *, vm, i, \
454 { \
455 vhash_mix_stage (vm->vhash, vm->n_vectors_div_4, N_KEY_U32); \
456 })
457
Dave Barachc3799992016-08-15 11:12:27 -0400458_(4);
459_(5);
460_(6);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700461
462#undef _
463
Dave Barachc3799992016-08-15 11:12:27 -0400464typedef enum
465{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700466 GET, SET, UNSET,
467} vhash_main_op_t;
468
469static void
470vhash_main_op (vhash_main_t * vm, vhash_main_op_t op)
471{
472 u32 n_keys = vec_len (vm->results);
473
474 vm->n_key_u32 = vm->vhash->n_key_u32;
475
476 vhash_validate_sizes (vm->vhash, vm->n_key_u32, n_keys);
477
478 vm->n_vectors_div_4 = n_keys / 4;
479 vm->n_vectors_mod_4 = n_keys % 4;
480
481 if (vm->n_vectors_div_4 > 0)
482 {
483 switch (vm->n_key_u32)
484 {
485 default:
486 ASSERT (0);
487 break;
488
489#define _(N_KEY_U32) \
490 case N_KEY_U32: \
491 if (op == GET) \
492 clib_pipeline_run_3_stage \
493 (vm->n_vectors_div_4, \
494 vm, \
495 vhash_main_gather_keys_stage_##N_KEY_U32, \
496 vhash_main_hash_finalize_stage_##N_KEY_U32, \
497 vhash_main_get_stage_##N_KEY_U32); \
498 else if (op == SET) \
499 clib_pipeline_run_3_stage \
500 (vm->n_vectors_div_4, \
501 vm, \
502 vhash_main_gather_keys_stage_##N_KEY_U32, \
503 vhash_main_hash_finalize_stage_##N_KEY_U32, \
504 vhash_main_set_stage_##N_KEY_U32); \
505 else \
506 clib_pipeline_run_3_stage \
507 (vm->n_vectors_div_4, \
508 vm, \
509 vhash_main_gather_keys_stage_##N_KEY_U32, \
510 vhash_main_hash_finalize_stage_##N_KEY_U32, \
511 vhash_main_unset_stage_##N_KEY_U32); \
512 break;
513
Dave Barachc3799992016-08-15 11:12:27 -0400514 _(1);
515 _(2);
516 _(3);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700517
518#undef _
519
520#define _(N_KEY_U32) \
521 case N_KEY_U32: \
522 if (op == GET) \
523 clib_pipeline_run_4_stage \
524 (vm->n_vectors_div_4, \
525 vm, \
526 vhash_main_gather_keys_stage_##N_KEY_U32, \
527 vhash_main_hash_mix_stage_##N_KEY_U32, \
528 vhash_main_hash_finalize_stage_##N_KEY_U32, \
529 vhash_main_get_stage_##N_KEY_U32); \
530 else if (op == SET) \
531 clib_pipeline_run_4_stage \
532 (vm->n_vectors_div_4, \
533 vm, \
534 vhash_main_gather_keys_stage_##N_KEY_U32, \
535 vhash_main_hash_mix_stage_##N_KEY_U32, \
536 vhash_main_hash_finalize_stage_##N_KEY_U32, \
537 vhash_main_set_stage_##N_KEY_U32); \
538 else \
539 clib_pipeline_run_4_stage \
540 (vm->n_vectors_div_4, \
541 vm, \
542 vhash_main_gather_keys_stage_##N_KEY_U32, \
543 vhash_main_hash_mix_stage_##N_KEY_U32, \
544 vhash_main_hash_finalize_stage_##N_KEY_U32, \
545 vhash_main_unset_stage_##N_KEY_U32); \
546 break;
547
Dave Barachc3799992016-08-15 11:12:27 -0400548 _(4);
549 _(5);
550 _(6);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700551
552#undef _
553 }
554 }
555
556
557 if (vm->n_vectors_mod_4 > 0)
558 {
559 switch (vm->n_key_u32)
560 {
561 default:
562 ASSERT (0);
563 break;
564
565#define _(N_KEY_U32) \
566 case N_KEY_U32: \
567 if (op == GET) \
568 clib_pipeline_run_3_stage \
569 (1, \
570 vm, \
571 vhash_main_gather_keys_mod_stage_##N_KEY_U32, \
572 vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \
573 vhash_main_get_mod_stage_##N_KEY_U32); \
574 else if (op == SET) \
575 clib_pipeline_run_3_stage \
576 (1, \
577 vm, \
578 vhash_main_gather_keys_mod_stage_##N_KEY_U32, \
579 vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \
580 vhash_main_set_mod_stage_##N_KEY_U32); \
581 else \
582 clib_pipeline_run_3_stage \
583 (1, \
584 vm, \
585 vhash_main_gather_keys_mod_stage_##N_KEY_U32, \
586 vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \
587 vhash_main_unset_mod_stage_##N_KEY_U32); \
588 break;
589
Dave Barachc3799992016-08-15 11:12:27 -0400590 _(1);
591 _(2);
592 _(3);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700593
594#undef _
595
596#define _(N_KEY_U32) \
597 case N_KEY_U32: \
598 if (op == GET) \
599 clib_pipeline_run_4_stage \
600 (1, \
601 vm, \
602 vhash_main_gather_keys_mod_stage_##N_KEY_U32, \
603 vhash_main_hash_mix_mod_stage_##N_KEY_U32, \
604 vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \
605 vhash_main_get_mod_stage_##N_KEY_U32); \
606 else if (op == SET) \
607 clib_pipeline_run_4_stage \
608 (1, \
609 vm, \
610 vhash_main_gather_keys_mod_stage_##N_KEY_U32, \
611 vhash_main_hash_mix_mod_stage_##N_KEY_U32, \
612 vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \
613 vhash_main_set_mod_stage_##N_KEY_U32); \
614 else \
615 clib_pipeline_run_4_stage \
616 (1, \
617 vm, \
618 vhash_main_gather_keys_mod_stage_##N_KEY_U32, \
619 vhash_main_hash_mix_mod_stage_##N_KEY_U32, \
620 vhash_main_hash_finalize_mod_stage_##N_KEY_U32, \
621 vhash_main_unset_mod_stage_##N_KEY_U32); \
622 break;
623
Dave Barachc3799992016-08-15 11:12:27 -0400624 _(4);
625 _(5);
626 _(6);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700627
628#undef _
629 }
630 }
631}
632
Dave Barachc3799992016-08-15 11:12:27 -0400633void
634vhash_main_get (vhash_main_t * vm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700635{
Dave Barachc3799992016-08-15 11:12:27 -0400636 vhash_main_op (vm, GET);
637}
638
639void
640vhash_main_set (vhash_main_t * vm)
641{
642 vhash_main_op (vm, SET);
643}
644
645void
646vhash_main_unset (vhash_main_t * vm)
647{
648 vhash_main_op (vm, UNSET);
649}
650
651u32
652vhash_resize_incremental (vhash_resize_t * vr, u32 vector_index,
653 u32 n_keys_this_call)
654{
655 vhash_t *old = vr->old;
656 vhash_main_t *vm = &vr->new;
657 vhash_t *new = vm->vhash;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658 uword i, j, n_key_u32;
659
660 n_key_u32 = old->n_key_u32;
661
662 if (vector_index == 0)
663 {
664 u32 hash_seeds[3];
665 hash_seeds[0] = old->hash_seeds[0].as_u32[0];
666 hash_seeds[1] = old->hash_seeds[1].as_u32[0];
667 hash_seeds[2] = old->hash_seeds[2].as_u32[0];
668 vhash_init (new, old->log2_n_keys + 1, n_key_u32, hash_seeds);
669 }
670
671 vec_reset_length (vm->keys);
672 vec_reset_length (vm->results);
673
674 if (0 == (vector_index >> old->log2_n_keys))
675 {
676 for (i = vector_index; 0 == (i >> (old->log2_n_keys - 2)); i++)
677 {
Dave Barachc3799992016-08-15 11:12:27 -0400678 vhash_search_bucket_t *b =
679 vhash_get_search_bucket_with_index (old, 4 * i, n_key_u32);
680 u32 r, *k;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700681
682#define _(I) \
683 if ((r = b->result.as_u32[I]) != 0) \
684 { \
685 vec_add1 (vm->results, r - 1); \
686 vec_add2 (vm->keys, k, n_key_u32); \
687 for (j = 0; j < n_key_u32; j++) \
688 k[j] = b->key[j].as_u32[I]; \
689 }
690
Dave Barachc3799992016-08-15 11:12:27 -0400691 _(0);
692 _(1);
693 _(2);
694 _(3);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700695
696#undef _
697
698 if (vec_len (vm->results) >= n_keys_this_call)
699 {
700 vhash_main_op (vm, SET);
701 return i;
702 }
703 }
704 }
Dave Barachc3799992016-08-15 11:12:27 -0400705
Ed Warnickecb9cada2015-12-08 15:45:58 -0700706 /* Add overflow buckets. */
707 {
Dave Barachc3799992016-08-15 11:12:27 -0400708 vhash_overflow_buckets_t *ob;
709 vhash_overflow_search_bucket_t *b;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700710
711 for (ob = old->overflow_buckets;
Dave Barachc3799992016-08-15 11:12:27 -0400712 ob < old->overflow_buckets + ARRAY_LEN (old->overflow_buckets); ob++)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700713 {
714 foreach_vhash_overflow_bucket (b, ob, old->n_key_u32)
Dave Barachc3799992016-08-15 11:12:27 -0400715 {
716 u32 r, *k;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700717
718#define _(I) \
719 if ((r = b->result.as_u32[I]) != 0) \
720 { \
721 vec_add1 (vm->results, r - 1); \
722 vec_add2 (vm->keys, k, n_key_u32); \
723 for (j = 0; j < n_key_u32; j++) \
724 k[j] = b->key[j].as_u32[I]; \
725 }
726
Dave Barachc3799992016-08-15 11:12:27 -0400727 _(0);
728 _(1);
729 _(2);
730 _(3);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700731
732#undef _
Dave Barachc3799992016-08-15 11:12:27 -0400733 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700734 }
735 }
736
737 vhash_main_op (vm, SET);
738
739 /* Let caller know we are done. */
740 return ~0;
741}
742
Dave Barachc3799992016-08-15 11:12:27 -0400743void
744vhash_resize (vhash_t * old, u32 log2_n_keys)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700745{
746 static vhash_resize_t vr;
747 vhash_t new;
748 u32 i = 0;
749
750 vr.old = old;
751 vr.new.vhash = &new;
752
753 while (1)
754 {
755 i = vhash_resize_incremental (&vr, i, 1024);
756 if (i == ~0)
757 break;
758 }
759
760 vhash_free (old);
761 *old = new;
762}
763
764#endif /* CLIB_HAVE_VEC128 */
Dave Barachc3799992016-08-15 11:12:27 -0400765
766/*
767 * fd.io coding-style-patch-verification: ON
768 *
769 * Local Variables:
770 * eval: (c-set-style "gnu")
771 * End:
772 */