blob: 3c754c8e29ff9487dad5c646794024c120f044e3 [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) 2001-2005 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#ifndef included_hash_h
39#define included_hash_h
40
41#include <vppinfra/error.h>
42#include <vppinfra/format.h>
43#include <vppinfra/vec.h>
44#include <vppinfra/vector.h>
45
46struct hash_header;
47
Dave Barachc3799992016-08-15 11:12:27 -040048typedef uword (hash_key_sum_function_t) (struct hash_header *, uword key);
Ed Warnickecb9cada2015-12-08 15:45:58 -070049typedef uword (hash_key_equal_function_t)
50 (struct hash_header *, uword key1, uword key2);
51
52/* Vector header for hash tables. */
Dave Barachc3799992016-08-15 11:12:27 -040053typedef struct hash_header
54{
Ed Warnickecb9cada2015-12-08 15:45:58 -070055 /* Number of elements in hash table. */
56 uword elts;
57
58 /* Flags as follows. */
59 u32 flags;
60
61 /* Set if user does not want table to auto-resize when sufficiently full. */
62#define HASH_FLAG_NO_AUTO_GROW (1 << 0)
63 /* Set if user does not want table to auto-resize when sufficiently empty. */
64#define HASH_FLAG_NO_AUTO_SHRINK (1 << 1)
65 /* Set when hash_next is in the process of iterating through this hash table. */
66#define HASH_FLAG_HASH_NEXT_IN_PROGRESS (1 << 2)
67
68 u32 log2_pair_size;
69
70 /* Function to compute the "sum" of a hash key.
71 Hash function is this sum modulo the prime size of
72 the hash table (vec_len (v)). */
Dave Barachc3799992016-08-15 11:12:27 -040073 hash_key_sum_function_t *key_sum;
Ed Warnickecb9cada2015-12-08 15:45:58 -070074
75 /* Special values for key_sum "function". */
Dave Barachc3799992016-08-15 11:12:27 -040076#define KEY_FUNC_NONE (0) /*< sum = key */
77#define KEY_FUNC_POINTER_UWORD (1) /*< sum = *(uword *) key */
78#define KEY_FUNC_POINTER_U32 (2) /*< sum = *(u32 *) key */
79#define KEY_FUNC_STRING (3) /*< sum = string_key_sum, etc. */
Ole Troan73710c72018-06-04 22:27:49 +020080#define KEY_FUNC_MEM (4) /*< sum = mem_key_sum */
Ed Warnickecb9cada2015-12-08 15:45:58 -070081
82 /* key comparison function */
Dave Barachc3799992016-08-15 11:12:27 -040083 hash_key_equal_function_t *key_equal;
Ed Warnickecb9cada2015-12-08 15:45:58 -070084
85 /* Hook for user's data. Used to parameterize sum/equal functions. */
86 any user;
87
88 /* Format a (k,v) pair */
Dave Barachc3799992016-08-15 11:12:27 -040089 format_function_t *format_pair;
Ed Warnickecb9cada2015-12-08 15:45:58 -070090
91 /* Format function arg */
Dave Barachc3799992016-08-15 11:12:27 -040092 void *format_pair_arg;
Ed Warnickecb9cada2015-12-08 15:45:58 -070093
94 /* Bit i is set if pair i is a user object (as opposed to being
95 either zero or an indirect array of pairs). */
Damjan Marion2b702da2022-03-17 17:54:48 +010096 uword *is_user;
Ed Warnickecb9cada2015-12-08 15:45:58 -070097} hash_t;
98
Ed Warnickecb9cada2015-12-08 15:45:58 -070099/* Returns a pointer to the hash header given the vector pointer */
Dave Barachc3799992016-08-15 11:12:27 -0400100always_inline hash_t *
101hash_header (void *v)
102{
Damjan Mariona4a28f02022-03-17 15:46:25 +0100103 return vec_header (v);
Dave Barachc3799992016-08-15 11:12:27 -0400104}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105
106/* Number of elements in the hash table */
Dave Barachc3799992016-08-15 11:12:27 -0400107always_inline uword
108hash_elts (void *v)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700109{
Dave Barachc3799992016-08-15 11:12:27 -0400110 hash_t *h = hash_header (v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700111 return v ? h->elts : 0;
112}
113
114/* Number of elements the hash table can hold */
Dave Barachc3799992016-08-15 11:12:27 -0400115always_inline uword
116hash_capacity (void *v)
117{
118 return vec_len (v);
119}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700120
121/* Returns 1 if the hash pair contains user data */
Dave Barachc3799992016-08-15 11:12:27 -0400122always_inline uword
123hash_is_user (void *v, uword i)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700124{
Dave Barachc3799992016-08-15 11:12:27 -0400125 hash_t *h = hash_header (v);
Gabriel Oginski813c1bd2022-10-21 07:05:56 +0000126 uword bits = BITS (h->is_user[0]);
127 uword i0 = i / bits;
128 uword i1 = i % bits;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700129 return (h->is_user[i0] & ((uword) 1 << i1)) != 0;
130}
131
132/* Set the format function and format argument for a hash table */
133always_inline void
Dave Barachc3799992016-08-15 11:12:27 -0400134hash_set_pair_format (void *v,
135 format_function_t * format_pair, void *format_pair_arg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700136{
Dave Barachc3799992016-08-15 11:12:27 -0400137 hash_t *h = hash_header (v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700138 h->format_pair = format_pair;
139 h->format_pair_arg = format_pair_arg;
140}
141
142/* Set hash table flags */
Dave Barachc3799992016-08-15 11:12:27 -0400143always_inline void
144hash_set_flags (void *v, uword flags)
145{
146 hash_header (v)->flags |= flags;
147}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700148
149/* Key value pairs. */
Dave Barachc3799992016-08-15 11:12:27 -0400150typedef struct
151{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700152 /* The Key */
153 uword key;
154
155 /* The Value. Length is 2^log2_pair_size - 1. */
156 uword value[0];
157} hash_pair_t;
158
159/* The indirect pair structure
160
161 If log2_pair_size > 0 we overload hash pairs
162 with indirect pairs for buckets with more than one
163 pair. */
Dave Barachc3799992016-08-15 11:12:27 -0400164typedef struct
165{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700166 /* pair vector */
Dave Barachc3799992016-08-15 11:12:27 -0400167 hash_pair_t *pairs;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700168 /* padding */
Dave Barachc3799992016-08-15 11:12:27 -0400169 u8 pad[sizeof (uword) - sizeof (hash_pair_t *)];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170 /* allocated length */
171 uword alloc_len;
Dave Barachc3799992016-08-15 11:12:27 -0400172}
173hash_pair_indirect_t;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174
175/* Direct / Indirect pair union */
Dave Barachc3799992016-08-15 11:12:27 -0400176typedef union
177{
178 hash_pair_t direct;
179 hash_pair_indirect_t indirect;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700180} hash_pair_union_t;
181
182#define LOG2_ALLOC_BITS (5)
183#define PAIR_BITS (BITS (uword) - LOG2_ALLOC_BITS)
184
185/* Log2 number of bytes allocated in pairs array. */
Dave Barachc3799992016-08-15 11:12:27 -0400186always_inline uword
187indirect_pair_get_log2_bytes (hash_pair_indirect_t * p)
188{
189 return p->alloc_len >> PAIR_BITS;
190}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700191
192/* Get the length of an indirect pair */
193always_inline uword
194indirect_pair_get_len (hash_pair_indirect_t * p)
195{
Dave Barachc3799992016-08-15 11:12:27 -0400196 if (!p->pairs)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700197 return 0;
198 else
199 return p->alloc_len & (((uword) 1 << PAIR_BITS) - 1);
200}
201
202/* Set the length of an indirect pair */
203always_inline void
Dave Barachc3799992016-08-15 11:12:27 -0400204indirect_pair_set (hash_pair_indirect_t * p, uword log2_alloc, uword len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700205{
206 ASSERT (len < ((uword) 1 << PAIR_BITS));
207 ASSERT (log2_alloc < ((uword) 1 << LOG2_ALLOC_BITS));
208 p->alloc_len = (log2_alloc << PAIR_BITS) | len;
209}
210
211/* internal routine to fetch value for given key */
Dave Barachc3799992016-08-15 11:12:27 -0400212uword *_hash_get (void *v, uword key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213
214/* internal routine to fetch value (key, value) pair for given key */
Dave Barachc3799992016-08-15 11:12:27 -0400215hash_pair_t *_hash_get_pair (void *v, uword key);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216
217/* internal routine to unset a (key, value) pair */
Dave Barachc3799992016-08-15 11:12:27 -0400218void *_hash_unset (void *v, uword key, void *old_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700219
220/* internal routine to set a (key, value) pair, return the old value */
Dave Barachc3799992016-08-15 11:12:27 -0400221void *_hash_set3 (void *v, uword key, void *value, void *old_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700222
223/* Resize a hash table */
Dave Barachc3799992016-08-15 11:12:27 -0400224void *hash_resize (void *old, uword new_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225
226/* duplicate a hash table */
Dave Barachc3799992016-08-15 11:12:27 -0400227void *hash_dup (void *old);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700228
229/* Returns the number of bytes used by a hash table */
Dave Barachc3799992016-08-15 11:12:27 -0400230uword hash_bytes (void *v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700231
232/* Public macro to set a (key, value) pair, return the old value */
233#define hash_set3(h,key,value,old_value) \
234({ \
235 uword _v = (uword) (value); \
236 (h) = _hash_set3 ((h), (uword) (key), (void *) &_v, (old_value)); \
237})
238
239/* Public macro to fetch value for given key */
240#define hash_get(h,key) _hash_get ((h), (uword) (key))
241
242/* Public macro to fetch value (key, value) pair for given key */
243#define hash_get_pair(h,key) _hash_get_pair ((h), (uword) (key))
244
245/* Public macro to set a (key, value) pair */
246#define hash_set(h,key,value) hash_set3(h,key,value,0)
247
248/* Public macro to set (key, 0) pair */
249#define hash_set1(h,key) (h) = _hash_set3(h,(uword) (key),0,0)
250
251/* Public macro to unset a (key, value) pair */
252#define hash_unset(h,key) ((h) = _hash_unset ((h), (uword) (key),0))
253
254/* Public macro to unset a (key, value) pair, return the old value */
255#define hash_unset3(h,key,old_value) ((h) = _hash_unset ((h), (uword) (key), (void *) (old_value)))
256
257/* get/set/unset for pointer keys. */
258
259/* Public macro to fetch value for given pointer key */
260#define hash_get_mem(h,key) _hash_get ((h), pointer_to_uword (key))
261
262/* Public macro to fetch (key, value) for given pointer key */
263#define hash_get_pair_mem(h,key) _hash_get_pair ((h), pointer_to_uword (key))
264
265/* Public macro to set (key, value) for pointer key */
266#define hash_set_mem(h,key,value) hash_set3 (h, pointer_to_uword (key), (value), 0)
267
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700268/* Public inline function allocate and copy key to use in hash for pointer key */
John Loe6bfeab2018-01-04 16:39:42 -0500269always_inline void
Neale Rannsc190cf02020-01-06 21:09:12 +0000270hash_set_mem_alloc (uword ** h, const void *key, uword v)
John Loe6bfeab2018-01-04 16:39:42 -0500271{
Damjan Marion56f54af2021-10-12 20:30:02 +0200272 int objsize = __builtin_object_size (key, 0);
John Loe6bfeab2018-01-04 16:39:42 -0500273 size_t ksz = hash_header (*h)->user;
Damjan Marion56f54af2021-10-12 20:30:02 +0200274 void *copy;
275 if (objsize > 0)
276 {
277 ASSERT (objsize == ksz);
278 copy = clib_mem_alloc (objsize);
279 clib_memcpy_fast (copy, key, objsize);
280 }
281 else
282 {
283 copy = clib_mem_alloc (ksz);
284 clib_memcpy_fast (copy, key, ksz);
285 }
John Loe6bfeab2018-01-04 16:39:42 -0500286 hash_set_mem (*h, copy, v);
287}
288
Ed Warnickecb9cada2015-12-08 15:45:58 -0700289/* Public macro to set (key, 0) for pointer key */
290#define hash_set1_mem(h,key) hash_set3 ((h), pointer_to_uword (key), 0, 0)
291
292/* Public macro to unset (key, value) for pointer key */
293#define hash_unset_mem(h,key) ((h) = _hash_unset ((h), pointer_to_uword (key),0))
294
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700295/* Public inline function to unset pointer key and then free the key memory */
John Loe6bfeab2018-01-04 16:39:42 -0500296always_inline void
Neale Rannsc190cf02020-01-06 21:09:12 +0000297hash_unset_mem_free (uword ** h, const void *key)
John Loe6bfeab2018-01-04 16:39:42 -0500298{
299 hash_pair_t *hp = hash_get_pair_mem (*h, key);
John Lo5957a142018-01-18 12:44:50 -0500300 if (PREDICT_TRUE (hp != NULL))
301 {
Neale Rannsc190cf02020-01-06 21:09:12 +0000302 void *_k = uword_to_pointer (hp->key, void *);
303 hash_unset_mem (*h, _k);
304 clib_mem_free (_k);
John Lo5957a142018-01-18 12:44:50 -0500305 }
John Loe6bfeab2018-01-04 16:39:42 -0500306}
307
Ed Warnickecb9cada2015-12-08 15:45:58 -0700308/* internal routine to free a hash table */
Dave Barachc3799992016-08-15 11:12:27 -0400309extern void *_hash_free (void *v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700310
311/* Public macro to free a hash table */
312#define hash_free(h) (h) = _hash_free ((h))
313
Dave Barachc3799992016-08-15 11:12:27 -0400314clib_error_t *hash_validate (void *v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700315
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700316/* Public inline function to get the number of value bytes for a hash table */
Dave Barachc3799992016-08-15 11:12:27 -0400317always_inline uword
318hash_value_bytes (hash_t * h)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700319{
Dave Barachc3799992016-08-15 11:12:27 -0400320 hash_pair_t *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700321 return (sizeof (p->value[0]) << h->log2_pair_size) - sizeof (p->key);
322}
323
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700324/* Public inline function to get log2(size of a (key,value) pair) */
Dave Barachc3799992016-08-15 11:12:27 -0400325always_inline uword
326hash_pair_log2_bytes (hash_t * h)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700327{
328 uword log2_bytes = h->log2_pair_size;
Dave Barachc3799992016-08-15 11:12:27 -0400329 ASSERT (BITS (hash_pair_t) == 32 || BITS (hash_pair_t) == 64);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700330 if (BITS (hash_pair_t) == 32)
331 log2_bytes += 2;
332 else if (BITS (hash_pair_t) == 64)
333 log2_bytes += 3;
334 return log2_bytes;
335}
336
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700337/* Public inline function to get size of a (key,value) pair */
Dave Barachc3799992016-08-15 11:12:27 -0400338always_inline uword
339hash_pair_bytes (hash_t * h)
340{
341 return (uword) 1 << hash_pair_log2_bytes (h);
342}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700343
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700344/* Public inline function to advance a pointer past one (key,value) pair */
Dave Barachc3799992016-08-15 11:12:27 -0400345always_inline void *
346hash_forward1 (hash_t * h, void *v)
347{
348 return (u8 *) v + hash_pair_bytes (h);
349}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700350
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700351/* Public inline function to advance a pointer past N (key,value) pairs */
Dave Barachc3799992016-08-15 11:12:27 -0400352always_inline void *
353hash_forward (hash_t * h, void *v, uword n)
354{
355 return (u8 *) v + ((n * sizeof (hash_pair_t)) << h->log2_pair_size);
356}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700357
Chris Luke5cdaf632016-07-30 15:05:07 -0400358/** Iterate over hash pairs.
359
360 @param p The current (key,value) pair. This should be of type
361 <code>(hash_pair_t *)</code>.
362 @param v The hash table to iterate.
363 @param body The operation to perform on each (key,value) pair.
364
365 Executes the expression or code block @c body with each active hash pair.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700366*/
Chris Luke5cdaf632016-07-30 15:05:07 -0400367/* A previous version of this macro made use of the hash_pair_union_t
368 * structure; this version does not since that approach mightily upset
369 * the static analysis tool. In the rare chance someone is reading this
370 * code, pretend that _p below is of type hash_pair_union_t and that when
371 * used as an rvalue it's really using one of the union members as the
372 * rvalue. If you were confused before you might be marginally less
373 * confused after.
374 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700375#define hash_foreach_pair(p,v,body) \
376do { \
377 __label__ _hash_foreach_done; \
378 hash_t * _h = hash_header (v); \
Chris Luke5cdaf632016-07-30 15:05:07 -0400379 void * _p; \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700380 hash_pair_t * _q, * _q_end; \
381 uword _i, _i1, _id, _pair_increment; \
382 \
Chris Luke5cdaf632016-07-30 15:05:07 -0400383 _p = (v); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700384 _i = 0; \
385 _pair_increment = 1; \
386 if ((v)) \
387 _pair_increment = 1 << _h->log2_pair_size; \
388 while (_i < hash_capacity (v)) \
389 { \
390 _id = _h->is_user[_i / BITS (_h->is_user[0])]; \
391 _i1 = _i + BITS (_h->is_user[0]); \
392 \
393 do { \
394 if (_id & 1) \
395 { \
Chris Luke5cdaf632016-07-30 15:05:07 -0400396 _q = _p; \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700397 _q_end = _q + _pair_increment; \
398 } \
399 else \
400 { \
Chris Luke5cdaf632016-07-30 15:05:07 -0400401 hash_pair_indirect_t * _pi = _p; \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700402 _q = _pi->pairs; \
403 if (_h->log2_pair_size > 0) \
404 _q_end = hash_forward (_h, _q, indirect_pair_get_len (_pi)); \
405 else \
406 _q_end = vec_end (_q); \
407 } \
408 \
409 /* Loop through all elements in bucket. \
410 Bucket may have 0 1 or more (indirect case) pairs. */ \
411 while (_q < _q_end) \
412 { \
413 uword _break_in_body = 1; \
414 (p) = _q; \
415 do { \
416 body; \
417 _break_in_body = 0; \
418 } while (0); \
419 if (_break_in_body) \
420 goto _hash_foreach_done; \
421 _q += _pair_increment; \
422 } \
423 \
Chris Luke5cdaf632016-07-30 15:05:07 -0400424 _p = (hash_pair_t *)_p + _pair_increment; \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700425 _id = _id / 2; \
426 _i++; \
427 } while (_i < _i1); \
428 } \
429 _hash_foreach_done: \
430 /* Be silent Mr. Compiler-Warning. */ \
431 ; \
432 } while (0)
433
434/* Iterate over key/value pairs
435
436 @param key_var the current key
437 @param value_var the current value
438 @param h the hash table to iterate across
Dave Barachc3799992016-08-15 11:12:27 -0400439 @param body the operation to perform on each (key_var,value_var) pair.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700440
441 calls body with each active hash pair
442*/
Paul Vinciguerraec11b132018-09-24 05:25:00 -0700443/* Iterate over key/value pairs. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700444#define hash_foreach(key_var,value_var,h,body) \
445do { \
446 hash_pair_t * _r; \
447 hash_foreach_pair (_r, (h), { \
448 (key_var) = (__typeof__ (key_var)) _r->key; \
449 (value_var) = (__typeof__ (value_var)) _r->value[0]; \
450 do { body; } while (0); \
451 }); \
452} while (0)
453
454/* Iterate over key/value pairs for pointer key hash tables
455
456 @param key_var the current key
457 @param value_var the current value
458 @param h the hash table to iterate across
Dave Barachc3799992016-08-15 11:12:27 -0400459 @param body the operation to perform on each (key_var,value_var) pair.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700460
461 calls body with each active hash pair
462*/
463#define hash_foreach_mem(key_var,value_var,h,body) \
464do { \
465 hash_pair_t * _r; \
466 hash_foreach_pair (_r, (h), { \
467 (key_var) = (__typeof__ (key_var)) uword_to_pointer (_r->key, void *); \
468 (value_var) = (__typeof__ (value_var)) _r->value[0]; \
469 do { body; } while (0); \
470 }); \
471} while (0)
472
473/* Support for iteration through hash table. */
474
475/* This struct saves iteration state for hash_next.
476 None of these fields are meant to be visible to the user.
477 Hence, the cryptic short-hand names. */
Dave Barachc3799992016-08-15 11:12:27 -0400478typedef struct
479{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700480 uword i, j, f;
481} hash_next_t;
482
Dave Barachc3799992016-08-15 11:12:27 -0400483hash_pair_t *hash_next (void *v, hash_next_t * hn);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700484
Dave Barachc3799992016-08-15 11:12:27 -0400485void *_hash_create (uword elts, hash_t * h);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700486
Dave Barachc3799992016-08-15 11:12:27 -0400487always_inline void
488hash_set_value_bytes (hash_t * h, uword value_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489{
Dave Barachc3799992016-08-15 11:12:27 -0400490 hash_pair_t *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700491 h->log2_pair_size =
Dave Barachc3799992016-08-15 11:12:27 -0400492 max_log2 ((sizeof (p->key) + value_bytes + sizeof (p->key) -
493 1) / sizeof (p->key));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700494}
495
496#define hash_create2(_elts,_user,_value_bytes, \
497 _key_sum,_key_equal, \
498 _format_pair,_format_pair_arg) \
499({ \
500 hash_t _h; \
Dave Barachb7b92992018-10-17 10:38:51 -0400501 clib_memset (&_h, 0, sizeof (_h)); \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700502 _h.user = (_user); \
503 _h.key_sum = (hash_key_sum_function_t *) (_key_sum); \
504 _h.key_equal = (_key_equal); \
505 hash_set_value_bytes (&_h, (_value_bytes)); \
506 _h.format_pair = (format_function_t *) (_format_pair); \
507 _h.format_pair_arg = (_format_pair_arg); \
508 _hash_create ((_elts), &_h); \
509})
510
511/* Hash function based on that of Bob Jenkins (bob_jenkins@compuserve.com).
512 Public domain per: http://www.burtleburtle.net/bob/hash/doobs.html
513 Thanks, Bob. */
514
515#define hash_mix_step(a,b,c,s0,s1,s2) \
516do { \
517 (a) -= (b) + (c); (a) ^= (c) >> (s0); \
518 (b) -= (c) + (a); (b) ^= (a) << (s1); \
519 (c) -= (a) + (b); (c) ^= (b) >> (s2); \
520} while (0)
521
522#define hash_mix32_step_1(a,b,c) hash_mix_step(a,b,c,13,8,13)
523#define hash_mix32_step_2(a,b,c) hash_mix_step(a,b,c,12,16,5)
524#define hash_mix32_step_3(a,b,c) hash_mix_step(a,b,c,3,10,15)
525
526#define hash_mix64_step_1(a,b,c) hash_mix_step(a,b,c,43,9,8)
527#define hash_mix64_step_2(a,b,c) hash_mix_step(a,b,c,38,23,5)
528#define hash_mix64_step_3(a,b,c) hash_mix_step(a,b,c,35,49,11)
529#define hash_mix64_step_4(a,b,c) hash_mix_step(a,b,c,12,18,22)
530
Damjan Marion87997682022-03-26 00:57:50 +0100531#if uword_bits == 64
532#define hash_mix(a, b, c) hash_mix64 (a, b, c)
533#else
534#define hash_mix(a, b, c) hash_mix32 (a, b, c)
535#endif
536
Ed Warnickecb9cada2015-12-08 15:45:58 -0700537/* Hash function based on that of Bob Jenkins (bob_jenkins@compuserve.com).
538 Thanks, Bob. */
539#define hash_mix64(a0,b0,c0) \
540do { \
541 hash_mix64_step_1 (a0, b0, c0); \
542 hash_mix64_step_2 (a0, b0, c0); \
543 hash_mix64_step_3 (a0, b0, c0); \
544 hash_mix64_step_4 (a0, b0, c0); \
545} while (0) \
546
547#define hash_mix32(a0,b0,c0) \
548do { \
549 hash_mix32_step_1 (a0, b0, c0); \
550 hash_mix32_step_2 (a0, b0, c0); \
551 hash_mix32_step_3 (a0, b0, c0); \
552} while (0) \
553
554/* Finalize from Bob Jenkins lookup3.c */
555
556always_inline uword
557hash32_rotate_left (u32 x, u32 i)
Dave Barachc3799992016-08-15 11:12:27 -0400558{
559 return (x << i) | (x >> (BITS (i) - i));
560}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700561
562#define hash_v3_mix32(a,b,c) \
563do { \
564 (a) -= (c); (a) ^= hash32_rotate_left ((c), 4); (c) += (b); \
565 (b) -= (a); (b) ^= hash32_rotate_left ((a), 6); (a) += (c); \
566 (c) -= (b); (c) ^= hash32_rotate_left ((b), 8); (b) += (a); \
567 (a) -= (c); (a) ^= hash32_rotate_left ((c),16); (c) += (b); \
568 (b) -= (a); (b) ^= hash32_rotate_left ((a),19); (a) += (c); \
569 (c) -= (b); (c) ^= hash32_rotate_left ((b), 4); (b) += (a); \
570} while (0)
571
572#define hash_v3_finalize32(a,b,c) \
573do { \
574 (c) ^= (b); (c) -= hash32_rotate_left ((b), 14); \
575 (a) ^= (c); (a) -= hash32_rotate_left ((c), 11); \
576 (b) ^= (a); (b) -= hash32_rotate_left ((a), 25); \
577 (c) ^= (b); (c) -= hash32_rotate_left ((b), 16); \
578 (a) ^= (c); (a) -= hash32_rotate_left ((c), 4); \
579 (b) ^= (a); (b) -= hash32_rotate_left ((a), 14); \
580 (c) ^= (b); (c) -= hash32_rotate_left ((b), 24); \
581} while (0)
582
583/* 32 bit mixing/finalize in steps. */
584
585#define hash_v3_mix32_step1(a,b,c) \
586do { \
587 (a) -= (c); (a) ^= hash32_rotate_left ((c), 4); (c) += (b); \
588 (b) -= (a); (b) ^= hash32_rotate_left ((a), 6); (a) += (c); \
589} while (0)
590
591#define hash_v3_mix32_step2(a,b,c) \
592do { \
593 (c) -= (b); (c) ^= hash32_rotate_left ((b), 8); (b) += (a); \
594 (a) -= (c); (a) ^= hash32_rotate_left ((c),16); (c) += (b); \
595} while (0)
596
597#define hash_v3_mix32_step3(a,b,c) \
598do { \
599 (b) -= (a); (b) ^= hash32_rotate_left ((a),19); (a) += (c); \
600 (c) -= (b); (c) ^= hash32_rotate_left ((b), 4); (b) += (a); \
601} while (0)
602
603#define hash_v3_finalize32_step1(a,b,c) \
604do { \
605 (c) ^= (b); (c) -= hash32_rotate_left ((b), 14); \
606 (a) ^= (c); (a) -= hash32_rotate_left ((c), 11); \
607} while (0)
608
609#define hash_v3_finalize32_step2(a,b,c) \
610do { \
611 (b) ^= (a); (b) -= hash32_rotate_left ((a), 25); \
612 (c) ^= (b); (c) -= hash32_rotate_left ((b), 16); \
613} while (0)
614
615#define hash_v3_finalize32_step3(a,b,c) \
616do { \
617 (a) ^= (c); (a) -= hash32_rotate_left ((c), 4); \
618 (b) ^= (a); (b) -= hash32_rotate_left ((a), 14); \
619 (c) ^= (b); (c) -= hash32_rotate_left ((b), 24); \
620} while (0)
621
622/* Vector v3 mixing/finalize. */
623#define hash_v3_mix_step_1_u32x(a,b,c) \
624do { \
625 (a) -= (c); (a) ^= u32x_irotate_left ((c), 4); (c) += (b); \
626 (b) -= (a); (b) ^= u32x_irotate_left ((a), 6); (a) += (c); \
627 (c) -= (b); (c) ^= u32x_irotate_left ((b), 8); (b) += (a); \
628} while (0)
629
630#define hash_v3_mix_step_2_u32x(a,b,c) \
631do { \
632 (a) -= (c); (a) ^= u32x_irotate_left ((c),16); (c) += (b); \
633 (b) -= (a); (b) ^= u32x_irotate_left ((a),19); (a) += (c); \
634 (c) -= (b); (c) ^= u32x_irotate_left ((b), 4); (b) += (a); \
635} while (0)
636
637#define hash_v3_finalize_step_1_u32x(a,b,c) \
638do { \
639 (c) ^= (b); (c) -= u32x_irotate_left ((b), 14); \
640 (a) ^= (c); (a) -= u32x_irotate_left ((c), 11); \
641 (b) ^= (a); (b) -= u32x_irotate_left ((a), 25); \
642} while (0)
643
644#define hash_v3_finalize_step_2_u32x(a,b,c) \
645do { \
646 (c) ^= (b); (c) -= u32x_irotate_left ((b), 16); \
647 (a) ^= (c); (a) -= u32x_irotate_left ((c), 4); \
648 (b) ^= (a); (b) -= u32x_irotate_left ((a), 14); \
649 (c) ^= (b); (c) -= u32x_irotate_left ((b), 24); \
650} while (0)
651
652#define hash_v3_mix_u32x(a,b,c) \
653do { \
654 hash_v3_mix_step_1_u32x(a,b,c); \
655 hash_v3_mix_step_2_u32x(a,b,c); \
656} while (0)
657
658#define hash_v3_finalize_u32x(a,b,c) \
659do { \
660 hash_v3_finalize_step_1_u32x(a,b,c); \
661 hash_v3_finalize_step_2_u32x(a,b,c); \
662} while (0)
663
Dave Barachc3799992016-08-15 11:12:27 -0400664extern uword hash_memory (void *p, word n_bytes, uword state);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700665
666extern uword mem_key_sum (hash_t * h, uword key);
667extern uword mem_key_equal (hash_t * h, uword key1, uword key2);
668
669#define hash_create_mem(elts,key_bytes,value_bytes) \
670 hash_create2((elts),(key_bytes),(value_bytes),mem_key_sum,mem_key_equal,0,0)
671
672extern uword vec_key_sum (hash_t * h, uword key);
673extern uword vec_key_equal (hash_t * h, uword key1, uword key2);
Dave Barachc3799992016-08-15 11:12:27 -0400674extern u8 *vec_key_format_pair (u8 * s, va_list * args);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700675
676#define hash_create_vec(elts,key_bytes,value_bytes) \
677 hash_create2((elts),(key_bytes),(value_bytes),\
678 vec_key_sum,vec_key_equal,vec_key_format_pair,0)
679
680extern uword string_key_sum (hash_t * h, uword key);
681extern uword string_key_equal (hash_t * h, uword key1, uword key2);
Dave Barachc3799992016-08-15 11:12:27 -0400682extern u8 *string_key_format_pair (u8 * s, va_list * args);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700683
Ole Troan73710c72018-06-04 22:27:49 +0200684/*
685 * Note: if you plan to put a hash into shared memory,
686 * the key sum and key equal functions MUST be set to magic constants!
687 * PIC means that whichever process sets up the hash won't have
688 * the actual key sum functions at the same place, leading to
689 * very hard-to-find bugs...
690 */
691
692#define hash_create_shmem(elts,key_bytes,value_bytes) \
693 hash_create2((elts),(key_bytes),(value_bytes), \
694 (hash_key_sum_function_t *) KEY_FUNC_MEM, \
695 (hash_key_equal_function_t *)KEY_FUNC_MEM, \
696 0, 0)
697
Ed Warnickecb9cada2015-12-08 15:45:58 -0700698#define hash_create_string(elts,value_bytes) \
699 hash_create2((elts),0,(value_bytes), \
700 (hash_key_sum_function_t *) KEY_FUNC_STRING, \
701 (hash_key_equal_function_t *)KEY_FUNC_STRING, \
702 0, 0)
703
704#define hash_create(elts,value_bytes) \
705 hash_create2((elts),0,(value_bytes), \
706 (hash_key_sum_function_t *) KEY_FUNC_NONE, \
707 (hash_key_equal_function_t *) KEY_FUNC_NONE, \
708 0,0)
709
710#define hash_create_uword(elts,value_bytes) \
711 hash_create2((elts),0,(value_bytes), \
712 (hash_key_sum_function_t *) KEY_FUNC_POINTER_UWORD, \
713 (hash_key_equal_function_t *) KEY_FUNC_POINTER_UWORD, \
714 0,0)
715
716#define hash_create_u32(elts,value_bytes) \
717 hash_create2((elts),0,(value_bytes), \
718 (hash_key_sum_function_t *) KEY_FUNC_POINTER_U32, \
719 (hash_key_equal_function_t *) KEY_FUNC_POINTER_U32, \
720 0,0)
721
Dave Barachc3799992016-08-15 11:12:27 -0400722u8 *format_hash (u8 * s, va_list * va);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700723
724/* Looks up input in hash table indexed by either vec string or
725 c string (null terminated). */
726unformat_function_t unformat_hash_vec_string;
727unformat_function_t unformat_hash_string;
728
Dave Barachc3799992016-08-15 11:12:27 -0400729/* Main test routine. */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700730int test_hash_main (unformat_input_t * input);
731
732#endif /* included_hash_h */
Dave Barachc3799992016-08-15 11:12:27 -0400733
734/*
735 * fd.io coding-style-patch-verification: ON
736 *
737 * Local Variables:
738 * eval: (c-set-style "gnu")
739 * End:
740 */