xref: /f-stack/dpdk/lib/librte_member/rte_member.h (revision 2d9fd380)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Intel Corporation
3  */
4 
5 /**
6  * @file
7  *
8  * RTE Membership Library
9  *
10  * The Membership Library is an extension and generalization of a traditional
11  * filter (for example Bloom Filter and cuckoo filter) structure that has
12  * multiple usages in a variety of workloads and applications. The library is
13  * used to test if a key belongs to certain sets. Two types of such
14  * "set-summary" structures are implemented: hash-table based (HT) and vector
15  * bloom filter (vBF). For HT setsummary, two subtypes or modes are available,
16  * cache and non-cache modes. The table below summarize some properties of
17  * the different implementations.
18  *
19  * @warning
20  * @b EXPERIMENTAL: this API may change without prior notice
21  */
22 
23 /**
24  * <!--
25  * +==========+=====================+================+=========================+
26  * |   type   |      vbf            |     HT-cache   |     HT-non-cache        |
27  * +==========+=====================+==========================================+
28  * |structure |  bloom-filter array |  hash-table like without storing key     |
29  * +----------+---------------------+------------------------------------------+
30  * |set id    | limited by bf count |           [1, 0x7fff]                    |
31  * |          | up to 32.           |                                          |
32  * +----------+---------------------+------------------------------------------+
33  * |usages &  | small set range,    | can delete,    | cache most recent keys, |
34  * |properties| user-specified      | big set range, | have both false-positive|
35  * |          | false-positive rate,| small false    | and false-negative      |
36  * |          | no deletion support.| positive depend| depend on table size,   |
37  * |          |                     | on table size, | automatic overwritten.  |
38  * |          |                     | new key does   |                         |
39  * |          |                     | not overwrite  |                         |
40  * |          |                     | existing key.  |                         |
41  * +----------+---------------------+----------------+-------------------------+
42  * -->
43  */
44 
45 #ifndef _RTE_MEMBER_H_
46 #define _RTE_MEMBER_H_
47 
48 #ifdef __cplusplus
49 extern "C" {
50 #endif
51 
52 #include <stdint.h>
53 
54 #include <rte_common.h>
55 #include <rte_config.h>
56 
57 /** The set ID type that stored internally in hash table based set summary. */
58 typedef uint16_t member_set_t;
59 /** Invalid set ID used to mean no match found. */
60 #define RTE_MEMBER_NO_MATCH 0
61 /** Maximum size of hash table that can be created. */
62 #define RTE_MEMBER_ENTRIES_MAX (1 << 30)
63 /** Maximum number of keys that can be searched as a bulk */
64 #define RTE_MEMBER_LOOKUP_BULK_MAX 64
65 /** Entry count per bucket in hash table based mode. */
66 #define RTE_MEMBER_BUCKET_ENTRIES 16
67 /** Maximum number of characters in setsum name. */
68 #define RTE_MEMBER_NAMESIZE 32
69 
70 /** @internal Hash function used by membership library. */
71 #if defined(RTE_ARCH_X86) || defined(__ARM_FEATURE_CRC32)
72 #include <rte_hash_crc.h>
73 #define MEMBER_HASH_FUNC       rte_hash_crc
74 #else
75 #include <rte_jhash.h>
76 #define MEMBER_HASH_FUNC       rte_jhash
77 #endif
78 
79 extern int librte_member_logtype;
80 
81 #define RTE_MEMBER_LOG(level, ...) \
82 	rte_log(RTE_LOG_ ## level, \
83 		librte_member_logtype, \
84 		RTE_FMT("%s(): " RTE_FMT_HEAD(__VA_ARGS__,), \
85 			__func__, \
86 			RTE_FMT_TAIL(__VA_ARGS__,)))
87 
88 /** @internal setsummary structure. */
89 struct rte_member_setsum;
90 
91 /**
92  * @warning
93  * @b EXPERIMENTAL: this API may change without prior notice
94  *
95  * Parameter struct used to create set summary
96  */
97 struct rte_member_parameters;
98 
99 /**
100  * @warning
101  * @b EXPERIMENTAL: this API may change without prior notice
102  *
103  * Define different set summary types
104  */
105 enum rte_member_setsum_type {
106 	RTE_MEMBER_TYPE_HT = 0,  /**< Hash table based set summary. */
107 	RTE_MEMBER_TYPE_VBF,     /**< Vector of bloom filters. */
108 	RTE_MEMBER_NUM_TYPE
109 };
110 
111 /** @internal compare function for different arch. */
112 enum rte_member_sig_compare_function {
113 	RTE_MEMBER_COMPARE_SCALAR = 0,
114 	RTE_MEMBER_COMPARE_AVX2,
115 	RTE_MEMBER_COMPARE_NUM
116 };
117 
118 /** @internal setsummary structure. */
119 struct rte_member_setsum {
120 	enum rte_member_setsum_type type; /* Type of the set summary. */
121 	uint32_t key_len;		/* Length of key. */
122 	uint32_t prim_hash_seed;	/* Primary hash function seed. */
123 	uint32_t sec_hash_seed;		/* Secondary hash function seed. */
124 
125 	/* Hash table based. */
126 	uint32_t bucket_cnt;		/* Number of buckets. */
127 	uint32_t bucket_mask;		/* Bit mask to get bucket index. */
128 	/* For runtime selecting AVX, scalar, etc for signature comparison. */
129 	enum rte_member_sig_compare_function sig_cmp_fn;
130 	uint8_t cache;			/* If it is cache mode for ht based. */
131 
132 	/* Vector bloom filter. */
133 	uint32_t num_set;		/* Number of set (bf) in vbf. */
134 	uint32_t bits;			/* Number of bits in each bf. */
135 	uint32_t bit_mask;	/* Bit mask to get bit location in bf. */
136 	uint32_t num_hashes;	/* Number of hash values to index bf. */
137 
138 	uint32_t mul_shift;  /* vbf internal variable used during bit test. */
139 	uint32_t div_shift;  /* vbf internal variable used during bit test. */
140 
141 	void *table;	/* This is the handler of hash table or vBF array. */
142 
143 
144 	/* Second cache line should start here. */
145 	uint32_t socket_id;          /* NUMA Socket ID for memory. */
146 	char name[RTE_MEMBER_NAMESIZE]; /* Name of this set summary. */
147 } __rte_cache_aligned;
148 
149 /**
150  * @warning
151  * @b EXPERIMENTAL: this API may change without prior notice
152  *
153  * Parameters used when create the set summary table. Currently user can
154  * specify two types of setsummary: HT based and vBF. For HT based, user can
155  * specify cache or non-cache mode. Here is a table to describe some differences
156  *
157  */
158 struct rte_member_parameters {
159 	const char *name;			/**< Name of the hash. */
160 
161 	/**
162 	 * User to specify the type of the setsummary from one of
163 	 * rte_member_setsum_type.
164 	 *
165 	 * HT based setsummary is implemented like a hash table. User should use
166 	 * this type when there are many sets.
167 	 *
168 	 * vBF setsummary is a vector of bloom filters. It is used when number
169 	 * of sets is not big (less than 32 for current implementation).
170 	 */
171 	enum rte_member_setsum_type type;
172 
173 	/**
174 	 * is_cache is only used for HT based setsummary.
175 	 *
176 	 * If it is HT based setsummary, user to specify the subtype or mode
177 	 * of the setsummary. It could be cache, or non-cache mode.
178 	 * Set is_cache to be 1 if to use as cache mode.
179 	 *
180 	 * For cache mode, keys can be evicted out of the HT setsummary. Keys
181 	 * with the same signature and map to the same bucket
182 	 * will overwrite each other in the setsummary table.
183 	 * This mode is useful for the case that the set-summary only
184 	 * needs to keep record of the recently inserted keys. Both
185 	 * false-negative and false-positive could happen.
186 	 *
187 	 * For non-cache mode, keys cannot be evicted out of the cache. So for
188 	 * this mode the setsummary will become full eventually. Keys with the
189 	 * same signature but map to the same bucket will still occupy multiple
190 	 * entries. This mode does not give false-negative result.
191 	 */
192 	uint8_t is_cache;
193 
194 	/**
195 	 * For HT setsummary, num_keys equals to the number of entries of the
196 	 * table. When the number of keys inserted in the HT setsummary
197 	 * approaches this number, eviction could happen. For cache mode,
198 	 * keys could be evicted out of the table. For non-cache mode, keys will
199 	 * be evicted to other buckets like cuckoo hash. The table will also
200 	 * likely to become full before the number of inserted keys equal to the
201 	 * total number of entries.
202 	 *
203 	 * For vBF, num_keys equal to the expected number of keys that will
204 	 * be inserted into the vBF. The implementation assumes the keys are
205 	 * evenly distributed to each BF in vBF. This is used to calculate the
206 	 * number of bits we need for each BF. User does not specify the size of
207 	 * each BF directly because the optimal size depends on the num_keys
208 	 * and false positive rate.
209 	 */
210 	uint32_t num_keys;
211 
212 	/**
213 	 * The length of key is used for hash calculation. Since key is not
214 	 * stored in set-summary, large key does not require more memory space.
215 	 */
216 	uint32_t key_len;
217 
218 	/**
219 	 * num_set is only used for vBF, but not used for HT setsummary.
220 	 *
221 	 * num_set is equal to the number of BFs in vBF. For current
222 	 * implementation, it only supports 1,2,4,8,16,32 BFs in one vBF set
223 	 * summary. If other number of sets are needed, for example 5, the user
224 	 * should allocate the minimum available value that larger than 5,
225 	 * which is 8.
226 	 */
227 	uint32_t num_set;
228 
229 	/**
230 	 * false_positive_rate is only used for vBF, but not used for HT
231 	 * setsummary.
232 	 *
233 	 * For vBF, false_positive_rate is the user-defined false positive rate
234 	 * given expected number of inserted keys (num_keys). It is used to
235 	 * calculate the total number of bits for each BF, and the number of
236 	 * hash values used during lookup and insertion. For details please
237 	 * refer to vBF implementation and membership library documentation.
238 	 *
239 	 * For HT, This parameter is not directly set by users.
240 	 * HT setsummary's false positive rate is in the order of:
241 	 * false_pos = (1/bucket_count)*(1/2^16), since we use 16-bit signature.
242 	 * This is because two keys needs to map to same bucket and same
243 	 * signature to have a collision (false positive). bucket_count is equal
244 	 * to number of entries (num_keys) divided by entry count per bucket
245 	 * (RTE_MEMBER_BUCKET_ENTRIES). Thus, the false_positive_rate is not
246 	 * directly set by users for HT mode.
247 	 */
248 	float false_positive_rate;
249 
250 	/**
251 	 * We use two seeds to calculate two independent hashes for each key.
252 	 *
253 	 * For HT type, one hash is used as signature, and the other is used
254 	 * for bucket location.
255 	 * For vBF type, these two hashes and their combinations are used as
256 	 * hash locations to index the bit array.
257 	 */
258 	uint32_t prim_hash_seed;
259 
260 	/**
261 	 * The secondary seed should be a different value from the primary seed.
262 	 */
263 	uint32_t sec_hash_seed;
264 
265 	int socket_id;			/**< NUMA Socket ID for memory. */
266 };
267 
268 /**
269  * @warning
270  * @b EXPERIMENTAL: this API may change without prior notice
271  *
272  * Find an existing set-summary and return a pointer to it.
273  *
274  * @param name
275  *   Name of the set-summary.
276  * @return
277  *   Pointer to the set-summary or NULL if object not found
278  *   with rte_errno set appropriately. Possible rte_errno values include:
279  *    - ENOENT - value not available for return
280  */
281 struct rte_member_setsum *
282 rte_member_find_existing(const char *name);
283 
284 /**
285  * @warning
286  * @b EXPERIMENTAL: this API may change without prior notice
287  *
288  * Create set-summary (SS).
289  *
290  * @param params
291  *   Parameters to initialize the setsummary.
292  * @return
293  *   Return the pointer to the setsummary.
294  *   Return value is NULL if the creation failed.
295  */
296 struct rte_member_setsum *
297 rte_member_create(const struct rte_member_parameters *params);
298 
299 /**
300  * @warning
301  * @b EXPERIMENTAL: this API may change without prior notice
302  *
303  * Lookup key in set-summary (SS).
304  * Single key lookup and return as soon as the first match found
305  *
306  * @param setsum
307  *   Pointer of a setsummary.
308  * @param key
309  *   Pointer of the key to be looked up.
310  * @param set_id
311  *   Output the set id matches the key.
312  * @return
313  *   Return 1 for found a match and 0 for not found a match.
314  */
315 int
316 rte_member_lookup(const struct rte_member_setsum *setsum, const void *key,
317 			member_set_t *set_id);
318 
319 /**
320  * @warning
321  * @b EXPERIMENTAL: this API may change without prior notice
322  *
323  * Lookup bulk of keys in set-summary (SS).
324  * Each key lookup returns as soon as the first match found
325  *
326  * @param setsum
327  *   Pointer of a setsummary.
328  * @param keys
329  *   Pointer of the bulk of keys to be looked up.
330  * @param num_keys
331  *   Number of keys that will be lookup.
332  * @param set_ids
333  *   Output set ids for all the keys to this array.
334  *   User should preallocate array that can contain all results, which size is
335  *   the num_keys.
336  * @return
337  *   The number of keys that found a match.
338  */
339 int
340 rte_member_lookup_bulk(const struct rte_member_setsum *setsum,
341 			const void **keys, uint32_t num_keys,
342 			member_set_t *set_ids);
343 
344 /**
345  * @warning
346  * @b EXPERIMENTAL: this API may change without prior notice
347  *
348  * Lookup a key in set-summary (SS) for multiple matches.
349  * The key lookup will find all matched entries (multiple match).
350  * Note that for cache mode of HT, each key can have at most one match. This is
351  * because keys with same signature that maps to same bucket will overwrite
352  * each other. So multi-match lookup should be used for vBF and non-cache HT.
353  *
354  * @param setsum
355  *   Pointer of a set-summary.
356  * @param key
357  *   Pointer of the key that to be looked up.
358  * @param max_match_per_key
359  *   User specified maximum number of matches for each key. The function returns
360  *   as soon as this number of matches found for the key.
361  * @param set_id
362  *   Output set ids for all the matches of the key. User needs to preallocate
363  *   the array that can contain max_match_per_key number of results.
364  * @return
365  *   The number of matches that found for the key.
366  *   For cache mode HT set-summary, the number should be at most 1.
367  */
368 int
369 rte_member_lookup_multi(const struct rte_member_setsum *setsum,
370 		const void *key, uint32_t max_match_per_key,
371 		member_set_t *set_id);
372 
373 /**
374  * @warning
375  * @b EXPERIMENTAL: this API may change without prior notice
376  *
377  * Lookup a bulk of keys in set-summary (SS) for multiple matches each key.
378  * Each key lookup will find all matched entries (multiple match).
379  * Note that for cache mode HT, each key can have at most one match. So
380  * multi-match function is mainly used for vBF and non-cache mode HT.
381  *
382  * @param setsum
383  *   Pointer of a setsummary.
384  * @param keys
385  *   Pointer of the keys to be looked up.
386  * @param num_keys
387  *   The number of keys that will be lookup.
388  * @param max_match_per_key
389  *   The possible maximum number of matches for each key.
390  * @param match_count
391  *   Output the number of matches for each key in an array.
392  * @param set_ids
393  *   Return set ids for all the matches of all keys. Users pass in a
394  *   preallocated 2D array with first dimension as key index and second
395  *   dimension as match index. For example set_ids[bulk_size][max_match_per_key]
396  * @return
397  *   The number of keys that found one or more matches in the set-summary.
398  */
399 int
400 rte_member_lookup_multi_bulk(const struct rte_member_setsum *setsum,
401 		const void **keys, uint32_t num_keys,
402 		uint32_t max_match_per_key,
403 		uint32_t *match_count,
404 		member_set_t *set_ids);
405 
406 /**
407  * @warning
408  * @b EXPERIMENTAL: this API may change without prior notice
409  *
410  * Insert key into set-summary (SS).
411  *
412  * @param setsum
413  *   Pointer of a set-summary.
414  * @param key
415  *   Pointer of the key to be added.
416  * @param set_id
417  *   The set id associated with the key that needs to be added. Different mode
418  *   supports different set_id ranges. 0 cannot be used as set_id since
419  *   RTE_MEMBER_NO_MATCH by default is set as 0.
420  *   For HT mode, the set_id has range as [1, 0x7FFF], MSB is reserved.
421  *   For vBF mode the set id is limited by the num_set parameter when create
422  *   the set-summary.
423  * @return
424  *   HT (cache mode) and vBF should never fail unless the set_id is not in the
425  *   valid range. In such case -EINVAL is returned.
426  *   For HT (non-cache mode) it could fail with -ENOSPC error code when table is
427  *   full.
428  *   For success it returns different values for different modes to provide
429  *   extra information for users.
430  *   Return 0 for HT (cache mode) if the add does not cause
431  *   eviction, return 1 otherwise. Return 0 for non-cache mode if success,
432  *   -ENOSPC for full, and 1 if cuckoo eviction happens.
433  *   Always returns 0 for vBF mode.
434  */
435 int
436 rte_member_add(const struct rte_member_setsum *setsum, const void *key,
437 			member_set_t set_id);
438 
439 /**
440  * @warning
441  * @b EXPERIMENTAL: this API may change without prior notice
442  *
443  * De-allocate memory used by set-summary.
444  *
445  * @param setsum
446  *   Pointer to the set summary.
447  */
448 void
449 rte_member_free(struct rte_member_setsum *setsum);
450 
451 /**
452  * @warning
453  * @b EXPERIMENTAL: this API may change without prior notice
454  *
455  * Reset the set-summary tables. E.g. reset bits to be 0 in BF,
456  * reset set_id in each entry to be RTE_MEMBER_NO_MATCH in HT based SS.
457  *
458  * @param setsum
459  *   Pointer to the set-summary.
460  */
461 void
462 rte_member_reset(const struct rte_member_setsum *setsum);
463 
464 /**
465  * @warning
466  * @b EXPERIMENTAL: this API may change without prior notice
467  *
468  * Delete items from the set-summary. Note that vBF does not support deletion
469  * in current implementation. For vBF, error code of -EINVAL will be returned.
470  *
471  * @param setsum
472  *   Pointer to the set-summary.
473  * @param key
474  *   Pointer of the key to be deleted.
475  * @param set_id
476  *   For HT mode, we need both key and its corresponding set_id to
477  *   properly delete the key. Without set_id, we may delete other keys with the
478  *   same signature.
479  * @return
480  *   If no entry found to delete, an error code of -ENOENT could be returned.
481  */
482 int
483 rte_member_delete(const struct rte_member_setsum *setsum, const void *key,
484 			member_set_t set_id);
485 
486 #ifdef __cplusplus
487 }
488 #endif
489 
490 #endif /* _RTE_MEMBER_H_ */
491