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