xref: /dpdk/lib/efd/rte_efd.c (revision 03ab51eafda992874a48c392ca66ffb577fe2b71)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2016-2017 Intel Corporation
3  */
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdint.h>
7 #include <inttypes.h>
8 #include <errno.h>
9 #include <stdarg.h>
10 #include <sys/queue.h>
11 
12 #include <rte_string_fns.h>
13 #include <rte_log.h>
14 #include <rte_eal_memconfig.h>
15 #include <rte_errno.h>
16 #include <rte_malloc.h>
17 #include <rte_prefetch.h>
18 #include <rte_branch_prediction.h>
19 #include <rte_memcpy.h>
20 #include <rte_ring.h>
21 #include <rte_jhash.h>
22 #include <rte_hash_crc.h>
23 #include <rte_tailq.h>
24 #include <rte_vect.h>
25 
26 #include "rte_efd.h"
27 #if defined(RTE_ARCH_X86)
28 #include "rte_efd_x86.h"
29 #elif defined(RTE_ARCH_ARM64)
30 #include "rte_efd_arm64.h"
31 #endif
32 
33 #define EFD_KEY(key_idx, table) (table->keys + ((key_idx) * table->key_len))
34 /** Hash function used to determine chunk_id and bin_id for a group */
35 #define EFD_HASH(key, table) \
36 	(uint32_t)(rte_jhash(key, table->key_len, 0xbc9f1d34))
37 /** Hash function used as constant component of perfect hash search */
38 #define EFD_HASHFUNCA(key, table) \
39 	(uint32_t)(rte_hash_crc(key, table->key_len, 0xbc9f1d35))
40 /** Hash function used as multiplicative component of perfect hash search */
41 #define EFD_HASHFUNCB(key, table) \
42 	(uint32_t)(rte_hash_crc(key, table->key_len, 0xbc9f1d36))
43 
44 /*************************************************************************
45  * Fixed constants
46  *************************************************************************/
47 
48 /* These parameters are fixed by the efd_bin_to_group balancing table */
49 #define EFD_CHUNK_NUM_GROUPS (64)
50 #define EFD_CHUNK_NUM_BINS   (256)
51 #define EFD_CHUNK_NUM_BIN_TO_GROUP_SETS \
52 	(EFD_CHUNK_NUM_BINS / EFD_CHUNK_NUM_GROUPS)
53 
54 /*
55  * Target number of rules that each chunk is created to handle.
56  * Used when initially allocating the table
57  */
58 #define EFD_TARGET_CHUNK_NUM_RULES  \
59 	(EFD_CHUNK_NUM_GROUPS * EFD_TARGET_GROUP_NUM_RULES)
60 /*
61  * Max number of rules that each chunk is created to handle.
62  * Used when initially allocating the table
63  */
64 #define EFD_TARGET_CHUNK_MAX_NUM_RULES  \
65 	(EFD_CHUNK_NUM_GROUPS * EFD_MAX_GROUP_NUM_RULES)
66 
67 /** This is fixed based on the bin_to_group permutation array */
68 #define EFD_MAX_GROUP_NUM_BINS (16)
69 
70 /**
71  * The end of the chunks array needs some extra padding to ensure
72  * that vectorization over-reads on the last online chunk stay within
73 allocated memory
74  */
75 #define EFD_NUM_CHUNK_PADDING_BYTES (256)
76 
77 /* All different internal lookup functions */
78 enum efd_lookup_internal_function {
79 	EFD_LOOKUP_SCALAR = 0,
80 	EFD_LOOKUP_AVX2,
81 	EFD_LOOKUP_NEON,
82 	EFD_LOOKUP_NUM
83 };
84 
85 TAILQ_HEAD(rte_efd_list, rte_tailq_entry);
86 
87 static struct rte_tailq_elem rte_efd_tailq = {
88 	.name = "RTE_EFD",
89 };
90 EAL_REGISTER_TAILQ(rte_efd_tailq);
91 
92 /** Internal permutation array used to shuffle bins into pseudorandom groups */
93 const uint32_t efd_bin_to_group[EFD_CHUNK_NUM_BIN_TO_GROUP_SETS][EFD_CHUNK_NUM_BINS] = {
94 	{
95 		0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
96 		4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
97 		8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11,
98 		12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15,
99 		16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19,
100 		20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,
101 		24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27,
102 		28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,
103 		32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35,
104 		36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39,
105 		40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43,
106 		44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47,
107 		48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51,
108 		52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55,
109 		56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, 59,
110 		60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63
111 	},
112 	{
113 		34, 33, 48, 59, 0, 21, 36, 18, 9, 49, 54, 38, 51, 23, 31, 5,
114 		44, 23, 37, 52, 11, 4, 58, 20, 38, 40, 38, 22, 26, 28, 42, 6,
115 		46, 16, 31, 28, 46, 14, 60, 0, 35, 53, 16, 58, 16, 29, 39, 7,
116 		1, 54, 15, 11, 48, 3, 62, 9, 58, 5, 30, 43, 17, 7, 36, 34,
117 		6, 36, 2, 14, 10, 1, 47, 47, 20, 45, 62, 56, 34, 25, 39, 18,
118 		51, 41, 61, 25, 56, 40, 41, 37, 52, 35, 30, 57, 11, 42, 37, 27,
119 		54, 19, 26, 13, 48, 31, 46, 15, 12, 10, 16, 20, 43, 17, 12, 55,
120 		45, 18, 8, 41, 7, 31, 42, 63, 12, 14, 21, 57, 24, 40, 5, 41,
121 		13, 44, 23, 59, 25, 57, 52, 50, 62, 1, 2, 49, 32, 57, 26, 43,
122 		56, 60, 55, 5, 49, 6, 3, 50, 46, 39, 27, 33, 17, 4, 53, 13,
123 		2, 19, 36, 51, 63, 0, 22, 33, 59, 28, 29, 23, 45, 33, 53, 27,
124 		22, 21, 40, 56, 4, 18, 44, 47, 28, 17, 4, 50, 21, 62, 8, 39,
125 		0, 8, 15, 24, 29, 24, 9, 11, 48, 61, 35, 55, 43, 1, 54, 42,
126 		53, 60, 22, 3, 32, 52, 25, 8, 15, 60, 7, 55, 27, 63, 19, 10,
127 		63, 24, 61, 19, 12, 38, 6, 29, 13, 37, 10, 3, 45, 32, 32, 30,
128 		49, 61, 44, 14, 20, 58, 35, 30, 2, 26, 34, 51, 9, 59, 47, 50
129 	},
130 	{
131 		32, 35, 32, 34, 55, 5, 6, 23, 49, 11, 6, 23, 52, 37, 29, 54,
132 		55, 40, 63, 50, 29, 52, 61, 25, 12, 56, 39, 38, 29, 11, 46, 1,
133 		40, 11, 19, 56, 7, 28, 51, 16, 15, 48, 21, 51, 60, 31, 14, 22,
134 		41, 47, 59, 56, 53, 28, 58, 26, 43, 27, 41, 33, 24, 52, 44, 38,
135 		13, 59, 48, 51, 60, 15, 3, 30, 15, 0, 10, 62, 44, 14, 28, 51,
136 		38, 2, 41, 26, 25, 49, 10, 12, 55, 57, 27, 35, 19, 33, 0, 30,
137 		5, 36, 47, 53, 5, 53, 20, 43, 34, 37, 52, 41, 21, 63, 59, 9,
138 		24, 1, 45, 24, 39, 44, 45, 16, 9, 17, 7, 50, 57, 22, 18, 28,
139 		25, 45, 2, 40, 58, 15, 17, 3, 1, 27, 61, 39, 19, 0, 19, 21,
140 		57, 62, 54, 60, 54, 40, 48, 33, 36, 37, 4, 42, 1, 43, 58, 8,
141 		13, 42, 10, 56, 35, 22, 48, 61, 63, 10, 49, 9, 24, 9, 25, 57,
142 		33, 18, 13, 31, 42, 36, 36, 55, 30, 37, 53, 34, 59, 4, 4, 23,
143 		8, 16, 58, 14, 30, 11, 12, 63, 49, 62, 2, 39, 47, 22, 2, 60,
144 		18, 8, 46, 31, 6, 20, 32, 29, 46, 42, 20, 31, 32, 61, 34, 4,
145 		47, 26, 20, 43, 26, 21, 7, 3, 16, 35, 18, 44, 27, 62, 13, 23,
146 		6, 50, 12, 8, 45, 17, 3, 46, 50, 7, 14, 5, 17, 54, 38, 0
147 	},
148 	{
149 		29, 56, 5, 7, 54, 48, 23, 37, 35, 44, 52, 40, 33, 49, 60, 0,
150 		59, 51, 28, 12, 41, 26, 2, 23, 34, 5, 59, 40, 3, 19, 6, 26,
151 		35, 53, 45, 49, 29, 57, 28, 62, 58, 59, 19, 53, 59, 62, 6, 54,
152 		13, 15, 48, 50, 45, 21, 41, 12, 34, 40, 24, 56, 19, 21, 35, 18,
153 		55, 45, 9, 61, 47, 61, 19, 15, 16, 39, 17, 31, 3, 51, 21, 50,
154 		17, 25, 25, 11, 44, 16, 18, 28, 14, 2, 37, 61, 58, 27, 62, 4,
155 		14, 17, 1, 9, 46, 28, 37, 0, 53, 43, 57, 7, 57, 46, 21, 41,
156 		39, 14, 52, 60, 44, 53, 49, 60, 49, 63, 13, 11, 29, 1, 55, 47,
157 		55, 12, 60, 43, 54, 37, 13, 6, 42, 10, 36, 13, 9, 8, 34, 51,
158 		31, 32, 12, 7, 57, 2, 26, 14, 3, 30, 63, 3, 32, 1, 5, 11,
159 		27, 24, 26, 44, 31, 23, 56, 38, 62, 0, 40, 30, 6, 23, 38, 2,
160 		47, 5, 15, 27, 16, 10, 31, 25, 22, 63, 30, 25, 20, 33, 32, 50,
161 		29, 43, 55, 10, 50, 45, 56, 20, 4, 7, 27, 46, 11, 16, 22, 52,
162 		35, 20, 41, 54, 46, 33, 42, 18, 63, 8, 22, 58, 36, 4, 51, 42,
163 		38, 32, 38, 22, 17, 0, 47, 8, 48, 8, 48, 1, 61, 36, 33, 20,
164 		24, 39, 39, 18, 30, 36, 9, 43, 42, 24, 10, 58, 4, 15, 34, 52
165 	},
166 };
167 
168 /*************************************************************************
169  * Offline region structures
170  *************************************************************************/
171 
172 /** Online group containing number of rules, values, keys and their bins
173  * for EFD_MAX_GROUP_NUM_RULES rules.
174  */
175 struct efd_offline_group_rules {
176 	uint32_t num_rules;
177 	/**< Sum of the number of rules in all bins assigned to this group. */
178 
179 	uint32_t key_idx[EFD_MAX_GROUP_NUM_RULES];
180 	/**< Array with all keys of the group. */
181 	efd_value_t value[EFD_MAX_GROUP_NUM_RULES];
182 	/**< Array with all values of the keys of the group. */
183 
184 	uint8_t bin_id[EFD_MAX_GROUP_NUM_RULES];
185 	/**< Stores the bin for each corresponding key to
186 	 * avoid having to recompute it
187 	 */
188 };
189 
190 /** Offline chunk record, containing EFD_TARGET_CHUNK_NUM_RULES rules.
191  * Those rules are split into EFD_CHUNK_NUM_GROUPS groups per chunk.
192  */
193 struct efd_offline_chunk_rules {
194 	uint16_t num_rules;
195 	/**< Number of rules in the entire chunk;
196 	 * used to detect unbalanced groups
197 	 */
198 
199 	struct efd_offline_group_rules group_rules[EFD_CHUNK_NUM_GROUPS];
200 	/**< Array of all groups in the chunk. */
201 };
202 
203 /*************************************************************************
204  * Online region structures
205  *************************************************************************/
206 
207 /** Online group containing values for EFD_MAX_GROUP_NUM_RULES rules. */
208 struct efd_online_group_entry {
209 	efd_hashfunc_t hash_idx[RTE_EFD_VALUE_NUM_BITS];
210 	efd_lookuptbl_t lookup_table[RTE_EFD_VALUE_NUM_BITS];
211 } __rte_packed;
212 
213 /**
214  * A single chunk record, containing EFD_TARGET_CHUNK_NUM_RULES rules.
215  * Those rules are split into EFD_CHUNK_NUM_GROUPS groups per chunk.
216  */
217 struct efd_online_chunk {
218 	uint8_t bin_choice_list[(EFD_CHUNK_NUM_BINS * 2 + 7) / 8];
219 	/**< This is a packed indirection index into the 'groups' array.
220 	 * Each byte contains four two-bit values which index into
221 	 * the efd_bin_to_group array.
222 	 * The efd_bin_to_group array returns the index into the groups array
223 	 */
224 
225 	struct efd_online_group_entry groups[EFD_CHUNK_NUM_GROUPS];
226 	/**< Array of all the groups in the chunk. */
227 } __rte_packed;
228 
229 /**
230  * EFD table structure
231  */
232 struct rte_efd_table {
233 	char name[RTE_EFD_NAMESIZE]; /**< Name of the efd table. */
234 
235 	uint32_t key_len; /**< Length of the key stored offline */
236 
237 	uint32_t max_num_rules;
238 	/**< Static maximum number of entries the table was constructed to hold. */
239 
240 	uint32_t num_rules;
241 	/**< Number of entries currently in the table . */
242 
243 	uint32_t num_chunks;
244 	/**< Number of chunks in the table needed to support num_rules. */
245 
246 	uint32_t num_chunks_shift;
247 	/**< Bits to shift to get chunk id, instead of dividing by num_chunk. */
248 
249 	enum efd_lookup_internal_function lookup_fn;
250 	/**< Indicates which lookup function to use. */
251 
252 	struct efd_online_chunk *chunks[RTE_MAX_NUMA_NODES];
253 	/**< Dynamic array of size num_chunks of chunk records. */
254 
255 	struct efd_offline_chunk_rules *offline_chunks;
256 	/**< Dynamic array of size num_chunks of key-value pairs. */
257 
258 	struct rte_ring *free_slots;
259 	/**< Ring that stores all indexes of the free slots in the key table */
260 
261 	uint8_t *keys; /**< Dynamic array of size max_num_rules of keys */
262 };
263 
264 /**
265  * Computes the chunk ID for a given key hash
266  *
267  * @param table
268  *   EFD table to reference
269  * @param hashed_key
270  *   32-bit key hash returned by EFD_HASH
271  *
272  * @return
273  *   chunk ID containing this key hash
274  */
275 static inline uint32_t
276 efd_get_chunk_id(const struct rte_efd_table * const table,
277 		const uint32_t hashed_key)
278 {
279 	return hashed_key & (table->num_chunks - 1);
280 }
281 
282 /**
283  * Computes the bin ID for a given key hash
284  *
285  * @param table
286  *   EFD table to reference
287  * @param hashed_key
288  *   32-bit key hash returned by EFD_HASH
289  *
290  * @return bin ID containing this key hash
291  */
292 static inline uint32_t
293 efd_get_bin_id(const struct rte_efd_table * const table,
294 		const uint32_t hashed_key)
295 {
296 	return (hashed_key >> table->num_chunks_shift) & (EFD_CHUNK_NUM_BINS - 1);
297 }
298 
299 /**
300  * Looks up the current permutation choice for a particular bin in the online table
301  *
302  * @param table
303  *  EFD table to reference
304  * @param socket_id
305  *   Socket ID to use to look up existing values (ideally caller's socket id)
306  * @param chunk_id
307  *   Chunk ID of bin to look up
308  * @param bin_id
309  *   Bin ID to look up
310  *
311  * @return
312  *   Currently active permutation choice in the online table
313  */
314 static inline uint8_t
315 efd_get_choice(const struct rte_efd_table * const table,
316 		const unsigned int socket_id, const uint32_t chunk_id,
317 		const uint32_t bin_id)
318 {
319 	struct efd_online_chunk *chunk = &table->chunks[socket_id][chunk_id];
320 
321 	/*
322 	 * Grab the chunk (byte) that contains the choices
323 	 * for four neighboring bins.
324 	 */
325 	uint8_t choice_chunk =
326 			chunk->bin_choice_list[bin_id / EFD_CHUNK_NUM_BIN_TO_GROUP_SETS];
327 
328 	/*
329 	 * Compute the offset into the chunk that contains
330 	 * the group_id lookup position
331 	 */
332 	int offset = (bin_id & 0x3) * 2;
333 
334 	/* Extract from the byte just the desired lookup position */
335 	return (uint8_t) ((choice_chunk >> offset) & 0x3);
336 }
337 
338 /**
339  * Compute the chunk_id and bin_id for a given key
340  *
341  * @param table
342  *   EFD table to reference
343  * @param key
344  *   Key to hash and find location of
345  * @param chunk_id
346  *   Computed chunk ID
347  * @param bin_id
348  *   Computed bin ID
349  *
350  */
351 static inline void
352 efd_compute_ids(const struct rte_efd_table * const table,
353 		const void *key, uint32_t * const chunk_id, uint32_t * const bin_id)
354 {
355 	/* Compute the position of the entry in the hash table */
356 	uint32_t h = EFD_HASH(key, table);
357 
358 	/* Compute the chunk_id where that entry can be found */
359 	*chunk_id = efd_get_chunk_id(table, h);
360 
361 	/*
362 	 * Compute the bin within that chunk where the entry
363 	 * can be found (0 - 255)
364 	 */
365 	*bin_id = efd_get_bin_id(table, h);
366 }
367 
368 /**
369  * Search for a hash function for a group that satisfies all group results
370  */
371 static inline int
372 efd_search_hash(struct rte_efd_table * const table,
373 		const struct efd_offline_group_rules * const off_group,
374 		struct efd_online_group_entry * const on_group)
375 {
376 	efd_hashfunc_t hash_idx;
377 	efd_hashfunc_t start_hash_idx[RTE_EFD_VALUE_NUM_BITS];
378 	efd_lookuptbl_t start_lookup_table[RTE_EFD_VALUE_NUM_BITS];
379 
380 	uint32_t i, j, rule_id;
381 	uint32_t hash_val_a[EFD_MAX_GROUP_NUM_RULES];
382 	uint32_t hash_val_b[EFD_MAX_GROUP_NUM_RULES];
383 	uint32_t hash_val[EFD_MAX_GROUP_NUM_RULES];
384 
385 
386 	rte_prefetch0(off_group->value);
387 
388 	/*
389 	 * Prepopulate the hash_val tables by running the two hash functions
390 	 * for each provided rule
391 	 */
392 	for (i = 0; i < off_group->num_rules; i++) {
393 		void *key_stored = EFD_KEY(off_group->key_idx[i], table);
394 		hash_val_b[i] = EFD_HASHFUNCB(key_stored, table);
395 		hash_val_a[i] = EFD_HASHFUNCA(key_stored, table);
396 	}
397 
398 	for (i = 0; i < RTE_EFD_VALUE_NUM_BITS; i++) {
399 		hash_idx = on_group->hash_idx[i];
400 		start_hash_idx[i] = hash_idx;
401 		start_lookup_table[i] = on_group->lookup_table[i];
402 
403 		do {
404 			efd_lookuptbl_t lookup_table = 0;
405 			efd_lookuptbl_t lookup_table_complement = 0;
406 
407 			for (rule_id = 0; rule_id < off_group->num_rules; rule_id++)
408 				hash_val[rule_id] = hash_val_a[rule_id] + (hash_idx *
409 					hash_val_b[rule_id]);
410 
411 			/*
412 			 * The goal here is to find a hash function for this
413 			 * particular bit entry that meets the following criteria:
414 			 * The most significant bits of the hash result define a
415 			 * shift into the lookup table where the bit will be stored
416 			 */
417 
418 			/* Iterate over each provided rule */
419 			for (rule_id = 0; rule_id < off_group->num_rules;
420 					rule_id++) {
421 				/*
422 				 * Use the few most significant bits (number based on
423 				 * EFD_LOOKUPTBL_SIZE) to see what position the
424 				 * expected bit should be set in the lookup_table
425 				 */
426 				uint32_t bucket_idx = hash_val[rule_id] >>
427 						EFD_LOOKUPTBL_SHIFT;
428 
429 				/*
430 				 * Get the current bit of interest.
431 				 * This only find an appropriate hash function
432 				 * for one bit at a time of the rule
433 				 */
434 				efd_lookuptbl_t expected =
435 						(off_group->value[rule_id] >> i) & 0x1;
436 
437 				/*
438 				 * Add the expected bit (if set) to a map
439 				 * (lookup_table). Also set its complement
440 				 * in lookup_table_complement
441 				 */
442 				lookup_table |= expected << bucket_idx;
443 				lookup_table_complement |= (1 - expected)
444 						<< bucket_idx;
445 
446 				/*
447 				 * If ever the hash function of two different
448 				 * elements result in different values at the
449 				 * same location in the lookup_table,
450 				 * the current hash_idx is not valid.
451 				 */
452 				if (lookup_table & lookup_table_complement)
453 					break;
454 			}
455 
456 			/*
457 			 * Check if the previous loop completed without
458 			 * breaking early
459 			 */
460 			if (rule_id == off_group->num_rules) {
461 				/*
462 				 * Current hash function worked, store it
463 				 * for the current group
464 				 */
465 				on_group->hash_idx[i] = hash_idx;
466 				on_group->lookup_table[i] = lookup_table;
467 
468 				/*
469 				 * Make sure that the hash function has changed
470 				 * from the starting value
471 				 */
472 				hash_idx = start_hash_idx[i] + 1;
473 				break;
474 			}
475 			hash_idx++;
476 
477 		} while (hash_idx != start_hash_idx[i]);
478 
479 		/* Failed to find perfect hash for this group */
480 		if (hash_idx == start_hash_idx[i]) {
481 			/*
482 			 * Restore previous hash_idx and lookup_table
483 			 * for all value bits
484 			 */
485 			for (j = 0; j < i; j++) {
486 				on_group->hash_idx[j] = start_hash_idx[j];
487 				on_group->lookup_table[j] = start_lookup_table[j];
488 			}
489 			return 1;
490 		}
491 	}
492 
493 	return 0;
494 }
495 
496 struct rte_efd_table *
497 rte_efd_create(const char *name, uint32_t max_num_rules, uint32_t key_len,
498 		uint64_t online_cpu_socket_bitmask, uint8_t offline_cpu_socket)
499 {
500 	struct rte_efd_table *table = NULL;
501 	uint8_t *key_array = NULL;
502 	uint32_t num_chunks, num_chunks_shift;
503 	uint8_t socket_id;
504 	struct rte_efd_list *efd_list = NULL;
505 	struct rte_tailq_entry *te;
506 	uint64_t offline_table_size;
507 	char ring_name[RTE_RING_NAMESIZE];
508 	struct rte_ring *r = NULL;
509 	unsigned int i;
510 
511 	efd_list = RTE_TAILQ_CAST(rte_efd_tailq.head, rte_efd_list);
512 
513 	if (online_cpu_socket_bitmask == 0) {
514 		RTE_LOG(ERR, EFD, "At least one CPU socket must be enabled "
515 				"in the bitmask\n");
516 		return NULL;
517 	}
518 
519 	if (max_num_rules == 0) {
520 		RTE_LOG(ERR, EFD, "Max num rules must be higher than 0\n");
521 		return NULL;
522 	}
523 
524 	/*
525 	 * Compute the minimum number of chunks (smallest power of 2)
526 	 * that can hold all of the rules
527 	 */
528 	if (max_num_rules % EFD_TARGET_CHUNK_NUM_RULES == 0)
529 		num_chunks = rte_align32pow2(max_num_rules /
530 			EFD_TARGET_CHUNK_NUM_RULES);
531 	else
532 		num_chunks = rte_align32pow2((max_num_rules /
533 			EFD_TARGET_CHUNK_NUM_RULES) + 1);
534 
535 	num_chunks_shift = rte_bsf32(num_chunks);
536 
537 	rte_mcfg_tailq_write_lock();
538 
539 	/*
540 	 * Guarantee there's no existing: this is normally already checked
541 	 * by ring creation above
542 	 */
543 	TAILQ_FOREACH(te, efd_list, next)
544 	{
545 		table = (struct rte_efd_table *) te->data;
546 		if (strncmp(name, table->name, RTE_EFD_NAMESIZE) == 0)
547 			break;
548 	}
549 
550 	table = NULL;
551 	if (te != NULL) {
552 		rte_errno = EEXIST;
553 		te = NULL;
554 		goto error_unlock_exit;
555 	}
556 
557 	te = rte_zmalloc("EFD_TAILQ_ENTRY", sizeof(*te), 0);
558 	if (te == NULL) {
559 		RTE_LOG(ERR, EFD, "tailq entry allocation failed\n");
560 		goto error_unlock_exit;
561 	}
562 
563 	/* Create a new EFD table management structure */
564 	table = rte_zmalloc_socket(NULL,
565 			sizeof(struct rte_efd_table),
566 			RTE_CACHE_LINE_SIZE,
567 			offline_cpu_socket);
568 	if (table == NULL) {
569 		RTE_LOG(ERR, EFD, "Allocating EFD table management structure"
570 				" on socket %u failed\n",
571 				offline_cpu_socket);
572 		goto error_unlock_exit;
573 	}
574 
575 
576 	RTE_LOG(DEBUG, EFD, "Allocated EFD table management structure "
577 			"on socket %u\n", offline_cpu_socket);
578 
579 	table->max_num_rules = num_chunks * EFD_TARGET_CHUNK_MAX_NUM_RULES;
580 	table->num_rules = 0;
581 	table->num_chunks = num_chunks;
582 	table->num_chunks_shift = num_chunks_shift;
583 	table->key_len = key_len;
584 
585 	/* key_array */
586 	key_array = rte_zmalloc_socket(NULL,
587 			table->max_num_rules * table->key_len,
588 			RTE_CACHE_LINE_SIZE,
589 			offline_cpu_socket);
590 	if (key_array == NULL) {
591 		RTE_LOG(ERR, EFD, "Allocating key array"
592 				" on socket %u failed\n",
593 				offline_cpu_socket);
594 		goto error_unlock_exit;
595 	}
596 	table->keys = key_array;
597 	strlcpy(table->name, name, sizeof(table->name));
598 
599 	RTE_LOG(DEBUG, EFD, "Creating an EFD table with %u chunks,"
600 			" which potentially supports %u entries\n",
601 			num_chunks, table->max_num_rules);
602 
603 	/* Make sure all the allocatable table pointers are NULL initially */
604 	for (socket_id = 0; socket_id < RTE_MAX_NUMA_NODES; socket_id++)
605 		table->chunks[socket_id] = NULL;
606 	table->offline_chunks = NULL;
607 
608 	/*
609 	 * Allocate one online table per socket specified
610 	 * in the user-supplied bitmask
611 	 */
612 	uint64_t online_table_size = num_chunks * sizeof(struct efd_online_chunk) +
613 			EFD_NUM_CHUNK_PADDING_BYTES;
614 
615 	for (socket_id = 0; socket_id < RTE_MAX_NUMA_NODES; socket_id++) {
616 		if ((online_cpu_socket_bitmask >> socket_id) & 0x01) {
617 			/*
618 			 * Allocate all of the EFD table chunks (the online portion)
619 			 * as a continuous block
620 			 */
621 			table->chunks[socket_id] =
622 				rte_zmalloc_socket(
623 				NULL,
624 				online_table_size,
625 				RTE_CACHE_LINE_SIZE,
626 				socket_id);
627 			if (table->chunks[socket_id] == NULL) {
628 				RTE_LOG(ERR, EFD,
629 						"Allocating EFD online table on "
630 						"socket %u failed\n",
631 						socket_id);
632 				goto error_unlock_exit;
633 			}
634 			RTE_LOG(DEBUG, EFD,
635 					"Allocated EFD online table of size "
636 					"%"PRIu64" bytes (%.2f MB) on socket %u\n",
637 					online_table_size,
638 					(float) online_table_size /
639 						(1024.0F * 1024.0F),
640 					socket_id);
641 		}
642 	}
643 
644 #if defined(RTE_ARCH_X86)
645 	/*
646 	 * For less than 4 bits, scalar function performs better
647 	 * than vectorised version
648 	 */
649 	if (RTE_EFD_VALUE_NUM_BITS > 3
650 			&& rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2)
651 			&& rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_256)
652 		table->lookup_fn = EFD_LOOKUP_AVX2;
653 	else
654 #endif
655 #if defined(RTE_ARCH_ARM64)
656 	/*
657 	 * For less than or equal to 16 bits, scalar function performs better
658 	 * than vectorised version
659 	 */
660 	if (RTE_EFD_VALUE_NUM_BITS > 16 &&
661 	    rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON) &&
662 			rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128)
663 		table->lookup_fn = EFD_LOOKUP_NEON;
664 	else
665 #endif
666 		table->lookup_fn = EFD_LOOKUP_SCALAR;
667 
668 	/*
669 	 * Allocate the EFD table offline portion (with the actual rules
670 	 * mapping keys to values) as a continuous block.
671 	 * This could be several gigabytes of memory.
672 	 */
673 	offline_table_size = num_chunks * sizeof(struct efd_offline_chunk_rules);
674 	table->offline_chunks =
675 			rte_zmalloc_socket(NULL,
676 			offline_table_size,
677 			RTE_CACHE_LINE_SIZE,
678 			offline_cpu_socket);
679 	if (table->offline_chunks == NULL) {
680 		RTE_LOG(ERR, EFD, "Allocating EFD offline table on socket %u "
681 				"failed\n", offline_cpu_socket);
682 		goto error_unlock_exit;
683 	}
684 
685 	RTE_LOG(DEBUG, EFD,
686 			"Allocated EFD offline table of size %"PRIu64" bytes "
687 			" (%.2f MB) on socket %u\n", offline_table_size,
688 			(float) offline_table_size / (1024.0F * 1024.0F),
689 			offline_cpu_socket);
690 
691 	te->data = (void *) table;
692 	TAILQ_INSERT_TAIL(efd_list, te, next);
693 	rte_mcfg_tailq_write_unlock();
694 
695 	snprintf(ring_name, sizeof(ring_name), "HT_%s", table->name);
696 	/* Create ring (Dummy slot index is not enqueued) */
697 	r = rte_ring_create(ring_name, rte_align32pow2(table->max_num_rules),
698 			offline_cpu_socket, 0);
699 	if (r == NULL) {
700 		RTE_LOG(ERR, EFD, "memory allocation failed\n");
701 		rte_efd_free(table);
702 		return NULL;
703 	}
704 
705 	/* Populate free slots ring. Entry zero is reserved for key misses. */
706 	for (i = 0; i < table->max_num_rules; i++)
707 		rte_ring_sp_enqueue(r, (void *) ((uintptr_t) i));
708 
709 	table->free_slots = r;
710 	return table;
711 
712 error_unlock_exit:
713 	rte_mcfg_tailq_write_unlock();
714 	rte_free(te);
715 	rte_efd_free(table);
716 
717 	return NULL;
718 }
719 
720 struct rte_efd_table *
721 rte_efd_find_existing(const char *name)
722 {
723 	struct rte_efd_table *table = NULL;
724 	struct rte_tailq_entry *te;
725 	struct rte_efd_list *efd_list;
726 
727 	efd_list = RTE_TAILQ_CAST(rte_efd_tailq.head, rte_efd_list);
728 
729 	rte_mcfg_tailq_read_lock();
730 
731 	TAILQ_FOREACH(te, efd_list, next)
732 	{
733 		table = (struct rte_efd_table *) te->data;
734 		if (strncmp(name, table->name, RTE_EFD_NAMESIZE) == 0)
735 			break;
736 	}
737 	rte_mcfg_tailq_read_unlock();
738 
739 	if (te == NULL) {
740 		rte_errno = ENOENT;
741 		return NULL;
742 	}
743 	return table;
744 }
745 
746 void
747 rte_efd_free(struct rte_efd_table *table)
748 {
749 	uint8_t socket_id;
750 	struct rte_efd_list *efd_list;
751 	struct rte_tailq_entry *te, *temp;
752 
753 	if (table == NULL)
754 		return;
755 
756 	for (socket_id = 0; socket_id < RTE_MAX_NUMA_NODES; socket_id++)
757 		rte_free(table->chunks[socket_id]);
758 
759 	efd_list = RTE_TAILQ_CAST(rte_efd_tailq.head, rte_efd_list);
760 	rte_mcfg_tailq_write_lock();
761 
762 	RTE_TAILQ_FOREACH_SAFE(te, efd_list, next, temp) {
763 		if (te->data == (void *) table) {
764 			TAILQ_REMOVE(efd_list, te, next);
765 			rte_free(te);
766 			break;
767 		}
768 	}
769 
770 	rte_mcfg_tailq_write_unlock();
771 	rte_ring_free(table->free_slots);
772 	rte_free(table->offline_chunks);
773 	rte_free(table->keys);
774 	rte_free(table);
775 }
776 
777 /**
778  * Applies a previously computed table entry to the specified table for all
779  * socket-local copies of the online table.
780  * Intended to apply an update for only a single change
781  * to a key/value pair at a time
782  *
783  * @param table
784  *   EFD table to reference
785  * @param socket_id
786  *   Socket ID to use to lookup existing values (ideally caller's socket id)
787  * @param chunk_id
788  *   Chunk index to update
789  * @param group_id
790  *   Group index to update
791  * @param bin_id
792  *   Bin within the group that this update affects
793  * @param new_bin_choice
794  *   Newly chosen permutation which this bin should use - only lower 2 bits
795  * @param new_group_entry
796  *   Previously computed updated chunk/group entry
797  */
798 static inline void
799 efd_apply_update(struct rte_efd_table * const table, const unsigned int socket_id,
800 		const uint32_t chunk_id, const uint32_t group_id,
801 		const uint32_t bin_id, const uint8_t new_bin_choice,
802 		const struct efd_online_group_entry * const new_group_entry)
803 {
804 	int i;
805 	struct efd_online_chunk *chunk = &table->chunks[socket_id][chunk_id];
806 	uint8_t bin_index = bin_id / EFD_CHUNK_NUM_BIN_TO_GROUP_SETS;
807 
808 	/*
809 	 * Grab the current byte that contains the choices
810 	 * for four neighboring bins
811 	 */
812 	uint8_t choice_chunk =
813 			chunk->bin_choice_list[bin_index];
814 
815 
816 	/* Compute the offset into the chunk that needs to be updated */
817 	int offset = (bin_id & 0x3) * 2;
818 
819 	/* Zero the two bits of interest and set them to new_bin_choice */
820 	choice_chunk = (choice_chunk & (~(0x03 << offset)))
821 			| ((new_bin_choice & 0x03) << offset);
822 
823 	/* Update the online table with the new data across all sockets */
824 	for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
825 		if (table->chunks[i] != NULL) {
826 			memcpy(&(table->chunks[i][chunk_id].groups[group_id]),
827 					new_group_entry,
828 					sizeof(struct efd_online_group_entry));
829 			table->chunks[i][chunk_id].bin_choice_list[bin_index] =
830 					choice_chunk;
831 		}
832 	}
833 }
834 
835 /*
836  * Move the bin from prev group to the new group
837  */
838 static inline void
839 move_groups(uint32_t bin_id, uint8_t bin_size,
840 		struct efd_offline_group_rules *new_group,
841 		struct efd_offline_group_rules * const current_group)
842 {
843 
844 	uint8_t empty_idx = 0;
845 	unsigned int i;
846 
847 	if (new_group == current_group)
848 		return;
849 
850 	for (i = 0; i < current_group->num_rules; i++) {
851 		/*
852 		 * Move keys that belong to the same bin
853 		 * to the new group
854 		 */
855 		if (current_group->bin_id[i] == bin_id) {
856 			new_group->key_idx[new_group->num_rules] =
857 					current_group->key_idx[i];
858 			new_group->value[new_group->num_rules] =
859 					current_group->value[i];
860 			new_group->bin_id[new_group->num_rules] =
861 					current_group->bin_id[i];
862 			new_group->num_rules++;
863 		} else {
864 			if (i != empty_idx) {
865 				/*
866 				 * Need to move this key towards
867 				 * the top of the array
868 				 */
869 				current_group->key_idx[empty_idx] =
870 						current_group->key_idx[i];
871 				current_group->value[empty_idx] =
872 						current_group->value[i];
873 				current_group->bin_id[empty_idx] =
874 						current_group->bin_id[i];
875 			}
876 			empty_idx++;
877 		}
878 
879 	}
880 	current_group->num_rules -= bin_size;
881 }
882 
883 /*
884  * Revert group/s to their previous state before
885  * trying to insert/add a new key
886  */
887 static inline void
888 revert_groups(struct efd_offline_group_rules *previous_group,
889 		struct efd_offline_group_rules *current_group, uint8_t bin_size)
890 {
891 	unsigned int i;
892 
893 	if (current_group == previous_group)
894 		return;
895 
896 	/* Move keys back to previous group */
897 	for (i = current_group->num_rules - bin_size;
898 			i < current_group->num_rules; i++) {
899 		previous_group->key_idx[previous_group->num_rules] =
900 				current_group->key_idx[i];
901 		previous_group->value[previous_group->num_rules] =
902 				current_group->value[i];
903 		previous_group->bin_id[previous_group->num_rules] =
904 				current_group->bin_id[i];
905 		previous_group->num_rules++;
906 	}
907 
908 	/*
909 	 * Decrease number of rules after the move
910 	 * in the new group
911 	 */
912 	current_group->num_rules -= bin_size;
913 }
914 
915 /**
916  * Computes an updated table entry where the supplied key points to a new host.
917  * If no entry exists, one is inserted.
918  *
919  * This function does NOT modify the online table(s)
920  * This function DOES modify the offline table
921  *
922  * @param table
923  *   EFD table to reference
924  * @param socket_id
925  *   Socket ID to use to lookup existing values (ideally caller's socket id)
926  * @param key
927  *   Key to insert
928  * @param value
929  *   Value to associate with key
930  * @param chunk_id
931  *   Chunk ID of the chunk that was modified
932  * @param group_id
933  *   Group ID of the group that was modified
934  * @param bin_id
935  *   Bin ID that was modified
936  * @param new_bin_choice
937  *   Newly chosen permutation which this bin will use
938  * @param entry
939  *   Newly computed online entry to apply later with efd_apply_update
940  *
941  * @return
942  *   RTE_EFD_UPDATE_WARN_GROUP_FULL
943  *     Operation is insert, and the last available space in the
944  *     key's group was just used. Future inserts may fail as groups fill up.
945  *     This operation was still successful, and entry contains a valid update
946  *   RTE_EFD_UPDATE_FAILED
947  *     Either the EFD failed to find a suitable perfect hash or the group was full
948  *     This is a fatal error, and the table is now in an indeterminate state
949  *   RTE_EFD_UPDATE_NO_CHANGE
950  *     Operation resulted in no change to the table (same value already exists)
951  *   0
952  *     Insert or update was successful, and the new efd_online_group_entry
953  *     is stored in *entry
954  *
955  * @warning
956  *   Note that entry will be UNCHANGED if the update has no effect, and thus any
957  *   subsequent use of the entry content will likely be invalid
958  */
959 static inline int
960 efd_compute_update(struct rte_efd_table * const table,
961 		const unsigned int socket_id, const void *key,
962 		const efd_value_t value, uint32_t * const chunk_id,
963 		uint32_t * const group_id, uint32_t * const bin_id,
964 		uint8_t * const new_bin_choice,
965 		struct efd_online_group_entry * const entry)
966 {
967 	unsigned int i;
968 	int ret;
969 	uint32_t new_idx;
970 	void *new_k, *slot_id = NULL;
971 	int status = EXIT_SUCCESS;
972 	unsigned int found = 0;
973 
974 	efd_compute_ids(table, key, chunk_id, bin_id);
975 
976 	struct efd_offline_chunk_rules * const chunk =
977 			&table->offline_chunks[*chunk_id];
978 	struct efd_offline_group_rules *new_group;
979 
980 	uint8_t current_choice = efd_get_choice(table, socket_id,
981 			*chunk_id, *bin_id);
982 	uint32_t current_group_id = efd_bin_to_group[current_choice][*bin_id];
983 	struct efd_offline_group_rules * const current_group =
984 			&chunk->group_rules[current_group_id];
985 	uint8_t bin_size = 0;
986 	uint8_t key_changed_index = 0;
987 	efd_value_t key_changed_previous_value = 0;
988 	uint32_t key_idx_previous = 0;
989 
990 	/* Scan the current group and see if the key is already present */
991 	for (i = 0; i < current_group->num_rules; i++) {
992 		if (current_group->bin_id[i] == *bin_id)
993 			bin_size++;
994 		else
995 			continue;
996 
997 		void *key_stored = EFD_KEY(current_group->key_idx[i], table);
998 		if (found == 0 && unlikely(memcmp(key_stored, key,
999 				table->key_len) == 0)) {
1000 			/* Key is already present */
1001 
1002 			/*
1003 			 * If previous value is same as new value,
1004 			 * no additional work is required
1005 			 */
1006 			if (current_group->value[i] == value)
1007 				return RTE_EFD_UPDATE_NO_CHANGE;
1008 
1009 			key_idx_previous = current_group->key_idx[i];
1010 			key_changed_previous_value = current_group->value[i];
1011 			key_changed_index = i;
1012 			current_group->value[i] = value;
1013 			found = 1;
1014 		}
1015 	}
1016 
1017 	if (found == 0) {
1018 		/* Key does not exist. Insert the rule into the bin/group */
1019 		if (unlikely(current_group->num_rules >= EFD_MAX_GROUP_NUM_RULES)) {
1020 			RTE_LOG(ERR, EFD,
1021 					"Fatal: No room remaining for insert into "
1022 					"chunk %u group %u bin %u\n",
1023 					*chunk_id,
1024 					current_group_id, *bin_id);
1025 			return RTE_EFD_UPDATE_FAILED;
1026 		}
1027 
1028 		if (unlikely(current_group->num_rules ==
1029 				(EFD_MAX_GROUP_NUM_RULES - 1))) {
1030 			RTE_LOG(INFO, EFD, "Warn: Insert into last "
1031 					"available slot in chunk %u "
1032 					"group %u bin %u\n", *chunk_id,
1033 					current_group_id, *bin_id);
1034 			status = RTE_EFD_UPDATE_WARN_GROUP_FULL;
1035 		}
1036 
1037 		if (rte_ring_sc_dequeue(table->free_slots, &slot_id) != 0)
1038 			return RTE_EFD_UPDATE_FAILED;
1039 
1040 		new_k = RTE_PTR_ADD(table->keys, (uintptr_t) slot_id *
1041 					table->key_len);
1042 		rte_prefetch0(new_k);
1043 		new_idx = (uint32_t) ((uintptr_t) slot_id);
1044 
1045 		rte_memcpy(EFD_KEY(new_idx, table), key, table->key_len);
1046 		current_group->key_idx[current_group->num_rules] = new_idx;
1047 		current_group->value[current_group->num_rules] = value;
1048 		current_group->bin_id[current_group->num_rules] = *bin_id;
1049 		current_group->num_rules++;
1050 		table->num_rules++;
1051 		bin_size++;
1052 	} else {
1053 		uint32_t last = current_group->num_rules - 1;
1054 		/* Swap the key with the last key inserted*/
1055 		current_group->key_idx[key_changed_index] =
1056 				current_group->key_idx[last];
1057 		current_group->value[key_changed_index] =
1058 				current_group->value[last];
1059 		current_group->bin_id[key_changed_index] =
1060 				current_group->bin_id[last];
1061 
1062 		/*
1063 		 * Key to be updated will always be available
1064 		 * at the end of the group
1065 		 */
1066 		current_group->key_idx[last] = key_idx_previous;
1067 		current_group->value[last] = value;
1068 		current_group->bin_id[last] = *bin_id;
1069 	}
1070 
1071 	*new_bin_choice = current_choice;
1072 	*group_id = current_group_id;
1073 	new_group = current_group;
1074 
1075 	/* Group need to be rebalanced when it starts to get loaded */
1076 	if (current_group->num_rules > EFD_MIN_BALANCED_NUM_RULES) {
1077 
1078 		/*
1079 		 * Subtract the number of entries in the bin from
1080 		 * the original group
1081 		 */
1082 		current_group->num_rules -= bin_size;
1083 
1084 		/*
1085 		 * Figure out which of the available groups that this bin
1086 		 * can map to is the smallest (using the current group
1087 		 * as baseline)
1088 		 */
1089 		uint8_t smallest_choice = current_choice;
1090 		uint8_t smallest_size = current_group->num_rules;
1091 		uint32_t smallest_group_id = current_group_id;
1092 		unsigned char choice;
1093 
1094 		for (choice = 0; choice < EFD_CHUNK_NUM_BIN_TO_GROUP_SETS;
1095 				choice++) {
1096 			uint32_t test_group_id =
1097 					efd_bin_to_group[choice][*bin_id];
1098 			uint32_t num_rules =
1099 					chunk->group_rules[test_group_id].num_rules;
1100 			if (num_rules < smallest_size) {
1101 				smallest_choice = choice;
1102 				smallest_size = num_rules;
1103 				smallest_group_id = test_group_id;
1104 			}
1105 		}
1106 
1107 		*new_bin_choice = smallest_choice;
1108 		*group_id = smallest_group_id;
1109 		new_group = &chunk->group_rules[smallest_group_id];
1110 		current_group->num_rules += bin_size;
1111 
1112 	}
1113 
1114 	uint8_t choice = 0;
1115 	for (;;) {
1116 		if (current_group != new_group &&
1117 				new_group->num_rules + bin_size >
1118 					EFD_MAX_GROUP_NUM_RULES) {
1119 			RTE_LOG(DEBUG, EFD,
1120 					"Unable to move_groups to dest group "
1121 					"containing %u entries."
1122 					"bin_size:%u choice:%02x\n",
1123 					new_group->num_rules, bin_size,
1124 					choice - 1);
1125 			goto next_choice;
1126 		}
1127 		move_groups(*bin_id, bin_size, new_group, current_group);
1128 		/*
1129 		 * Recompute the hash function for the modified group,
1130 		 * and return it to the caller
1131 		 */
1132 		ret = efd_search_hash(table, new_group, entry);
1133 
1134 		if (!ret)
1135 			return status;
1136 
1137 		RTE_LOG(DEBUG, EFD,
1138 				"Failed to find perfect hash for group "
1139 				"containing %u entries. bin_size:%u choice:%02x\n",
1140 				new_group->num_rules, bin_size, choice - 1);
1141 		/* Restore groups modified to their previous state */
1142 		revert_groups(current_group, new_group, bin_size);
1143 
1144 next_choice:
1145 		if (choice == EFD_CHUNK_NUM_BIN_TO_GROUP_SETS)
1146 			break;
1147 		*new_bin_choice = choice;
1148 		*group_id = efd_bin_to_group[choice][*bin_id];
1149 		new_group = &chunk->group_rules[*group_id];
1150 		choice++;
1151 	}
1152 
1153 	if (!found) {
1154 		current_group->num_rules--;
1155 		table->num_rules--;
1156 	} else
1157 		current_group->value[current_group->num_rules - 1] =
1158 			key_changed_previous_value;
1159 	return RTE_EFD_UPDATE_FAILED;
1160 }
1161 
1162 int
1163 rte_efd_update(struct rte_efd_table * const table, const unsigned int socket_id,
1164 		const void *key, const efd_value_t value)
1165 {
1166 	uint32_t chunk_id = 0, group_id = 0, bin_id = 0;
1167 	uint8_t new_bin_choice = 0;
1168 	struct efd_online_group_entry entry;
1169 
1170 	int status = efd_compute_update(table, socket_id, key, value,
1171 			&chunk_id, &group_id, &bin_id,
1172 			&new_bin_choice, &entry);
1173 
1174 	if (status == RTE_EFD_UPDATE_NO_CHANGE)
1175 		return EXIT_SUCCESS;
1176 
1177 	if (status == RTE_EFD_UPDATE_FAILED)
1178 		return status;
1179 
1180 	efd_apply_update(table, socket_id, chunk_id, group_id, bin_id,
1181 			new_bin_choice, &entry);
1182 	return status;
1183 }
1184 
1185 int
1186 rte_efd_delete(struct rte_efd_table * const table, const unsigned int socket_id,
1187 		const void *key, efd_value_t * const prev_value)
1188 {
1189 	unsigned int i;
1190 	uint32_t chunk_id, bin_id;
1191 	uint8_t not_found = 1;
1192 
1193 	efd_compute_ids(table, key, &chunk_id, &bin_id);
1194 
1195 	struct efd_offline_chunk_rules * const chunk =
1196 			&table->offline_chunks[chunk_id];
1197 
1198 	uint8_t current_choice = efd_get_choice(table, socket_id,
1199 			chunk_id, bin_id);
1200 	uint32_t current_group_id = efd_bin_to_group[current_choice][bin_id];
1201 	struct efd_offline_group_rules * const current_group =
1202 			&chunk->group_rules[current_group_id];
1203 
1204 	/*
1205 	 * Search the current group for the specified key.
1206 	 * If it exists, remove it and re-pack the other values
1207 	 */
1208 	for (i = 0; i < current_group->num_rules; i++) {
1209 		if (not_found) {
1210 			/* Found key that needs to be removed */
1211 			if (memcmp(EFD_KEY(current_group->key_idx[i], table),
1212 					key, table->key_len) == 0) {
1213 				/* Store previous value if requested by caller */
1214 				if (prev_value != NULL)
1215 					*prev_value = current_group->value[i];
1216 
1217 				not_found = 0;
1218 				rte_ring_sp_enqueue(table->free_slots,
1219 					(void *)((uintptr_t)current_group->key_idx[i]));
1220 			}
1221 		} else {
1222 			/*
1223 			 * If the desired key has been found,
1224 			 * need to shift other values up one
1225 			 */
1226 
1227 			/* Need to shift this entry back up one index */
1228 			current_group->key_idx[i - 1] = current_group->key_idx[i];
1229 			current_group->value[i - 1] = current_group->value[i];
1230 			current_group->bin_id[i - 1] = current_group->bin_id[i];
1231 		}
1232 	}
1233 
1234 	if (not_found == 0) {
1235 		table->num_rules--;
1236 		current_group->num_rules--;
1237 	}
1238 
1239 	return not_found;
1240 }
1241 
1242 static inline efd_value_t
1243 efd_lookup_internal_scalar(const efd_hashfunc_t *group_hash_idx,
1244 		const efd_lookuptbl_t *group_lookup_table,
1245 		const uint32_t hash_val_a, const uint32_t hash_val_b)
1246 {
1247 	efd_value_t value = 0;
1248 	uint32_t i;
1249 
1250 	for (i = 0; i < RTE_EFD_VALUE_NUM_BITS; i++) {
1251 		value <<= 1;
1252 		uint32_t h = hash_val_a + (hash_val_b *
1253 			group_hash_idx[RTE_EFD_VALUE_NUM_BITS - i - 1]);
1254 		uint16_t bucket_idx = h >> EFD_LOOKUPTBL_SHIFT;
1255 		value |= (group_lookup_table[
1256 				RTE_EFD_VALUE_NUM_BITS - i - 1] >>
1257 				bucket_idx) & 0x1;
1258 	}
1259 
1260 	return value;
1261 }
1262 
1263 
1264 static inline efd_value_t
1265 efd_lookup_internal(const struct efd_online_group_entry * const group,
1266 		const uint32_t hash_val_a, const uint32_t hash_val_b,
1267 		enum efd_lookup_internal_function lookup_fn)
1268 {
1269 	efd_value_t value = 0;
1270 
1271 	switch (lookup_fn) {
1272 
1273 #if defined(RTE_ARCH_X86) && defined(CC_SUPPORT_AVX2)
1274 	case EFD_LOOKUP_AVX2:
1275 		return efd_lookup_internal_avx2(group->hash_idx,
1276 					group->lookup_table,
1277 					hash_val_a,
1278 					hash_val_b);
1279 		break;
1280 #endif
1281 #if defined(RTE_ARCH_ARM64)
1282 	case EFD_LOOKUP_NEON:
1283 		return efd_lookup_internal_neon(group->hash_idx,
1284 					group->lookup_table,
1285 					hash_val_a,
1286 					hash_val_b);
1287 		break;
1288 #endif
1289 	case EFD_LOOKUP_SCALAR:
1290 	/* Fall-through */
1291 	default:
1292 		return efd_lookup_internal_scalar(group->hash_idx,
1293 					group->lookup_table,
1294 					hash_val_a,
1295 					hash_val_b);
1296 	}
1297 
1298 	return value;
1299 }
1300 
1301 efd_value_t
1302 rte_efd_lookup(const struct rte_efd_table * const table,
1303 		const unsigned int socket_id, const void *key)
1304 {
1305 	uint32_t chunk_id, group_id, bin_id;
1306 	uint8_t bin_choice;
1307 	const struct efd_online_group_entry *group;
1308 	const struct efd_online_chunk * const chunks = table->chunks[socket_id];
1309 
1310 	/* Determine the chunk and group location for the given key */
1311 	efd_compute_ids(table, key, &chunk_id, &bin_id);
1312 	bin_choice = efd_get_choice(table, socket_id, chunk_id, bin_id);
1313 	group_id = efd_bin_to_group[bin_choice][bin_id];
1314 	group = &chunks[chunk_id].groups[group_id];
1315 
1316 	return efd_lookup_internal(group,
1317 			EFD_HASHFUNCA(key, table),
1318 			EFD_HASHFUNCB(key, table),
1319 			table->lookup_fn);
1320 }
1321 
1322 void rte_efd_lookup_bulk(const struct rte_efd_table * const table,
1323 		const unsigned int socket_id, const int num_keys,
1324 		const void **key_list, efd_value_t * const value_list)
1325 {
1326 	int i;
1327 	uint32_t chunk_id_list[RTE_EFD_BURST_MAX];
1328 	uint32_t bin_id_list[RTE_EFD_BURST_MAX];
1329 	uint8_t bin_choice_list[RTE_EFD_BURST_MAX];
1330 	uint32_t group_id_list[RTE_EFD_BURST_MAX];
1331 	struct efd_online_group_entry *group;
1332 
1333 	struct efd_online_chunk *chunks = table->chunks[socket_id];
1334 
1335 	for (i = 0; i < num_keys; i++) {
1336 		efd_compute_ids(table, key_list[i], &chunk_id_list[i],
1337 				&bin_id_list[i]);
1338 		rte_prefetch0(&chunks[chunk_id_list[i]].bin_choice_list);
1339 	}
1340 
1341 	for (i = 0; i < num_keys; i++) {
1342 		bin_choice_list[i] = efd_get_choice(table, socket_id,
1343 				chunk_id_list[i], bin_id_list[i]);
1344 		group_id_list[i] =
1345 				efd_bin_to_group[bin_choice_list[i]][bin_id_list[i]];
1346 		group = &chunks[chunk_id_list[i]].groups[group_id_list[i]];
1347 		rte_prefetch0(group);
1348 	}
1349 
1350 	for (i = 0; i < num_keys; i++) {
1351 		group = &chunks[chunk_id_list[i]].groups[group_id_list[i]];
1352 		value_list[i] = efd_lookup_internal(group,
1353 				EFD_HASHFUNCA(key_list[i], table),
1354 				EFD_HASHFUNCB(key_list[i], table),
1355 				table->lookup_fn);
1356 	}
1357 }
1358