blob: 3b9fa8f34aa44e87e88e385e5bfbb5bae96f9e11 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 Copyright (c) 2013 Cisco and/or its affiliates.
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15*/
16
17#include <vppinfra/pfhash.h>
18#include <vppinfra/format.h>
19
20/* This is incredibly handy when debugging */
21u32 vl (void *v) __attribute__ ((weak));
Dave Barachc3799992016-08-15 11:12:27 -040022u32
23vl (void *v)
24{
25 return vec_len (v);
26}
Ed Warnickecb9cada2015-12-08 15:45:58 -070027
28#if defined(CLIB_HAVE_VEC128) && ! defined (__ALTIVEC__)
29
Dave Barachc3799992016-08-15 11:12:27 -040030typedef struct
31{
32 u8 *key[16];
Ed Warnickecb9cada2015-12-08 15:45:58 -070033 u64 value;
34} pfhash_show_t;
35
Dave Barachc3799992016-08-15 11:12:27 -040036static int
37sh_compare (pfhash_show_t * sh0, pfhash_show_t * sh1)
Ed Warnickecb9cada2015-12-08 15:45:58 -070038{
Dave Barachc3799992016-08-15 11:12:27 -040039 return ((i32) (sh0->value) - ((i32) sh1->value));
40}
41
42u8 *
43format_pfhash (u8 * s, va_list * args)
44{
45 pfhash_t *p = va_arg (*args, pfhash_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070046 int verbose = va_arg (*args, int);
47
48 if (p == 0 || p->overflow_hash == 0 || p->buckets == 0)
49 {
50 s = format (s, "*** uninitialized ***");
51 return s;
52 }
53
54 s = format (s, "Prefetch hash '%s'\n", p->name);
Dave Barachc3799992016-08-15 11:12:27 -040055 s =
56 format (s, " %d buckets, %u bucket overflows, %.1f%% bucket overflow \n",
57 vec_len (p->buckets), p->overflow_count,
58 100.0 * ((f64) p->overflow_count) / ((f64) vec_len (p->buckets)));
Ed Warnickecb9cada2015-12-08 15:45:58 -070059 if (p->nitems)
Dave Barachc3799992016-08-15 11:12:27 -040060 s =
61 format (s,
62 " %u items, %u items in overflow, %.1f%% items in overflow\n",
63 p->nitems, p->nitems_in_overflow,
64 100.0 * ((f64) p->nitems_in_overflow) / ((f64) p->nitems));
Ed Warnickecb9cada2015-12-08 15:45:58 -070065
66 if (verbose)
67 {
Dave Barachc3799992016-08-15 11:12:27 -040068 pfhash_show_t *shs = 0, *sh;
69 hash_pair_t *hp;
Ed Warnickecb9cada2015-12-08 15:45:58 -070070 int i, j;
71
72 for (i = 0; i < vec_len (p->buckets); i++)
Dave Barachc3799992016-08-15 11:12:27 -040073 {
74 pfhash_kv_t *kv;
75 pfhash_kv_16_t *kv16;
76 pfhash_kv_8_t *kv8;
77 pfhash_kv_8v8_t *kv8v8;
78 pfhash_kv_4_t *kv4;
Ed Warnickecb9cada2015-12-08 15:45:58 -070079
Dave Barachc3799992016-08-15 11:12:27 -040080 if (p->buckets[i] == 0 || p->buckets[i] == PFHASH_BUCKET_OVERFLOW)
81 continue;
82
83 kv = pool_elt_at_index (p->kvp, p->buckets[i]);
84
85 switch (p->key_size)
86 {
87 case 16:
88 kv16 = &kv->kv16;
89 for (j = 0; j < 3; j++)
90 {
91 if (kv16->values[j] != (u32) ~ 0)
92 {
93 vec_add2 (shs, sh, 1);
94 clib_memcpy (sh->key, &kv16->kb.k_u32x4[j],
95 p->key_size);
96 sh->value = kv16->values[j];
97 }
98 }
99 break;
100 case 8:
101 if (p->value_size == 4)
102 {
103 kv8 = &kv->kv8;
104 for (j = 0; j < 5; j++)
105 {
106 if (kv8->values[j] != (u32) ~ 0)
107 {
108 vec_add2 (shs, sh, 1);
109 clib_memcpy (sh->key, &kv8->kb.k_u64[j],
110 p->key_size);
111 sh->value = kv8->values[j];
112 }
113 }
114 }
115 else
116 {
117 kv8v8 = &kv->kv8v8;
118 for (j = 0; j < 4; j++)
119 {
120 if (kv8v8->values[j] != (u64) ~ 0)
121 {
122 vec_add2 (shs, sh, 1);
123 clib_memcpy (sh->key, &kv8v8->kb.k_u64[j],
124 p->key_size);
125 sh->value = kv8v8->values[j];
126 }
127 }
128
129 }
130 break;
131 case 4:
132 kv4 = &kv->kv4;
133 for (j = 0; j < 8; j++)
134 {
135 if (kv4->values[j] != (u32) ~ 0)
136 {
137 vec_add2 (shs, sh, 1);
138 clib_memcpy (sh->key, &kv4->kb.kb[j], p->key_size);
139 sh->value = kv4->values[j];
140 }
141 }
142 break;
143 }
144 }
145
146 /* *INDENT-OFF* */
147 hash_foreach_pair (hp, p->overflow_hash,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700148 ({
149 vec_add2 (shs, sh, 1);
Damjan Marionf1213b82016-03-13 02:22:06 +0100150 clib_memcpy (sh->key, (u8 *)hp->key, p->key_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700151 sh->value = hp->value[0];
Dave Barachc3799992016-08-15 11:12:27 -0400152 }));
153 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700154
155 vec_sort_with_function (shs, sh_compare);
156
157 for (i = 0; i < vec_len (shs); i++)
Dave Barachc3799992016-08-15 11:12:27 -0400158 {
159 sh = vec_elt_at_index (shs, i);
160 s = format (s, " %U value %u\n", format_hex_bytes, sh->key,
161 p->key_size, sh->value);
162 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700163 vec_free (shs);
164 }
165 return s;
166}
167
168
Dave Barachc3799992016-08-15 11:12:27 -0400169void abort (void);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170
Dave Barachc3799992016-08-15 11:12:27 -0400171void
172pfhash_init (pfhash_t * p, char *name, u32 key_size, u32 value_size,
173 u32 nbuckets)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174{
Dave Barachc3799992016-08-15 11:12:27 -0400175 pfhash_kv_t *kv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700176 memset (p, 0, sizeof (*p));
177 u32 key_bytes;
Dave Barachc3799992016-08-15 11:12:27 -0400178
179 switch (key_size)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700180 {
181 case 4:
182 key_bytes = 4;
183 break;
184 case 8:
185 key_bytes = 8;
186 break;
187 case 16:
188 key_bytes = 16;
189 break;
190 default:
Dave Barachc3799992016-08-15 11:12:27 -0400191 ASSERT (0);
192 abort ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700193 }
194
Dave Barachc3799992016-08-15 11:12:27 -0400195 switch (value_size)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196 {
197 case 4:
198 case 8:
199 break;
Dave Barachc3799992016-08-15 11:12:27 -0400200 default:
201 ASSERT (0);
202 abort ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700203 }
204
205
206 p->name = format (0, "%s", name);
Dave Barachc3799992016-08-15 11:12:27 -0400207 vec_add1 (p->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700208 p->overflow_hash = hash_create_mem (0, key_bytes, sizeof (uword));
209
210 nbuckets = 1 << (max_log2 (nbuckets));
211
212 /* This sets the entire bucket array to zero */
Dave Barachc3799992016-08-15 11:12:27 -0400213 vec_validate (p->buckets, nbuckets - 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214 p->key_size = key_size;
215 p->value_size = value_size;
216
Dave Barachc3799992016-08-15 11:12:27 -0400217 /*
218 * Unset buckets implicitly point at the 0th pool elt.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700219 * All search routines will return ~0 if they go there.
220 */
221 pool_get_aligned (p->kvp, kv, 16);
222 memset (kv, 0xff, sizeof (*kv));
223}
224
Dave Barachc3799992016-08-15 11:12:27 -0400225static pfhash_kv_16_t *
226pfhash_get_kv_16 (pfhash_t * p, u32 bucket_contents,
227 u32x4 * key, u32 * match_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700228{
229 u32x4 diff[3];
230 u32 is_equal[3];
231 pfhash_kv_16_t *kv = 0;
Dave Barachc3799992016-08-15 11:12:27 -0400232
233 *match_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700234
235 kv = &p->kvp[bucket_contents].kv16;
236
237 diff[0] = u32x4_sub (kv->kb.k_u32x4[0], key[0]);
238 diff[1] = u32x4_sub (kv->kb.k_u32x4[1], key[0]);
239 diff[2] = u32x4_sub (kv->kb.k_u32x4[2], key[0]);
Dave Barachc3799992016-08-15 11:12:27 -0400240
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241 is_equal[0] = u32x4_zero_byte_mask (diff[0]) == 0xffff;
242 is_equal[1] = u32x4_zero_byte_mask (diff[1]) == 0xffff;
243 is_equal[2] = u32x4_zero_byte_mask (diff[2]) == 0xffff;
Dave Barachc3799992016-08-15 11:12:27 -0400244
Ed Warnickecb9cada2015-12-08 15:45:58 -0700245 if (is_equal[0])
246 *match_index = 0;
247 if (is_equal[1])
248 *match_index = 1;
249 if (is_equal[2])
250 *match_index = 2;
Dave Barachc3799992016-08-15 11:12:27 -0400251
Ed Warnickecb9cada2015-12-08 15:45:58 -0700252 return kv;
253}
254
Dave Barachc3799992016-08-15 11:12:27 -0400255static pfhash_kv_8_t *
256pfhash_get_kv_8 (pfhash_t * p, u32 bucket_contents,
257 u64 * key, u32 * match_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700258{
259 pfhash_kv_8_t *kv;
Dave Barachc3799992016-08-15 11:12:27 -0400260
261 *match_index = (u32) ~ 0;
262
Ed Warnickecb9cada2015-12-08 15:45:58 -0700263 kv = &p->kvp[bucket_contents].kv8;
Dave Barachc3799992016-08-15 11:12:27 -0400264
Ed Warnickecb9cada2015-12-08 15:45:58 -0700265 if (kv->kb.k_u64[0] == key[0])
266 *match_index = 0;
267 if (kv->kb.k_u64[1] == key[0])
268 *match_index = 1;
269 if (kv->kb.k_u64[2] == key[0])
270 *match_index = 2;
271 if (kv->kb.k_u64[3] == key[0])
272 *match_index = 3;
273 if (kv->kb.k_u64[4] == key[0])
274 *match_index = 4;
Dave Barachc3799992016-08-15 11:12:27 -0400275
Ed Warnickecb9cada2015-12-08 15:45:58 -0700276 return kv;
277}
278
Dave Barachc3799992016-08-15 11:12:27 -0400279static pfhash_kv_8v8_t *
280pfhash_get_kv_8v8 (pfhash_t * p,
281 u32 bucket_contents, u64 * key, u32 * match_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700282{
283 pfhash_kv_8v8_t *kv;
284
Dave Barachc3799992016-08-15 11:12:27 -0400285 *match_index = (u32) ~ 0;
286
Ed Warnickecb9cada2015-12-08 15:45:58 -0700287 kv = &p->kvp[bucket_contents].kv8v8;
Dave Barachc3799992016-08-15 11:12:27 -0400288
Ed Warnickecb9cada2015-12-08 15:45:58 -0700289 if (kv->kb.k_u64[0] == key[0])
290 *match_index = 0;
291 if (kv->kb.k_u64[1] == key[0])
292 *match_index = 1;
293 if (kv->kb.k_u64[2] == key[0])
294 *match_index = 2;
295 if (kv->kb.k_u64[3] == key[0])
296 *match_index = 3;
297
298 return kv;
299}
300
Dave Barachc3799992016-08-15 11:12:27 -0400301static pfhash_kv_4_t *
302pfhash_get_kv_4 (pfhash_t * p, u32 bucket_contents,
303 u32 * key, u32 * match_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700304{
305 u32x4 vector_key;
306 u32x4 is_equal[2];
307 u32 zbm[2], winner_index;
308 pfhash_kv_4_t *kv;
309
Dave Barachc3799992016-08-15 11:12:27 -0400310 *match_index = (u32) ~ 0;
311
Ed Warnickecb9cada2015-12-08 15:45:58 -0700312 kv = &p->kvp[bucket_contents].kv4;
Dave Barachc3799992016-08-15 11:12:27 -0400313
Ed Warnickecb9cada2015-12-08 15:45:58 -0700314 vector_key = u32x4_splat (key[0]);
Dave Barachc3799992016-08-15 11:12:27 -0400315
Ed Warnickecb9cada2015-12-08 15:45:58 -0700316 is_equal[0] = u32x4_is_equal (kv->kb.k_u32x4[0], vector_key);
317 is_equal[1] = u32x4_is_equal (kv->kb.k_u32x4[1], vector_key);
318 zbm[0] = ~u32x4_zero_byte_mask (is_equal[0]) & 0xFFFF;
319 zbm[1] = ~u32x4_zero_byte_mask (is_equal[1]) & 0xFFFF;
Dave Barachc3799992016-08-15 11:12:27 -0400320
321 if (PREDICT_FALSE ((zbm[0] == 0) && (zbm[1] == 0)))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700322 return kv;
Dave Barachc3799992016-08-15 11:12:27 -0400323
324 winner_index = min_log2 (zbm[0]) >> 2;
325 winner_index = zbm[1] ? (4 + (min_log2 (zbm[1]) >> 2)) : winner_index;
326
Ed Warnickecb9cada2015-12-08 15:45:58 -0700327 *match_index = winner_index;
328 return kv;
329}
330
Dave Barachc3799992016-08-15 11:12:27 -0400331static pfhash_kv_t *
332pfhash_get_internal (pfhash_t * p, u32 bucket_contents,
333 void *key, u32 * match_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700334{
335 pfhash_kv_t *kv = 0;
336
337 switch (p->key_size)
338 {
339 case 16:
Dave Barachc3799992016-08-15 11:12:27 -0400340 kv =
341 (pfhash_kv_t *) pfhash_get_kv_16 (p, bucket_contents, key,
342 match_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700343 break;
344 case 8:
345 if (p->value_size == 4)
Dave Barachc3799992016-08-15 11:12:27 -0400346 kv = (pfhash_kv_t *) pfhash_get_kv_8 (p, bucket_contents,
347 key, match_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348 else
Dave Barachc3799992016-08-15 11:12:27 -0400349 kv = (pfhash_kv_t *) pfhash_get_kv_8v8 (p, bucket_contents,
350 key, match_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700351 break;
352 case 4:
Dave Barachc3799992016-08-15 11:12:27 -0400353 kv =
354 (pfhash_kv_t *) pfhash_get_kv_4 (p, bucket_contents, key,
355 match_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700356 break;
357 default:
Dave Barachc3799992016-08-15 11:12:27 -0400358 ASSERT (0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700359 }
360 return kv;
361}
362
Dave Barachc3799992016-08-15 11:12:27 -0400363u64
364pfhash_get (pfhash_t * p, u32 bucket, void *key)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700365{
366 pfhash_kv_t *kv;
Dave Barachc3799992016-08-15 11:12:27 -0400367 u32 match_index = ~0;
368 pfhash_kv_16_t *kv16;
369 pfhash_kv_8_t *kv8;
370 pfhash_kv_8v8_t *kv8v8;
371 pfhash_kv_4_t *kv4;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700372
373 u32 bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket);
374
375 if (bucket_contents == PFHASH_BUCKET_OVERFLOW)
376 {
Dave Barachc3799992016-08-15 11:12:27 -0400377 uword *hp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700378
379 hp = hash_get_mem (p->overflow_hash, key);
380 if (hp)
Dave Barachc3799992016-08-15 11:12:27 -0400381 return hp[0];
382 return (u64) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700383 }
384
385 kv = pfhash_get_internal (p, bucket_contents, key, &match_index);
Dave Barachc3799992016-08-15 11:12:27 -0400386 if (match_index == (u32) ~ 0)
387 return (u64) ~ 0;
388
Ed Warnickecb9cada2015-12-08 15:45:58 -0700389 kv16 = (void *) kv;
390 kv8 = (void *) kv;
391 kv4 = (void *) kv;
392 kv8v8 = (void *) kv;
393
394 switch (p->key_size)
395 {
396 case 16:
Dave Barachc3799992016-08-15 11:12:27 -0400397 return (kv16->values[match_index] == (u32) ~ 0)
398 ? (u64) ~ 0 : (u64) kv16->values[match_index];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700399 case 8:
400 if (p->value_size == 4)
Dave Barachc3799992016-08-15 11:12:27 -0400401 return (kv8->values[match_index] == (u32) ~ 0)
402 ? (u64) ~ 0 : (u64) kv8->values[match_index];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700403 else
Dave Barachc3799992016-08-15 11:12:27 -0400404 return kv8v8->values[match_index];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405 case 4:
Dave Barachc3799992016-08-15 11:12:27 -0400406 return (kv4->values[match_index] == (u32) ~ 0)
407 ? (u64) ~ 0 : (u64) kv4->values[match_index];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700408 default:
Dave Barachc3799992016-08-15 11:12:27 -0400409 ASSERT (0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700410 }
Dave Barachc3799992016-08-15 11:12:27 -0400411 return (u64) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700412}
413
Dave Barachc3799992016-08-15 11:12:27 -0400414void
415pfhash_set (pfhash_t * p, u32 bucket, void *key, void *value)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700416{
417 u32 bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket);
Dave Barachc3799992016-08-15 11:12:27 -0400418 u32 match_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700419 pfhash_kv_t *kv;
Dave Barachc3799992016-08-15 11:12:27 -0400420 pfhash_kv_16_t *kv16;
421 pfhash_kv_8_t *kv8;
422 pfhash_kv_8v8_t *kv8v8;
423 pfhash_kv_4_t *kv4;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700424 int i;
425 u8 *kcopy;
426
427 if (bucket_contents == PFHASH_BUCKET_OVERFLOW)
428 {
429 hash_pair_t *hp;
430 hp = hash_get_pair_mem (p->overflow_hash, key);
431 if (hp)
Dave Barachc3799992016-08-15 11:12:27 -0400432 {
433 clib_warning ("replace value 0x%08x with value 0x%08x",
434 hp->value[0], (u64) value);
435 hp->value[0] = (u64) value;
436 return;
437 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700438 kcopy = clib_mem_alloc (p->key_size);
Damjan Marionf1213b82016-03-13 02:22:06 +0100439 clib_memcpy (kcopy, key, p->key_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700440 hash_set_mem (p->overflow_hash, kcopy, value);
441 p->nitems++;
442 p->nitems_in_overflow++;
443 return;
444 }
445
446 if (bucket_contents == 0)
447 {
448 pool_get_aligned (p->kvp, kv, 16);
449 memset (kv, 0xff, sizeof (*kv));
450 p->buckets[bucket] = kv - p->kvp;
451 }
452 else
453 kv = pfhash_get_internal (p, bucket_contents, key, &match_index);
454
Dave Barachc3799992016-08-15 11:12:27 -0400455 kv16 = (void *) kv;
456 kv8 = (void *) kv;
457 kv8v8 = (void *) kv;
458 kv4 = (void *) kv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700459
460 p->nitems++;
461
Dave Barachc3799992016-08-15 11:12:27 -0400462 if (match_index != (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700463 {
464 switch (p->key_size)
Dave Barachc3799992016-08-15 11:12:27 -0400465 {
466 case 16:
467 kv16->values[match_index] = (u32) (u64) value;
468 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700469
Dave Barachc3799992016-08-15 11:12:27 -0400470 case 8:
471 if (p->value_size == 4)
472 kv8->values[match_index] = (u32) (u64) value;
473 else
474 kv8v8->values[match_index] = (u64) value;
475 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700476
Dave Barachc3799992016-08-15 11:12:27 -0400477 case 4:
478 kv4->values[match_index] = (u64) value;
479 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700480
Dave Barachc3799992016-08-15 11:12:27 -0400481 default:
482 ASSERT (0);
483 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700484 }
485
486 switch (p->key_size)
487 {
488 case 16:
489 for (i = 0; i < 3; i++)
Dave Barachc3799992016-08-15 11:12:27 -0400490 {
491 if (kv16->values[i] == (u32) ~ 0)
492 {
493 clib_memcpy (&kv16->kb.k_u32x4[i], key, p->key_size);
494 kv16->values[i] = (u32) (u64) value;
495 return;
496 }
497 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700498 /* copy bucket contents to overflow hash tbl */
Dave Barachc3799992016-08-15 11:12:27 -0400499 for (i = 0; i < 3; i++)
500 {
501 kcopy = clib_mem_alloc (p->key_size);
502 clib_memcpy (kcopy, &kv16->kb.k_u32x4[i], p->key_size);
503 hash_set_mem (p->overflow_hash, kcopy, kv16->values[i]);
504 p->nitems_in_overflow++;
505 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700506 /* Add new key to overflow */
507 kcopy = clib_mem_alloc (p->key_size);
Damjan Marionf1213b82016-03-13 02:22:06 +0100508 clib_memcpy (kcopy, key, p->key_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700509 hash_set_mem (p->overflow_hash, kcopy, value);
510 p->buckets[bucket] = PFHASH_BUCKET_OVERFLOW;
511 p->overflow_count++;
512 p->nitems_in_overflow++;
513 return;
514
515 case 8:
516 if (p->value_size == 4)
Dave Barachc3799992016-08-15 11:12:27 -0400517 {
518 for (i = 0; i < 5; i++)
519 {
520 if (kv8->values[i] == (u32) ~ 0)
521 {
522 clib_memcpy (&kv8->kb.k_u64[i], key, 8);
523 kv8->values[i] = (u32) (u64) value;
524 return;
525 }
526 }
527 /* copy bucket contents to overflow hash tbl */
528 for (i = 0; i < 5; i++)
529 {
530 kcopy = clib_mem_alloc (p->key_size);
531 clib_memcpy (kcopy, &kv8->kb.k_u64[i], 8);
532 hash_set_mem (p->overflow_hash, kcopy, kv8->values[i]);
533 p->nitems_in_overflow++;
534 }
535 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700536 else
Dave Barachc3799992016-08-15 11:12:27 -0400537 {
538 for (i = 0; i < 4; i++)
539 {
540 if (kv8v8->values[i] == (u64) ~ 0)
541 {
542 clib_memcpy (&kv8v8->kb.k_u64[i], key, 8);
543 kv8v8->values[i] = (u64) value;
544 return;
545 }
546 }
547 /* copy bucket contents to overflow hash tbl */
548 for (i = 0; i < 4; i++)
549 {
550 kcopy = clib_mem_alloc (p->key_size);
551 clib_memcpy (kcopy, &kv8v8->kb.k_u64[i], 8);
552 hash_set_mem (p->overflow_hash, kcopy, kv8v8->values[i]);
553 p->nitems_in_overflow++;
554 }
555
556 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700557 /* Add new key to overflow */
558 kcopy = clib_mem_alloc (p->key_size);
Damjan Marionf1213b82016-03-13 02:22:06 +0100559 clib_memcpy (kcopy, key, p->key_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700560 hash_set_mem (p->overflow_hash, kcopy, value);
561 p->buckets[bucket] = PFHASH_BUCKET_OVERFLOW;
562 p->overflow_count++;
563 p->nitems_in_overflow++;
564 return;
565
566 case 4:
567 for (i = 0; i < 8; i++)
Dave Barachc3799992016-08-15 11:12:27 -0400568 {
569 if (kv4->values[i] == (u32) ~ 0)
570 {
571 clib_memcpy (&kv4->kb.kb[i], key, 4);
572 kv4->values[i] = (u32) (u64) value;
573 return;
574 }
575 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700576 /* copy bucket contents to overflow hash tbl */
Dave Barachc3799992016-08-15 11:12:27 -0400577 for (i = 0; i < 8; i++)
578 {
579 kcopy = clib_mem_alloc (p->key_size);
580 clib_memcpy (kcopy, &kv4->kb.kb[i], 4);
581 hash_set_mem (p->overflow_hash, kcopy, kv4->values[i]);
582 p->nitems_in_overflow++;
583 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700584 /* Add new key to overflow */
585 kcopy = clib_mem_alloc (p->key_size);
Damjan Marionf1213b82016-03-13 02:22:06 +0100586 clib_memcpy (kcopy, key, p->key_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700587 hash_set_mem (p->overflow_hash, kcopy, value);
588 p->buckets[bucket] = PFHASH_BUCKET_OVERFLOW;
589 p->overflow_count++;
590 p->nitems_in_overflow++;
591 return;
592
593 default:
Dave Barachc3799992016-08-15 11:12:27 -0400594 ASSERT (0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700595 }
596}
597
Dave Barachc3799992016-08-15 11:12:27 -0400598void
599pfhash_unset (pfhash_t * p, u32 bucket, void *key)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700600{
601 u32 bucket_contents = pfhash_read_bucket_prefetch_kv (p, bucket);
Dave Barachc3799992016-08-15 11:12:27 -0400602 u32 match_index = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700603 pfhash_kv_t *kv;
Dave Barachc3799992016-08-15 11:12:27 -0400604 pfhash_kv_16_t *kv16;
605 pfhash_kv_8_t *kv8;
606 pfhash_kv_8v8_t *kv8v8;
607 pfhash_kv_4_t *kv4;
608 void *oldkey;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700609
610 if (bucket_contents == PFHASH_BUCKET_OVERFLOW)
611 {
612 hash_pair_t *hp;
613 hp = hash_get_pair_mem (p->overflow_hash, key);
614 if (hp)
Dave Barachc3799992016-08-15 11:12:27 -0400615 {
616 oldkey = (void *) hp->key;
617 hash_unset_mem (p->overflow_hash, key);
618 clib_mem_free (oldkey);
619 p->nitems--;
620 p->nitems_in_overflow--;
621 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700622 return;
623 }
624
625 kv = pfhash_get_internal (p, bucket_contents, key, &match_index);
Dave Barachc3799992016-08-15 11:12:27 -0400626 if (match_index == (u32) ~ 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700627 return;
Dave Barachc3799992016-08-15 11:12:27 -0400628
Ed Warnickecb9cada2015-12-08 15:45:58 -0700629 p->nitems--;
630
Dave Barachc3799992016-08-15 11:12:27 -0400631 kv16 = (void *) kv;
632 kv8 = (void *) kv;
633 kv8v8 = (void *) kv;
634 kv4 = (void *) kv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700635
636 switch (p->key_size)
637 {
638 case 16:
Dave Barachc3799992016-08-15 11:12:27 -0400639 kv16->values[match_index] = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700640 return;
641
642 case 8:
643 if (p->value_size == 4)
Dave Barachc3799992016-08-15 11:12:27 -0400644 kv8->values[match_index] = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700645 else
Dave Barachc3799992016-08-15 11:12:27 -0400646 kv8v8->values[match_index] = (u64) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700647 return;
648
649 case 4:
Dave Barachc3799992016-08-15 11:12:27 -0400650 kv4->values[match_index] = (u32) ~ 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700651 return;
652
653 default:
Dave Barachc3799992016-08-15 11:12:27 -0400654 ASSERT (0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700655 }
656}
657
Dave Barachc3799992016-08-15 11:12:27 -0400658void
659pfhash_free (pfhash_t * p)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700660{
661 hash_pair_t *hp;
662 int i;
Dave Barachc3799992016-08-15 11:12:27 -0400663 u8 **keys = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700664
665 vec_free (p->name);
666
667 pool_free (p->kvp);
668
Dave Barachc3799992016-08-15 11:12:27 -0400669 /* *INDENT-OFF* */
670 hash_foreach_pair (hp, p->overflow_hash,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700671 ({
672 vec_add1 (keys, (u8 *)hp->key);
Dave Barachc3799992016-08-15 11:12:27 -0400673 }));
674 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700675 hash_free (p->overflow_hash);
676 for (i = 0; i < vec_len (keys); i++)
677 vec_free (keys[i]);
678 vec_free (keys);
679}
680
681#endif
Dave Barachc3799992016-08-15 11:12:27 -0400682
683/*
684 * fd.io coding-style-patch-verification: ON
685 *
686 * Local Variables:
687 * eval: (c-set-style "gnu")
688 * End:
689 */