CNDP  22.08.0
cne_fbk_hash.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2010-2022 Intel Corporation
3  */
4 
5 #ifndef _CNE_FBK_HASH_H_
6 #define _CNE_FBK_HASH_H_
7 
18 #include <stdint.h> // for uint32_t, uint16_t, uint64_t
19 #include <errno.h> // for ENOENT, ENOSPC
20 #include <sys/queue.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #include <string.h> // for memset
27 #include <cne_hash_crc.h>
28 #include <cne_jhash.h>
29 
30 #ifndef CNE_FBK_HASH_INIT_VAL_DEFAULT
32 #define CNE_FBK_HASH_INIT_VAL_DEFAULT 0xFFFFFFFF
33 #endif
34 
36 #define CNE_FBK_HASH_ENTRIES_MAX (1 << 20)
37 
39 #define CNE_FBK_HASH_ENTRIES_PER_BUCKET_MAX 256
40 
42 #define CNE_FBK_HASH_NAMESIZE 32
43 
45 typedef uint32_t (*cne_fbk_hash_fn)(uint32_t key, uint32_t init_val);
46 
49  const char *name;
50  uint32_t entries;
51  uint32_t entries_per_bucket;
52  int socket_id;
54  uint32_t init_val;
55 };
56 
59  uint64_t whole_entry;
60  struct {
61  uint16_t is_entry;
62  uint16_t value;
63  uint32_t key;
64  } entry;
65 };
66 
70  uint32_t entries;
71  uint32_t entries_per_bucket;
72  uint32_t used_entries;
73  uint32_t bucket_mask;
74  uint32_t bucket_shift;
76  uint32_t init_val;
79  union cne_fbk_hash_entry t[];
80 };
81 
92 static inline uint32_t
93 cne_fbk_hash_get_bucket(const struct cne_fbk_hash_table *ht, uint32_t key)
94 {
95  return (ht->hash_func(key, ht->init_val) & ht->bucket_mask) << ht->bucket_shift;
96 }
97 
114 static inline int
116  uint32_t bucket)
117 {
118  /*
119  * The writing of a new value to the hash table is done as a single
120  * 64bit operation. This should help prevent individual entries being
121  * corrupted due to race conditions, but it's still possible to
122  * overwrite entries that have just been made valid.
123  */
124  const uint64_t new_entry =
125  ((uint64_t)(key) << 32) | ((uint64_t)(value) << 16) | 1; /* 1 = is_entry bit. */
126  uint32_t i;
127 
128  for (i = 0; i < ht->entries_per_bucket; i++) {
129  /* Set entry if unused. */
130  if (!ht->t[bucket + i].entry.is_entry) {
131  ht->t[bucket + i].whole_entry = new_entry;
132  ht->used_entries++;
133  return 0;
134  }
135  /* Change value if key already exists. */
136  if (ht->t[bucket + i].entry.key == key) {
137  ht->t[bucket + i].entry.value = value;
138  return 0;
139  }
140  }
141 
142  return -ENOSPC; /* No space in bucket. */
143 }
144 
158 static inline int
159 cne_fbk_hash_add_key(struct cne_fbk_hash_table *ht, uint32_t key, uint16_t value)
160 {
162 }
163 
178 static inline int
179 cne_fbk_hash_delete_key_with_bucket(struct cne_fbk_hash_table *ht, uint32_t key, uint32_t bucket)
180 {
181  uint32_t last_entry = ht->entries_per_bucket - 1;
182  uint32_t i, j;
183 
184  for (i = 0; i < ht->entries_per_bucket; i++) {
185  if (ht->t[bucket + i].entry.key == key) {
186  /* Find last key in bucket. */
187  for (j = ht->entries_per_bucket - 1; j > i; j--) {
188  if (!ht->t[bucket + j].entry.is_entry) {
189  last_entry = j - 1;
190  }
191  }
192  /*
193  * Move the last key to the deleted key's position, and
194  * delete the last key. lastEntry and i may be same but
195  * it doesn't matter.
196  */
197  ht->t[bucket + i].whole_entry = ht->t[bucket + last_entry].whole_entry;
198  ht->t[bucket + last_entry].whole_entry = 0;
199 
200  ht->used_entries--;
201  return 0;
202  }
203  }
204 
205  return -ENOENT; /* Key didn't exist. */
206 }
207 
219 static inline int
221 {
223 }
224 
238 static inline int
239 cne_fbk_hash_lookup_with_bucket(const struct cne_fbk_hash_table *ht, uint32_t key, uint32_t bucket)
240 {
241  union cne_fbk_hash_entry current_entry;
242  uint32_t i;
243 
244  for (i = 0; i < ht->entries_per_bucket; i++) {
245  /* Single read of entry, which should be atomic. */
246  current_entry.whole_entry = ht->t[bucket + i].whole_entry;
247  if (!current_entry.entry.is_entry) {
248  return -ENOENT; /* Error once we hit an empty field. */
249  }
250  if (current_entry.entry.key == key) {
251  return current_entry.entry.value;
252  }
253  }
254  return -ENOENT; /* Key didn't exist. */
255 }
256 
267 static inline int
268 cne_fbk_hash_lookup(const struct cne_fbk_hash_table *ht, uint32_t key)
269 {
271 }
272 
280 static inline void
282 {
283  memset(ht->t, 0, sizeof(ht->t[0]) * ht->entries);
284  ht->used_entries = 0;
285 }
286 
295 static inline double
297 {
298  return (double)ht->used_entries / (double)ht->entries;
299 }
300 
314 
333 
342 
343 #ifdef __cplusplus
344 }
345 #endif
346 
347 #endif /* _CNE_FBK_HASH_H_ */
static double cne_fbk_hash_get_load_factor(struct cne_fbk_hash_table *ht)
Definition: cne_fbk_hash.h:296
static void cne_fbk_hash_clear_all(struct cne_fbk_hash_table *ht)
Definition: cne_fbk_hash.h:281
struct cne_fbk_hash_table * cne_fbk_hash_create(const struct cne_fbk_hash_params *params)
static int cne_fbk_hash_lookup_with_bucket(const struct cne_fbk_hash_table *ht, uint32_t key, uint32_t bucket)
Definition: cne_fbk_hash.h:239
static int cne_fbk_hash_delete_key_with_bucket(struct cne_fbk_hash_table *ht, uint32_t key, uint32_t bucket)
Definition: cne_fbk_hash.h:179
void cne_fbk_hash_free(struct cne_fbk_hash_table *ht)
uint32_t(* cne_fbk_hash_fn)(uint32_t key, uint32_t init_val)
Definition: cne_fbk_hash.h:45
static uint32_t cne_fbk_hash_get_bucket(const struct cne_fbk_hash_table *ht, uint32_t key)
Definition: cne_fbk_hash.h:93
static int cne_fbk_hash_delete_key(struct cne_fbk_hash_table *ht, uint32_t key)
Definition: cne_fbk_hash.h:220
#define CNE_FBK_HASH_NAMESIZE
Definition: cne_fbk_hash.h:42
static int cne_fbk_hash_add_key(struct cne_fbk_hash_table *ht, uint32_t key, uint16_t value)
Definition: cne_fbk_hash.h:159
static int cne_fbk_hash_add_key_with_bucket(struct cne_fbk_hash_table *ht, uint32_t key, uint16_t value, uint32_t bucket)
Definition: cne_fbk_hash.h:115
struct cne_fbk_hash_table * cne_fbk_hash_find_existing(const char *name)
static int cne_fbk_hash_lookup(const struct cne_fbk_hash_table *ht, uint32_t key)
Definition: cne_fbk_hash.h:268
cne_fbk_hash_fn hash_func
Definition: cne_fbk_hash.h:53
const char * name
Definition: cne_fbk_hash.h:49
uint32_t entries_per_bucket
Definition: cne_fbk_hash.h:51
cne_fbk_hash_fn hash_func
Definition: cne_fbk_hash.h:75
union cne_fbk_hash_entry t[]
Definition: cne_fbk_hash.h:79
uint32_t bucket_shift
Definition: cne_fbk_hash.h:74
char name[CNE_FBK_HASH_NAMESIZE]
Definition: cne_fbk_hash.h:69
uint32_t bucket_mask
Definition: cne_fbk_hash.h:73
uint32_t used_entries
Definition: cne_fbk_hash.h:72
uint32_t entries_per_bucket
Definition: cne_fbk_hash.h:71
Definition: cne_fbk_hash.h:58
uint64_t whole_entry
Definition: cne_fbk_hash.h:59
uint32_t key
Definition: cne_fbk_hash.h:63
uint16_t value
Definition: cne_fbk_hash.h:62
struct cne_fbk_hash_entry::@28 entry
uint16_t is_entry
Definition: cne_fbk_hash.h:61