1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2a9de470cSBruce Richardson * Copyright(c) 2010-2015 Intel Corporation 3a9de470cSBruce Richardson */ 4a9de470cSBruce Richardson 5a9de470cSBruce Richardson #include <stdio.h> 6a9de470cSBruce Richardson #include <stdint.h> 7a9de470cSBruce Richardson #include <string.h> 8a9de470cSBruce Richardson #include <stdlib.h> 9a9de470cSBruce Richardson #include <stdarg.h> 10a9de470cSBruce Richardson #include <errno.h> 11a9de470cSBruce Richardson #include <sys/queue.h> 12a9de470cSBruce Richardson 13a9de470cSBruce Richardson #include <rte_common.h> 14a9de470cSBruce Richardson #include <rte_malloc.h> 15a9de470cSBruce Richardson #include <rte_cycles.h> 16a9de470cSBruce Richardson #include <rte_random.h> 17a9de470cSBruce Richardson #include <rte_memory.h> 18a9de470cSBruce Richardson #include <rte_eal.h> 19a9de470cSBruce Richardson #include <rte_ip.h> 20a9de470cSBruce Richardson #include <rte_string_fns.h> 21a9de470cSBruce Richardson 22a9de470cSBruce Richardson #include "test.h" 23a9de470cSBruce Richardson 24a9de470cSBruce Richardson #include <rte_hash.h> 25a9de470cSBruce Richardson #include <rte_fbk_hash.h> 26a9de470cSBruce Richardson #include <rte_jhash.h> 27a9de470cSBruce Richardson #include <rte_hash_crc.h> 28a9de470cSBruce Richardson 29a9de470cSBruce Richardson /******************************************************************************* 30a9de470cSBruce Richardson * Hash function performance test configuration section. Each performance test 31a9de470cSBruce Richardson * will be performed HASHTEST_ITERATIONS times. 32a9de470cSBruce Richardson * 33a9de470cSBruce Richardson * The five arrays below control what tests are performed. Every combination 34a9de470cSBruce Richardson * from the array entries is tested. 35a9de470cSBruce Richardson */ 36a9de470cSBruce Richardson static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc}; 37a9de470cSBruce Richardson static uint32_t hashtest_initvals[] = {0}; 38a9de470cSBruce Richardson static uint32_t hashtest_key_lens[] = {0, 2, 4, 5, 6, 7, 8, 10, 11, 15, 16, 21, 31, 32, 33, 63, 64}; 39a9de470cSBruce Richardson #define MAX_KEYSIZE 64 40a9de470cSBruce Richardson /******************************************************************************/ 41a9de470cSBruce Richardson #define LOCAL_FBK_HASH_ENTRIES_MAX (1 << 15) 42a9de470cSBruce Richardson 43a9de470cSBruce Richardson /* 44a9de470cSBruce Richardson * Check condition and return an error if true. Assumes that "handle" is the 45a9de470cSBruce Richardson * name of the hash structure pointer to be freed. 46a9de470cSBruce Richardson */ 47a9de470cSBruce Richardson #define RETURN_IF_ERROR(cond, str, ...) do { \ 48a9de470cSBruce Richardson if (cond) { \ 49a9de470cSBruce Richardson printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \ 50a9de470cSBruce Richardson if (handle) rte_hash_free(handle); \ 51a9de470cSBruce Richardson return -1; \ 52a9de470cSBruce Richardson } \ 53a9de470cSBruce Richardson } while(0) 54a9de470cSBruce Richardson 55a9de470cSBruce Richardson #define RETURN_IF_ERROR_FBK(cond, str, ...) do { \ 56a9de470cSBruce Richardson if (cond) { \ 57a9de470cSBruce Richardson printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \ 58a9de470cSBruce Richardson if (handle) rte_fbk_hash_free(handle); \ 59a9de470cSBruce Richardson return -1; \ 60a9de470cSBruce Richardson } \ 61a9de470cSBruce Richardson } while(0) 62a9de470cSBruce Richardson 639c7d8eedSDharmik Thakkar #define RETURN_IF_ERROR_RCU_QSBR(cond, str, ...) do { \ 649c7d8eedSDharmik Thakkar if (cond) { \ 659c7d8eedSDharmik Thakkar printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \ 669c7d8eedSDharmik Thakkar if (rcu_cfg.mode == RTE_HASH_QSBR_MODE_SYNC) { \ 679c7d8eedSDharmik Thakkar writer_done = 1; \ 689c7d8eedSDharmik Thakkar /* Wait until reader exited. */ \ 699c7d8eedSDharmik Thakkar rte_eal_mp_wait_lcore(); \ 709c7d8eedSDharmik Thakkar } \ 719c7d8eedSDharmik Thakkar rte_hash_free(g_handle); \ 729c7d8eedSDharmik Thakkar rte_free(g_qsv); \ 739c7d8eedSDharmik Thakkar return -1; \ 749c7d8eedSDharmik Thakkar } \ 759c7d8eedSDharmik Thakkar } while (0) 769c7d8eedSDharmik Thakkar 77e30ef3a3SVladimir Medvedkin /* 78e30ef3a3SVladimir Medvedkin * 5-tuple key type. 79e30ef3a3SVladimir Medvedkin * Should be packed to avoid holes with potentially 80e30ef3a3SVladimir Medvedkin * undefined content in the middle. 81e30ef3a3SVladimir Medvedkin */ 82*b5662e6dSAndre Muezerie struct __rte_packed_begin flow_key { 83a9de470cSBruce Richardson uint32_t ip_src; 84a9de470cSBruce Richardson uint32_t ip_dst; 85a9de470cSBruce Richardson uint16_t port_src; 86a9de470cSBruce Richardson uint16_t port_dst; 87e30ef3a3SVladimir Medvedkin uint32_t proto; 88*b5662e6dSAndre Muezerie } __rte_packed_end; 89a9de470cSBruce Richardson 90a9de470cSBruce Richardson /* 91a9de470cSBruce Richardson * Hash function that always returns the same value, to easily test what 92a9de470cSBruce Richardson * happens when a bucket is full. 93a9de470cSBruce Richardson */ 94f2fc83b4SThomas Monjalon static uint32_t pseudo_hash(__rte_unused const void *keys, 95f2fc83b4SThomas Monjalon __rte_unused uint32_t key_len, 96f2fc83b4SThomas Monjalon __rte_unused uint32_t init_val) 97a9de470cSBruce Richardson { 9864b2907cSYoan Picchi return 3 | (3 << 16); 99a9de470cSBruce Richardson } 100a9de470cSBruce Richardson 1019c99878aSJerin Jacob RTE_LOG_REGISTER(hash_logtype_test, test.hash, INFO); 10254e5545dSDharmik Thakkar 103a9de470cSBruce Richardson /* 104a9de470cSBruce Richardson * Print out result of unit test hash operation. 105a9de470cSBruce Richardson */ 106a9de470cSBruce Richardson static void print_key_info(const char *msg, const struct flow_key *key, 107a9de470cSBruce Richardson int32_t pos) 108a9de470cSBruce Richardson { 109a9de470cSBruce Richardson const uint8_t *p = (const uint8_t *)key; 110a9de470cSBruce Richardson unsigned int i; 111a9de470cSBruce Richardson 11254e5545dSDharmik Thakkar rte_log(RTE_LOG_DEBUG, hash_logtype_test, "%s key:0x", msg); 113a9de470cSBruce Richardson for (i = 0; i < sizeof(struct flow_key); i++) 11454e5545dSDharmik Thakkar rte_log(RTE_LOG_DEBUG, hash_logtype_test, "%02X", p[i]); 11554e5545dSDharmik Thakkar rte_log(RTE_LOG_DEBUG, hash_logtype_test, " @ pos %d\n", pos); 116a9de470cSBruce Richardson } 117a9de470cSBruce Richardson 11864b2907cSYoan Picchi #define KEY_PER_BUCKET 8 11964b2907cSYoan Picchi 120a9de470cSBruce Richardson /* Keys used by unit test functions */ 12164b2907cSYoan Picchi static struct flow_key keys[KEY_PER_BUCKET+1] = { { 1220c9da755SDavid Marchand .ip_src = RTE_IPV4(0x03, 0x02, 0x01, 0x00), 1230c9da755SDavid Marchand .ip_dst = RTE_IPV4(0x07, 0x06, 0x05, 0x04), 124a9de470cSBruce Richardson .port_src = 0x0908, 125a9de470cSBruce Richardson .port_dst = 0x0b0a, 126a9de470cSBruce Richardson .proto = 0x0c, 127a9de470cSBruce Richardson }, { 1280c9da755SDavid Marchand .ip_src = RTE_IPV4(0x13, 0x12, 0x11, 0x10), 1290c9da755SDavid Marchand .ip_dst = RTE_IPV4(0x17, 0x16, 0x15, 0x14), 130a9de470cSBruce Richardson .port_src = 0x1918, 131a9de470cSBruce Richardson .port_dst = 0x1b1a, 132a9de470cSBruce Richardson .proto = 0x1c, 133a9de470cSBruce Richardson }, { 1340c9da755SDavid Marchand .ip_src = RTE_IPV4(0x23, 0x22, 0x21, 0x20), 1350c9da755SDavid Marchand .ip_dst = RTE_IPV4(0x27, 0x26, 0x25, 0x24), 136a9de470cSBruce Richardson .port_src = 0x2928, 137a9de470cSBruce Richardson .port_dst = 0x2b2a, 138a9de470cSBruce Richardson .proto = 0x2c, 139a9de470cSBruce Richardson }, { 1400c9da755SDavid Marchand .ip_src = RTE_IPV4(0x33, 0x32, 0x31, 0x30), 1410c9da755SDavid Marchand .ip_dst = RTE_IPV4(0x37, 0x36, 0x35, 0x34), 142a9de470cSBruce Richardson .port_src = 0x3938, 143a9de470cSBruce Richardson .port_dst = 0x3b3a, 144a9de470cSBruce Richardson .proto = 0x3c, 145a9de470cSBruce Richardson }, { 1460c9da755SDavid Marchand .ip_src = RTE_IPV4(0x43, 0x42, 0x41, 0x40), 1470c9da755SDavid Marchand .ip_dst = RTE_IPV4(0x47, 0x46, 0x45, 0x44), 148a9de470cSBruce Richardson .port_src = 0x4948, 149a9de470cSBruce Richardson .port_dst = 0x4b4a, 150a9de470cSBruce Richardson .proto = 0x4c, 15164b2907cSYoan Picchi }, { 15264b2907cSYoan Picchi .ip_src = RTE_IPV4(0x53, 0x52, 0x51, 0x50), 15364b2907cSYoan Picchi .ip_dst = RTE_IPV4(0x57, 0x56, 0x55, 0x54), 15464b2907cSYoan Picchi .port_src = 0x5958, 15564b2907cSYoan Picchi .port_dst = 0x5b5a, 15664b2907cSYoan Picchi .proto = 0x5c, 15764b2907cSYoan Picchi }, { 15864b2907cSYoan Picchi .ip_src = RTE_IPV4(0x63, 0x62, 0x61, 0x60), 15964b2907cSYoan Picchi .ip_dst = RTE_IPV4(0x67, 0x66, 0x65, 0x64), 16064b2907cSYoan Picchi .port_src = 0x6968, 16164b2907cSYoan Picchi .port_dst = 0x6b6a, 16264b2907cSYoan Picchi .proto = 0x6c, 16364b2907cSYoan Picchi }, { 16464b2907cSYoan Picchi .ip_src = RTE_IPV4(0x73, 0x72, 0x71, 0x70), 16564b2907cSYoan Picchi .ip_dst = RTE_IPV4(0x77, 0x76, 0x75, 0x74), 16664b2907cSYoan Picchi .port_src = 0x7978, 16764b2907cSYoan Picchi .port_dst = 0x7b7a, 16864b2907cSYoan Picchi .proto = 0x7c, 16964b2907cSYoan Picchi }, { 17064b2907cSYoan Picchi .ip_src = RTE_IPV4(0x83, 0x82, 0x81, 0x80), 17164b2907cSYoan Picchi .ip_dst = RTE_IPV4(0x87, 0x86, 0x85, 0x84), 17264b2907cSYoan Picchi .port_src = 0x8988, 17364b2907cSYoan Picchi .port_dst = 0x8b8a, 17464b2907cSYoan Picchi .proto = 0x8c, 175a9de470cSBruce Richardson } }; 176a9de470cSBruce Richardson 177a9de470cSBruce Richardson /* Parameters used for hash table in unit test functions. Name set later. */ 178a9de470cSBruce Richardson static struct rte_hash_parameters ut_params = { 179a9de470cSBruce Richardson .entries = 64, 180e30ef3a3SVladimir Medvedkin .key_len = sizeof(struct flow_key), 181a9de470cSBruce Richardson .hash_func = rte_jhash, 182a9de470cSBruce Richardson .hash_func_init_val = 0, 183a9de470cSBruce Richardson .socket_id = 0, 184a9de470cSBruce Richardson }; 185a9de470cSBruce Richardson 186a9de470cSBruce Richardson #define CRC32_ITERATIONS (1U << 10) 187a9de470cSBruce Richardson #define CRC32_DWORDS (1U << 6) 188a9de470cSBruce Richardson /* 189a9de470cSBruce Richardson * Test if all CRC32 implementations yield the same hash value 190a9de470cSBruce Richardson */ 191a9de470cSBruce Richardson static int 192a9de470cSBruce Richardson test_crc32_hash_alg_equiv(void) 193a9de470cSBruce Richardson { 194a9de470cSBruce Richardson uint32_t hash_val; 195a9de470cSBruce Richardson uint32_t init_val; 196a9de470cSBruce Richardson uint64_t data64[CRC32_DWORDS]; 197a9de470cSBruce Richardson unsigned i, j; 198a9de470cSBruce Richardson size_t data_len; 199a9de470cSBruce Richardson 200a9de470cSBruce Richardson printf("\n# CRC32 implementations equivalence test\n"); 201a9de470cSBruce Richardson for (i = 0; i < CRC32_ITERATIONS; i++) { 202a9de470cSBruce Richardson /* Randomizing data_len of data set */ 203a9de470cSBruce Richardson data_len = (size_t) ((rte_rand() % sizeof(data64)) + 1); 204a9de470cSBruce Richardson init_val = (uint32_t) rte_rand(); 205a9de470cSBruce Richardson 206a9de470cSBruce Richardson /* Fill the data set */ 207a9de470cSBruce Richardson for (j = 0; j < CRC32_DWORDS; j++) 208a9de470cSBruce Richardson data64[j] = rte_rand(); 209a9de470cSBruce Richardson 210a9de470cSBruce Richardson /* Calculate software CRC32 */ 211a9de470cSBruce Richardson rte_hash_crc_set_alg(CRC32_SW); 212a9de470cSBruce Richardson hash_val = rte_hash_crc(data64, data_len, init_val); 213a9de470cSBruce Richardson 214a9de470cSBruce Richardson /* Check against 4-byte-operand sse4.2 CRC32 if available */ 215a9de470cSBruce Richardson rte_hash_crc_set_alg(CRC32_SSE42); 216a9de470cSBruce Richardson if (hash_val != rte_hash_crc(data64, data_len, init_val)) { 217a9de470cSBruce Richardson printf("Failed checking CRC32_SW against CRC32_SSE42\n"); 218a9de470cSBruce Richardson break; 219a9de470cSBruce Richardson } 220a9de470cSBruce Richardson 221a9de470cSBruce Richardson /* Check against 8-byte-operand sse4.2 CRC32 if available */ 222a9de470cSBruce Richardson rte_hash_crc_set_alg(CRC32_SSE42_x64); 223a9de470cSBruce Richardson if (hash_val != rte_hash_crc(data64, data_len, init_val)) { 224a9de470cSBruce Richardson printf("Failed checking CRC32_SW against CRC32_SSE42_x64\n"); 225a9de470cSBruce Richardson break; 226a9de470cSBruce Richardson } 227a9de470cSBruce Richardson 228a9de470cSBruce Richardson /* Check against 8-byte-operand ARM64 CRC32 if available */ 229a9de470cSBruce Richardson rte_hash_crc_set_alg(CRC32_ARM64); 230a9de470cSBruce Richardson if (hash_val != rte_hash_crc(data64, data_len, init_val)) { 231a9de470cSBruce Richardson printf("Failed checking CRC32_SW against CRC32_ARM64\n"); 232a9de470cSBruce Richardson break; 233a9de470cSBruce Richardson } 234a9de470cSBruce Richardson } 235a9de470cSBruce Richardson 236a9de470cSBruce Richardson /* Resetting to best available algorithm */ 237a9de470cSBruce Richardson rte_hash_crc_set_alg(CRC32_SSE42_x64); 238a9de470cSBruce Richardson 239a9de470cSBruce Richardson if (i == CRC32_ITERATIONS) 240a9de470cSBruce Richardson return 0; 241a9de470cSBruce Richardson 242a9de470cSBruce Richardson printf("Failed test data (hex, %zu bytes total):\n", data_len); 243a9de470cSBruce Richardson for (j = 0; j < data_len; j++) 244a9de470cSBruce Richardson printf("%02X%c", ((uint8_t *)data64)[j], 245a9de470cSBruce Richardson ((j+1) % 16 == 0 || j == data_len - 1) ? '\n' : ' '); 246a9de470cSBruce Richardson 247a9de470cSBruce Richardson return -1; 248a9de470cSBruce Richardson } 249a9de470cSBruce Richardson 250a9de470cSBruce Richardson /* 251a9de470cSBruce Richardson * Test a hash function. 252a9de470cSBruce Richardson */ 253a9de470cSBruce Richardson static void run_hash_func_test(rte_hash_function f, uint32_t init_val, 254a9de470cSBruce Richardson uint32_t key_len) 255a9de470cSBruce Richardson { 256a9de470cSBruce Richardson static uint8_t key[MAX_KEYSIZE]; 257a9de470cSBruce Richardson unsigned i; 258a9de470cSBruce Richardson 259a9de470cSBruce Richardson 260a9de470cSBruce Richardson for (i = 0; i < key_len; i++) 261a9de470cSBruce Richardson key[i] = (uint8_t) rte_rand(); 262a9de470cSBruce Richardson 263a9de470cSBruce Richardson /* just to be on the safe side */ 264a9de470cSBruce Richardson if (!f) 265a9de470cSBruce Richardson return; 266a9de470cSBruce Richardson 267a9de470cSBruce Richardson f(key, key_len, init_val); 268a9de470cSBruce Richardson } 269a9de470cSBruce Richardson 270a9de470cSBruce Richardson /* 271a9de470cSBruce Richardson * Test all hash functions. 272a9de470cSBruce Richardson */ 273a9de470cSBruce Richardson static void run_hash_func_tests(void) 274a9de470cSBruce Richardson { 275a9de470cSBruce Richardson unsigned i, j, k; 276a9de470cSBruce Richardson 27771bdd8a1SPavan Nikhilesh for (i = 0; i < RTE_DIM(hashtest_funcs); i++) { 27871bdd8a1SPavan Nikhilesh for (j = 0; j < RTE_DIM(hashtest_initvals); j++) { 27971bdd8a1SPavan Nikhilesh for (k = 0; k < RTE_DIM(hashtest_key_lens); k++) { 280a9de470cSBruce Richardson run_hash_func_test(hashtest_funcs[i], 281a9de470cSBruce Richardson hashtest_initvals[j], 282a9de470cSBruce Richardson hashtest_key_lens[k]); 283a9de470cSBruce Richardson } 284a9de470cSBruce Richardson } 285a9de470cSBruce Richardson } 286a9de470cSBruce Richardson } 287a9de470cSBruce Richardson 288a9de470cSBruce Richardson /* 289a9de470cSBruce Richardson * Basic sequence of operations for a single key: 290a9de470cSBruce Richardson * - add 291a9de470cSBruce Richardson * - lookup (hit) 292a9de470cSBruce Richardson * - delete 293a9de470cSBruce Richardson * - lookup (miss) 294a9de470cSBruce Richardson * 295a9de470cSBruce Richardson * Repeat the test case when 'free on delete' is disabled. 296a9de470cSBruce Richardson * - add 297a9de470cSBruce Richardson * - lookup (hit) 298a9de470cSBruce Richardson * - delete 299a9de470cSBruce Richardson * - lookup (miss) 300a9de470cSBruce Richardson * - free 301a9de470cSBruce Richardson */ 302a9de470cSBruce Richardson static int test_add_delete(void) 303a9de470cSBruce Richardson { 304a9de470cSBruce Richardson struct rte_hash *handle; 305a9de470cSBruce Richardson /* test with standard add/lookup/delete functions */ 306a9de470cSBruce Richardson int pos0, expectedPos0; 307a9de470cSBruce Richardson 308a9de470cSBruce Richardson ut_params.name = "test1"; 309a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 310a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 311a9de470cSBruce Richardson 312a9de470cSBruce Richardson pos0 = rte_hash_add_key(handle, &keys[0]); 313a9de470cSBruce Richardson print_key_info("Add", &keys[0], pos0); 314a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0); 315a9de470cSBruce Richardson expectedPos0 = pos0; 316a9de470cSBruce Richardson 317a9de470cSBruce Richardson pos0 = rte_hash_lookup(handle, &keys[0]); 318a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos0); 319a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != expectedPos0, 320a9de470cSBruce Richardson "failed to find key (pos0=%d)", pos0); 321a9de470cSBruce Richardson 322a9de470cSBruce Richardson pos0 = rte_hash_del_key(handle, &keys[0]); 323a9de470cSBruce Richardson print_key_info("Del", &keys[0], pos0); 324a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != expectedPos0, 325a9de470cSBruce Richardson "failed to delete key (pos0=%d)", pos0); 326a9de470cSBruce Richardson 327a9de470cSBruce Richardson pos0 = rte_hash_lookup(handle, &keys[0]); 328a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos0); 329a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != -ENOENT, 330a9de470cSBruce Richardson "fail: found key after deleting! (pos0=%d)", pos0); 331a9de470cSBruce Richardson 332a9de470cSBruce Richardson rte_hash_free(handle); 333a9de470cSBruce Richardson 334a9de470cSBruce Richardson /* repeat test with precomputed hash functions */ 335a9de470cSBruce Richardson hash_sig_t hash_value; 336a9de470cSBruce Richardson int pos1, expectedPos1, delPos1; 337a9de470cSBruce Richardson 338a9de470cSBruce Richardson ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL; 339a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 340a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 341a9de470cSBruce Richardson ut_params.extra_flag = 0; 342a9de470cSBruce Richardson 343a9de470cSBruce Richardson hash_value = rte_hash_hash(handle, &keys[0]); 344a9de470cSBruce Richardson pos1 = rte_hash_add_key_with_hash(handle, &keys[0], hash_value); 345a9de470cSBruce Richardson print_key_info("Add", &keys[0], pos1); 346a9de470cSBruce Richardson RETURN_IF_ERROR(pos1 < 0, "failed to add key (pos1=%d)", pos1); 347a9de470cSBruce Richardson expectedPos1 = pos1; 348a9de470cSBruce Richardson 349a9de470cSBruce Richardson pos1 = rte_hash_lookup_with_hash(handle, &keys[0], hash_value); 350a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos1); 351a9de470cSBruce Richardson RETURN_IF_ERROR(pos1 != expectedPos1, 352a9de470cSBruce Richardson "failed to find key (pos1=%d)", pos1); 353a9de470cSBruce Richardson 354a9de470cSBruce Richardson pos1 = rte_hash_del_key_with_hash(handle, &keys[0], hash_value); 355a9de470cSBruce Richardson print_key_info("Del", &keys[0], pos1); 356a9de470cSBruce Richardson RETURN_IF_ERROR(pos1 != expectedPos1, 357a9de470cSBruce Richardson "failed to delete key (pos1=%d)", pos1); 358a9de470cSBruce Richardson delPos1 = pos1; 359a9de470cSBruce Richardson 360a9de470cSBruce Richardson pos1 = rte_hash_lookup_with_hash(handle, &keys[0], hash_value); 361a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos1); 362a9de470cSBruce Richardson RETURN_IF_ERROR(pos1 != -ENOENT, 363a9de470cSBruce Richardson "fail: found key after deleting! (pos1=%d)", pos1); 364a9de470cSBruce Richardson 365a9de470cSBruce Richardson pos1 = rte_hash_free_key_with_position(handle, delPos1); 366a9de470cSBruce Richardson print_key_info("Free", &keys[0], delPos1); 367a9de470cSBruce Richardson RETURN_IF_ERROR(pos1 != 0, 368a9de470cSBruce Richardson "failed to free key (pos1=%d)", delPos1); 369a9de470cSBruce Richardson 370a9de470cSBruce Richardson rte_hash_free(handle); 371a9de470cSBruce Richardson 372a9de470cSBruce Richardson return 0; 373a9de470cSBruce Richardson } 374a9de470cSBruce Richardson 375a9de470cSBruce Richardson /* 376a9de470cSBruce Richardson * Sequence of operations for a single key: 377a9de470cSBruce Richardson * - delete: miss 378a9de470cSBruce Richardson * - add 379a9de470cSBruce Richardson * - lookup: hit 380a9de470cSBruce Richardson * - add: update 381a9de470cSBruce Richardson * - lookup: hit (updated data) 382a9de470cSBruce Richardson * - delete: hit 383a9de470cSBruce Richardson * - delete: miss 384a9de470cSBruce Richardson * - lookup: miss 385a9de470cSBruce Richardson */ 386a9de470cSBruce Richardson static int test_add_update_delete(void) 387a9de470cSBruce Richardson { 388a9de470cSBruce Richardson struct rte_hash *handle; 389a9de470cSBruce Richardson int pos0, expectedPos0; 390a9de470cSBruce Richardson 391a9de470cSBruce Richardson ut_params.name = "test2"; 392a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 393a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 394a9de470cSBruce Richardson 395a9de470cSBruce Richardson pos0 = rte_hash_del_key(handle, &keys[0]); 396a9de470cSBruce Richardson print_key_info("Del", &keys[0], pos0); 397a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != -ENOENT, 398a9de470cSBruce Richardson "fail: found non-existent key (pos0=%d)", pos0); 399a9de470cSBruce Richardson 400a9de470cSBruce Richardson pos0 = rte_hash_add_key(handle, &keys[0]); 401a9de470cSBruce Richardson print_key_info("Add", &keys[0], pos0); 402a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0); 403a9de470cSBruce Richardson expectedPos0 = pos0; 404a9de470cSBruce Richardson 405a9de470cSBruce Richardson pos0 = rte_hash_lookup(handle, &keys[0]); 406a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos0); 407a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != expectedPos0, 408a9de470cSBruce Richardson "failed to find key (pos0=%d)", pos0); 409a9de470cSBruce Richardson 410a9de470cSBruce Richardson pos0 = rte_hash_add_key(handle, &keys[0]); 411a9de470cSBruce Richardson print_key_info("Add", &keys[0], pos0); 412a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != expectedPos0, 413a9de470cSBruce Richardson "failed to re-add key (pos0=%d)", pos0); 414a9de470cSBruce Richardson 415a9de470cSBruce Richardson pos0 = rte_hash_lookup(handle, &keys[0]); 416a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos0); 417a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != expectedPos0, 418a9de470cSBruce Richardson "failed to find key (pos0=%d)", pos0); 419a9de470cSBruce Richardson 420a9de470cSBruce Richardson pos0 = rte_hash_del_key(handle, &keys[0]); 421a9de470cSBruce Richardson print_key_info("Del", &keys[0], pos0); 422a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != expectedPos0, 423a9de470cSBruce Richardson "failed to delete key (pos0=%d)", pos0); 424a9de470cSBruce Richardson 425a9de470cSBruce Richardson pos0 = rte_hash_del_key(handle, &keys[0]); 426a9de470cSBruce Richardson print_key_info("Del", &keys[0], pos0); 427a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != -ENOENT, 428a9de470cSBruce Richardson "fail: deleted already deleted key (pos0=%d)", pos0); 429a9de470cSBruce Richardson 430a9de470cSBruce Richardson pos0 = rte_hash_lookup(handle, &keys[0]); 431a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos0); 432a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != -ENOENT, 433a9de470cSBruce Richardson "fail: found key after deleting! (pos0=%d)", pos0); 434a9de470cSBruce Richardson 435a9de470cSBruce Richardson rte_hash_free(handle); 436a9de470cSBruce Richardson return 0; 437a9de470cSBruce Richardson } 438a9de470cSBruce Richardson 439a9de470cSBruce Richardson /* 440a9de470cSBruce Richardson * Sequence of operations for a single key with 'disable free on del' set: 441a9de470cSBruce Richardson * - delete: miss 442a9de470cSBruce Richardson * - add 443a9de470cSBruce Richardson * - lookup: hit 444a9de470cSBruce Richardson * - add: update 445a9de470cSBruce Richardson * - lookup: hit (updated data) 446a9de470cSBruce Richardson * - delete: hit 447a9de470cSBruce Richardson * - delete: miss 448a9de470cSBruce Richardson * - lookup: miss 449a9de470cSBruce Richardson * - free: hit 450a9de470cSBruce Richardson * - lookup: miss 451a9de470cSBruce Richardson */ 452a9de470cSBruce Richardson static int test_add_update_delete_free(void) 453a9de470cSBruce Richardson { 454a9de470cSBruce Richardson struct rte_hash *handle; 455a9de470cSBruce Richardson int pos0, expectedPos0, delPos0, result; 456a9de470cSBruce Richardson 457a9de470cSBruce Richardson ut_params.name = "test2"; 458a9de470cSBruce Richardson ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL; 459a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 460a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 461a9de470cSBruce Richardson ut_params.extra_flag = 0; 462a9de470cSBruce Richardson 463a9de470cSBruce Richardson pos0 = rte_hash_del_key(handle, &keys[0]); 464a9de470cSBruce Richardson print_key_info("Del", &keys[0], pos0); 465a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != -ENOENT, 466a9de470cSBruce Richardson "fail: found non-existent key (pos0=%d)", pos0); 467a9de470cSBruce Richardson 468a9de470cSBruce Richardson pos0 = rte_hash_add_key(handle, &keys[0]); 469a9de470cSBruce Richardson print_key_info("Add", &keys[0], pos0); 470a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0); 471a9de470cSBruce Richardson expectedPos0 = pos0; 472a9de470cSBruce Richardson 473a9de470cSBruce Richardson pos0 = rte_hash_lookup(handle, &keys[0]); 474a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos0); 475a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != expectedPos0, 476a9de470cSBruce Richardson "failed to find key (pos0=%d)", pos0); 477a9de470cSBruce Richardson 478a9de470cSBruce Richardson pos0 = rte_hash_add_key(handle, &keys[0]); 479a9de470cSBruce Richardson print_key_info("Add", &keys[0], pos0); 480a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != expectedPos0, 481a9de470cSBruce Richardson "failed to re-add key (pos0=%d)", pos0); 482a9de470cSBruce Richardson 483a9de470cSBruce Richardson pos0 = rte_hash_lookup(handle, &keys[0]); 484a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos0); 485a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != expectedPos0, 486a9de470cSBruce Richardson "failed to find key (pos0=%d)", pos0); 487a9de470cSBruce Richardson 488a9de470cSBruce Richardson delPos0 = rte_hash_del_key(handle, &keys[0]); 489a9de470cSBruce Richardson print_key_info("Del", &keys[0], delPos0); 490a9de470cSBruce Richardson RETURN_IF_ERROR(delPos0 != expectedPos0, 491a9de470cSBruce Richardson "failed to delete key (pos0=%d)", delPos0); 492a9de470cSBruce Richardson 493a9de470cSBruce Richardson pos0 = rte_hash_del_key(handle, &keys[0]); 494a9de470cSBruce Richardson print_key_info("Del", &keys[0], pos0); 495a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != -ENOENT, 496a9de470cSBruce Richardson "fail: deleted already deleted key (pos0=%d)", pos0); 497a9de470cSBruce Richardson 498a9de470cSBruce Richardson pos0 = rte_hash_lookup(handle, &keys[0]); 499a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos0); 500a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != -ENOENT, 501a9de470cSBruce Richardson "fail: found key after deleting! (pos0=%d)", pos0); 502a9de470cSBruce Richardson 503a9de470cSBruce Richardson result = rte_hash_free_key_with_position(handle, delPos0); 504a9de470cSBruce Richardson print_key_info("Free", &keys[0], delPos0); 505a9de470cSBruce Richardson RETURN_IF_ERROR(result != 0, 506a9de470cSBruce Richardson "failed to free key (pos1=%d)", delPos0); 507a9de470cSBruce Richardson 508a9de470cSBruce Richardson pos0 = rte_hash_lookup(handle, &keys[0]); 509a9de470cSBruce Richardson print_key_info("Lkp", &keys[0], pos0); 510a9de470cSBruce Richardson RETURN_IF_ERROR(pos0 != -ENOENT, 511a9de470cSBruce Richardson "fail: found key after deleting! (pos0=%d)", pos0); 512a9de470cSBruce Richardson 513a9de470cSBruce Richardson rte_hash_free(handle); 514a9de470cSBruce Richardson return 0; 515a9de470cSBruce Richardson } 516a9de470cSBruce Richardson 517a9de470cSBruce Richardson /* 518a55f182bSDharmik Thakkar * Sequence of operations for a single key with 'rw concurrency lock free' set: 519a55f182bSDharmik Thakkar * - add 520a55f182bSDharmik Thakkar * - delete: hit 521a55f182bSDharmik Thakkar * - free: hit 522a55f182bSDharmik Thakkar * Repeat the test case when 'multi writer add' is enabled. 523a55f182bSDharmik Thakkar * - add 524a55f182bSDharmik Thakkar * - delete: hit 525a55f182bSDharmik Thakkar * - free: hit 526a55f182bSDharmik Thakkar */ 527a55f182bSDharmik Thakkar static int test_add_delete_free_lf(void) 528a55f182bSDharmik Thakkar { 529a55f182bSDharmik Thakkar /* Should match the #define LCORE_CACHE_SIZE value in rte_cuckoo_hash.h */ 530a55f182bSDharmik Thakkar #define LCORE_CACHE_SIZE 64 531a55f182bSDharmik Thakkar struct rte_hash *handle; 532a55f182bSDharmik Thakkar hash_sig_t hash_value; 533a55f182bSDharmik Thakkar int pos, expectedPos, delPos; 534a55f182bSDharmik Thakkar uint8_t extra_flag; 535a55f182bSDharmik Thakkar uint32_t i, ip_src; 536a55f182bSDharmik Thakkar 537a55f182bSDharmik Thakkar extra_flag = ut_params.extra_flag; 538a55f182bSDharmik Thakkar ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF; 539a55f182bSDharmik Thakkar handle = rte_hash_create(&ut_params); 540a55f182bSDharmik Thakkar RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 541a55f182bSDharmik Thakkar ut_params.extra_flag = extra_flag; 542a55f182bSDharmik Thakkar 543a55f182bSDharmik Thakkar /* 544a55f182bSDharmik Thakkar * The number of iterations is at least the same as the number of slots 545a55f182bSDharmik Thakkar * rte_hash allocates internally. This is to reveal potential issues of 546a55f182bSDharmik Thakkar * not freeing keys successfully. 547a55f182bSDharmik Thakkar */ 548a55f182bSDharmik Thakkar for (i = 0; i < ut_params.entries + 1; i++) { 549a55f182bSDharmik Thakkar hash_value = rte_hash_hash(handle, &keys[0]); 550a55f182bSDharmik Thakkar pos = rte_hash_add_key_with_hash(handle, &keys[0], hash_value); 551a55f182bSDharmik Thakkar print_key_info("Add", &keys[0], pos); 552a55f182bSDharmik Thakkar RETURN_IF_ERROR(pos < 0, "failed to add key (pos=%d)", pos); 553a55f182bSDharmik Thakkar expectedPos = pos; 554a55f182bSDharmik Thakkar 555a55f182bSDharmik Thakkar pos = rte_hash_del_key_with_hash(handle, &keys[0], hash_value); 556a55f182bSDharmik Thakkar print_key_info("Del", &keys[0], pos); 557a55f182bSDharmik Thakkar RETURN_IF_ERROR(pos != expectedPos, 558a55f182bSDharmik Thakkar "failed to delete key (pos=%d)", pos); 559a55f182bSDharmik Thakkar delPos = pos; 560a55f182bSDharmik Thakkar 561a55f182bSDharmik Thakkar pos = rte_hash_free_key_with_position(handle, delPos); 562a55f182bSDharmik Thakkar print_key_info("Free", &keys[0], delPos); 563a55f182bSDharmik Thakkar RETURN_IF_ERROR(pos != 0, 564a55f182bSDharmik Thakkar "failed to free key (pos=%d)", delPos); 565a55f182bSDharmik Thakkar } 566a55f182bSDharmik Thakkar 567a55f182bSDharmik Thakkar rte_hash_free(handle); 568a55f182bSDharmik Thakkar 569a55f182bSDharmik Thakkar extra_flag = ut_params.extra_flag; 570a55f182bSDharmik Thakkar ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF | 571a55f182bSDharmik Thakkar RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD; 572a55f182bSDharmik Thakkar handle = rte_hash_create(&ut_params); 573a55f182bSDharmik Thakkar RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 574a55f182bSDharmik Thakkar ut_params.extra_flag = extra_flag; 575a55f182bSDharmik Thakkar 576a55f182bSDharmik Thakkar ip_src = keys[0].ip_src; 577a55f182bSDharmik Thakkar /* 578a55f182bSDharmik Thakkar * The number of iterations is at least the same as the number of slots 579a55f182bSDharmik Thakkar * rte_hash allocates internally. This is to reveal potential issues of 580a55f182bSDharmik Thakkar * not freeing keys successfully. 581a55f182bSDharmik Thakkar */ 582a55f182bSDharmik Thakkar for (i = 0; i < ut_params.entries + (RTE_MAX_LCORE - 1) * 583a55f182bSDharmik Thakkar (LCORE_CACHE_SIZE - 1) + 1; i++) { 584a55f182bSDharmik Thakkar keys[0].ip_src++; 585a55f182bSDharmik Thakkar hash_value = rte_hash_hash(handle, &keys[0]); 586a55f182bSDharmik Thakkar pos = rte_hash_add_key_with_hash(handle, &keys[0], hash_value); 587a55f182bSDharmik Thakkar print_key_info("Add", &keys[0], pos); 588a55f182bSDharmik Thakkar RETURN_IF_ERROR(pos < 0, "failed to add key (pos=%d)", pos); 589a55f182bSDharmik Thakkar expectedPos = pos; 590a55f182bSDharmik Thakkar 591a55f182bSDharmik Thakkar pos = rte_hash_del_key_with_hash(handle, &keys[0], hash_value); 592a55f182bSDharmik Thakkar print_key_info("Del", &keys[0], pos); 593a55f182bSDharmik Thakkar RETURN_IF_ERROR(pos != expectedPos, 594a55f182bSDharmik Thakkar "failed to delete key (pos=%d)", pos); 595a55f182bSDharmik Thakkar delPos = pos; 596a55f182bSDharmik Thakkar 597a55f182bSDharmik Thakkar pos = rte_hash_free_key_with_position(handle, delPos); 598a55f182bSDharmik Thakkar print_key_info("Free", &keys[0], delPos); 599a55f182bSDharmik Thakkar RETURN_IF_ERROR(pos != 0, 600a55f182bSDharmik Thakkar "failed to free key (pos=%d)", delPos); 601a55f182bSDharmik Thakkar } 602a55f182bSDharmik Thakkar keys[0].ip_src = ip_src; 603a55f182bSDharmik Thakkar 604a55f182bSDharmik Thakkar rte_hash_free(handle); 605a55f182bSDharmik Thakkar 606a55f182bSDharmik Thakkar return 0; 607a55f182bSDharmik Thakkar } 608a55f182bSDharmik Thakkar 609a55f182bSDharmik Thakkar /* 610a9de470cSBruce Richardson * Sequence of operations for retrieving a key with its position 611a9de470cSBruce Richardson * 612a9de470cSBruce Richardson * - create table 613a9de470cSBruce Richardson * - add key 614a9de470cSBruce Richardson * - get the key with its position: hit 615a9de470cSBruce Richardson * - delete key 616a9de470cSBruce Richardson * - try to get the deleted key: miss 617a9de470cSBruce Richardson * 618a9de470cSBruce Richardson * Repeat the test case when 'free on delete' is disabled. 619a9de470cSBruce Richardson * - create table 620a9de470cSBruce Richardson * - add key 621a9de470cSBruce Richardson * - get the key with its position: hit 622a9de470cSBruce Richardson * - delete key 623a9de470cSBruce Richardson * - try to get the deleted key: hit 624a9de470cSBruce Richardson * - free key 625a9de470cSBruce Richardson * - try to get the deleted key: miss 626a9de470cSBruce Richardson * 627a9de470cSBruce Richardson */ 628a9de470cSBruce Richardson static int test_hash_get_key_with_position(void) 629a9de470cSBruce Richardson { 630a9de470cSBruce Richardson struct rte_hash *handle = NULL; 631a9de470cSBruce Richardson int pos, expectedPos, delPos, result; 632a9de470cSBruce Richardson void *key; 633a9de470cSBruce Richardson 634a9de470cSBruce Richardson ut_params.name = "hash_get_key_w_pos"; 635a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 636a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 637a9de470cSBruce Richardson 638a9de470cSBruce Richardson pos = rte_hash_add_key(handle, &keys[0]); 639a9de470cSBruce Richardson print_key_info("Add", &keys[0], pos); 640a9de470cSBruce Richardson RETURN_IF_ERROR(pos < 0, "failed to add key (pos0=%d)", pos); 641a9de470cSBruce Richardson expectedPos = pos; 642a9de470cSBruce Richardson 643a9de470cSBruce Richardson result = rte_hash_get_key_with_position(handle, pos, &key); 644a9de470cSBruce Richardson RETURN_IF_ERROR(result != 0, "error retrieving a key"); 645a9de470cSBruce Richardson 646a9de470cSBruce Richardson pos = rte_hash_del_key(handle, &keys[0]); 647a9de470cSBruce Richardson print_key_info("Del", &keys[0], pos); 648a9de470cSBruce Richardson RETURN_IF_ERROR(pos != expectedPos, 649a9de470cSBruce Richardson "failed to delete key (pos0=%d)", pos); 650a9de470cSBruce Richardson 651a9de470cSBruce Richardson result = rte_hash_get_key_with_position(handle, pos, &key); 652a9de470cSBruce Richardson RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved"); 653a9de470cSBruce Richardson 654a9de470cSBruce Richardson rte_hash_free(handle); 655a9de470cSBruce Richardson 656a9de470cSBruce Richardson ut_params.name = "hash_get_key_w_pos"; 657a9de470cSBruce Richardson ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL; 658a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 659a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 660a9de470cSBruce Richardson ut_params.extra_flag = 0; 661a9de470cSBruce Richardson 662a9de470cSBruce Richardson pos = rte_hash_add_key(handle, &keys[0]); 663a9de470cSBruce Richardson print_key_info("Add", &keys[0], pos); 664a9de470cSBruce Richardson RETURN_IF_ERROR(pos < 0, "failed to add key (pos0=%d)", pos); 665a9de470cSBruce Richardson expectedPos = pos; 666a9de470cSBruce Richardson 667a9de470cSBruce Richardson result = rte_hash_get_key_with_position(handle, pos, &key); 668a9de470cSBruce Richardson RETURN_IF_ERROR(result != 0, "error retrieving a key"); 669a9de470cSBruce Richardson 670a9de470cSBruce Richardson delPos = rte_hash_del_key(handle, &keys[0]); 671a9de470cSBruce Richardson print_key_info("Del", &keys[0], delPos); 672a9de470cSBruce Richardson RETURN_IF_ERROR(delPos != expectedPos, 673a9de470cSBruce Richardson "failed to delete key (pos0=%d)", delPos); 674a9de470cSBruce Richardson 675a9de470cSBruce Richardson result = rte_hash_get_key_with_position(handle, delPos, &key); 676a9de470cSBruce Richardson RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved"); 677a9de470cSBruce Richardson 678a9de470cSBruce Richardson result = rte_hash_free_key_with_position(handle, delPos); 679a9de470cSBruce Richardson print_key_info("Free", &keys[0], delPos); 680a9de470cSBruce Richardson RETURN_IF_ERROR(result != 0, 681a9de470cSBruce Richardson "failed to free key (pos1=%d)", delPos); 682a9de470cSBruce Richardson 683a9de470cSBruce Richardson result = rte_hash_get_key_with_position(handle, delPos, &key); 684a9de470cSBruce Richardson RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved"); 685a9de470cSBruce Richardson 686a9de470cSBruce Richardson rte_hash_free(handle); 687a9de470cSBruce Richardson return 0; 688a9de470cSBruce Richardson } 689a9de470cSBruce Richardson 690a9de470cSBruce Richardson /* 691a9de470cSBruce Richardson * Sequence of operations for find existing hash table 692a9de470cSBruce Richardson * 693a9de470cSBruce Richardson * - create table 694a9de470cSBruce Richardson * - find existing table: hit 695a9de470cSBruce Richardson * - find non-existing table: miss 696a9de470cSBruce Richardson * 697a9de470cSBruce Richardson */ 698a9de470cSBruce Richardson static int test_hash_find_existing(void) 699a9de470cSBruce Richardson { 700a9de470cSBruce Richardson struct rte_hash *handle = NULL, *result = NULL; 701a9de470cSBruce Richardson 702a9de470cSBruce Richardson /* Create hash table. */ 703a9de470cSBruce Richardson ut_params.name = "hash_find_existing"; 704a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 705a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 706a9de470cSBruce Richardson 707a9de470cSBruce Richardson /* Try to find existing hash table */ 708a9de470cSBruce Richardson result = rte_hash_find_existing("hash_find_existing"); 709a9de470cSBruce Richardson RETURN_IF_ERROR(result != handle, "could not find existing hash table"); 710a9de470cSBruce Richardson 711a9de470cSBruce Richardson /* Try to find non-existing hash table */ 712a9de470cSBruce Richardson result = rte_hash_find_existing("hash_find_non_existing"); 713a9de470cSBruce Richardson RETURN_IF_ERROR(!(result == NULL), "found table that shouldn't exist"); 714a9de470cSBruce Richardson 715a9de470cSBruce Richardson /* Cleanup. */ 716a9de470cSBruce Richardson rte_hash_free(handle); 717a9de470cSBruce Richardson 718a9de470cSBruce Richardson return 0; 719a9de470cSBruce Richardson } 720a9de470cSBruce Richardson 721a9de470cSBruce Richardson /* 722a9de470cSBruce Richardson * Sequence of operations for 5 keys 723a9de470cSBruce Richardson * - add keys 724a9de470cSBruce Richardson * - lookup keys: hit 725a9de470cSBruce Richardson * - add keys (update) 726a9de470cSBruce Richardson * - lookup keys: hit (updated data) 727a9de470cSBruce Richardson * - delete keys : hit 728a9de470cSBruce Richardson * - lookup keys: miss 729a9de470cSBruce Richardson */ 730a9de470cSBruce Richardson static int test_five_keys(void) 731a9de470cSBruce Richardson { 732a9de470cSBruce Richardson struct rte_hash *handle; 733a9de470cSBruce Richardson const void *key_array[5] = {0}; 734a9de470cSBruce Richardson int pos[5]; 735a9de470cSBruce Richardson int expected_pos[5]; 736a9de470cSBruce Richardson unsigned i; 737a9de470cSBruce Richardson int ret; 738a9de470cSBruce Richardson 739a9de470cSBruce Richardson ut_params.name = "test3"; 740a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 741a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 742a9de470cSBruce Richardson 743a9de470cSBruce Richardson /* Add */ 744a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 745a9de470cSBruce Richardson pos[i] = rte_hash_add_key(handle, &keys[i]); 746a9de470cSBruce Richardson print_key_info("Add", &keys[i], pos[i]); 747a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] < 0, 748a9de470cSBruce Richardson "failed to add key (pos[%u]=%d)", i, pos[i]); 749a9de470cSBruce Richardson expected_pos[i] = pos[i]; 750a9de470cSBruce Richardson } 751a9de470cSBruce Richardson 752a9de470cSBruce Richardson /* Lookup */ 753a9de470cSBruce Richardson for(i = 0; i < 5; i++) 754a9de470cSBruce Richardson key_array[i] = &keys[i]; 755a9de470cSBruce Richardson 756a9de470cSBruce Richardson ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos); 757a9de470cSBruce Richardson if(ret == 0) 758a9de470cSBruce Richardson for(i = 0; i < 5; i++) { 759a9de470cSBruce Richardson print_key_info("Lkp", key_array[i], pos[i]); 760a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 761a9de470cSBruce Richardson "failed to find key (pos[%u]=%d)", i, pos[i]); 762a9de470cSBruce Richardson } 763a9de470cSBruce Richardson 764a9de470cSBruce Richardson /* Add - update */ 765a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 766a9de470cSBruce Richardson pos[i] = rte_hash_add_key(handle, &keys[i]); 767a9de470cSBruce Richardson print_key_info("Add", &keys[i], pos[i]); 768a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 769a9de470cSBruce Richardson "failed to add key (pos[%u]=%d)", i, pos[i]); 770a9de470cSBruce Richardson } 771a9de470cSBruce Richardson 772a9de470cSBruce Richardson /* Lookup */ 773a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 774a9de470cSBruce Richardson pos[i] = rte_hash_lookup(handle, &keys[i]); 775a9de470cSBruce Richardson print_key_info("Lkp", &keys[i], pos[i]); 776a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 777a9de470cSBruce Richardson "failed to find key (pos[%u]=%d)", i, pos[i]); 778a9de470cSBruce Richardson } 779a9de470cSBruce Richardson 780a9de470cSBruce Richardson /* Delete */ 781a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 782a9de470cSBruce Richardson pos[i] = rte_hash_del_key(handle, &keys[i]); 783a9de470cSBruce Richardson print_key_info("Del", &keys[i], pos[i]); 784a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 785a9de470cSBruce Richardson "failed to delete key (pos[%u]=%d)", i, pos[i]); 786a9de470cSBruce Richardson } 787a9de470cSBruce Richardson 788a9de470cSBruce Richardson /* Lookup */ 789a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 790a9de470cSBruce Richardson pos[i] = rte_hash_lookup(handle, &keys[i]); 791a9de470cSBruce Richardson print_key_info("Lkp", &keys[i], pos[i]); 792a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != -ENOENT, 793a9de470cSBruce Richardson "found non-existent key (pos[%u]=%d)", i, pos[i]); 794a9de470cSBruce Richardson } 795a9de470cSBruce Richardson 796a9de470cSBruce Richardson /* Lookup multi */ 797a9de470cSBruce Richardson ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos); 798a9de470cSBruce Richardson if (ret == 0) 799a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 800a9de470cSBruce Richardson print_key_info("Lkp", key_array[i], pos[i]); 801a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != -ENOENT, 802a9de470cSBruce Richardson "found not-existent key (pos[%u]=%d)", i, pos[i]); 803a9de470cSBruce Richardson } 804a9de470cSBruce Richardson 805a9de470cSBruce Richardson rte_hash_free(handle); 806a9de470cSBruce Richardson 807a9de470cSBruce Richardson return 0; 808a9de470cSBruce Richardson } 809a9de470cSBruce Richardson 810a9de470cSBruce Richardson /* 811a9de470cSBruce Richardson * Add keys to the same bucket until bucket full. 81264b2907cSYoan Picchi * - add 9 keys to the same bucket (hash created with 8 keys per bucket): 81364b2907cSYoan Picchi * first 8 successful, 9th successful, pushing existing item in bucket 81464b2907cSYoan Picchi * - lookup the 9 keys: 9 hits 81564b2907cSYoan Picchi * - bulk lookup for all the 9 keys: 9 hits 81664b2907cSYoan Picchi * - add the 9 keys again: 9 OK 81764b2907cSYoan Picchi * - lookup the 9 keys: 9 hits (updated data) 81864b2907cSYoan Picchi * - delete the 9 keys: 9 OK 81964b2907cSYoan Picchi * - lookup the 9 keys: 9 misses 82064b2907cSYoan Picchi * - bulk lookup for all the 9 keys: 9 misses 821a9de470cSBruce Richardson */ 822a9de470cSBruce Richardson static int test_full_bucket(void) 823a9de470cSBruce Richardson { 824a9de470cSBruce Richardson struct rte_hash_parameters params_pseudo_hash = { 825a9de470cSBruce Richardson .name = "test4", 826a9de470cSBruce Richardson .entries = 64, 827e30ef3a3SVladimir Medvedkin .key_len = sizeof(struct flow_key), 828a9de470cSBruce Richardson .hash_func = pseudo_hash, 829a9de470cSBruce Richardson .hash_func_init_val = 0, 830a9de470cSBruce Richardson .socket_id = 0, 831a9de470cSBruce Richardson }; 83264b2907cSYoan Picchi const void *key_array[KEY_PER_BUCKET+1] = {0}; 833a9de470cSBruce Richardson struct rte_hash *handle; 83464b2907cSYoan Picchi int pos[KEY_PER_BUCKET+1]; 83564b2907cSYoan Picchi int expected_pos[KEY_PER_BUCKET+1]; 836a9de470cSBruce Richardson unsigned i; 83764b2907cSYoan Picchi int ret; 838a9de470cSBruce Richardson handle = rte_hash_create(¶ms_pseudo_hash); 839a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 840a9de470cSBruce Richardson 841a9de470cSBruce Richardson /* Fill bucket */ 84264b2907cSYoan Picchi for (i = 0; i < KEY_PER_BUCKET; i++) { 843a9de470cSBruce Richardson pos[i] = rte_hash_add_key(handle, &keys[i]); 844a9de470cSBruce Richardson print_key_info("Add", &keys[i], pos[i]); 845a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] < 0, 846a9de470cSBruce Richardson "failed to add key (pos[%u]=%d)", i, pos[i]); 847a9de470cSBruce Richardson expected_pos[i] = pos[i]; 848a9de470cSBruce Richardson } 849a9de470cSBruce Richardson /* 850a9de470cSBruce Richardson * This should work and will push one of the items 851a9de470cSBruce Richardson * in the bucket because it is full 852a9de470cSBruce Richardson */ 85364b2907cSYoan Picchi pos[KEY_PER_BUCKET] = rte_hash_add_key(handle, &keys[KEY_PER_BUCKET]); 85464b2907cSYoan Picchi print_key_info("Add", &keys[KEY_PER_BUCKET], pos[KEY_PER_BUCKET]); 85564b2907cSYoan Picchi RETURN_IF_ERROR(pos[KEY_PER_BUCKET] < 0, 85664b2907cSYoan Picchi "failed to add key (pos[%d]=%d)", KEY_PER_BUCKET, pos[KEY_PER_BUCKET]); 85764b2907cSYoan Picchi expected_pos[KEY_PER_BUCKET] = pos[KEY_PER_BUCKET]; 858a9de470cSBruce Richardson 859a9de470cSBruce Richardson /* Lookup */ 86064b2907cSYoan Picchi for (i = 0; i < KEY_PER_BUCKET+1; i++) { 861a9de470cSBruce Richardson pos[i] = rte_hash_lookup(handle, &keys[i]); 862a9de470cSBruce Richardson print_key_info("Lkp", &keys[i], pos[i]); 863a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 864a9de470cSBruce Richardson "failed to find key (pos[%u]=%d)", i, pos[i]); 865a9de470cSBruce Richardson } 866a9de470cSBruce Richardson 86764b2907cSYoan Picchi for (i = 0; i < KEY_PER_BUCKET+1; i++) 86864b2907cSYoan Picchi key_array[i] = &keys[i]; 86964b2907cSYoan Picchi 87064b2907cSYoan Picchi /*Bulk lookup after add with same hash*/ 87164b2907cSYoan Picchi ret = rte_hash_lookup_bulk(handle, key_array, KEY_PER_BUCKET+1, (int32_t *)pos); 87264b2907cSYoan Picchi RETURN_IF_ERROR(ret, "rte_hash_lookup_bulk returned an error: %d\n", ret); 87364b2907cSYoan Picchi for (i = 0; i < KEY_PER_BUCKET+1; i++) { 87464b2907cSYoan Picchi print_key_info("Blk_Lkp", key_array[i], pos[i]); 87564b2907cSYoan Picchi RETURN_IF_ERROR(pos[i] != expected_pos[i], 87664b2907cSYoan Picchi "failed to find key (pos[%u]=%d)", i, pos[i]); 87764b2907cSYoan Picchi } 87864b2907cSYoan Picchi 87964b2907cSYoan Picchi 88064b2907cSYoan Picchi 881a9de470cSBruce Richardson /* Add - update */ 88264b2907cSYoan Picchi for (i = 0; i < KEY_PER_BUCKET+1; i++) { 883a9de470cSBruce Richardson pos[i] = rte_hash_add_key(handle, &keys[i]); 884a9de470cSBruce Richardson print_key_info("Add", &keys[i], pos[i]); 885a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 886a9de470cSBruce Richardson "failed to add key (pos[%u]=%d)", i, pos[i]); 887a9de470cSBruce Richardson } 888a9de470cSBruce Richardson 889a9de470cSBruce Richardson /* Lookup */ 89064b2907cSYoan Picchi for (i = 0; i < KEY_PER_BUCKET+1; i++) { 891a9de470cSBruce Richardson pos[i] = rte_hash_lookup(handle, &keys[i]); 892a9de470cSBruce Richardson print_key_info("Lkp", &keys[i], pos[i]); 893a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 894a9de470cSBruce Richardson "failed to find key (pos[%u]=%d)", i, pos[i]); 895a9de470cSBruce Richardson } 896a9de470cSBruce Richardson 897a9de470cSBruce Richardson /* Delete 1 key, check other keys are still found */ 898a9de470cSBruce Richardson pos[1] = rte_hash_del_key(handle, &keys[1]); 899a9de470cSBruce Richardson print_key_info("Del", &keys[1], pos[1]); 900a9de470cSBruce Richardson RETURN_IF_ERROR(pos[1] != expected_pos[1], 901a9de470cSBruce Richardson "failed to delete key (pos[1]=%d)", pos[1]); 902a9de470cSBruce Richardson pos[3] = rte_hash_lookup(handle, &keys[3]); 903a9de470cSBruce Richardson print_key_info("Lkp", &keys[3], pos[3]); 904a9de470cSBruce Richardson RETURN_IF_ERROR(pos[3] != expected_pos[3], 905a9de470cSBruce Richardson "failed lookup after deleting key from same bucket " 906a9de470cSBruce Richardson "(pos[3]=%d)", pos[3]); 907a9de470cSBruce Richardson 908a9de470cSBruce Richardson /* Go back to previous state */ 909a9de470cSBruce Richardson pos[1] = rte_hash_add_key(handle, &keys[1]); 910a9de470cSBruce Richardson print_key_info("Add", &keys[1], pos[1]); 911a9de470cSBruce Richardson expected_pos[1] = pos[1]; 912a9de470cSBruce Richardson RETURN_IF_ERROR(pos[1] < 0, "failed to add key (pos[1]=%d)", pos[1]); 913a9de470cSBruce Richardson 914a9de470cSBruce Richardson /* Delete */ 91564b2907cSYoan Picchi for (i = 0; i < KEY_PER_BUCKET+1; i++) { 916a9de470cSBruce Richardson pos[i] = rte_hash_del_key(handle, &keys[i]); 917a9de470cSBruce Richardson print_key_info("Del", &keys[i], pos[i]); 918a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 919a9de470cSBruce Richardson "failed to delete key (pos[%u]=%d)", i, pos[i]); 920a9de470cSBruce Richardson } 921a9de470cSBruce Richardson 922a9de470cSBruce Richardson /* Lookup */ 92364b2907cSYoan Picchi for (i = 0; i < KEY_PER_BUCKET+1; i++) { 924a9de470cSBruce Richardson pos[i] = rte_hash_lookup(handle, &keys[i]); 925a9de470cSBruce Richardson print_key_info("Lkp", &keys[i], pos[i]); 926a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != -ENOENT, 927a9de470cSBruce Richardson "fail: found non-existent key (pos[%u]=%d)", i, pos[i]); 928a9de470cSBruce Richardson } 929a9de470cSBruce Richardson 93064b2907cSYoan Picchi /* Bulk Lookup on empty table*/ 93164b2907cSYoan Picchi ret = rte_hash_lookup_bulk(handle, &key_array[0], KEY_PER_BUCKET+1, (int32_t *)pos); 93264b2907cSYoan Picchi RETURN_IF_ERROR(ret, "rte_hash_lookup_bulk returned an error: %d\n", ret); 93364b2907cSYoan Picchi for (i = 0; i < KEY_PER_BUCKET+1; i++) { 93464b2907cSYoan Picchi print_key_info("Blk_Lkp", key_array[i], pos[i]); 93564b2907cSYoan Picchi RETURN_IF_ERROR(pos[i] != -ENOENT, 93664b2907cSYoan Picchi "failed to find key (pos[%u]=%d)", i, pos[i]); 93764b2907cSYoan Picchi } 93864b2907cSYoan Picchi 939a9de470cSBruce Richardson rte_hash_free(handle); 940a9de470cSBruce Richardson 941a9de470cSBruce Richardson /* Cover the NULL case. */ 942a9de470cSBruce Richardson rte_hash_free(0); 943a9de470cSBruce Richardson return 0; 944a9de470cSBruce Richardson } 945a9de470cSBruce Richardson 946a9de470cSBruce Richardson /* 947a9de470cSBruce Richardson * Similar to the test above (full bucket test), but for extendable buckets. 948a9de470cSBruce Richardson */ 949a9de470cSBruce Richardson static int test_extendable_bucket(void) 950a9de470cSBruce Richardson { 951a9de470cSBruce Richardson struct rte_hash_parameters params_pseudo_hash = { 952a9de470cSBruce Richardson .name = "test5", 953a9de470cSBruce Richardson .entries = 64, 954e30ef3a3SVladimir Medvedkin .key_len = sizeof(struct flow_key), 955a9de470cSBruce Richardson .hash_func = pseudo_hash, 956a9de470cSBruce Richardson .hash_func_init_val = 0, 957a9de470cSBruce Richardson .socket_id = 0, 958a9de470cSBruce Richardson .extra_flag = RTE_HASH_EXTRA_FLAGS_EXT_TABLE 959a9de470cSBruce Richardson }; 960a9de470cSBruce Richardson struct rte_hash *handle; 961a9de470cSBruce Richardson int pos[64]; 962a9de470cSBruce Richardson int expected_pos[64]; 963a9de470cSBruce Richardson unsigned int i; 964a9de470cSBruce Richardson struct flow_key rand_keys[64]; 965a9de470cSBruce Richardson 966a9de470cSBruce Richardson for (i = 0; i < 64; i++) { 967a9de470cSBruce Richardson rand_keys[i].port_dst = i; 968a9de470cSBruce Richardson rand_keys[i].port_src = i+1; 969a9de470cSBruce Richardson } 970a9de470cSBruce Richardson 971a9de470cSBruce Richardson handle = rte_hash_create(¶ms_pseudo_hash); 972a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 973a9de470cSBruce Richardson 974a9de470cSBruce Richardson /* Fill bucket */ 975a9de470cSBruce Richardson for (i = 0; i < 64; i++) { 976a9de470cSBruce Richardson pos[i] = rte_hash_add_key(handle, &rand_keys[i]); 977a9de470cSBruce Richardson print_key_info("Add", &rand_keys[i], pos[i]); 978a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] < 0, 979a9de470cSBruce Richardson "failed to add key (pos[%u]=%d)", i, pos[i]); 980a9de470cSBruce Richardson expected_pos[i] = pos[i]; 981a9de470cSBruce Richardson } 982a9de470cSBruce Richardson 983a9de470cSBruce Richardson /* Lookup */ 984a9de470cSBruce Richardson for (i = 0; i < 64; i++) { 985a9de470cSBruce Richardson pos[i] = rte_hash_lookup(handle, &rand_keys[i]); 986a9de470cSBruce Richardson print_key_info("Lkp", &rand_keys[i], pos[i]); 987a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 988a9de470cSBruce Richardson "failed to find key (pos[%u]=%d)", i, pos[i]); 989a9de470cSBruce Richardson } 990a9de470cSBruce Richardson 991a9de470cSBruce Richardson /* Add - update */ 992a9de470cSBruce Richardson for (i = 0; i < 64; i++) { 993a9de470cSBruce Richardson pos[i] = rte_hash_add_key(handle, &rand_keys[i]); 994a9de470cSBruce Richardson print_key_info("Add", &rand_keys[i], pos[i]); 995a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 996a9de470cSBruce Richardson "failed to add key (pos[%u]=%d)", i, pos[i]); 997a9de470cSBruce Richardson } 998a9de470cSBruce Richardson 999a9de470cSBruce Richardson /* Lookup */ 1000a9de470cSBruce Richardson for (i = 0; i < 64; i++) { 1001a9de470cSBruce Richardson pos[i] = rte_hash_lookup(handle, &rand_keys[i]); 1002a9de470cSBruce Richardson print_key_info("Lkp", &rand_keys[i], pos[i]); 1003a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 1004a9de470cSBruce Richardson "failed to find key (pos[%u]=%d)", i, pos[i]); 1005a9de470cSBruce Richardson } 1006a9de470cSBruce Richardson 1007a9de470cSBruce Richardson /* Delete 1 key, check other keys are still found */ 1008a9de470cSBruce Richardson pos[35] = rte_hash_del_key(handle, &rand_keys[35]); 1009a9de470cSBruce Richardson print_key_info("Del", &rand_keys[35], pos[35]); 1010a9de470cSBruce Richardson RETURN_IF_ERROR(pos[35] != expected_pos[35], 1011a9de470cSBruce Richardson "failed to delete key (pos[1]=%d)", pos[35]); 1012a9de470cSBruce Richardson pos[20] = rte_hash_lookup(handle, &rand_keys[20]); 1013a9de470cSBruce Richardson print_key_info("Lkp", &rand_keys[20], pos[20]); 1014a9de470cSBruce Richardson RETURN_IF_ERROR(pos[20] != expected_pos[20], 1015a9de470cSBruce Richardson "failed lookup after deleting key from same bucket " 1016a9de470cSBruce Richardson "(pos[20]=%d)", pos[20]); 1017a9de470cSBruce Richardson 1018a9de470cSBruce Richardson /* Go back to previous state */ 1019a9de470cSBruce Richardson pos[35] = rte_hash_add_key(handle, &rand_keys[35]); 1020a9de470cSBruce Richardson print_key_info("Add", &rand_keys[35], pos[35]); 1021a9de470cSBruce Richardson expected_pos[35] = pos[35]; 1022a9de470cSBruce Richardson RETURN_IF_ERROR(pos[35] < 0, "failed to add key (pos[1]=%d)", pos[35]); 1023a9de470cSBruce Richardson 1024a9de470cSBruce Richardson /* Delete */ 1025a9de470cSBruce Richardson for (i = 0; i < 64; i++) { 1026a9de470cSBruce Richardson pos[i] = rte_hash_del_key(handle, &rand_keys[i]); 1027a9de470cSBruce Richardson print_key_info("Del", &rand_keys[i], pos[i]); 1028a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != expected_pos[i], 1029a9de470cSBruce Richardson "failed to delete key (pos[%u]=%d)", i, pos[i]); 1030a9de470cSBruce Richardson } 1031a9de470cSBruce Richardson 1032a9de470cSBruce Richardson /* Lookup */ 1033a9de470cSBruce Richardson for (i = 0; i < 64; i++) { 1034a9de470cSBruce Richardson pos[i] = rte_hash_lookup(handle, &rand_keys[i]); 1035a9de470cSBruce Richardson print_key_info("Lkp", &rand_keys[i], pos[i]); 1036a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] != -ENOENT, 1037a9de470cSBruce Richardson "fail: found non-existent key (pos[%u]=%d)", i, pos[i]); 1038a9de470cSBruce Richardson } 1039a9de470cSBruce Richardson 1040a9de470cSBruce Richardson /* Add again */ 1041a9de470cSBruce Richardson for (i = 0; i < 64; i++) { 1042a9de470cSBruce Richardson pos[i] = rte_hash_add_key(handle, &rand_keys[i]); 1043a9de470cSBruce Richardson print_key_info("Add", &rand_keys[i], pos[i]); 1044a9de470cSBruce Richardson RETURN_IF_ERROR(pos[i] < 0, 1045a9de470cSBruce Richardson "failed to add key (pos[%u]=%d)", i, pos[i]); 1046a9de470cSBruce Richardson expected_pos[i] = pos[i]; 1047a9de470cSBruce Richardson } 1048a9de470cSBruce Richardson 1049a9de470cSBruce Richardson rte_hash_free(handle); 1050a9de470cSBruce Richardson 1051a9de470cSBruce Richardson /* Cover the NULL case. */ 1052a9de470cSBruce Richardson rte_hash_free(0); 1053a9de470cSBruce Richardson return 0; 1054a9de470cSBruce Richardson } 1055a9de470cSBruce Richardson 1056a9de470cSBruce Richardson /******************************************************************************/ 1057a9de470cSBruce Richardson static int 1058a9de470cSBruce Richardson fbk_hash_unit_test(void) 1059a9de470cSBruce Richardson { 1060a9de470cSBruce Richardson struct rte_fbk_hash_params params = { 1061a9de470cSBruce Richardson .name = "fbk_hash_test", 1062a9de470cSBruce Richardson .entries = LOCAL_FBK_HASH_ENTRIES_MAX, 1063a9de470cSBruce Richardson .entries_per_bucket = 4, 1064a9de470cSBruce Richardson .socket_id = 0, 1065a9de470cSBruce Richardson }; 1066a9de470cSBruce Richardson 1067a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_1 = { 1068a9de470cSBruce Richardson .name = "invalid_1", 1069a9de470cSBruce Richardson .entries = LOCAL_FBK_HASH_ENTRIES_MAX + 1, /* Not power of 2 */ 1070a9de470cSBruce Richardson .entries_per_bucket = 4, 1071a9de470cSBruce Richardson .socket_id = 0, 1072a9de470cSBruce Richardson }; 1073a9de470cSBruce Richardson 1074a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_2 = { 1075a9de470cSBruce Richardson .name = "invalid_2", 1076a9de470cSBruce Richardson .entries = 4, 1077a9de470cSBruce Richardson .entries_per_bucket = 3, /* Not power of 2 */ 1078a9de470cSBruce Richardson .socket_id = 0, 1079a9de470cSBruce Richardson }; 1080a9de470cSBruce Richardson 1081a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_3 = { 1082a9de470cSBruce Richardson .name = "invalid_3", 1083a9de470cSBruce Richardson .entries = 0, /* Entries is 0 */ 1084a9de470cSBruce Richardson .entries_per_bucket = 4, 1085a9de470cSBruce Richardson .socket_id = 0, 1086a9de470cSBruce Richardson }; 1087a9de470cSBruce Richardson 1088a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_4 = { 1089a9de470cSBruce Richardson .name = "invalid_4", 1090a9de470cSBruce Richardson .entries = LOCAL_FBK_HASH_ENTRIES_MAX, 1091a9de470cSBruce Richardson .entries_per_bucket = 0, /* Entries per bucket is 0 */ 1092a9de470cSBruce Richardson .socket_id = 0, 1093a9de470cSBruce Richardson }; 1094a9de470cSBruce Richardson 1095a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_5 = { 1096a9de470cSBruce Richardson .name = "invalid_5", 1097a9de470cSBruce Richardson .entries = 4, 1098a9de470cSBruce Richardson .entries_per_bucket = 8, /* Entries per bucket > entries */ 1099a9de470cSBruce Richardson .socket_id = 0, 1100a9de470cSBruce Richardson }; 1101a9de470cSBruce Richardson 1102a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_6 = { 1103a9de470cSBruce Richardson .name = "invalid_6", 1104a9de470cSBruce Richardson .entries = RTE_FBK_HASH_ENTRIES_MAX * 2, /* Entries > max allowed */ 1105a9de470cSBruce Richardson .entries_per_bucket = 4, 1106a9de470cSBruce Richardson .socket_id = 0, 1107a9de470cSBruce Richardson }; 1108a9de470cSBruce Richardson 1109a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_7 = { 1110a9de470cSBruce Richardson .name = "invalid_7", 1111a9de470cSBruce Richardson .entries = RTE_FBK_HASH_ENTRIES_MAX, 1112a9de470cSBruce Richardson .entries_per_bucket = RTE_FBK_HASH_ENTRIES_PER_BUCKET_MAX * 2, /* Entries > max allowed */ 1113a9de470cSBruce Richardson .socket_id = 0, 1114a9de470cSBruce Richardson }; 1115a9de470cSBruce Richardson 1116a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_8 = { 1117a9de470cSBruce Richardson .name = "invalid_7", 1118a9de470cSBruce Richardson .entries = RTE_FBK_HASH_ENTRIES_MAX, 1119a9de470cSBruce Richardson .entries_per_bucket = 4, 1120a9de470cSBruce Richardson .socket_id = RTE_MAX_NUMA_NODES + 1, /* invalid socket */ 1121a9de470cSBruce Richardson }; 1122a9de470cSBruce Richardson 1123a9de470cSBruce Richardson /* try to create two hashes with identical names 1124a9de470cSBruce Richardson * in this case, trying to create a second one will not 1125a9de470cSBruce Richardson * fail but will simply return pointer to the existing 1126a9de470cSBruce Richardson * hash with that name. sort of like a "find hash by name" :-) 1127a9de470cSBruce Richardson */ 1128a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_same_name_1 = { 1129a9de470cSBruce Richardson .name = "same_name", /* hash with identical name */ 1130a9de470cSBruce Richardson .entries = 4, 1131a9de470cSBruce Richardson .entries_per_bucket = 2, 1132a9de470cSBruce Richardson .socket_id = 0, 1133a9de470cSBruce Richardson }; 1134a9de470cSBruce Richardson 1135a9de470cSBruce Richardson /* trying to create this hash should return a pointer to an existing hash */ 1136a9de470cSBruce Richardson struct rte_fbk_hash_params invalid_params_same_name_2 = { 1137a9de470cSBruce Richardson .name = "same_name", /* hash with identical name */ 1138a9de470cSBruce Richardson .entries = RTE_FBK_HASH_ENTRIES_MAX, 1139a9de470cSBruce Richardson .entries_per_bucket = 4, 1140a9de470cSBruce Richardson .socket_id = 0, 1141a9de470cSBruce Richardson }; 1142a9de470cSBruce Richardson 1143a9de470cSBruce Richardson /* this is a sanity check for "same name" test 1144a9de470cSBruce Richardson * creating this hash will check if we are actually able to create 1145a9de470cSBruce Richardson * multiple hashes with different names (instead of having just one). 1146a9de470cSBruce Richardson */ 1147a9de470cSBruce Richardson struct rte_fbk_hash_params different_name = { 1148a9de470cSBruce Richardson .name = "different_name", /* different name */ 1149a9de470cSBruce Richardson .entries = LOCAL_FBK_HASH_ENTRIES_MAX, 1150a9de470cSBruce Richardson .entries_per_bucket = 4, 1151a9de470cSBruce Richardson .socket_id = 0, 1152a9de470cSBruce Richardson }; 1153a9de470cSBruce Richardson 1154a9de470cSBruce Richardson struct rte_fbk_hash_params params_jhash = { 1155a9de470cSBruce Richardson .name = "valid", 1156a9de470cSBruce Richardson .entries = LOCAL_FBK_HASH_ENTRIES_MAX, 1157a9de470cSBruce Richardson .entries_per_bucket = 4, 1158a9de470cSBruce Richardson .socket_id = 0, 1159a9de470cSBruce Richardson .hash_func = rte_jhash_1word, /* Tests for different hash_func */ 1160a9de470cSBruce Richardson .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT, 1161a9de470cSBruce Richardson }; 1162a9de470cSBruce Richardson 1163a9de470cSBruce Richardson struct rte_fbk_hash_params params_nohash = { 1164a9de470cSBruce Richardson .name = "valid nohash", 1165a9de470cSBruce Richardson .entries = LOCAL_FBK_HASH_ENTRIES_MAX, 1166a9de470cSBruce Richardson .entries_per_bucket = 4, 1167a9de470cSBruce Richardson .socket_id = 0, 1168a9de470cSBruce Richardson .hash_func = NULL, /* Tests for null hash_func */ 1169a9de470cSBruce Richardson .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT, 1170a9de470cSBruce Richardson }; 1171a9de470cSBruce Richardson 1172a9de470cSBruce Richardson struct rte_fbk_hash_table *handle, *tmp; 1173a9de470cSBruce Richardson uint32_t keys[5] = 1174a9de470cSBruce Richardson {0xc6e18639, 0xe67c201c, 0xd4c8cffd, 0x44728691, 0xd5430fa9}; 1175a9de470cSBruce Richardson uint16_t vals[5] = {28108, 5699, 38490, 2166, 61571}; 1176a9de470cSBruce Richardson int status; 1177a9de470cSBruce Richardson unsigned i; 1178a9de470cSBruce Richardson double used_entries; 1179a9de470cSBruce Richardson 1180a9de470cSBruce Richardson /* Try creating hashes with invalid parameters */ 1181a9de470cSBruce Richardson printf("# Testing hash creation with invalid parameters " 1182a9de470cSBruce Richardson "- expect error msgs\n"); 1183a9de470cSBruce Richardson handle = rte_fbk_hash_create(&invalid_params_1); 1184a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); 1185a9de470cSBruce Richardson 1186a9de470cSBruce Richardson handle = rte_fbk_hash_create(&invalid_params_2); 1187a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); 1188a9de470cSBruce Richardson 1189a9de470cSBruce Richardson handle = rte_fbk_hash_create(&invalid_params_3); 1190a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); 1191a9de470cSBruce Richardson 1192a9de470cSBruce Richardson handle = rte_fbk_hash_create(&invalid_params_4); 1193a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); 1194a9de470cSBruce Richardson 1195a9de470cSBruce Richardson handle = rte_fbk_hash_create(&invalid_params_5); 1196a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); 1197a9de470cSBruce Richardson 1198a9de470cSBruce Richardson handle = rte_fbk_hash_create(&invalid_params_6); 1199a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); 1200a9de470cSBruce Richardson 1201a9de470cSBruce Richardson handle = rte_fbk_hash_create(&invalid_params_7); 1202a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); 1203a9de470cSBruce Richardson 120427fb5dd2SRuifeng Wang if (rte_eal_has_hugepages()) { 1205a9de470cSBruce Richardson handle = rte_fbk_hash_create(&invalid_params_8); 120627fb5dd2SRuifeng Wang RETURN_IF_ERROR_FBK(handle != NULL, 120727fb5dd2SRuifeng Wang "fbk hash creation should have failed"); 120827fb5dd2SRuifeng Wang } 1209a9de470cSBruce Richardson 1210a9de470cSBruce Richardson handle = rte_fbk_hash_create(&invalid_params_same_name_1); 1211a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation should have succeeded"); 1212a9de470cSBruce Richardson 1213a9de470cSBruce Richardson tmp = rte_fbk_hash_create(&invalid_params_same_name_2); 1214a9de470cSBruce Richardson rte_fbk_hash_free(tmp); 1215a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(tmp != NULL, "fbk hash creation should have failed"); 1216a9de470cSBruce Richardson 1217a9de470cSBruce Richardson /* we are not freeing handle here because we need a hash list 1218a9de470cSBruce Richardson * to be not empty for the next test */ 1219a9de470cSBruce Richardson 1220a9de470cSBruce Richardson /* create a hash in non-empty list - good for coverage */ 1221a9de470cSBruce Richardson tmp = rte_fbk_hash_create(&different_name); 1222a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(tmp == NULL, "fbk hash creation should have succeeded"); 1223a9de470cSBruce Richardson 1224a9de470cSBruce Richardson /* free both hashes */ 1225a9de470cSBruce Richardson rte_fbk_hash_free(handle); 1226a9de470cSBruce Richardson rte_fbk_hash_free(tmp); 1227a9de470cSBruce Richardson 1228a9de470cSBruce Richardson /* Create empty jhash hash. */ 1229a9de470cSBruce Richardson handle = rte_fbk_hash_create(¶ms_jhash); 1230a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle == NULL, "fbk jhash hash creation failed"); 1231a9de470cSBruce Richardson 1232a9de470cSBruce Richardson /* Cleanup. */ 1233a9de470cSBruce Richardson rte_fbk_hash_free(handle); 1234a9de470cSBruce Richardson 1235a9de470cSBruce Richardson /* Create empty jhash hash. */ 1236a9de470cSBruce Richardson handle = rte_fbk_hash_create(¶ms_nohash); 1237a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle == NULL, "fbk nohash hash creation failed"); 1238a9de470cSBruce Richardson 1239a9de470cSBruce Richardson /* Cleanup. */ 1240a9de470cSBruce Richardson rte_fbk_hash_free(handle); 1241a9de470cSBruce Richardson 1242a9de470cSBruce Richardson /* Create empty hash. */ 1243a9de470cSBruce Richardson handle = rte_fbk_hash_create(¶ms); 1244a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed"); 1245a9de470cSBruce Richardson 1246a9de470cSBruce Richardson used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX; 1247a9de470cSBruce Richardson RETURN_IF_ERROR_FBK((unsigned)used_entries != 0, \ 1248a9de470cSBruce Richardson "load factor right after creation is not zero but it should be"); 1249a9de470cSBruce Richardson /* Add keys. */ 1250a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 1251a9de470cSBruce Richardson status = rte_fbk_hash_add_key(handle, keys[i], vals[i]); 1252a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != 0, "fbk hash add failed"); 1253a9de470cSBruce Richardson } 1254a9de470cSBruce Richardson 1255a9de470cSBruce Richardson used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX; 1256a9de470cSBruce Richardson RETURN_IF_ERROR_FBK((unsigned)used_entries != (unsigned)((((double)5)/LOCAL_FBK_HASH_ENTRIES_MAX)*LOCAL_FBK_HASH_ENTRIES_MAX), \ 1257a9de470cSBruce Richardson "load factor now is not as expected"); 1258a9de470cSBruce Richardson /* Find value of added keys. */ 1259a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 1260a9de470cSBruce Richardson status = rte_fbk_hash_lookup(handle, keys[i]); 1261a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != vals[i], 1262a9de470cSBruce Richardson "fbk hash lookup failed"); 1263a9de470cSBruce Richardson } 1264a9de470cSBruce Richardson 1265a9de470cSBruce Richardson /* Change value of added keys. */ 1266a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 1267a9de470cSBruce Richardson status = rte_fbk_hash_add_key(handle, keys[i], vals[4 - i]); 1268a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != 0, "fbk hash update failed"); 1269a9de470cSBruce Richardson } 1270a9de470cSBruce Richardson 1271a9de470cSBruce Richardson /* Find new values. */ 1272a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 1273a9de470cSBruce Richardson status = rte_fbk_hash_lookup(handle, keys[i]); 1274a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != vals[4-i], 1275a9de470cSBruce Richardson "fbk hash lookup failed"); 1276a9de470cSBruce Richardson } 1277a9de470cSBruce Richardson 1278a9de470cSBruce Richardson /* Delete keys individually. */ 1279a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 1280a9de470cSBruce Richardson status = rte_fbk_hash_delete_key(handle, keys[i]); 1281a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != 0, "fbk hash delete failed"); 1282a9de470cSBruce Richardson } 1283a9de470cSBruce Richardson 1284a9de470cSBruce Richardson used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX; 1285a9de470cSBruce Richardson RETURN_IF_ERROR_FBK((unsigned)used_entries != 0, \ 1286a9de470cSBruce Richardson "load factor right after deletion is not zero but it should be"); 1287a9de470cSBruce Richardson /* Lookup should now fail. */ 1288a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 1289a9de470cSBruce Richardson status = rte_fbk_hash_lookup(handle, keys[i]); 1290a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status == 0, 1291a9de470cSBruce Richardson "fbk hash lookup should have failed"); 1292a9de470cSBruce Richardson } 1293a9de470cSBruce Richardson 1294a9de470cSBruce Richardson /* Add keys again. */ 1295a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 1296a9de470cSBruce Richardson status = rte_fbk_hash_add_key(handle, keys[i], vals[i]); 1297a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != 0, "fbk hash add failed"); 1298a9de470cSBruce Richardson } 1299a9de470cSBruce Richardson 1300a9de470cSBruce Richardson /* Make sure they were added. */ 1301a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 1302a9de470cSBruce Richardson status = rte_fbk_hash_lookup(handle, keys[i]); 1303a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != vals[i], 1304a9de470cSBruce Richardson "fbk hash lookup failed"); 1305a9de470cSBruce Richardson } 1306a9de470cSBruce Richardson 1307a9de470cSBruce Richardson /* Clear all entries. */ 1308a9de470cSBruce Richardson rte_fbk_hash_clear_all(handle); 1309a9de470cSBruce Richardson 1310a9de470cSBruce Richardson /* Lookup should fail. */ 1311a9de470cSBruce Richardson for (i = 0; i < 5; i++) { 1312a9de470cSBruce Richardson status = rte_fbk_hash_lookup(handle, keys[i]); 1313a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status == 0, 1314a9de470cSBruce Richardson "fbk hash lookup should have failed"); 1315a9de470cSBruce Richardson } 1316a9de470cSBruce Richardson 1317a9de470cSBruce Richardson /* coverage */ 1318a9de470cSBruce Richardson 1319a9de470cSBruce Richardson /* fill up the hash_table */ 1320a9de470cSBruce Richardson for (i = 0; i < RTE_FBK_HASH_ENTRIES_MAX + 1; i++) 1321a9de470cSBruce Richardson rte_fbk_hash_add_key(handle, i, (uint16_t) i); 1322a9de470cSBruce Richardson 1323a9de470cSBruce Richardson /* Find non-existent key in a full hashtable */ 1324a9de470cSBruce Richardson status = rte_fbk_hash_lookup(handle, RTE_FBK_HASH_ENTRIES_MAX + 1); 1325a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != -ENOENT, 1326a9de470cSBruce Richardson "fbk hash lookup succeeded"); 1327a9de470cSBruce Richardson 1328a9de470cSBruce Richardson /* Delete non-existent key in a full hashtable */ 1329a9de470cSBruce Richardson status = rte_fbk_hash_delete_key(handle, RTE_FBK_HASH_ENTRIES_MAX + 1); 1330a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != -ENOENT, 1331a9de470cSBruce Richardson "fbk hash delete succeeded"); 1332a9de470cSBruce Richardson 1333a9de470cSBruce Richardson /* Delete one key from a full hashtable */ 1334a9de470cSBruce Richardson status = rte_fbk_hash_delete_key(handle, 1); 1335a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(status != 0, 1336a9de470cSBruce Richardson "fbk hash delete failed"); 1337a9de470cSBruce Richardson 1338a9de470cSBruce Richardson /* Clear all entries. */ 1339a9de470cSBruce Richardson rte_fbk_hash_clear_all(handle); 1340a9de470cSBruce Richardson 1341a9de470cSBruce Richardson /* Cleanup. */ 1342a9de470cSBruce Richardson rte_fbk_hash_free(handle); 1343a9de470cSBruce Richardson 1344a9de470cSBruce Richardson /* Cover the NULL case. */ 1345a9de470cSBruce Richardson rte_fbk_hash_free(0); 1346a9de470cSBruce Richardson 1347a9de470cSBruce Richardson return 0; 1348a9de470cSBruce Richardson } 1349a9de470cSBruce Richardson 1350a9de470cSBruce Richardson /* 1351a9de470cSBruce Richardson * Sequence of operations for find existing fbk hash table 1352a9de470cSBruce Richardson * 1353a9de470cSBruce Richardson * - create table 1354a9de470cSBruce Richardson * - find existing table: hit 1355a9de470cSBruce Richardson * - find non-existing table: miss 1356a9de470cSBruce Richardson * 1357a9de470cSBruce Richardson */ 1358a9de470cSBruce Richardson static int test_fbk_hash_find_existing(void) 1359a9de470cSBruce Richardson { 1360a9de470cSBruce Richardson struct rte_fbk_hash_params params = { 1361a9de470cSBruce Richardson .name = "fbk_hash_find_existing", 1362a9de470cSBruce Richardson .entries = LOCAL_FBK_HASH_ENTRIES_MAX, 1363a9de470cSBruce Richardson .entries_per_bucket = 4, 1364a9de470cSBruce Richardson .socket_id = 0, 1365a9de470cSBruce Richardson }; 1366a9de470cSBruce Richardson struct rte_fbk_hash_table *handle = NULL, *result = NULL; 1367a9de470cSBruce Richardson 1368a9de470cSBruce Richardson /* Create hash table. */ 1369a9de470cSBruce Richardson handle = rte_fbk_hash_create(¶ms); 1370a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed"); 1371a9de470cSBruce Richardson 1372a9de470cSBruce Richardson /* Try to find existing fbk hash table */ 1373a9de470cSBruce Richardson result = rte_fbk_hash_find_existing("fbk_hash_find_existing"); 1374a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(result != handle, "could not find existing fbk hash table"); 1375a9de470cSBruce Richardson 1376a9de470cSBruce Richardson /* Try to find non-existing fbk hash table */ 1377a9de470cSBruce Richardson result = rte_fbk_hash_find_existing("fbk_hash_find_non_existing"); 1378a9de470cSBruce Richardson RETURN_IF_ERROR_FBK(!(result == NULL), "found fbk table that shouldn't exist"); 1379a9de470cSBruce Richardson 1380a9de470cSBruce Richardson /* Cleanup. */ 1381a9de470cSBruce Richardson rte_fbk_hash_free(handle); 1382a9de470cSBruce Richardson 1383a9de470cSBruce Richardson return 0; 1384a9de470cSBruce Richardson } 1385a9de470cSBruce Richardson 1386a9de470cSBruce Richardson #define BUCKET_ENTRIES 4 1387a9de470cSBruce Richardson /* 1388a9de470cSBruce Richardson * Do tests for hash creation with bad parameters. 1389a9de470cSBruce Richardson */ 1390a9de470cSBruce Richardson static int test_hash_creation_with_bad_parameters(void) 1391a9de470cSBruce Richardson { 1392a9de470cSBruce Richardson struct rte_hash *handle, *tmp; 1393a9de470cSBruce Richardson struct rte_hash_parameters params; 1394a9de470cSBruce Richardson 1395a9de470cSBruce Richardson handle = rte_hash_create(NULL); 1396a9de470cSBruce Richardson if (handle != NULL) { 1397a9de470cSBruce Richardson rte_hash_free(handle); 1398a9de470cSBruce Richardson printf("Impossible creating hash successfully without any parameter\n"); 1399a9de470cSBruce Richardson return -1; 1400a9de470cSBruce Richardson } 1401a9de470cSBruce Richardson 1402a9de470cSBruce Richardson memcpy(¶ms, &ut_params, sizeof(params)); 1403a9de470cSBruce Richardson params.name = "creation_with_bad_parameters_0"; 1404a9de470cSBruce Richardson params.entries = RTE_HASH_ENTRIES_MAX + 1; 1405a9de470cSBruce Richardson handle = rte_hash_create(¶ms); 1406a9de470cSBruce Richardson if (handle != NULL) { 1407a9de470cSBruce Richardson rte_hash_free(handle); 1408a9de470cSBruce Richardson printf("Impossible creating hash successfully with entries in parameter exceeded\n"); 1409a9de470cSBruce Richardson return -1; 1410a9de470cSBruce Richardson } 1411a9de470cSBruce Richardson 1412a9de470cSBruce Richardson memcpy(¶ms, &ut_params, sizeof(params)); 1413a9de470cSBruce Richardson params.name = "creation_with_bad_parameters_2"; 1414a9de470cSBruce Richardson params.entries = BUCKET_ENTRIES - 1; 1415a9de470cSBruce Richardson handle = rte_hash_create(¶ms); 1416a9de470cSBruce Richardson if (handle != NULL) { 1417a9de470cSBruce Richardson rte_hash_free(handle); 1418a9de470cSBruce Richardson printf("Impossible creating hash successfully if entries less than bucket_entries in parameter\n"); 1419a9de470cSBruce Richardson return -1; 1420a9de470cSBruce Richardson } 1421a9de470cSBruce Richardson 1422a9de470cSBruce Richardson memcpy(¶ms, &ut_params, sizeof(params)); 1423a9de470cSBruce Richardson params.name = "creation_with_bad_parameters_3"; 1424a9de470cSBruce Richardson params.key_len = 0; 1425a9de470cSBruce Richardson handle = rte_hash_create(¶ms); 1426a9de470cSBruce Richardson if (handle != NULL) { 1427a9de470cSBruce Richardson rte_hash_free(handle); 1428a9de470cSBruce Richardson printf("Impossible creating hash successfully if key_len in parameter is zero\n"); 1429a9de470cSBruce Richardson return -1; 1430a9de470cSBruce Richardson } 1431a9de470cSBruce Richardson 1432a9de470cSBruce Richardson memcpy(¶ms, &ut_params, sizeof(params)); 1433a9de470cSBruce Richardson params.name = "creation_with_bad_parameters_4"; 1434a9de470cSBruce Richardson params.socket_id = RTE_MAX_NUMA_NODES + 1; 1435a9de470cSBruce Richardson handle = rte_hash_create(¶ms); 1436a9de470cSBruce Richardson if (handle != NULL) { 1437a9de470cSBruce Richardson rte_hash_free(handle); 1438a9de470cSBruce Richardson printf("Impossible creating hash successfully with invalid socket\n"); 1439a9de470cSBruce Richardson return -1; 1440a9de470cSBruce Richardson } 1441a9de470cSBruce Richardson 1442a9de470cSBruce Richardson /* test with same name should fail */ 1443a9de470cSBruce Richardson memcpy(¶ms, &ut_params, sizeof(params)); 1444a9de470cSBruce Richardson params.name = "same_name"; 1445a9de470cSBruce Richardson handle = rte_hash_create(¶ms); 1446a9de470cSBruce Richardson if (handle == NULL) { 1447a9de470cSBruce Richardson printf("Cannot create first hash table with 'same_name'\n"); 1448a9de470cSBruce Richardson return -1; 1449a9de470cSBruce Richardson } 1450a9de470cSBruce Richardson tmp = rte_hash_create(¶ms); 1451a9de470cSBruce Richardson if (tmp != NULL) { 1452a9de470cSBruce Richardson printf("Creation of hash table with same name should fail\n"); 1453a9de470cSBruce Richardson rte_hash_free(handle); 1454a9de470cSBruce Richardson rte_hash_free(tmp); 1455a9de470cSBruce Richardson return -1; 1456a9de470cSBruce Richardson } 1457a9de470cSBruce Richardson rte_hash_free(handle); 1458a9de470cSBruce Richardson 1459a9de470cSBruce Richardson printf("# Test successful. No more errors expected\n"); 1460a9de470cSBruce Richardson 1461a9de470cSBruce Richardson return 0; 1462a9de470cSBruce Richardson } 1463a9de470cSBruce Richardson 1464a9de470cSBruce Richardson /* 1465a9de470cSBruce Richardson * Do tests for hash creation with parameters that look incorrect 1466a9de470cSBruce Richardson * but are actually valid. 1467a9de470cSBruce Richardson */ 1468a9de470cSBruce Richardson static int 1469a9de470cSBruce Richardson test_hash_creation_with_good_parameters(void) 1470a9de470cSBruce Richardson { 1471a9de470cSBruce Richardson struct rte_hash *handle; 1472a9de470cSBruce Richardson struct rte_hash_parameters params; 1473a9de470cSBruce Richardson 1474a9de470cSBruce Richardson /* create with null hash function - should choose DEFAULT_HASH_FUNC */ 1475a9de470cSBruce Richardson memcpy(¶ms, &ut_params, sizeof(params)); 1476a9de470cSBruce Richardson params.name = "name"; 1477a9de470cSBruce Richardson params.hash_func = NULL; 1478a9de470cSBruce Richardson handle = rte_hash_create(¶ms); 1479a9de470cSBruce Richardson if (handle == NULL) { 1480a9de470cSBruce Richardson printf("Creating hash with null hash_func failed\n"); 1481a9de470cSBruce Richardson return -1; 1482a9de470cSBruce Richardson } 1483a9de470cSBruce Richardson 1484a9de470cSBruce Richardson rte_hash_free(handle); 1485a9de470cSBruce Richardson 1486a9de470cSBruce Richardson return 0; 1487a9de470cSBruce Richardson } 1488a9de470cSBruce Richardson 1489a9de470cSBruce Richardson #define ITERATIONS 3 1490a9de470cSBruce Richardson /* 1491a9de470cSBruce Richardson * Test to see the average table utilization (entries added/max entries) 1492a9de470cSBruce Richardson * before hitting a random entry that cannot be added 1493a9de470cSBruce Richardson */ 1494a9de470cSBruce Richardson static int test_average_table_utilization(uint32_t ext_table) 1495a9de470cSBruce Richardson { 1496a9de470cSBruce Richardson struct rte_hash *handle; 1497a9de470cSBruce Richardson uint8_t simple_key[MAX_KEYSIZE]; 1498a9de470cSBruce Richardson unsigned i, j; 1499a9de470cSBruce Richardson unsigned added_keys, average_keys_added = 0; 1500a9de470cSBruce Richardson int ret; 1501a9de470cSBruce Richardson unsigned int cnt; 1502a9de470cSBruce Richardson 1503a9de470cSBruce Richardson printf("\n# Running test to determine average utilization" 1504a9de470cSBruce Richardson "\n before adding elements begins to fail\n"); 1505a9de470cSBruce Richardson if (ext_table) 1506a9de470cSBruce Richardson printf("ext table is enabled\n"); 1507a9de470cSBruce Richardson else 1508a9de470cSBruce Richardson printf("ext table is disabled\n"); 1509a9de470cSBruce Richardson 1510a9de470cSBruce Richardson printf("Measuring performance, please wait"); 1511a9de470cSBruce Richardson fflush(stdout); 1512a9de470cSBruce Richardson ut_params.entries = 1 << 16; 1513a9de470cSBruce Richardson ut_params.name = "test_average_utilization"; 1514a9de470cSBruce Richardson ut_params.hash_func = rte_jhash; 1515a9de470cSBruce Richardson if (ext_table) 1516a9de470cSBruce Richardson ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE; 1517a9de470cSBruce Richardson else 1518a9de470cSBruce Richardson ut_params.extra_flag &= ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE; 1519a9de470cSBruce Richardson 1520a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 1521a9de470cSBruce Richardson 1522a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 1523a9de470cSBruce Richardson 1524a9de470cSBruce Richardson for (j = 0; j < ITERATIONS; j++) { 1525a9de470cSBruce Richardson ret = 0; 1526a9de470cSBruce Richardson /* Add random entries until key cannot be added */ 1527a9de470cSBruce Richardson for (added_keys = 0; ret >= 0; added_keys++) { 1528a9de470cSBruce Richardson for (i = 0; i < ut_params.key_len; i++) 1529a9de470cSBruce Richardson simple_key[i] = rte_rand() % 255; 1530a9de470cSBruce Richardson ret = rte_hash_add_key(handle, simple_key); 1531a9de470cSBruce Richardson if (ret < 0) 1532a9de470cSBruce Richardson break; 1533a9de470cSBruce Richardson } 1534a9de470cSBruce Richardson 1535a9de470cSBruce Richardson if (ret != -ENOSPC) { 1536a9de470cSBruce Richardson printf("Unexpected error when adding keys\n"); 1537a9de470cSBruce Richardson rte_hash_free(handle); 1538a9de470cSBruce Richardson return -1; 1539a9de470cSBruce Richardson } 1540a9de470cSBruce Richardson 1541a9de470cSBruce Richardson cnt = rte_hash_count(handle); 1542a9de470cSBruce Richardson if (cnt != added_keys) { 1543a9de470cSBruce Richardson printf("rte_hash_count returned wrong value %u, %u," 1544a9de470cSBruce Richardson "%u\n", j, added_keys, cnt); 1545a9de470cSBruce Richardson rte_hash_free(handle); 1546a9de470cSBruce Richardson return -1; 1547a9de470cSBruce Richardson } 1548a9de470cSBruce Richardson if (ext_table) { 1549a9de470cSBruce Richardson if (cnt != ut_params.entries) { 1550a9de470cSBruce Richardson printf("rte_hash_count returned wrong value " 1551a9de470cSBruce Richardson "%u, %u, %u\n", j, added_keys, cnt); 1552a9de470cSBruce Richardson rte_hash_free(handle); 1553a9de470cSBruce Richardson return -1; 1554a9de470cSBruce Richardson } 1555a9de470cSBruce Richardson } 1556a9de470cSBruce Richardson 1557a9de470cSBruce Richardson average_keys_added += added_keys; 1558a9de470cSBruce Richardson 1559a9de470cSBruce Richardson /* Reset the table */ 1560a9de470cSBruce Richardson rte_hash_reset(handle); 1561a9de470cSBruce Richardson 1562a9de470cSBruce Richardson /* Print a dot to show progress on operations */ 1563a9de470cSBruce Richardson printf("."); 1564a9de470cSBruce Richardson fflush(stdout); 1565a9de470cSBruce Richardson } 1566a9de470cSBruce Richardson 1567a9de470cSBruce Richardson average_keys_added /= ITERATIONS; 1568a9de470cSBruce Richardson 1569a9de470cSBruce Richardson printf("\nAverage table utilization = %.2f%% (%u/%u)\n", 1570a9de470cSBruce Richardson ((double) average_keys_added / ut_params.entries * 100), 1571a9de470cSBruce Richardson average_keys_added, ut_params.entries); 1572a9de470cSBruce Richardson rte_hash_free(handle); 1573a9de470cSBruce Richardson 1574a9de470cSBruce Richardson return 0; 1575a9de470cSBruce Richardson } 1576a9de470cSBruce Richardson 1577a9de470cSBruce Richardson #define NUM_ENTRIES 256 1578a9de470cSBruce Richardson static int test_hash_iteration(uint32_t ext_table) 1579a9de470cSBruce Richardson { 1580a9de470cSBruce Richardson struct rte_hash *handle; 1581a9de470cSBruce Richardson unsigned i; 1582a9de470cSBruce Richardson uint8_t keys[NUM_ENTRIES][MAX_KEYSIZE]; 1583a9de470cSBruce Richardson const void *next_key; 1584a9de470cSBruce Richardson void *next_data; 1585a9de470cSBruce Richardson void *data[NUM_ENTRIES]; 1586a9de470cSBruce Richardson unsigned added_keys; 1587a9de470cSBruce Richardson uint32_t iter = 0; 1588a9de470cSBruce Richardson int ret = 0; 1589a9de470cSBruce Richardson 1590a9de470cSBruce Richardson ut_params.entries = NUM_ENTRIES; 1591a9de470cSBruce Richardson ut_params.name = "test_hash_iteration"; 1592a9de470cSBruce Richardson ut_params.hash_func = rte_jhash; 1593a9de470cSBruce Richardson ut_params.key_len = 16; 1594a9de470cSBruce Richardson if (ext_table) 1595a9de470cSBruce Richardson ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE; 1596a9de470cSBruce Richardson else 1597a9de470cSBruce Richardson ut_params.extra_flag &= ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE; 1598a9de470cSBruce Richardson 1599a9de470cSBruce Richardson handle = rte_hash_create(&ut_params); 1600a9de470cSBruce Richardson RETURN_IF_ERROR(handle == NULL, "hash creation failed"); 1601a9de470cSBruce Richardson 1602a9de470cSBruce Richardson /* Add random entries until key cannot be added */ 1603a9de470cSBruce Richardson for (added_keys = 0; added_keys < NUM_ENTRIES; added_keys++) { 1604a9de470cSBruce Richardson data[added_keys] = (void *) ((uintptr_t) rte_rand()); 1605a9de470cSBruce Richardson for (i = 0; i < ut_params.key_len; i++) 1606a9de470cSBruce Richardson keys[added_keys][i] = rte_rand() % 255; 1607a9de470cSBruce Richardson ret = rte_hash_add_key_data(handle, keys[added_keys], data[added_keys]); 1608a9de470cSBruce Richardson if (ret < 0) { 1609a9de470cSBruce Richardson if (ext_table) { 1610a9de470cSBruce Richardson printf("Insertion failed for ext table\n"); 1611a9de470cSBruce Richardson goto err; 1612a9de470cSBruce Richardson } 1613a9de470cSBruce Richardson break; 1614a9de470cSBruce Richardson } 1615a9de470cSBruce Richardson } 1616a9de470cSBruce Richardson 1617a9de470cSBruce Richardson /* Iterate through the hash table */ 1618a9de470cSBruce Richardson while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) { 1619a9de470cSBruce Richardson /* Search for the key in the list of keys added */ 1620a9de470cSBruce Richardson for (i = 0; i < NUM_ENTRIES; i++) { 1621a9de470cSBruce Richardson if (memcmp(next_key, keys[i], ut_params.key_len) == 0) { 1622a9de470cSBruce Richardson if (next_data != data[i]) { 1623a9de470cSBruce Richardson printf("Data found in the hash table is" 1624a9de470cSBruce Richardson "not the data added with the key\n"); 1625a9de470cSBruce Richardson goto err; 1626a9de470cSBruce Richardson } 1627a9de470cSBruce Richardson added_keys--; 1628a9de470cSBruce Richardson break; 1629a9de470cSBruce Richardson } 1630a9de470cSBruce Richardson } 1631a9de470cSBruce Richardson if (i == NUM_ENTRIES) { 1632a9de470cSBruce Richardson printf("Key found in the hash table was not added\n"); 1633a9de470cSBruce Richardson goto err; 1634a9de470cSBruce Richardson } 1635a9de470cSBruce Richardson } 1636a9de470cSBruce Richardson 1637a9de470cSBruce Richardson /* Check if all keys have been iterated */ 1638a9de470cSBruce Richardson if (added_keys != 0) { 1639a9de470cSBruce Richardson printf("There were still %u keys to iterate\n", added_keys); 1640a9de470cSBruce Richardson goto err; 1641a9de470cSBruce Richardson } 1642a9de470cSBruce Richardson 1643a9de470cSBruce Richardson rte_hash_free(handle); 1644a9de470cSBruce Richardson return 0; 1645a9de470cSBruce Richardson 1646a9de470cSBruce Richardson err: 1647a9de470cSBruce Richardson rte_hash_free(handle); 1648a9de470cSBruce Richardson return -1; 1649a9de470cSBruce Richardson } 1650a9de470cSBruce Richardson 1651a9de470cSBruce Richardson static uint8_t key[16] = {0x00, 0x01, 0x02, 0x03, 1652a9de470cSBruce Richardson 0x04, 0x05, 0x06, 0x07, 1653a9de470cSBruce Richardson 0x08, 0x09, 0x0a, 0x0b, 1654a9de470cSBruce Richardson 0x0c, 0x0d, 0x0e, 0x0f}; 1655a9de470cSBruce Richardson static struct rte_hash_parameters hash_params_ex = { 1656a9de470cSBruce Richardson .name = NULL, 1657a9de470cSBruce Richardson .entries = 64, 1658a9de470cSBruce Richardson .key_len = 0, 1659a9de470cSBruce Richardson .hash_func = NULL, 1660a9de470cSBruce Richardson .hash_func_init_val = 0, 1661a9de470cSBruce Richardson .socket_id = 0, 1662a9de470cSBruce Richardson }; 1663a9de470cSBruce Richardson 1664a9de470cSBruce Richardson /* 1665e30ef3a3SVladimir Medvedkin * Wrapper function around rte_jhash_32b. 1666e30ef3a3SVladimir Medvedkin * It is required because rte_jhash_32b() accepts the length 1667e30ef3a3SVladimir Medvedkin * as size of 4-byte units. 1668e30ef3a3SVladimir Medvedkin */ 1669e30ef3a3SVladimir Medvedkin static inline uint32_t 1670e30ef3a3SVladimir Medvedkin test_jhash_32b(const void *k, uint32_t length, uint32_t initval) 1671e30ef3a3SVladimir Medvedkin { 1672e30ef3a3SVladimir Medvedkin return rte_jhash_32b(k, length >> 2, initval); 1673e30ef3a3SVladimir Medvedkin } 1674e30ef3a3SVladimir Medvedkin 1675e30ef3a3SVladimir Medvedkin /* 1676a9de470cSBruce Richardson * add/delete key with jhash2 1677a9de470cSBruce Richardson */ 1678a9de470cSBruce Richardson static int 1679a9de470cSBruce Richardson test_hash_add_delete_jhash2(void) 1680a9de470cSBruce Richardson { 1681a9de470cSBruce Richardson int ret = -1; 1682a9de470cSBruce Richardson struct rte_hash *handle; 1683a9de470cSBruce Richardson int32_t pos1, pos2; 1684a9de470cSBruce Richardson 1685a9de470cSBruce Richardson hash_params_ex.name = "hash_test_jhash2"; 1686a9de470cSBruce Richardson hash_params_ex.key_len = 4; 1687e30ef3a3SVladimir Medvedkin hash_params_ex.hash_func = (rte_hash_function)test_jhash_32b; 1688a9de470cSBruce Richardson 1689a9de470cSBruce Richardson handle = rte_hash_create(&hash_params_ex); 1690a9de470cSBruce Richardson if (handle == NULL) { 1691a9de470cSBruce Richardson printf("test_hash_add_delete_jhash2 fail to create hash\n"); 1692a9de470cSBruce Richardson goto fail_jhash2; 1693a9de470cSBruce Richardson } 1694a9de470cSBruce Richardson pos1 = rte_hash_add_key(handle, (void *)&key[0]); 1695a9de470cSBruce Richardson if (pos1 < 0) { 1696a9de470cSBruce Richardson printf("test_hash_add_delete_jhash2 fail to add hash key\n"); 1697a9de470cSBruce Richardson goto fail_jhash2; 1698a9de470cSBruce Richardson } 1699a9de470cSBruce Richardson 1700a9de470cSBruce Richardson pos2 = rte_hash_del_key(handle, (void *)&key[0]); 1701a9de470cSBruce Richardson if (pos2 < 0 || pos1 != pos2) { 1702a9de470cSBruce Richardson printf("test_hash_add_delete_jhash2 delete different key from being added\n"); 1703a9de470cSBruce Richardson goto fail_jhash2; 1704a9de470cSBruce Richardson } 1705a9de470cSBruce Richardson ret = 0; 1706a9de470cSBruce Richardson 1707a9de470cSBruce Richardson fail_jhash2: 1708a9de470cSBruce Richardson rte_hash_free(handle); 1709a9de470cSBruce Richardson 1710a9de470cSBruce Richardson return ret; 1711a9de470cSBruce Richardson } 1712a9de470cSBruce Richardson 1713a9de470cSBruce Richardson /* 1714a9de470cSBruce Richardson * add/delete (2) key with jhash2 1715a9de470cSBruce Richardson */ 1716a9de470cSBruce Richardson static int 1717a9de470cSBruce Richardson test_hash_add_delete_2_jhash2(void) 1718a9de470cSBruce Richardson { 1719a9de470cSBruce Richardson int ret = -1; 1720a9de470cSBruce Richardson struct rte_hash *handle; 1721a9de470cSBruce Richardson int32_t pos1, pos2; 1722a9de470cSBruce Richardson 1723a9de470cSBruce Richardson hash_params_ex.name = "hash_test_2_jhash2"; 1724a9de470cSBruce Richardson hash_params_ex.key_len = 8; 1725e30ef3a3SVladimir Medvedkin hash_params_ex.hash_func = (rte_hash_function)test_jhash_32b; 1726a9de470cSBruce Richardson 1727a9de470cSBruce Richardson handle = rte_hash_create(&hash_params_ex); 1728a9de470cSBruce Richardson if (handle == NULL) 1729a9de470cSBruce Richardson goto fail_2_jhash2; 1730a9de470cSBruce Richardson 1731a9de470cSBruce Richardson pos1 = rte_hash_add_key(handle, (void *)&key[0]); 1732a9de470cSBruce Richardson if (pos1 < 0) 1733a9de470cSBruce Richardson goto fail_2_jhash2; 1734a9de470cSBruce Richardson 1735a9de470cSBruce Richardson pos2 = rte_hash_del_key(handle, (void *)&key[0]); 1736a9de470cSBruce Richardson if (pos2 < 0 || pos1 != pos2) 1737a9de470cSBruce Richardson goto fail_2_jhash2; 1738a9de470cSBruce Richardson 1739a9de470cSBruce Richardson ret = 0; 1740a9de470cSBruce Richardson 1741a9de470cSBruce Richardson fail_2_jhash2: 1742a9de470cSBruce Richardson rte_hash_free(handle); 1743a9de470cSBruce Richardson 1744a9de470cSBruce Richardson return ret; 1745a9de470cSBruce Richardson } 1746a9de470cSBruce Richardson 1747a9de470cSBruce Richardson static uint32_t 1748a9de470cSBruce Richardson test_hash_jhash_1word(const void *key, uint32_t length, uint32_t initval) 1749a9de470cSBruce Richardson { 1750a9de470cSBruce Richardson const uint32_t *k = key; 1751a9de470cSBruce Richardson 1752a9de470cSBruce Richardson RTE_SET_USED(length); 1753a9de470cSBruce Richardson 1754a9de470cSBruce Richardson return rte_jhash_1word(k[0], initval); 1755a9de470cSBruce Richardson } 1756a9de470cSBruce Richardson 1757a9de470cSBruce Richardson static uint32_t 1758a9de470cSBruce Richardson test_hash_jhash_2word(const void *key, uint32_t length, uint32_t initval) 1759a9de470cSBruce Richardson { 1760a9de470cSBruce Richardson const uint32_t *k = key; 1761a9de470cSBruce Richardson 1762a9de470cSBruce Richardson RTE_SET_USED(length); 1763a9de470cSBruce Richardson 1764a9de470cSBruce Richardson return rte_jhash_2words(k[0], k[1], initval); 1765a9de470cSBruce Richardson } 1766a9de470cSBruce Richardson 1767a9de470cSBruce Richardson static uint32_t 1768a9de470cSBruce Richardson test_hash_jhash_3word(const void *key, uint32_t length, uint32_t initval) 1769a9de470cSBruce Richardson { 1770a9de470cSBruce Richardson const uint32_t *k = key; 1771a9de470cSBruce Richardson 1772a9de470cSBruce Richardson RTE_SET_USED(length); 1773a9de470cSBruce Richardson 1774a9de470cSBruce Richardson return rte_jhash_3words(k[0], k[1], k[2], initval); 1775a9de470cSBruce Richardson } 1776a9de470cSBruce Richardson 1777a9de470cSBruce Richardson /* 1778a9de470cSBruce Richardson * add/delete key with jhash 1word 1779a9de470cSBruce Richardson */ 1780a9de470cSBruce Richardson static int 1781a9de470cSBruce Richardson test_hash_add_delete_jhash_1word(void) 1782a9de470cSBruce Richardson { 1783a9de470cSBruce Richardson int ret = -1; 1784a9de470cSBruce Richardson struct rte_hash *handle; 1785a9de470cSBruce Richardson int32_t pos1, pos2; 1786a9de470cSBruce Richardson 1787a9de470cSBruce Richardson hash_params_ex.name = "hash_test_jhash_1word"; 1788a9de470cSBruce Richardson hash_params_ex.key_len = 4; 1789a9de470cSBruce Richardson hash_params_ex.hash_func = test_hash_jhash_1word; 1790a9de470cSBruce Richardson 1791a9de470cSBruce Richardson handle = rte_hash_create(&hash_params_ex); 1792a9de470cSBruce Richardson if (handle == NULL) 1793a9de470cSBruce Richardson goto fail_jhash_1word; 1794a9de470cSBruce Richardson 1795a9de470cSBruce Richardson pos1 = rte_hash_add_key(handle, (void *)&key[0]); 1796a9de470cSBruce Richardson if (pos1 < 0) 1797a9de470cSBruce Richardson goto fail_jhash_1word; 1798a9de470cSBruce Richardson 1799a9de470cSBruce Richardson pos2 = rte_hash_del_key(handle, (void *)&key[0]); 1800a9de470cSBruce Richardson if (pos2 < 0 || pos1 != pos2) 1801a9de470cSBruce Richardson goto fail_jhash_1word; 1802a9de470cSBruce Richardson 1803a9de470cSBruce Richardson ret = 0; 1804a9de470cSBruce Richardson 1805a9de470cSBruce Richardson fail_jhash_1word: 1806a9de470cSBruce Richardson rte_hash_free(handle); 1807a9de470cSBruce Richardson 1808a9de470cSBruce Richardson return ret; 1809a9de470cSBruce Richardson } 1810a9de470cSBruce Richardson 1811a9de470cSBruce Richardson /* 1812a9de470cSBruce Richardson * add/delete key with jhash 2word 1813a9de470cSBruce Richardson */ 1814a9de470cSBruce Richardson static int 1815a9de470cSBruce Richardson test_hash_add_delete_jhash_2word(void) 1816a9de470cSBruce Richardson { 1817a9de470cSBruce Richardson int ret = -1; 1818a9de470cSBruce Richardson struct rte_hash *handle; 1819a9de470cSBruce Richardson int32_t pos1, pos2; 1820a9de470cSBruce Richardson 1821a9de470cSBruce Richardson hash_params_ex.name = "hash_test_jhash_2word"; 1822a9de470cSBruce Richardson hash_params_ex.key_len = 8; 1823a9de470cSBruce Richardson hash_params_ex.hash_func = test_hash_jhash_2word; 1824a9de470cSBruce Richardson 1825a9de470cSBruce Richardson handle = rte_hash_create(&hash_params_ex); 1826a9de470cSBruce Richardson if (handle == NULL) 1827a9de470cSBruce Richardson goto fail_jhash_2word; 1828a9de470cSBruce Richardson 1829a9de470cSBruce Richardson pos1 = rte_hash_add_key(handle, (void *)&key[0]); 1830a9de470cSBruce Richardson if (pos1 < 0) 1831a9de470cSBruce Richardson goto fail_jhash_2word; 1832a9de470cSBruce Richardson 1833a9de470cSBruce Richardson pos2 = rte_hash_del_key(handle, (void *)&key[0]); 1834a9de470cSBruce Richardson if (pos2 < 0 || pos1 != pos2) 1835a9de470cSBruce Richardson goto fail_jhash_2word; 1836a9de470cSBruce Richardson 1837a9de470cSBruce Richardson ret = 0; 1838a9de470cSBruce Richardson 1839a9de470cSBruce Richardson fail_jhash_2word: 1840a9de470cSBruce Richardson rte_hash_free(handle); 1841a9de470cSBruce Richardson 1842a9de470cSBruce Richardson return ret; 1843a9de470cSBruce Richardson } 1844a9de470cSBruce Richardson 1845a9de470cSBruce Richardson /* 1846a9de470cSBruce Richardson * add/delete key with jhash 3word 1847a9de470cSBruce Richardson */ 1848a9de470cSBruce Richardson static int 1849a9de470cSBruce Richardson test_hash_add_delete_jhash_3word(void) 1850a9de470cSBruce Richardson { 1851a9de470cSBruce Richardson int ret = -1; 1852a9de470cSBruce Richardson struct rte_hash *handle; 1853a9de470cSBruce Richardson int32_t pos1, pos2; 1854a9de470cSBruce Richardson 1855a9de470cSBruce Richardson hash_params_ex.name = "hash_test_jhash_3word"; 1856a9de470cSBruce Richardson hash_params_ex.key_len = 12; 1857a9de470cSBruce Richardson hash_params_ex.hash_func = test_hash_jhash_3word; 1858a9de470cSBruce Richardson 1859a9de470cSBruce Richardson handle = rte_hash_create(&hash_params_ex); 1860a9de470cSBruce Richardson if (handle == NULL) 1861a9de470cSBruce Richardson goto fail_jhash_3word; 1862a9de470cSBruce Richardson 1863a9de470cSBruce Richardson pos1 = rte_hash_add_key(handle, (void *)&key[0]); 1864a9de470cSBruce Richardson if (pos1 < 0) 1865a9de470cSBruce Richardson goto fail_jhash_3word; 1866a9de470cSBruce Richardson 1867a9de470cSBruce Richardson pos2 = rte_hash_del_key(handle, (void *)&key[0]); 1868a9de470cSBruce Richardson if (pos2 < 0 || pos1 != pos2) 1869a9de470cSBruce Richardson goto fail_jhash_3word; 1870a9de470cSBruce Richardson 1871a9de470cSBruce Richardson ret = 0; 1872a9de470cSBruce Richardson 1873a9de470cSBruce Richardson fail_jhash_3word: 1874a9de470cSBruce Richardson rte_hash_free(handle); 1875a9de470cSBruce Richardson 1876a9de470cSBruce Richardson return ret; 1877a9de470cSBruce Richardson } 1878a9de470cSBruce Richardson 18799c7d8eedSDharmik Thakkar static struct rte_hash *g_handle; 18809c7d8eedSDharmik Thakkar static struct rte_rcu_qsbr *g_qsv; 18819c7d8eedSDharmik Thakkar static volatile uint8_t writer_done; 18829c7d8eedSDharmik Thakkar struct flow_key g_rand_keys[9]; 18839c7d8eedSDharmik Thakkar 18849c7d8eedSDharmik Thakkar /* 18859c7d8eedSDharmik Thakkar * rte_hash_rcu_qsbr_add positive and negative tests. 18869c7d8eedSDharmik Thakkar * - Add RCU QSBR variable to Hash 18879c7d8eedSDharmik Thakkar * - Add another RCU QSBR variable to Hash 18889c7d8eedSDharmik Thakkar * - Check returns 18899c7d8eedSDharmik Thakkar */ 18909c7d8eedSDharmik Thakkar static int 18919c7d8eedSDharmik Thakkar test_hash_rcu_qsbr_add(void) 18929c7d8eedSDharmik Thakkar { 18939c7d8eedSDharmik Thakkar size_t sz; 18949c7d8eedSDharmik Thakkar struct rte_rcu_qsbr *qsv2 = NULL; 18959c7d8eedSDharmik Thakkar int32_t status; 18969c7d8eedSDharmik Thakkar struct rte_hash_rcu_config rcu_cfg = {0}; 18979c7d8eedSDharmik Thakkar struct rte_hash_parameters params; 18989c7d8eedSDharmik Thakkar 18999c7d8eedSDharmik Thakkar printf("\n# Running RCU QSBR add tests\n"); 19009c7d8eedSDharmik Thakkar memcpy(¶ms, &ut_params, sizeof(params)); 19019c7d8eedSDharmik Thakkar params.name = "test_hash_rcu_qsbr_add"; 19029c7d8eedSDharmik Thakkar params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF | 19039c7d8eedSDharmik Thakkar RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD; 19049c7d8eedSDharmik Thakkar g_handle = rte_hash_create(¶ms); 19059c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed"); 19069c7d8eedSDharmik Thakkar 19079c7d8eedSDharmik Thakkar /* Create RCU QSBR variable */ 19089c7d8eedSDharmik Thakkar sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE); 19099c7d8eedSDharmik Thakkar g_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, 19109c7d8eedSDharmik Thakkar RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 19119c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL, 19129c7d8eedSDharmik Thakkar "RCU QSBR variable creation failed"); 19139c7d8eedSDharmik Thakkar 19149c7d8eedSDharmik Thakkar status = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE); 19159c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(status != 0, 19169c7d8eedSDharmik Thakkar "RCU QSBR variable initialization failed"); 19179c7d8eedSDharmik Thakkar 19189c7d8eedSDharmik Thakkar rcu_cfg.v = g_qsv; 19199c7d8eedSDharmik Thakkar /* Invalid QSBR mode */ 19209c7d8eedSDharmik Thakkar rcu_cfg.mode = 0xff; 19219c7d8eedSDharmik Thakkar status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg); 19229c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(status == 0, "Invalid QSBR mode test failed"); 19239c7d8eedSDharmik Thakkar 19249c7d8eedSDharmik Thakkar rcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ; 19259c7d8eedSDharmik Thakkar /* Attach RCU QSBR to hash table */ 19269c7d8eedSDharmik Thakkar status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg); 19279c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(status != 0, 19289c7d8eedSDharmik Thakkar "Attach RCU QSBR to hash table failed"); 19299c7d8eedSDharmik Thakkar 19309c7d8eedSDharmik Thakkar /* Create and attach another RCU QSBR to hash table */ 19319c7d8eedSDharmik Thakkar qsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, 19329c7d8eedSDharmik Thakkar RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 19339c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(qsv2 == NULL, 19349c7d8eedSDharmik Thakkar "RCU QSBR variable creation failed"); 19359c7d8eedSDharmik Thakkar 19369c7d8eedSDharmik Thakkar rcu_cfg.v = qsv2; 19379c7d8eedSDharmik Thakkar rcu_cfg.mode = RTE_HASH_QSBR_MODE_SYNC; 19389c7d8eedSDharmik Thakkar status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg); 19399c7d8eedSDharmik Thakkar rte_free(qsv2); 19409c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(status == 0, 19419c7d8eedSDharmik Thakkar "Attach RCU QSBR to hash table succeeded where failure" 19429c7d8eedSDharmik Thakkar " is expected"); 19439c7d8eedSDharmik Thakkar 19449c7d8eedSDharmik Thakkar rte_hash_free(g_handle); 19459c7d8eedSDharmik Thakkar rte_free(g_qsv); 19469c7d8eedSDharmik Thakkar 19479c7d8eedSDharmik Thakkar return 0; 19489c7d8eedSDharmik Thakkar } 19499c7d8eedSDharmik Thakkar 19509c7d8eedSDharmik Thakkar /* 19519c7d8eedSDharmik Thakkar * rte_hash_rcu_qsbr_add DQ mode functional test. 19529c7d8eedSDharmik Thakkar * Reader and writer are in the same thread in this test. 19539c7d8eedSDharmik Thakkar * - Create hash which supports maximum 8 (9 if ext bkt is enabled) entries 19549c7d8eedSDharmik Thakkar * - Add RCU QSBR variable to hash 19559c7d8eedSDharmik Thakkar * - Add 8 hash entries and fill the bucket 19569c7d8eedSDharmik Thakkar * - If ext bkt is enabled, add 1 extra entry that is available in the ext bkt 19579c7d8eedSDharmik Thakkar * - Register a reader thread (not a real thread) 19589c7d8eedSDharmik Thakkar * - Reader lookup existing entry 19599c7d8eedSDharmik Thakkar * - Writer deletes the entry 19609c7d8eedSDharmik Thakkar * - Reader lookup the entry 19619c7d8eedSDharmik Thakkar * - Writer re-add the entry (no available free index) 19629c7d8eedSDharmik Thakkar * - Reader report quiescent state and unregister 19639c7d8eedSDharmik Thakkar * - Writer re-add the entry 19649c7d8eedSDharmik Thakkar * - Reader lookup the entry 19659c7d8eedSDharmik Thakkar */ 19669c7d8eedSDharmik Thakkar static int 19679c7d8eedSDharmik Thakkar test_hash_rcu_qsbr_dq_mode(uint8_t ext_bkt) 19689c7d8eedSDharmik Thakkar { 19699c7d8eedSDharmik Thakkar uint32_t total_entries = (ext_bkt == 0) ? 8 : 9; 19709c7d8eedSDharmik Thakkar 19719c7d8eedSDharmik Thakkar uint8_t hash_extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF; 19729c7d8eedSDharmik Thakkar 19739c7d8eedSDharmik Thakkar if (ext_bkt) 19749c7d8eedSDharmik Thakkar hash_extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE; 19759c7d8eedSDharmik Thakkar 19769c7d8eedSDharmik Thakkar struct rte_hash_parameters params_pseudo_hash = { 19779c7d8eedSDharmik Thakkar .name = "test_hash_rcu_qsbr_dq_mode", 19789c7d8eedSDharmik Thakkar .entries = total_entries, 1979e30ef3a3SVladimir Medvedkin .key_len = sizeof(struct flow_key), 19809c7d8eedSDharmik Thakkar .hash_func = pseudo_hash, 19819c7d8eedSDharmik Thakkar .hash_func_init_val = 0, 19829c7d8eedSDharmik Thakkar .socket_id = 0, 19839c7d8eedSDharmik Thakkar .extra_flag = hash_extra_flag, 19849c7d8eedSDharmik Thakkar }; 19859c7d8eedSDharmik Thakkar int pos[total_entries]; 19869c7d8eedSDharmik Thakkar int expected_pos[total_entries]; 19879c7d8eedSDharmik Thakkar unsigned int i; 19889c7d8eedSDharmik Thakkar size_t sz; 19899c7d8eedSDharmik Thakkar int32_t status; 19909c7d8eedSDharmik Thakkar struct rte_hash_rcu_config rcu_cfg = {0}; 19919c7d8eedSDharmik Thakkar 19929c7d8eedSDharmik Thakkar g_qsv = NULL; 19939c7d8eedSDharmik Thakkar g_handle = NULL; 19949c7d8eedSDharmik Thakkar 19959c7d8eedSDharmik Thakkar for (i = 0; i < total_entries; i++) { 19969c7d8eedSDharmik Thakkar g_rand_keys[i].port_dst = i; 19979c7d8eedSDharmik Thakkar g_rand_keys[i].port_src = i+1; 19989c7d8eedSDharmik Thakkar } 19999c7d8eedSDharmik Thakkar 20009c7d8eedSDharmik Thakkar if (ext_bkt) 20019c7d8eedSDharmik Thakkar printf("\n# Running RCU QSBR DQ mode functional test with" 20029c7d8eedSDharmik Thakkar " ext bkt\n"); 20039c7d8eedSDharmik Thakkar else 20049c7d8eedSDharmik Thakkar printf("\n# Running RCU QSBR DQ mode functional test\n"); 20059c7d8eedSDharmik Thakkar 20069c7d8eedSDharmik Thakkar g_handle = rte_hash_create(¶ms_pseudo_hash); 20079c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed"); 20089c7d8eedSDharmik Thakkar 20099c7d8eedSDharmik Thakkar /* Create RCU QSBR variable */ 20109c7d8eedSDharmik Thakkar sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE); 20119c7d8eedSDharmik Thakkar g_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, 20129c7d8eedSDharmik Thakkar RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 20139c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL, 20149c7d8eedSDharmik Thakkar "RCU QSBR variable creation failed"); 20159c7d8eedSDharmik Thakkar 20169c7d8eedSDharmik Thakkar status = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE); 20179c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(status != 0, 20189c7d8eedSDharmik Thakkar "RCU QSBR variable initialization failed"); 20199c7d8eedSDharmik Thakkar 20209c7d8eedSDharmik Thakkar rcu_cfg.v = g_qsv; 20219c7d8eedSDharmik Thakkar rcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ; 20229c7d8eedSDharmik Thakkar /* Attach RCU QSBR to hash table */ 20239c7d8eedSDharmik Thakkar status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg); 20249c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(status != 0, 20259c7d8eedSDharmik Thakkar "Attach RCU QSBR to hash table failed"); 20269c7d8eedSDharmik Thakkar 20279c7d8eedSDharmik Thakkar /* Fill bucket */ 20289c7d8eedSDharmik Thakkar for (i = 0; i < total_entries; i++) { 20299c7d8eedSDharmik Thakkar pos[i] = rte_hash_add_key(g_handle, &g_rand_keys[i]); 20309c7d8eedSDharmik Thakkar print_key_info("Add", &g_rand_keys[i], pos[i]); 20319c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[i] < 0, 20329c7d8eedSDharmik Thakkar "failed to add key (pos[%u]=%d)", i, 20339c7d8eedSDharmik Thakkar pos[i]); 20349c7d8eedSDharmik Thakkar expected_pos[i] = pos[i]; 20359c7d8eedSDharmik Thakkar } 20369c7d8eedSDharmik Thakkar 20379c7d8eedSDharmik Thakkar /* Register pseudo reader */ 20389c7d8eedSDharmik Thakkar status = rte_rcu_qsbr_thread_register(g_qsv, 0); 20399c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(status != 0, 20409c7d8eedSDharmik Thakkar "RCU QSBR thread registration failed"); 20419c7d8eedSDharmik Thakkar rte_rcu_qsbr_thread_online(g_qsv, 0); 20429c7d8eedSDharmik Thakkar 20439c7d8eedSDharmik Thakkar /* Lookup */ 20449c7d8eedSDharmik Thakkar pos[0] = rte_hash_lookup(g_handle, &g_rand_keys[0]); 20459c7d8eedSDharmik Thakkar print_key_info("Lkp", &g_rand_keys[0], pos[0]); 20469c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0], 20479c7d8eedSDharmik Thakkar "failed to find correct key (pos[%u]=%d)", 0, 20489c7d8eedSDharmik Thakkar pos[0]); 20499c7d8eedSDharmik Thakkar 20509c7d8eedSDharmik Thakkar /* Writer update */ 20519c7d8eedSDharmik Thakkar pos[0] = rte_hash_del_key(g_handle, &g_rand_keys[0]); 20529c7d8eedSDharmik Thakkar print_key_info("Del", &g_rand_keys[0], pos[0]); 20539c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0], 20549c7d8eedSDharmik Thakkar "failed to del correct key (pos[%u]=%d)", 0, 20559c7d8eedSDharmik Thakkar pos[0]); 20569c7d8eedSDharmik Thakkar 20579c7d8eedSDharmik Thakkar /* Lookup */ 20589c7d8eedSDharmik Thakkar pos[0] = rte_hash_lookup(g_handle, &g_rand_keys[0]); 20599c7d8eedSDharmik Thakkar print_key_info("Lkp", &g_rand_keys[0], pos[0]); 20609c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[0] != -ENOENT, 20619c7d8eedSDharmik Thakkar "found deleted key (pos[%u]=%d)", 0, pos[0]); 20629c7d8eedSDharmik Thakkar 20639c7d8eedSDharmik Thakkar /* Fill bucket */ 20649c7d8eedSDharmik Thakkar pos[0] = rte_hash_add_key(g_handle, &g_rand_keys[0]); 20659c7d8eedSDharmik Thakkar print_key_info("Add", &g_rand_keys[0], pos[0]); 20669c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[0] != -ENOSPC, 20679c7d8eedSDharmik Thakkar "Added key successfully (pos[%u]=%d)", 0, pos[0]); 20689c7d8eedSDharmik Thakkar 20699c7d8eedSDharmik Thakkar /* Reader quiescent */ 20709c7d8eedSDharmik Thakkar rte_rcu_qsbr_quiescent(g_qsv, 0); 20719c7d8eedSDharmik Thakkar 20729c7d8eedSDharmik Thakkar /* Fill bucket */ 20739c7d8eedSDharmik Thakkar pos[0] = rte_hash_add_key(g_handle, &g_rand_keys[0]); 20749c7d8eedSDharmik Thakkar print_key_info("Add", &g_rand_keys[0], pos[0]); 20759c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[0] < 0, 20769c7d8eedSDharmik Thakkar "failed to add key (pos[%u]=%d)", 0, pos[0]); 20779c7d8eedSDharmik Thakkar expected_pos[0] = pos[0]; 20789c7d8eedSDharmik Thakkar 20799c7d8eedSDharmik Thakkar rte_rcu_qsbr_thread_offline(g_qsv, 0); 20809c7d8eedSDharmik Thakkar (void)rte_rcu_qsbr_thread_unregister(g_qsv, 0); 20819c7d8eedSDharmik Thakkar 20829c7d8eedSDharmik Thakkar /* Lookup */ 20839c7d8eedSDharmik Thakkar pos[0] = rte_hash_lookup(g_handle, &g_rand_keys[0]); 20849c7d8eedSDharmik Thakkar print_key_info("Lkp", &g_rand_keys[0], pos[0]); 20859c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0], 20869c7d8eedSDharmik Thakkar "failed to find correct key (pos[%u]=%d)", 0, 20879c7d8eedSDharmik Thakkar pos[0]); 20889c7d8eedSDharmik Thakkar 20899c7d8eedSDharmik Thakkar rte_hash_free(g_handle); 20909c7d8eedSDharmik Thakkar rte_free(g_qsv); 20919c7d8eedSDharmik Thakkar return 0; 20929c7d8eedSDharmik Thakkar 20939c7d8eedSDharmik Thakkar } 20949c7d8eedSDharmik Thakkar 20959c7d8eedSDharmik Thakkar /* Report quiescent state interval every 1024 lookups. Larger critical 20969c7d8eedSDharmik Thakkar * sections in reader will result in writer polling multiple times. 20979c7d8eedSDharmik Thakkar */ 20989c7d8eedSDharmik Thakkar #define QSBR_REPORTING_INTERVAL 1024 20999c7d8eedSDharmik Thakkar #define WRITER_ITERATIONS 512 21009c7d8eedSDharmik Thakkar 21019c7d8eedSDharmik Thakkar /* 21029c7d8eedSDharmik Thakkar * Reader thread using rte_hash data structure with RCU. 21039c7d8eedSDharmik Thakkar */ 21049c7d8eedSDharmik Thakkar static int 21059c7d8eedSDharmik Thakkar test_hash_rcu_qsbr_reader(void *arg) 21069c7d8eedSDharmik Thakkar { 21079c7d8eedSDharmik Thakkar int i; 21089c7d8eedSDharmik Thakkar 21099c7d8eedSDharmik Thakkar RTE_SET_USED(arg); 21109c7d8eedSDharmik Thakkar /* Register this thread to report quiescent state */ 21119c7d8eedSDharmik Thakkar (void)rte_rcu_qsbr_thread_register(g_qsv, 0); 21129c7d8eedSDharmik Thakkar rte_rcu_qsbr_thread_online(g_qsv, 0); 21139c7d8eedSDharmik Thakkar 21149c7d8eedSDharmik Thakkar do { 21159c7d8eedSDharmik Thakkar for (i = 0; i < QSBR_REPORTING_INTERVAL; i++) 21169c7d8eedSDharmik Thakkar rte_hash_lookup(g_handle, &g_rand_keys[0]); 21179c7d8eedSDharmik Thakkar 21189c7d8eedSDharmik Thakkar /* Update quiescent state */ 21199c7d8eedSDharmik Thakkar rte_rcu_qsbr_quiescent(g_qsv, 0); 21209c7d8eedSDharmik Thakkar } while (!writer_done); 21219c7d8eedSDharmik Thakkar 21229c7d8eedSDharmik Thakkar rte_rcu_qsbr_thread_offline(g_qsv, 0); 21239c7d8eedSDharmik Thakkar (void)rte_rcu_qsbr_thread_unregister(g_qsv, 0); 21249c7d8eedSDharmik Thakkar 21259c7d8eedSDharmik Thakkar return 0; 21269c7d8eedSDharmik Thakkar } 21279c7d8eedSDharmik Thakkar 21289c7d8eedSDharmik Thakkar /* 21299c7d8eedSDharmik Thakkar * rte_hash_rcu_qsbr_add sync mode functional test. 21309c7d8eedSDharmik Thakkar * 1 Reader and 1 writer. They cannot be in the same thread in this test. 21319c7d8eedSDharmik Thakkar * - Create hash which supports maximum 8 (9 if ext bkt is enabled) entries 21329c7d8eedSDharmik Thakkar * - Add RCU QSBR variable to hash 21339c7d8eedSDharmik Thakkar * - Register a reader thread. Reader keeps looking up a specific key. 21349c7d8eedSDharmik Thakkar * - Writer keeps adding and deleting a specific key. 21359c7d8eedSDharmik Thakkar */ 21369c7d8eedSDharmik Thakkar static int 21379c7d8eedSDharmik Thakkar test_hash_rcu_qsbr_sync_mode(uint8_t ext_bkt) 21389c7d8eedSDharmik Thakkar { 21399c7d8eedSDharmik Thakkar uint32_t total_entries = (ext_bkt == 0) ? 8 : 9; 21409c7d8eedSDharmik Thakkar 21419c7d8eedSDharmik Thakkar uint8_t hash_extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF; 21429c7d8eedSDharmik Thakkar 21439c7d8eedSDharmik Thakkar if (ext_bkt) 21449c7d8eedSDharmik Thakkar hash_extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE; 21459c7d8eedSDharmik Thakkar 21469c7d8eedSDharmik Thakkar struct rte_hash_parameters params_pseudo_hash = { 21479c7d8eedSDharmik Thakkar .name = "test_hash_rcu_qsbr_sync_mode", 21489c7d8eedSDharmik Thakkar .entries = total_entries, 2149e30ef3a3SVladimir Medvedkin .key_len = sizeof(struct flow_key), 21509c7d8eedSDharmik Thakkar .hash_func = pseudo_hash, 21519c7d8eedSDharmik Thakkar .hash_func_init_val = 0, 21529c7d8eedSDharmik Thakkar .socket_id = 0, 21539c7d8eedSDharmik Thakkar .extra_flag = hash_extra_flag, 21549c7d8eedSDharmik Thakkar }; 21559c7d8eedSDharmik Thakkar int pos[total_entries]; 21569c7d8eedSDharmik Thakkar int expected_pos[total_entries]; 21579c7d8eedSDharmik Thakkar unsigned int i; 21589c7d8eedSDharmik Thakkar size_t sz; 21599c7d8eedSDharmik Thakkar int32_t status; 21609c7d8eedSDharmik Thakkar struct rte_hash_rcu_config rcu_cfg = {0}; 21619c7d8eedSDharmik Thakkar 21629c7d8eedSDharmik Thakkar g_qsv = NULL; 21639c7d8eedSDharmik Thakkar g_handle = NULL; 21649c7d8eedSDharmik Thakkar 21659c7d8eedSDharmik Thakkar for (i = 0; i < total_entries; i++) { 21669c7d8eedSDharmik Thakkar g_rand_keys[i].port_dst = i; 21679c7d8eedSDharmik Thakkar g_rand_keys[i].port_src = i+1; 21689c7d8eedSDharmik Thakkar } 21699c7d8eedSDharmik Thakkar 21709c7d8eedSDharmik Thakkar if (ext_bkt) 21719c7d8eedSDharmik Thakkar printf("\n# Running RCU QSBR sync mode functional test with" 21729c7d8eedSDharmik Thakkar " ext bkt\n"); 21739c7d8eedSDharmik Thakkar else 21749c7d8eedSDharmik Thakkar printf("\n# Running RCU QSBR sync mode functional test\n"); 21759c7d8eedSDharmik Thakkar 21769c7d8eedSDharmik Thakkar g_handle = rte_hash_create(¶ms_pseudo_hash); 21779c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed"); 21789c7d8eedSDharmik Thakkar 21799c7d8eedSDharmik Thakkar /* Create RCU QSBR variable */ 21809c7d8eedSDharmik Thakkar sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE); 21819c7d8eedSDharmik Thakkar g_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, 21829c7d8eedSDharmik Thakkar RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 21839c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL, 21849c7d8eedSDharmik Thakkar "RCU QSBR variable creation failed"); 21859c7d8eedSDharmik Thakkar 21869c7d8eedSDharmik Thakkar status = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE); 21879c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(status != 0, 21889c7d8eedSDharmik Thakkar "RCU QSBR variable initialization failed"); 21899c7d8eedSDharmik Thakkar 21909c7d8eedSDharmik Thakkar rcu_cfg.v = g_qsv; 21919c7d8eedSDharmik Thakkar rcu_cfg.mode = RTE_HASH_QSBR_MODE_SYNC; 21929c7d8eedSDharmik Thakkar /* Attach RCU QSBR to hash table */ 21939c7d8eedSDharmik Thakkar status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg); 21949c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(status != 0, 21959c7d8eedSDharmik Thakkar "Attach RCU QSBR to hash table failed"); 21969c7d8eedSDharmik Thakkar 21979c7d8eedSDharmik Thakkar /* Launch reader thread */ 21989c7d8eedSDharmik Thakkar rte_eal_remote_launch(test_hash_rcu_qsbr_reader, NULL, 21999c7d8eedSDharmik Thakkar rte_get_next_lcore(-1, 1, 0)); 22009c7d8eedSDharmik Thakkar 22019c7d8eedSDharmik Thakkar /* Fill bucket */ 22029c7d8eedSDharmik Thakkar for (i = 0; i < total_entries; i++) { 22039c7d8eedSDharmik Thakkar pos[i] = rte_hash_add_key(g_handle, &g_rand_keys[i]); 22049c7d8eedSDharmik Thakkar print_key_info("Add", &g_rand_keys[i], pos[i]); 22059c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[i] < 0, 22069c7d8eedSDharmik Thakkar "failed to add key (pos[%u]=%d)", i, pos[i]); 22079c7d8eedSDharmik Thakkar expected_pos[i] = pos[i]; 22089c7d8eedSDharmik Thakkar } 22099c7d8eedSDharmik Thakkar writer_done = 0; 22109c7d8eedSDharmik Thakkar 22119c7d8eedSDharmik Thakkar /* Writer Update */ 22129c7d8eedSDharmik Thakkar for (i = 0; i < WRITER_ITERATIONS; i++) { 22139c7d8eedSDharmik Thakkar expected_pos[0] = pos[0]; 22149c7d8eedSDharmik Thakkar pos[0] = rte_hash_del_key(g_handle, &g_rand_keys[0]); 22159c7d8eedSDharmik Thakkar print_key_info("Del", &g_rand_keys[0], status); 22169c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0], 22179c7d8eedSDharmik Thakkar "failed to del correct key (pos[%u]=%d)" 22189c7d8eedSDharmik Thakkar , 0, pos[0]); 22199c7d8eedSDharmik Thakkar 22209c7d8eedSDharmik Thakkar pos[0] = rte_hash_add_key(g_handle, &g_rand_keys[0]); 22219c7d8eedSDharmik Thakkar print_key_info("Add", &g_rand_keys[0], pos[0]); 22229c7d8eedSDharmik Thakkar RETURN_IF_ERROR_RCU_QSBR(pos[0] < 0, 22239c7d8eedSDharmik Thakkar "failed to add key (pos[%u]=%d)", 0, 22249c7d8eedSDharmik Thakkar pos[0]); 22259c7d8eedSDharmik Thakkar } 22269c7d8eedSDharmik Thakkar 22279c7d8eedSDharmik Thakkar writer_done = 1; 22289c7d8eedSDharmik Thakkar /* Wait until reader exited. */ 22299c7d8eedSDharmik Thakkar rte_eal_mp_wait_lcore(); 22309c7d8eedSDharmik Thakkar 22319c7d8eedSDharmik Thakkar rte_hash_free(g_handle); 22329c7d8eedSDharmik Thakkar rte_free(g_qsv); 22339c7d8eedSDharmik Thakkar 22349c7d8eedSDharmik Thakkar return 0; 22359c7d8eedSDharmik Thakkar 22369c7d8eedSDharmik Thakkar } 22379c7d8eedSDharmik Thakkar 2238a9de470cSBruce Richardson /* 2239567bb951SAbdullah Ömer Yamaç * rte_hash_rcu_qsbr_dq_reclaim unit test. 2240567bb951SAbdullah Ömer Yamaç */ 2241567bb951SAbdullah Ömer Yamaç static int 2242567bb951SAbdullah Ömer Yamaç test_hash_rcu_qsbr_dq_reclaim(void) 2243567bb951SAbdullah Ömer Yamaç { 2244567bb951SAbdullah Ömer Yamaç size_t sz; 2245567bb951SAbdullah Ömer Yamaç int32_t status; 2246567bb951SAbdullah Ömer Yamaç unsigned int total_entries = 8; 2247567bb951SAbdullah Ömer Yamaç unsigned int freed, pending, available; 2248567bb951SAbdullah Ömer Yamaç uint32_t reclaim_keys[8] = {10, 11, 12, 13, 14, 15, 16, 17}; 2249567bb951SAbdullah Ömer Yamaç struct rte_hash_rcu_config rcu_cfg = {0}; 2250567bb951SAbdullah Ömer Yamaç struct rte_hash_parameters hash_params = { 2251567bb951SAbdullah Ömer Yamaç .name = "test_hash_rcu_qsbr_dq_reclaim", 2252567bb951SAbdullah Ömer Yamaç .entries = total_entries, 2253567bb951SAbdullah Ömer Yamaç .key_len = sizeof(uint32_t), 2254567bb951SAbdullah Ömer Yamaç .hash_func = NULL, 2255567bb951SAbdullah Ömer Yamaç .hash_func_init_val = 0, 2256567bb951SAbdullah Ömer Yamaç .socket_id = 0, 2257567bb951SAbdullah Ömer Yamaç }; 2258567bb951SAbdullah Ömer Yamaç 2259567bb951SAbdullah Ömer Yamaç hash_params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF; 2260567bb951SAbdullah Ömer Yamaç 2261567bb951SAbdullah Ömer Yamaç g_qsv = NULL; 2262567bb951SAbdullah Ömer Yamaç g_handle = NULL; 2263567bb951SAbdullah Ömer Yamaç 2264567bb951SAbdullah Ömer Yamaç printf("\n# Running RCU QSBR DQ mode, reclaim defer queue functional test\n"); 2265567bb951SAbdullah Ömer Yamaç 2266567bb951SAbdullah Ömer Yamaç g_handle = rte_hash_create(&hash_params); 2267567bb951SAbdullah Ömer Yamaç RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed"); 2268567bb951SAbdullah Ömer Yamaç 2269567bb951SAbdullah Ömer Yamaç /* Create RCU QSBR variable */ 2270567bb951SAbdullah Ömer Yamaç sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE); 2271567bb951SAbdullah Ömer Yamaç g_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket( 2272567bb951SAbdullah Ömer Yamaç NULL, sz, RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY); 2273567bb951SAbdullah Ömer Yamaç RETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL, "RCU QSBR variable creation failed"); 2274567bb951SAbdullah Ömer Yamaç 2275567bb951SAbdullah Ömer Yamaç status = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE); 2276567bb951SAbdullah Ömer Yamaç RETURN_IF_ERROR_RCU_QSBR(status != 0, "RCU QSBR variable initialization failed"); 2277567bb951SAbdullah Ömer Yamaç 2278567bb951SAbdullah Ömer Yamaç rcu_cfg.v = g_qsv; 2279567bb951SAbdullah Ömer Yamaç rcu_cfg.dq_size = total_entries; 2280567bb951SAbdullah Ömer Yamaç rcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ; 2281567bb951SAbdullah Ömer Yamaç 2282567bb951SAbdullah Ömer Yamaç /* Attach RCU QSBR to hash table */ 2283567bb951SAbdullah Ömer Yamaç status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg); 2284567bb951SAbdullah Ömer Yamaç RETURN_IF_ERROR_RCU_QSBR(status != 0, "Attach RCU QSBR to hash table failed"); 2285567bb951SAbdullah Ömer Yamaç 2286567bb951SAbdullah Ömer Yamaç /* Register pseudo reader */ 2287567bb951SAbdullah Ömer Yamaç status = rte_rcu_qsbr_thread_register(g_qsv, 0); 2288567bb951SAbdullah Ömer Yamaç RETURN_IF_ERROR_RCU_QSBR(status != 0, "RCU QSBR thread registration failed"); 2289567bb951SAbdullah Ömer Yamaç rte_rcu_qsbr_thread_online(g_qsv, 0); 2290567bb951SAbdullah Ömer Yamaç 2291567bb951SAbdullah Ömer Yamaç /* Fill half of the hash table */ 2292567bb951SAbdullah Ömer Yamaç for (size_t i = 0; i < total_entries / 2; i++) 2293567bb951SAbdullah Ömer Yamaç status = rte_hash_add_key(g_handle, &reclaim_keys[i]); 2294567bb951SAbdullah Ömer Yamaç 2295567bb951SAbdullah Ömer Yamaç /* Try to put these elements into the defer queue*/ 2296567bb951SAbdullah Ömer Yamaç for (size_t i = 0; i < total_entries / 2; i++) 2297567bb951SAbdullah Ömer Yamaç rte_hash_del_key(g_handle, &reclaim_keys[i]); 2298567bb951SAbdullah Ömer Yamaç 2299567bb951SAbdullah Ömer Yamaç /* Reader quiescent */ 2300567bb951SAbdullah Ömer Yamaç rte_rcu_qsbr_quiescent(g_qsv, 0); 2301567bb951SAbdullah Ömer Yamaç 2302567bb951SAbdullah Ömer Yamaç status = rte_hash_add_key(g_handle, &reclaim_keys[0]); 2303567bb951SAbdullah Ömer Yamaç RETURN_IF_ERROR_RCU_QSBR(status < 0, "failed to add key (pos[%u]=%d)", 0, status); 2304567bb951SAbdullah Ömer Yamaç 2305567bb951SAbdullah Ömer Yamaç /* This should be (total_entries / 2) + 1 (last add) */ 2306567bb951SAbdullah Ömer Yamaç unsigned int hash_size = rte_hash_count(g_handle); 2307567bb951SAbdullah Ömer Yamaç 2308567bb951SAbdullah Ömer Yamaç /* Freed size should be (total_entries / 2) */ 2309567bb951SAbdullah Ömer Yamaç rte_hash_rcu_qsbr_dq_reclaim(g_handle, &freed, &pending, &available); 2310567bb951SAbdullah Ömer Yamaç 2311567bb951SAbdullah Ömer Yamaç rte_hash_free(g_handle); 2312567bb951SAbdullah Ömer Yamaç rte_free(g_qsv); 2313567bb951SAbdullah Ömer Yamaç 2314567bb951SAbdullah Ömer Yamaç if (hash_size != (total_entries / 2 + 1) || freed != (total_entries / 2)) { 2315567bb951SAbdullah Ömer Yamaç printf("Failed to reclaim defer queue\n"); 2316567bb951SAbdullah Ömer Yamaç return -1; 2317567bb951SAbdullah Ömer Yamaç } 2318567bb951SAbdullah Ömer Yamaç 2319567bb951SAbdullah Ömer Yamaç return 0; 2320567bb951SAbdullah Ömer Yamaç } 2321567bb951SAbdullah Ömer Yamaç 2322567bb951SAbdullah Ömer Yamaç /* 2323a9de470cSBruce Richardson * Do all unit and performance tests. 2324a9de470cSBruce Richardson */ 2325a9de470cSBruce Richardson static int 2326a9de470cSBruce Richardson test_hash(void) 2327a9de470cSBruce Richardson { 2328e30ef3a3SVladimir Medvedkin RTE_BUILD_BUG_ON(sizeof(struct flow_key) % sizeof(uint32_t) != 0); 2329e30ef3a3SVladimir Medvedkin 2330a9de470cSBruce Richardson if (test_add_delete() < 0) 2331a9de470cSBruce Richardson return -1; 2332a9de470cSBruce Richardson if (test_hash_add_delete_jhash2() < 0) 2333a9de470cSBruce Richardson return -1; 2334a9de470cSBruce Richardson if (test_hash_add_delete_2_jhash2() < 0) 2335a9de470cSBruce Richardson return -1; 2336a9de470cSBruce Richardson if (test_hash_add_delete_jhash_1word() < 0) 2337a9de470cSBruce Richardson return -1; 2338a9de470cSBruce Richardson if (test_hash_add_delete_jhash_2word() < 0) 2339a9de470cSBruce Richardson return -1; 2340a9de470cSBruce Richardson if (test_hash_add_delete_jhash_3word() < 0) 2341a9de470cSBruce Richardson return -1; 2342a9de470cSBruce Richardson if (test_hash_get_key_with_position() < 0) 2343a9de470cSBruce Richardson return -1; 2344a9de470cSBruce Richardson if (test_hash_find_existing() < 0) 2345a9de470cSBruce Richardson return -1; 2346a9de470cSBruce Richardson if (test_add_update_delete() < 0) 2347a9de470cSBruce Richardson return -1; 2348a9de470cSBruce Richardson if (test_add_update_delete_free() < 0) 2349a9de470cSBruce Richardson return -1; 2350a55f182bSDharmik Thakkar if (test_add_delete_free_lf() < 0) 2351a55f182bSDharmik Thakkar return -1; 2352a9de470cSBruce Richardson if (test_five_keys() < 0) 2353a9de470cSBruce Richardson return -1; 2354a9de470cSBruce Richardson if (test_full_bucket() < 0) 2355a9de470cSBruce Richardson return -1; 2356a9de470cSBruce Richardson if (test_extendable_bucket() < 0) 2357a9de470cSBruce Richardson return -1; 2358a9de470cSBruce Richardson 2359a9de470cSBruce Richardson if (test_fbk_hash_find_existing() < 0) 2360a9de470cSBruce Richardson return -1; 2361a9de470cSBruce Richardson if (fbk_hash_unit_test() < 0) 2362a9de470cSBruce Richardson return -1; 2363a9de470cSBruce Richardson if (test_hash_creation_with_bad_parameters() < 0) 2364a9de470cSBruce Richardson return -1; 2365a9de470cSBruce Richardson if (test_hash_creation_with_good_parameters() < 0) 2366a9de470cSBruce Richardson return -1; 2367a9de470cSBruce Richardson 2368a9de470cSBruce Richardson /* ext table disabled */ 2369a9de470cSBruce Richardson if (test_average_table_utilization(0) < 0) 2370a9de470cSBruce Richardson return -1; 2371a9de470cSBruce Richardson if (test_hash_iteration(0) < 0) 2372a9de470cSBruce Richardson return -1; 2373a9de470cSBruce Richardson 2374a9de470cSBruce Richardson /* ext table enabled */ 2375a9de470cSBruce Richardson if (test_average_table_utilization(1) < 0) 2376a9de470cSBruce Richardson return -1; 2377a9de470cSBruce Richardson if (test_hash_iteration(1) < 0) 2378a9de470cSBruce Richardson return -1; 2379a9de470cSBruce Richardson 2380a9de470cSBruce Richardson run_hash_func_tests(); 2381a9de470cSBruce Richardson 2382a9de470cSBruce Richardson if (test_crc32_hash_alg_equiv() < 0) 2383a9de470cSBruce Richardson return -1; 2384a9de470cSBruce Richardson 23859c7d8eedSDharmik Thakkar if (test_hash_rcu_qsbr_add() < 0) 23869c7d8eedSDharmik Thakkar return -1; 23879c7d8eedSDharmik Thakkar 23889c7d8eedSDharmik Thakkar if (test_hash_rcu_qsbr_dq_mode(0) < 0) 23899c7d8eedSDharmik Thakkar return -1; 23909c7d8eedSDharmik Thakkar 23919c7d8eedSDharmik Thakkar if (test_hash_rcu_qsbr_dq_mode(1) < 0) 23929c7d8eedSDharmik Thakkar return -1; 23939c7d8eedSDharmik Thakkar 23949c7d8eedSDharmik Thakkar if (test_hash_rcu_qsbr_sync_mode(0) < 0) 23959c7d8eedSDharmik Thakkar return -1; 23969c7d8eedSDharmik Thakkar 23979c7d8eedSDharmik Thakkar if (test_hash_rcu_qsbr_sync_mode(1) < 0) 23989c7d8eedSDharmik Thakkar return -1; 23999c7d8eedSDharmik Thakkar 2400567bb951SAbdullah Ömer Yamaç if (test_hash_rcu_qsbr_dq_reclaim() < 0) 2401567bb951SAbdullah Ömer Yamaç return -1; 2402567bb951SAbdullah Ömer Yamaç 2403a9de470cSBruce Richardson return 0; 2404a9de470cSBruce Richardson } 2405a9de470cSBruce Richardson 2406e0a8442cSBruce Richardson REGISTER_FAST_TEST(hash_autotest, true, true, test_hash); 2407