10c6bd470Sfengbojiang /* SPDX-License-Identifier: BSD-3-Clause
20c6bd470Sfengbojiang  * Copyright(c) 2018 Arm Limited
30c6bd470Sfengbojiang  */
40c6bd470Sfengbojiang 
50c6bd470Sfengbojiang #include <inttypes.h>
60c6bd470Sfengbojiang #include <locale.h>
70c6bd470Sfengbojiang 
80c6bd470Sfengbojiang #include <rte_cycles.h>
90c6bd470Sfengbojiang #include <rte_hash.h>
100c6bd470Sfengbojiang #include <rte_hash_crc.h>
110c6bd470Sfengbojiang #include <rte_jhash.h>
120c6bd470Sfengbojiang #include <rte_launch.h>
130c6bd470Sfengbojiang #include <rte_malloc.h>
140c6bd470Sfengbojiang #include <rte_random.h>
150c6bd470Sfengbojiang #include <rte_spinlock.h>
160c6bd470Sfengbojiang 
170c6bd470Sfengbojiang #include "test.h"
180c6bd470Sfengbojiang 
190c6bd470Sfengbojiang #ifndef RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF
200c6bd470Sfengbojiang #define RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF 0
210c6bd470Sfengbojiang #endif
220c6bd470Sfengbojiang 
230c6bd470Sfengbojiang #define BULK_LOOKUP_SIZE 32
240c6bd470Sfengbojiang 
250c6bd470Sfengbojiang #define RUN_WITH_HTM_DISABLED 0
260c6bd470Sfengbojiang 
270c6bd470Sfengbojiang #if (RUN_WITH_HTM_DISABLED)
280c6bd470Sfengbojiang 
290c6bd470Sfengbojiang #define TOTAL_ENTRY (5*1024)
300c6bd470Sfengbojiang #define TOTAL_INSERT (5*1024)
310c6bd470Sfengbojiang 
320c6bd470Sfengbojiang #else
330c6bd470Sfengbojiang 
340c6bd470Sfengbojiang #define TOTAL_ENTRY (4*1024*1024)
350c6bd470Sfengbojiang #define TOTAL_INSERT (4*1024*1024)
360c6bd470Sfengbojiang 
370c6bd470Sfengbojiang #endif
380c6bd470Sfengbojiang 
390c6bd470Sfengbojiang #define READ_FAIL 1
400c6bd470Sfengbojiang #define READ_PASS_NO_KEY_SHIFTS 2
410c6bd470Sfengbojiang #define READ_PASS_SHIFT_PATH 4
420c6bd470Sfengbojiang #define READ_PASS_NON_SHIFT_PATH 8
430c6bd470Sfengbojiang #define BULK_LOOKUP 16
440c6bd470Sfengbojiang #define READ_PASS_KEY_SHIFTS_EXTBKT 32
450c6bd470Sfengbojiang 
460c6bd470Sfengbojiang #define WRITE_NO_KEY_SHIFT 0
470c6bd470Sfengbojiang #define WRITE_KEY_SHIFT 1
480c6bd470Sfengbojiang #define WRITE_EXT_BKT 2
490c6bd470Sfengbojiang 
500c6bd470Sfengbojiang #define NUM_TEST 3
51*2d9fd380Sjfb8856606 
52*2d9fd380Sjfb8856606 #define QSBR_REPORTING_INTERVAL 1024
53*2d9fd380Sjfb8856606 
540c6bd470Sfengbojiang static unsigned int rwc_core_cnt[NUM_TEST] = {1, 2, 4};
550c6bd470Sfengbojiang 
560c6bd470Sfengbojiang struct rwc_perf {
570c6bd470Sfengbojiang 	uint32_t w_no_ks_r_hit[2][NUM_TEST];
580c6bd470Sfengbojiang 	uint32_t w_no_ks_r_miss[2][NUM_TEST];
590c6bd470Sfengbojiang 	uint32_t w_ks_r_hit_nsp[2][NUM_TEST];
600c6bd470Sfengbojiang 	uint32_t w_ks_r_hit_sp[2][NUM_TEST];
610c6bd470Sfengbojiang 	uint32_t w_ks_r_miss[2][NUM_TEST];
620c6bd470Sfengbojiang 	uint32_t multi_rw[NUM_TEST - 1][2][NUM_TEST];
630c6bd470Sfengbojiang 	uint32_t w_ks_r_hit_extbkt[2][NUM_TEST];
64*2d9fd380Sjfb8856606 	uint32_t writer_add_del[NUM_TEST];
650c6bd470Sfengbojiang };
660c6bd470Sfengbojiang 
670c6bd470Sfengbojiang static struct rwc_perf rwc_lf_results, rwc_non_lf_results;
680c6bd470Sfengbojiang 
690c6bd470Sfengbojiang static struct {
700c6bd470Sfengbojiang 	uint32_t *keys;
710c6bd470Sfengbojiang 	uint32_t *keys_no_ks;
720c6bd470Sfengbojiang 	uint32_t *keys_ks;
730c6bd470Sfengbojiang 	uint32_t *keys_absent;
740c6bd470Sfengbojiang 	uint32_t *keys_shift_path;
750c6bd470Sfengbojiang 	uint32_t *keys_non_shift_path;
760c6bd470Sfengbojiang 	uint32_t *keys_ext_bkt;
770c6bd470Sfengbojiang 	uint32_t *keys_ks_extbkt;
780c6bd470Sfengbojiang 	uint32_t count_keys_no_ks;
790c6bd470Sfengbojiang 	uint32_t count_keys_ks;
800c6bd470Sfengbojiang 	uint32_t count_keys_absent;
810c6bd470Sfengbojiang 	uint32_t count_keys_shift_path;
820c6bd470Sfengbojiang 	uint32_t count_keys_non_shift_path;
830c6bd470Sfengbojiang 	uint32_t count_keys_extbkt;
840c6bd470Sfengbojiang 	uint32_t count_keys_ks_extbkt;
850c6bd470Sfengbojiang 	uint32_t single_insert;
860c6bd470Sfengbojiang 	struct rte_hash *h;
870c6bd470Sfengbojiang } tbl_rwc_test_param;
880c6bd470Sfengbojiang 
89*2d9fd380Sjfb8856606 static uint64_t gread_cycles;
90*2d9fd380Sjfb8856606 static uint64_t greads;
91*2d9fd380Sjfb8856606 static uint64_t gwrite_cycles;
92*2d9fd380Sjfb8856606 static uint64_t gwrites;
930c6bd470Sfengbojiang 
940c6bd470Sfengbojiang static volatile uint8_t writer_done;
950c6bd470Sfengbojiang 
960c6bd470Sfengbojiang static uint16_t enabled_core_ids[RTE_MAX_LCORE];
970c6bd470Sfengbojiang 
980c6bd470Sfengbojiang static uint8_t *scanned_bkts;
990c6bd470Sfengbojiang 
1000c6bd470Sfengbojiang static inline uint16_t
get_short_sig(const hash_sig_t hash)1010c6bd470Sfengbojiang get_short_sig(const hash_sig_t hash)
1020c6bd470Sfengbojiang {
1030c6bd470Sfengbojiang 	return hash >> 16;
1040c6bd470Sfengbojiang }
1050c6bd470Sfengbojiang 
1060c6bd470Sfengbojiang static inline uint32_t
get_prim_bucket_index(__rte_unused const struct rte_hash * h,const hash_sig_t hash)107*2d9fd380Sjfb8856606 get_prim_bucket_index(__rte_unused const struct rte_hash *h,
1080c6bd470Sfengbojiang 		      const hash_sig_t hash)
1090c6bd470Sfengbojiang {
1100c6bd470Sfengbojiang 	uint32_t num_buckets;
1110c6bd470Sfengbojiang 	uint32_t bucket_bitmask;
1120c6bd470Sfengbojiang 	num_buckets  = rte_align32pow2(TOTAL_ENTRY) / 8;
1130c6bd470Sfengbojiang 	bucket_bitmask = num_buckets - 1;
1140c6bd470Sfengbojiang 	return hash & bucket_bitmask;
1150c6bd470Sfengbojiang }
1160c6bd470Sfengbojiang 
1170c6bd470Sfengbojiang static inline uint32_t
get_alt_bucket_index(__rte_unused const struct rte_hash * h,uint32_t cur_bkt_idx,uint16_t sig)118*2d9fd380Sjfb8856606 get_alt_bucket_index(__rte_unused const struct rte_hash *h,
1190c6bd470Sfengbojiang 			uint32_t cur_bkt_idx, uint16_t sig)
1200c6bd470Sfengbojiang {
1210c6bd470Sfengbojiang 	uint32_t num_buckets;
1220c6bd470Sfengbojiang 	uint32_t bucket_bitmask;
1230c6bd470Sfengbojiang 	num_buckets  = rte_align32pow2(TOTAL_ENTRY) / 8;
1240c6bd470Sfengbojiang 	bucket_bitmask = num_buckets - 1;
1250c6bd470Sfengbojiang 	return (cur_bkt_idx ^ sig) & bucket_bitmask;
1260c6bd470Sfengbojiang }
1270c6bd470Sfengbojiang 
1280c6bd470Sfengbojiang 
1290c6bd470Sfengbojiang static inline int
get_enabled_cores_list(void)1300c6bd470Sfengbojiang get_enabled_cores_list(void)
1310c6bd470Sfengbojiang {
1320c6bd470Sfengbojiang 	uint32_t i = 0;
1330c6bd470Sfengbojiang 	uint16_t core_id;
1340c6bd470Sfengbojiang 	uint32_t max_cores = rte_lcore_count();
1350c6bd470Sfengbojiang 	RTE_LCORE_FOREACH(core_id) {
1360c6bd470Sfengbojiang 		enabled_core_ids[i] = core_id;
1370c6bd470Sfengbojiang 		i++;
1380c6bd470Sfengbojiang 	}
1390c6bd470Sfengbojiang 
1400c6bd470Sfengbojiang 	if (i != max_cores) {
1410c6bd470Sfengbojiang 		printf("Number of enabled cores in list is different from "
1420c6bd470Sfengbojiang 			"number given by rte_lcore_count()\n");
1430c6bd470Sfengbojiang 		return -1;
1440c6bd470Sfengbojiang 	}
1450c6bd470Sfengbojiang 	return 0;
1460c6bd470Sfengbojiang }
1470c6bd470Sfengbojiang 
1480c6bd470Sfengbojiang static int
init_params(int rwc_lf,int use_jhash,int htm,int ext_bkt)1490c6bd470Sfengbojiang init_params(int rwc_lf, int use_jhash, int htm, int ext_bkt)
1500c6bd470Sfengbojiang {
1510c6bd470Sfengbojiang 	struct rte_hash *handle;
1520c6bd470Sfengbojiang 
1530c6bd470Sfengbojiang 	struct rte_hash_parameters hash_params = {
1540c6bd470Sfengbojiang 		.entries = TOTAL_ENTRY,
1550c6bd470Sfengbojiang 		.key_len = sizeof(uint32_t),
1560c6bd470Sfengbojiang 		.hash_func_init_val = 0,
1570c6bd470Sfengbojiang 		.socket_id = rte_socket_id(),
1580c6bd470Sfengbojiang 	};
1590c6bd470Sfengbojiang 
1600c6bd470Sfengbojiang 	if (use_jhash)
1610c6bd470Sfengbojiang 		hash_params.hash_func = rte_jhash;
1620c6bd470Sfengbojiang 	else
1630c6bd470Sfengbojiang 		hash_params.hash_func = rte_hash_crc;
1640c6bd470Sfengbojiang 
1650c6bd470Sfengbojiang 	if (rwc_lf)
1660c6bd470Sfengbojiang 		hash_params.extra_flag =
1670c6bd470Sfengbojiang 			RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF |
1680c6bd470Sfengbojiang 			RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
1690c6bd470Sfengbojiang 	else if (htm)
1700c6bd470Sfengbojiang 		hash_params.extra_flag =
1710c6bd470Sfengbojiang 			RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT |
1720c6bd470Sfengbojiang 			RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY |
1730c6bd470Sfengbojiang 			RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
1740c6bd470Sfengbojiang 	else
1750c6bd470Sfengbojiang 		hash_params.extra_flag =
1760c6bd470Sfengbojiang 			RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY |
1770c6bd470Sfengbojiang 			RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
1780c6bd470Sfengbojiang 
1790c6bd470Sfengbojiang 	if (ext_bkt)
1800c6bd470Sfengbojiang 		hash_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1810c6bd470Sfengbojiang 
1820c6bd470Sfengbojiang 	hash_params.name = "tests";
1830c6bd470Sfengbojiang 
1840c6bd470Sfengbojiang 	handle = rte_hash_create(&hash_params);
1850c6bd470Sfengbojiang 	if (handle == NULL) {
1860c6bd470Sfengbojiang 		printf("hash creation failed");
1870c6bd470Sfengbojiang 		return -1;
1880c6bd470Sfengbojiang 	}
1890c6bd470Sfengbojiang 
1900c6bd470Sfengbojiang 	tbl_rwc_test_param.h = handle;
1910c6bd470Sfengbojiang 	return 0;
1920c6bd470Sfengbojiang }
1930c6bd470Sfengbojiang 
1940c6bd470Sfengbojiang static inline int
check_bucket(uint32_t bkt_idx,uint32_t key)1950c6bd470Sfengbojiang check_bucket(uint32_t bkt_idx, uint32_t key)
1960c6bd470Sfengbojiang {
1970c6bd470Sfengbojiang 	uint32_t iter;
1980c6bd470Sfengbojiang 	uint32_t prev_iter;
1990c6bd470Sfengbojiang 	uint32_t diff;
2000c6bd470Sfengbojiang 	uint32_t count = 0;
2010c6bd470Sfengbojiang 	const void *next_key;
2020c6bd470Sfengbojiang 	void *next_data;
2030c6bd470Sfengbojiang 
2040c6bd470Sfengbojiang 	/* Temporary bucket to hold the keys */
2050c6bd470Sfengbojiang 	uint32_t keys_in_bkt[8];
2060c6bd470Sfengbojiang 
2070c6bd470Sfengbojiang 	iter = bkt_idx * 8;
2080c6bd470Sfengbojiang 	prev_iter = iter;
2090c6bd470Sfengbojiang 	while (rte_hash_iterate(tbl_rwc_test_param.h,
2100c6bd470Sfengbojiang 			&next_key, &next_data, &iter) >= 0) {
2110c6bd470Sfengbojiang 
2120c6bd470Sfengbojiang 		/* Check for duplicate entries */
2130c6bd470Sfengbojiang 		if (*(const uint32_t *)next_key == key)
2140c6bd470Sfengbojiang 			return 1;
2150c6bd470Sfengbojiang 
2160c6bd470Sfengbojiang 		/* Identify if there is any free entry in the bucket */
2170c6bd470Sfengbojiang 		diff = iter - prev_iter;
2180c6bd470Sfengbojiang 		if (diff > 1)
2190c6bd470Sfengbojiang 			break;
2200c6bd470Sfengbojiang 
2210c6bd470Sfengbojiang 		prev_iter = iter;
2220c6bd470Sfengbojiang 		keys_in_bkt[count] = *(const uint32_t *)next_key;
2230c6bd470Sfengbojiang 		count++;
2240c6bd470Sfengbojiang 
2250c6bd470Sfengbojiang 		/* All entries in the bucket are occupied */
2260c6bd470Sfengbojiang 		if (count == 8) {
2270c6bd470Sfengbojiang 
2280c6bd470Sfengbojiang 			/*
2290c6bd470Sfengbojiang 			 * Check if bucket was not scanned before, to avoid
2300c6bd470Sfengbojiang 			 * duplicate keys.
2310c6bd470Sfengbojiang 			 */
2320c6bd470Sfengbojiang 			if (scanned_bkts[bkt_idx] == 0) {
2330c6bd470Sfengbojiang 				/*
2340c6bd470Sfengbojiang 				 * Since this bucket (pointed to by bkt_idx) is
2350c6bd470Sfengbojiang 				 * full, it is likely that key(s) in this
2360c6bd470Sfengbojiang 				 * bucket will be on the shift path, when
2370c6bd470Sfengbojiang 				 * collision occurs. Thus, add it to
2380c6bd470Sfengbojiang 				 * keys_shift_path.
2390c6bd470Sfengbojiang 				 */
2400c6bd470Sfengbojiang 				memcpy(tbl_rwc_test_param.keys_shift_path +
2410c6bd470Sfengbojiang 					tbl_rwc_test_param.count_keys_shift_path
2420c6bd470Sfengbojiang 					, keys_in_bkt, 32);
2430c6bd470Sfengbojiang 				tbl_rwc_test_param.count_keys_shift_path += 8;
2440c6bd470Sfengbojiang 				scanned_bkts[bkt_idx] = 1;
2450c6bd470Sfengbojiang 			}
2460c6bd470Sfengbojiang 			return -1;
2470c6bd470Sfengbojiang 		}
2480c6bd470Sfengbojiang 	}
2490c6bd470Sfengbojiang 	return 0;
2500c6bd470Sfengbojiang }
2510c6bd470Sfengbojiang 
2520c6bd470Sfengbojiang static int
generate_keys(void)2530c6bd470Sfengbojiang generate_keys(void)
2540c6bd470Sfengbojiang {
2550c6bd470Sfengbojiang 	uint32_t *keys = NULL;
2560c6bd470Sfengbojiang 	uint32_t *keys_no_ks = NULL;
2570c6bd470Sfengbojiang 	uint32_t *keys_ks = NULL;
2580c6bd470Sfengbojiang 	uint32_t *keys_absent = NULL;
2590c6bd470Sfengbojiang 	uint32_t *keys_non_shift_path = NULL;
2600c6bd470Sfengbojiang 	uint32_t *keys_ext_bkt = NULL;
2610c6bd470Sfengbojiang 	uint32_t *keys_ks_extbkt = NULL;
2620c6bd470Sfengbojiang 	uint32_t *found = NULL;
2630c6bd470Sfengbojiang 	uint32_t count_keys_no_ks = 0;
2640c6bd470Sfengbojiang 	uint32_t count_keys_ks = 0;
2650c6bd470Sfengbojiang 	uint32_t count_keys_extbkt = 0;
2660c6bd470Sfengbojiang 	uint32_t i;
2670c6bd470Sfengbojiang 
2680c6bd470Sfengbojiang 	if (init_params(0, 0, 0, 0) != 0)
2690c6bd470Sfengbojiang 		return -1;
2700c6bd470Sfengbojiang 
2710c6bd470Sfengbojiang 	/*
2720c6bd470Sfengbojiang 	 * keys will consist of a) keys whose addition to the hash table
2730c6bd470Sfengbojiang 	 * will result in shifting of the existing keys to their alternate
2740c6bd470Sfengbojiang 	 * locations b) keys whose addition to the hash table will not result
2750c6bd470Sfengbojiang 	 * in shifting of the existing keys.
2760c6bd470Sfengbojiang 	 */
2770c6bd470Sfengbojiang 	keys = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
2780c6bd470Sfengbojiang 	if (keys == NULL) {
2790c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
2800c6bd470Sfengbojiang 		goto err;
2810c6bd470Sfengbojiang 	}
2820c6bd470Sfengbojiang 
2830c6bd470Sfengbojiang 	/*
2840c6bd470Sfengbojiang 	 * keys_no_ks (no key-shifts): Subset of 'keys' - consists of keys  that
2850c6bd470Sfengbojiang 	 * will NOT result in shifting of the existing keys to their alternate
2860c6bd470Sfengbojiang 	 * locations. Roughly around 900K keys.
2870c6bd470Sfengbojiang 	 */
2880c6bd470Sfengbojiang 	keys_no_ks = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
2890c6bd470Sfengbojiang 	if (keys_no_ks == NULL) {
2900c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
2910c6bd470Sfengbojiang 		goto err;
2920c6bd470Sfengbojiang 	}
2930c6bd470Sfengbojiang 
2940c6bd470Sfengbojiang 	/*
2950c6bd470Sfengbojiang 	 * keys_ks (key-shifts): Subset of 'keys' - consists of keys that will
2960c6bd470Sfengbojiang 	 * result in shifting of the existing keys to their alternate locations.
2970c6bd470Sfengbojiang 	 * Roughly around 146K keys. There might be repeating keys. More code is
2980c6bd470Sfengbojiang 	 * required to filter out these keys which will complicate the test case
2990c6bd470Sfengbojiang 	 */
3000c6bd470Sfengbojiang 	keys_ks = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
3010c6bd470Sfengbojiang 	if (keys_ks == NULL) {
3020c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
3030c6bd470Sfengbojiang 		goto err;
3040c6bd470Sfengbojiang 	}
3050c6bd470Sfengbojiang 
3060c6bd470Sfengbojiang 	/* Used to identify keys not inserted in the hash table */
3070c6bd470Sfengbojiang 	found = rte_zmalloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
3080c6bd470Sfengbojiang 	if (found == NULL) {
3090c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
3100c6bd470Sfengbojiang 		goto err;
3110c6bd470Sfengbojiang 	}
3120c6bd470Sfengbojiang 
3130c6bd470Sfengbojiang 	/*
3140c6bd470Sfengbojiang 	 * This consist of keys not inserted to the hash table.
3150c6bd470Sfengbojiang 	 * Used to test perf of lookup on keys that do not exist in the table.
3160c6bd470Sfengbojiang 	 */
3170c6bd470Sfengbojiang 	keys_absent = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
3180c6bd470Sfengbojiang 	if (keys_absent == NULL) {
3190c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
3200c6bd470Sfengbojiang 		goto err;
3210c6bd470Sfengbojiang 	}
3220c6bd470Sfengbojiang 
3230c6bd470Sfengbojiang 	/*
3240c6bd470Sfengbojiang 	 * This consist of keys which are likely to be on the shift
3250c6bd470Sfengbojiang 	 * path (i.e. being moved to alternate location), when collision occurs
3260c6bd470Sfengbojiang 	 * on addition of a key to an already full primary bucket.
3270c6bd470Sfengbojiang 	 * Used to test perf of lookup on keys that are on the shift path.
3280c6bd470Sfengbojiang 	 */
3290c6bd470Sfengbojiang 	tbl_rwc_test_param.keys_shift_path = rte_malloc(NULL, sizeof(uint32_t) *
3300c6bd470Sfengbojiang 							TOTAL_INSERT, 0);
3310c6bd470Sfengbojiang 	if (tbl_rwc_test_param.keys_shift_path == NULL) {
3320c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
3330c6bd470Sfengbojiang 		goto err;
3340c6bd470Sfengbojiang 	}
3350c6bd470Sfengbojiang 
3360c6bd470Sfengbojiang 	/*
3370c6bd470Sfengbojiang 	 * This consist of keys which are never on the shift
3380c6bd470Sfengbojiang 	 * path (i.e. being moved to alternate location), when collision occurs
3390c6bd470Sfengbojiang 	 * on addition of a key to an already full primary bucket.
3400c6bd470Sfengbojiang 	 * Used to test perf of lookup on keys that are not on the shift path.
3410c6bd470Sfengbojiang 	 */
3420c6bd470Sfengbojiang 	keys_non_shift_path = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT,
3430c6bd470Sfengbojiang 					 0);
3440c6bd470Sfengbojiang 	if (keys_non_shift_path == NULL) {
3450c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
3460c6bd470Sfengbojiang 		goto err;
3470c6bd470Sfengbojiang 	}
3480c6bd470Sfengbojiang 
3490c6bd470Sfengbojiang 	/*
3500c6bd470Sfengbojiang 	 * This consist of keys which will be stored in extended buckets
3510c6bd470Sfengbojiang 	 */
3520c6bd470Sfengbojiang 	keys_ext_bkt = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
3530c6bd470Sfengbojiang 	if (keys_ext_bkt == NULL) {
3540c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
3550c6bd470Sfengbojiang 		goto err;
3560c6bd470Sfengbojiang 	}
3570c6bd470Sfengbojiang 
3580c6bd470Sfengbojiang 	/*
3590c6bd470Sfengbojiang 	 * This consist of keys which when deleted causes shifting of keys
3600c6bd470Sfengbojiang 	 * in extended buckets to respective secondary buckets
3610c6bd470Sfengbojiang 	 */
3620c6bd470Sfengbojiang 	keys_ks_extbkt = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
3630c6bd470Sfengbojiang 	if (keys_ks_extbkt == NULL) {
3640c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
3650c6bd470Sfengbojiang 		goto err;
3660c6bd470Sfengbojiang 	}
3670c6bd470Sfengbojiang 
3680c6bd470Sfengbojiang 	hash_sig_t sig;
3690c6bd470Sfengbojiang 	uint32_t prim_bucket_idx;
3700c6bd470Sfengbojiang 	uint32_t sec_bucket_idx;
3710c6bd470Sfengbojiang 	uint16_t short_sig;
3720c6bd470Sfengbojiang 	uint32_t num_buckets;
3730c6bd470Sfengbojiang 	num_buckets  = rte_align32pow2(TOTAL_ENTRY) / 8;
3740c6bd470Sfengbojiang 	int ret;
3750c6bd470Sfengbojiang 
3760c6bd470Sfengbojiang 	/*
3770c6bd470Sfengbojiang 	 * Used to mark bkts in which at least one key was shifted to its
3780c6bd470Sfengbojiang 	 * alternate location
3790c6bd470Sfengbojiang 	 */
3800c6bd470Sfengbojiang 	scanned_bkts = rte_malloc(NULL, sizeof(uint8_t) * num_buckets, 0);
3810c6bd470Sfengbojiang 	if (scanned_bkts == NULL) {
3820c6bd470Sfengbojiang 		printf("RTE_MALLOC failed\n");
3830c6bd470Sfengbojiang 		goto err;
3840c6bd470Sfengbojiang 	}
3850c6bd470Sfengbojiang 
3860c6bd470Sfengbojiang 	tbl_rwc_test_param.keys = keys;
3870c6bd470Sfengbojiang 	tbl_rwc_test_param.keys_no_ks = keys_no_ks;
3880c6bd470Sfengbojiang 	tbl_rwc_test_param.keys_ks = keys_ks;
3890c6bd470Sfengbojiang 	tbl_rwc_test_param.keys_absent = keys_absent;
3900c6bd470Sfengbojiang 	tbl_rwc_test_param.keys_non_shift_path = keys_non_shift_path;
3910c6bd470Sfengbojiang 	tbl_rwc_test_param.keys_ext_bkt = keys_ext_bkt;
3920c6bd470Sfengbojiang 	tbl_rwc_test_param.keys_ks_extbkt = keys_ks_extbkt;
3930c6bd470Sfengbojiang 	/* Generate keys by adding previous two keys, neglect overflow */
3940c6bd470Sfengbojiang 	printf("Generating keys...\n");
3950c6bd470Sfengbojiang 	keys[0] = 0;
3960c6bd470Sfengbojiang 	keys[1] = 1;
3970c6bd470Sfengbojiang 	for (i = 2; i < TOTAL_INSERT; i++)
3980c6bd470Sfengbojiang 		keys[i] = keys[i-1] + keys[i-2];
3990c6bd470Sfengbojiang 
4000c6bd470Sfengbojiang 	/* Segregate keys into keys_no_ks and keys_ks */
4010c6bd470Sfengbojiang 	for (i = 0; i < TOTAL_INSERT; i++) {
4020c6bd470Sfengbojiang 		/* Check if primary bucket has space.*/
4030c6bd470Sfengbojiang 		sig = rte_hash_hash(tbl_rwc_test_param.h,
4040c6bd470Sfengbojiang 					tbl_rwc_test_param.keys+i);
4050c6bd470Sfengbojiang 		prim_bucket_idx = get_prim_bucket_index(tbl_rwc_test_param.h,
4060c6bd470Sfengbojiang 							sig);
4070c6bd470Sfengbojiang 		ret = check_bucket(prim_bucket_idx, keys[i]);
4080c6bd470Sfengbojiang 		if (ret < 0) {
4090c6bd470Sfengbojiang 			/*
4100c6bd470Sfengbojiang 			 * Primary bucket is full, this key will result in
4110c6bd470Sfengbojiang 			 * shifting of the keys to their alternate locations.
4120c6bd470Sfengbojiang 			 */
4130c6bd470Sfengbojiang 			keys_ks[count_keys_ks] = keys[i];
4140c6bd470Sfengbojiang 			count_keys_ks++;
4150c6bd470Sfengbojiang 		} else if (ret == 0) {
4160c6bd470Sfengbojiang 			/*
4170c6bd470Sfengbojiang 			 * Primary bucket has space, this key will not result in
4180c6bd470Sfengbojiang 			 * shifting of the keys. Hence, add key to the table.
4190c6bd470Sfengbojiang 			 */
4200c6bd470Sfengbojiang 			ret = rte_hash_add_key_data(tbl_rwc_test_param.h,
4210c6bd470Sfengbojiang 							keys+i,
4220c6bd470Sfengbojiang 							(void *)((uintptr_t)i));
4230c6bd470Sfengbojiang 			if (ret < 0) {
4240c6bd470Sfengbojiang 				printf("writer failed %"PRIu32"\n", i);
4250c6bd470Sfengbojiang 				break;
4260c6bd470Sfengbojiang 			}
4270c6bd470Sfengbojiang 			keys_no_ks[count_keys_no_ks] = keys[i];
4280c6bd470Sfengbojiang 			count_keys_no_ks++;
4290c6bd470Sfengbojiang 		}
4300c6bd470Sfengbojiang 	}
4310c6bd470Sfengbojiang 
4320c6bd470Sfengbojiang 	for (i = 0; i < count_keys_no_ks; i++) {
4330c6bd470Sfengbojiang 		/*
4340c6bd470Sfengbojiang 		 * Identify keys in keys_no_ks with value less than
4350c6bd470Sfengbojiang 		 * 4M (HTM enabled) OR 5K (HTM disabled)
4360c6bd470Sfengbojiang 		 */
4370c6bd470Sfengbojiang 		if (keys_no_ks[i] < TOTAL_INSERT)
4380c6bd470Sfengbojiang 			found[keys_no_ks[i]]++;
4390c6bd470Sfengbojiang 	}
4400c6bd470Sfengbojiang 
4410c6bd470Sfengbojiang 	for (i = 0; i < count_keys_ks; i++) {
4420c6bd470Sfengbojiang 		/*
4430c6bd470Sfengbojiang 		 * Identify keys in keys_ks with value less than
4440c6bd470Sfengbojiang 		 * 4M (HTM enabled) OR 5K (HTM disabled)
4450c6bd470Sfengbojiang 		 */
4460c6bd470Sfengbojiang 		if (keys_ks[i] < TOTAL_INSERT)
4470c6bd470Sfengbojiang 			found[keys_ks[i]]++;
4480c6bd470Sfengbojiang 	}
4490c6bd470Sfengbojiang 
4500c6bd470Sfengbojiang 	uint32_t count_keys_absent = 0;
4510c6bd470Sfengbojiang 	for (i = 0; i < TOTAL_INSERT; i++) {
4520c6bd470Sfengbojiang 		/*
4530c6bd470Sfengbojiang 		 * Identify missing keys between 0 and
4540c6bd470Sfengbojiang 		 * 4M (HTM enabled) OR 5K (HTM disabled)
4550c6bd470Sfengbojiang 		 */
4560c6bd470Sfengbojiang 		if (found[i] == 0)
4570c6bd470Sfengbojiang 			keys_absent[count_keys_absent++] = i;
4580c6bd470Sfengbojiang 	}
4590c6bd470Sfengbojiang 
4600c6bd470Sfengbojiang 	/* Find keys that will not be on the shift path */
4610c6bd470Sfengbojiang 	uint32_t iter;
4620c6bd470Sfengbojiang 	const void *next_key;
4630c6bd470Sfengbojiang 	void *next_data;
4640c6bd470Sfengbojiang 	uint32_t count = 0;
4650c6bd470Sfengbojiang 	for (i = 0; i < num_buckets; i++) {
4660c6bd470Sfengbojiang 		/* Check bucket for no keys shifted to alternate locations */
4670c6bd470Sfengbojiang 		if (scanned_bkts[i] == 0) {
4680c6bd470Sfengbojiang 			iter = i * 8;
4690c6bd470Sfengbojiang 			while (rte_hash_iterate(tbl_rwc_test_param.h,
4700c6bd470Sfengbojiang 				&next_key, &next_data, &iter) >= 0) {
4710c6bd470Sfengbojiang 
4720c6bd470Sfengbojiang 				/* Check if key belongs to the current bucket */
4730c6bd470Sfengbojiang 				if (i >= (iter-1)/8)
4740c6bd470Sfengbojiang 					keys_non_shift_path[count++]
4750c6bd470Sfengbojiang 						= *(const uint32_t *)next_key;
4760c6bd470Sfengbojiang 				else
4770c6bd470Sfengbojiang 					break;
4780c6bd470Sfengbojiang 			}
4790c6bd470Sfengbojiang 		}
4800c6bd470Sfengbojiang 	}
4810c6bd470Sfengbojiang 
4820c6bd470Sfengbojiang 	tbl_rwc_test_param.count_keys_no_ks = count_keys_no_ks;
4830c6bd470Sfengbojiang 	tbl_rwc_test_param.count_keys_ks = count_keys_ks;
4840c6bd470Sfengbojiang 	tbl_rwc_test_param.count_keys_absent = count_keys_absent;
4850c6bd470Sfengbojiang 	tbl_rwc_test_param.count_keys_non_shift_path = count;
4860c6bd470Sfengbojiang 
4870c6bd470Sfengbojiang 	memset(scanned_bkts, 0, num_buckets);
4880c6bd470Sfengbojiang 	count = 0;
4890c6bd470Sfengbojiang 	/* Find keys that will be in extended buckets */
4900c6bd470Sfengbojiang 	for (i = 0; i < count_keys_ks; i++) {
4910c6bd470Sfengbojiang 		ret = rte_hash_add_key(tbl_rwc_test_param.h, keys_ks + i);
4920c6bd470Sfengbojiang 		if (ret < 0) {
4930c6bd470Sfengbojiang 			/* Key will be added to ext bkt */
4940c6bd470Sfengbojiang 			keys_ext_bkt[count_keys_extbkt++] = keys_ks[i];
4950c6bd470Sfengbojiang 			/* Sec bkt to be added to keys_ks_extbkt */
4960c6bd470Sfengbojiang 			sig = rte_hash_hash(tbl_rwc_test_param.h,
4970c6bd470Sfengbojiang 					tbl_rwc_test_param.keys_ks + i);
4980c6bd470Sfengbojiang 			prim_bucket_idx = get_prim_bucket_index(
4990c6bd470Sfengbojiang 						tbl_rwc_test_param.h, sig);
5000c6bd470Sfengbojiang 			short_sig = get_short_sig(sig);
5010c6bd470Sfengbojiang 			sec_bucket_idx = get_alt_bucket_index(
5020c6bd470Sfengbojiang 						tbl_rwc_test_param.h,
5030c6bd470Sfengbojiang 						prim_bucket_idx, short_sig);
5040c6bd470Sfengbojiang 			if (scanned_bkts[sec_bucket_idx] == 0)
5050c6bd470Sfengbojiang 				scanned_bkts[sec_bucket_idx] = 1;
5060c6bd470Sfengbojiang 		}
5070c6bd470Sfengbojiang 	}
5080c6bd470Sfengbojiang 
5090c6bd470Sfengbojiang 	/* Find keys that will shift keys in ext bucket*/
5100c6bd470Sfengbojiang 	for (i = 0; i < num_buckets; i++) {
5110c6bd470Sfengbojiang 		if (scanned_bkts[i] == 1) {
5120c6bd470Sfengbojiang 			iter = i * 8;
5130c6bd470Sfengbojiang 			while (rte_hash_iterate(tbl_rwc_test_param.h,
5140c6bd470Sfengbojiang 				&next_key, &next_data, &iter) >= 0) {
5150c6bd470Sfengbojiang 				/* Check if key belongs to the current bucket */
5160c6bd470Sfengbojiang 				if (i >= (iter-1)/8)
5170c6bd470Sfengbojiang 					keys_ks_extbkt[count++]
5180c6bd470Sfengbojiang 						= *(const uint32_t *)next_key;
5190c6bd470Sfengbojiang 				else
5200c6bd470Sfengbojiang 					break;
5210c6bd470Sfengbojiang 			}
5220c6bd470Sfengbojiang 		}
5230c6bd470Sfengbojiang 	}
5240c6bd470Sfengbojiang 
5250c6bd470Sfengbojiang 	tbl_rwc_test_param.count_keys_ks_extbkt = count;
5260c6bd470Sfengbojiang 	tbl_rwc_test_param.count_keys_extbkt = count_keys_extbkt;
5270c6bd470Sfengbojiang 
5280c6bd470Sfengbojiang 	printf("\nCount of keys NOT causing shifting of existing keys to "
5290c6bd470Sfengbojiang 	"alternate location: %d\n", tbl_rwc_test_param.count_keys_no_ks);
5300c6bd470Sfengbojiang 	printf("\nCount of keys causing shifting of existing keys to alternate "
5310c6bd470Sfengbojiang 		"locations: %d\n\n", tbl_rwc_test_param.count_keys_ks);
5320c6bd470Sfengbojiang 	printf("Count of absent keys that will never be added to the hash "
5330c6bd470Sfengbojiang 		"table: %d\n\n", tbl_rwc_test_param.count_keys_absent);
5340c6bd470Sfengbojiang 	printf("Count of keys likely to be on the shift path: %d\n\n",
5350c6bd470Sfengbojiang 	       tbl_rwc_test_param.count_keys_shift_path);
5360c6bd470Sfengbojiang 	printf("Count of keys not likely to be on the shift path: %d\n\n",
5370c6bd470Sfengbojiang 	       tbl_rwc_test_param.count_keys_non_shift_path);
5380c6bd470Sfengbojiang 	printf("Count of keys in extended buckets: %d\n\n",
5390c6bd470Sfengbojiang 	       tbl_rwc_test_param.count_keys_extbkt);
5400c6bd470Sfengbojiang 	printf("Count of keys shifting keys in ext buckets: %d\n\n",
5410c6bd470Sfengbojiang 	       tbl_rwc_test_param.count_keys_ks_extbkt);
5420c6bd470Sfengbojiang 
5430c6bd470Sfengbojiang 	rte_free(found);
5440c6bd470Sfengbojiang 	rte_free(scanned_bkts);
5450c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
5460c6bd470Sfengbojiang 	return 0;
5470c6bd470Sfengbojiang 
5480c6bd470Sfengbojiang err:
5490c6bd470Sfengbojiang 	rte_free(keys);
5500c6bd470Sfengbojiang 	rte_free(keys_no_ks);
5510c6bd470Sfengbojiang 	rte_free(keys_ks);
5520c6bd470Sfengbojiang 	rte_free(keys_absent);
5530c6bd470Sfengbojiang 	rte_free(found);
5540c6bd470Sfengbojiang 	rte_free(tbl_rwc_test_param.keys_shift_path);
5550c6bd470Sfengbojiang 	rte_free(keys_non_shift_path);
5560c6bd470Sfengbojiang 	rte_free(keys_ext_bkt);
5570c6bd470Sfengbojiang 	rte_free(keys_ks_extbkt);
5580c6bd470Sfengbojiang 	rte_free(scanned_bkts);
5590c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
5600c6bd470Sfengbojiang 	return -1;
5610c6bd470Sfengbojiang }
5620c6bd470Sfengbojiang 
5630c6bd470Sfengbojiang static int
test_rwc_reader(__rte_unused void * arg)564*2d9fd380Sjfb8856606 test_rwc_reader(__rte_unused void *arg)
5650c6bd470Sfengbojiang {
5660c6bd470Sfengbojiang 	uint32_t i, j;
5670c6bd470Sfengbojiang 	int ret;
5680c6bd470Sfengbojiang 	uint64_t begin, cycles;
5690c6bd470Sfengbojiang 	uint32_t loop_cnt = 0;
5700c6bd470Sfengbojiang 	uint8_t read_type = (uint8_t)((uintptr_t)arg);
5710c6bd470Sfengbojiang 	uint32_t read_cnt;
5720c6bd470Sfengbojiang 	uint32_t *keys;
5730c6bd470Sfengbojiang 	uint32_t extra_keys;
5740c6bd470Sfengbojiang 	int32_t pos[BULK_LOOKUP_SIZE];
5750c6bd470Sfengbojiang 	void *temp_a[BULK_LOOKUP_SIZE];
5760c6bd470Sfengbojiang 
5770c6bd470Sfengbojiang 	if (read_type & READ_FAIL) {
5780c6bd470Sfengbojiang 		keys = tbl_rwc_test_param.keys_absent;
5790c6bd470Sfengbojiang 		read_cnt = tbl_rwc_test_param.count_keys_absent;
5800c6bd470Sfengbojiang 	} else if (read_type & READ_PASS_NO_KEY_SHIFTS) {
5810c6bd470Sfengbojiang 		keys = tbl_rwc_test_param.keys_no_ks;
5820c6bd470Sfengbojiang 		read_cnt = tbl_rwc_test_param.count_keys_no_ks;
5830c6bd470Sfengbojiang 	} else if (read_type & READ_PASS_SHIFT_PATH) {
5840c6bd470Sfengbojiang 		keys = tbl_rwc_test_param.keys_shift_path;
5850c6bd470Sfengbojiang 		read_cnt = tbl_rwc_test_param.count_keys_shift_path;
5860c6bd470Sfengbojiang 	} else if (read_type & READ_PASS_KEY_SHIFTS_EXTBKT) {
5870c6bd470Sfengbojiang 		keys = tbl_rwc_test_param.keys_ext_bkt;
5880c6bd470Sfengbojiang 		read_cnt = tbl_rwc_test_param.count_keys_extbkt;
5890c6bd470Sfengbojiang 	} else {
5900c6bd470Sfengbojiang 		keys = tbl_rwc_test_param.keys_non_shift_path;
5910c6bd470Sfengbojiang 		read_cnt = tbl_rwc_test_param.count_keys_non_shift_path;
5920c6bd470Sfengbojiang 	}
5930c6bd470Sfengbojiang 
5940c6bd470Sfengbojiang 	extra_keys = read_cnt & (BULK_LOOKUP_SIZE - 1);
5950c6bd470Sfengbojiang 
5960c6bd470Sfengbojiang 	begin = rte_rdtsc_precise();
5970c6bd470Sfengbojiang 	do {
5980c6bd470Sfengbojiang 		if (read_type & BULK_LOOKUP) {
5990c6bd470Sfengbojiang 			for (i = 0; i < (read_cnt - extra_keys);
6000c6bd470Sfengbojiang 			     i += BULK_LOOKUP_SIZE) {
6010c6bd470Sfengbojiang 				/* Array of  pointer to the list of keys */
6020c6bd470Sfengbojiang 				for (j = 0; j < BULK_LOOKUP_SIZE; j++)
6030c6bd470Sfengbojiang 					temp_a[j] = keys + i + j;
6040c6bd470Sfengbojiang 				rte_hash_lookup_bulk(tbl_rwc_test_param.h,
6050c6bd470Sfengbojiang 						   (const void **)
6060c6bd470Sfengbojiang 						   ((uintptr_t)temp_a),
6070c6bd470Sfengbojiang 						   BULK_LOOKUP_SIZE, pos);
6080c6bd470Sfengbojiang 				/* Validate lookup result */
6090c6bd470Sfengbojiang 				for (j = 0; j < BULK_LOOKUP_SIZE; j++)
6100c6bd470Sfengbojiang 					if ((read_type & READ_FAIL &&
6110c6bd470Sfengbojiang 					     pos[j] != -ENOENT) ||
6120c6bd470Sfengbojiang 					    (!(read_type & READ_FAIL) &&
6130c6bd470Sfengbojiang 					     pos[j] == -ENOENT)) {
6140c6bd470Sfengbojiang 						printf("lookup failed!"
6150c6bd470Sfengbojiang 						       "%"PRIu32"\n",
6160c6bd470Sfengbojiang 						       keys[i + j]);
6170c6bd470Sfengbojiang 						return -1;
6180c6bd470Sfengbojiang 					}
6190c6bd470Sfengbojiang 			}
6200c6bd470Sfengbojiang 			for (j = 0; j < extra_keys; j++)
6210c6bd470Sfengbojiang 				temp_a[j] = keys + i + j;
6220c6bd470Sfengbojiang 
6230c6bd470Sfengbojiang 			rte_hash_lookup_bulk(tbl_rwc_test_param.h,
6240c6bd470Sfengbojiang 					   (const void **)
6250c6bd470Sfengbojiang 					   ((uintptr_t)temp_a),
6260c6bd470Sfengbojiang 					   extra_keys, pos);
6270c6bd470Sfengbojiang 			for (j = 0; j < extra_keys; j++)
6280c6bd470Sfengbojiang 				if ((read_type & READ_FAIL &&
6290c6bd470Sfengbojiang 				     pos[j] != -ENOENT) ||
6300c6bd470Sfengbojiang 				    (!(read_type & READ_FAIL) &&
6310c6bd470Sfengbojiang 				     pos[j] == -ENOENT)) {
6320c6bd470Sfengbojiang 					printf("lookup failed! %"PRIu32"\n",
6330c6bd470Sfengbojiang 					       keys[i + j]);
6340c6bd470Sfengbojiang 					return -1;
6350c6bd470Sfengbojiang 				}
6360c6bd470Sfengbojiang 		} else {
6370c6bd470Sfengbojiang 			for (i = 0; i < read_cnt; i++) {
6380c6bd470Sfengbojiang 				ret = rte_hash_lookup
6390c6bd470Sfengbojiang 					(tbl_rwc_test_param.h, keys + i);
6400c6bd470Sfengbojiang 				if (((read_type & READ_FAIL) &&
6410c6bd470Sfengbojiang 				     (ret != -ENOENT)) ||
6420c6bd470Sfengbojiang 				    (!(read_type & READ_FAIL) &&
6430c6bd470Sfengbojiang 					ret == -ENOENT)) {
6440c6bd470Sfengbojiang 					printf("lookup failed! %"PRIu32"\n",
6450c6bd470Sfengbojiang 					       keys[i]);
6460c6bd470Sfengbojiang 					return -1;
6470c6bd470Sfengbojiang 				}
6480c6bd470Sfengbojiang 			}
6490c6bd470Sfengbojiang 		}
6500c6bd470Sfengbojiang 		loop_cnt++;
6510c6bd470Sfengbojiang 	} while (!writer_done);
6520c6bd470Sfengbojiang 
6530c6bd470Sfengbojiang 	cycles = rte_rdtsc_precise() - begin;
654*2d9fd380Sjfb8856606 	__atomic_fetch_add(&gread_cycles, cycles, __ATOMIC_RELAXED);
655*2d9fd380Sjfb8856606 	__atomic_fetch_add(&greads, read_cnt*loop_cnt, __ATOMIC_RELAXED);
6560c6bd470Sfengbojiang 	return 0;
6570c6bd470Sfengbojiang }
6580c6bd470Sfengbojiang 
6590c6bd470Sfengbojiang static int
write_keys(uint8_t write_type)6600c6bd470Sfengbojiang write_keys(uint8_t write_type)
6610c6bd470Sfengbojiang {
6620c6bd470Sfengbojiang 	uint32_t i;
6630c6bd470Sfengbojiang 	int ret;
6640c6bd470Sfengbojiang 	uint32_t key_cnt = 0;
6650c6bd470Sfengbojiang 	uint32_t *keys;
6660c6bd470Sfengbojiang 	if (write_type == WRITE_KEY_SHIFT) {
6670c6bd470Sfengbojiang 		key_cnt = tbl_rwc_test_param.count_keys_ks;
6680c6bd470Sfengbojiang 		keys = tbl_rwc_test_param.keys_ks;
6690c6bd470Sfengbojiang 	} else if (write_type == WRITE_NO_KEY_SHIFT) {
6700c6bd470Sfengbojiang 		key_cnt = tbl_rwc_test_param.count_keys_no_ks;
6710c6bd470Sfengbojiang 		keys = tbl_rwc_test_param.keys_no_ks;
6720c6bd470Sfengbojiang 	} else if (write_type == WRITE_EXT_BKT) {
6730c6bd470Sfengbojiang 		key_cnt = tbl_rwc_test_param.count_keys_extbkt;
6740c6bd470Sfengbojiang 		keys = tbl_rwc_test_param.keys_ext_bkt;
6750c6bd470Sfengbojiang 	}
6760c6bd470Sfengbojiang 	for (i = 0; i < key_cnt; i++) {
6770c6bd470Sfengbojiang 		ret = rte_hash_add_key(tbl_rwc_test_param.h, keys + i);
6780c6bd470Sfengbojiang 		if ((write_type == WRITE_NO_KEY_SHIFT) && ret < 0) {
6790c6bd470Sfengbojiang 			printf("writer failed %"PRIu32"\n", i);
6800c6bd470Sfengbojiang 			return -1;
6810c6bd470Sfengbojiang 		}
6820c6bd470Sfengbojiang 	}
6830c6bd470Sfengbojiang 	return 0;
6840c6bd470Sfengbojiang }
6850c6bd470Sfengbojiang 
6860c6bd470Sfengbojiang static int
test_rwc_multi_writer(__rte_unused void * arg)687*2d9fd380Sjfb8856606 test_rwc_multi_writer(__rte_unused void *arg)
6880c6bd470Sfengbojiang {
6890c6bd470Sfengbojiang 	uint32_t i, offset;
6900c6bd470Sfengbojiang 	uint32_t pos_core = (uint32_t)((uintptr_t)arg);
6910c6bd470Sfengbojiang 	offset = pos_core * tbl_rwc_test_param.single_insert;
6920c6bd470Sfengbojiang 	for (i = offset; i < offset + tbl_rwc_test_param.single_insert; i++)
6930c6bd470Sfengbojiang 		rte_hash_add_key(tbl_rwc_test_param.h,
6940c6bd470Sfengbojiang 				 tbl_rwc_test_param.keys_ks + i);
6950c6bd470Sfengbojiang 	return 0;
6960c6bd470Sfengbojiang }
6970c6bd470Sfengbojiang 
6980c6bd470Sfengbojiang /*
6990c6bd470Sfengbojiang  * Test lookup perf:
7000c6bd470Sfengbojiang  * Reader(s) lookup keys present in the table.
7010c6bd470Sfengbojiang  */
7020c6bd470Sfengbojiang static int
test_hash_add_no_ks_lookup_hit(struct rwc_perf * rwc_perf_results,int rwc_lf,int htm,int ext_bkt)7030c6bd470Sfengbojiang test_hash_add_no_ks_lookup_hit(struct rwc_perf *rwc_perf_results, int rwc_lf,
7040c6bd470Sfengbojiang 				int htm, int ext_bkt)
7050c6bd470Sfengbojiang {
7060c6bd470Sfengbojiang 	unsigned int n, m;
7070c6bd470Sfengbojiang 	uint64_t i;
7080c6bd470Sfengbojiang 	int use_jhash = 0;
7090c6bd470Sfengbojiang 	uint8_t write_type = WRITE_NO_KEY_SHIFT;
7100c6bd470Sfengbojiang 	uint8_t read_type = READ_PASS_NO_KEY_SHIFTS;
7110c6bd470Sfengbojiang 
7120c6bd470Sfengbojiang 	if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
7130c6bd470Sfengbojiang 		goto err;
7140c6bd470Sfengbojiang 	printf("\nTest: Hash add - no key-shifts, read - hit\n");
7150c6bd470Sfengbojiang 	for (m = 0; m < 2; m++) {
7160c6bd470Sfengbojiang 		if (m == 1) {
7170c6bd470Sfengbojiang 			printf("\n** With bulk-lookup **\n");
7180c6bd470Sfengbojiang 			read_type |= BULK_LOOKUP;
7190c6bd470Sfengbojiang 		}
7200c6bd470Sfengbojiang 		for (n = 0; n < NUM_TEST; n++) {
7210c6bd470Sfengbojiang 			unsigned int tot_lcore = rte_lcore_count();
7220c6bd470Sfengbojiang 			if (tot_lcore < rwc_core_cnt[n] + 1)
7230c6bd470Sfengbojiang 				goto finish;
7240c6bd470Sfengbojiang 
7250c6bd470Sfengbojiang 			printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
7260c6bd470Sfengbojiang 
727*2d9fd380Sjfb8856606 			__atomic_store_n(&greads, 0, __ATOMIC_RELAXED);
728*2d9fd380Sjfb8856606 			__atomic_store_n(&gread_cycles, 0, __ATOMIC_RELAXED);
7290c6bd470Sfengbojiang 
7300c6bd470Sfengbojiang 			rte_hash_reset(tbl_rwc_test_param.h);
7310c6bd470Sfengbojiang 			writer_done = 0;
7320c6bd470Sfengbojiang 			if (write_keys(write_type) < 0)
7330c6bd470Sfengbojiang 				goto err;
7340c6bd470Sfengbojiang 			writer_done = 1;
7350c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
7360c6bd470Sfengbojiang 				rte_eal_remote_launch(test_rwc_reader,
7370c6bd470Sfengbojiang 						(void *)(uintptr_t)read_type,
7380c6bd470Sfengbojiang 							enabled_core_ids[i]);
7390c6bd470Sfengbojiang 
7400c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
7410c6bd470Sfengbojiang 				if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
7420c6bd470Sfengbojiang 					goto err;
7430c6bd470Sfengbojiang 
7440c6bd470Sfengbojiang 			unsigned long long cycles_per_lookup =
745*2d9fd380Sjfb8856606 				__atomic_load_n(&gread_cycles, __ATOMIC_RELAXED)
746*2d9fd380Sjfb8856606 				/ __atomic_load_n(&greads, __ATOMIC_RELAXED);
7470c6bd470Sfengbojiang 			rwc_perf_results->w_no_ks_r_hit[m][n]
7480c6bd470Sfengbojiang 						= cycles_per_lookup;
7490c6bd470Sfengbojiang 			printf("Cycles per lookup: %llu\n", cycles_per_lookup);
7500c6bd470Sfengbojiang 		}
7510c6bd470Sfengbojiang 	}
7520c6bd470Sfengbojiang 
7530c6bd470Sfengbojiang finish:
7540c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
7550c6bd470Sfengbojiang 	return 0;
7560c6bd470Sfengbojiang 
7570c6bd470Sfengbojiang err:
7580c6bd470Sfengbojiang 	rte_eal_mp_wait_lcore();
7590c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
7600c6bd470Sfengbojiang 	return -1;
7610c6bd470Sfengbojiang }
7620c6bd470Sfengbojiang 
7630c6bd470Sfengbojiang /*
7640c6bd470Sfengbojiang  * Test lookup perf:
7650c6bd470Sfengbojiang  * Reader(s) lookup keys absent in the table while
7660c6bd470Sfengbojiang  * 'Main' thread adds with no key-shifts.
7670c6bd470Sfengbojiang  */
7680c6bd470Sfengbojiang static int
test_hash_add_no_ks_lookup_miss(struct rwc_perf * rwc_perf_results,int rwc_lf,int htm,int ext_bkt)7690c6bd470Sfengbojiang test_hash_add_no_ks_lookup_miss(struct rwc_perf *rwc_perf_results, int rwc_lf,
7700c6bd470Sfengbojiang 				int htm, int ext_bkt)
7710c6bd470Sfengbojiang {
7720c6bd470Sfengbojiang 	unsigned int n, m;
7730c6bd470Sfengbojiang 	uint64_t i;
7740c6bd470Sfengbojiang 	int use_jhash = 0;
7750c6bd470Sfengbojiang 	uint8_t write_type = WRITE_NO_KEY_SHIFT;
7760c6bd470Sfengbojiang 	uint8_t read_type = READ_FAIL;
7770c6bd470Sfengbojiang 	int ret;
7780c6bd470Sfengbojiang 
7790c6bd470Sfengbojiang 	if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
7800c6bd470Sfengbojiang 		goto err;
7810c6bd470Sfengbojiang 	printf("\nTest: Hash add - no key-shifts, Hash lookup - miss\n");
7820c6bd470Sfengbojiang 	for (m = 0; m < 2; m++) {
7830c6bd470Sfengbojiang 		if (m == 1) {
7840c6bd470Sfengbojiang 			printf("\n** With bulk-lookup **\n");
7850c6bd470Sfengbojiang 			read_type |= BULK_LOOKUP;
7860c6bd470Sfengbojiang 		}
7870c6bd470Sfengbojiang 		for (n = 0; n < NUM_TEST; n++) {
7880c6bd470Sfengbojiang 			unsigned int tot_lcore = rte_lcore_count();
7890c6bd470Sfengbojiang 			if (tot_lcore < rwc_core_cnt[n] + 1)
7900c6bd470Sfengbojiang 				goto finish;
7910c6bd470Sfengbojiang 
7920c6bd470Sfengbojiang 			printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
7930c6bd470Sfengbojiang 
794*2d9fd380Sjfb8856606 			__atomic_store_n(&greads, 0, __ATOMIC_RELAXED);
795*2d9fd380Sjfb8856606 			__atomic_store_n(&gread_cycles, 0, __ATOMIC_RELAXED);
7960c6bd470Sfengbojiang 
7970c6bd470Sfengbojiang 			rte_hash_reset(tbl_rwc_test_param.h);
7980c6bd470Sfengbojiang 			writer_done = 0;
7990c6bd470Sfengbojiang 
8000c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
8010c6bd470Sfengbojiang 				rte_eal_remote_launch(test_rwc_reader,
8020c6bd470Sfengbojiang 						(void *)(uintptr_t)read_type,
8030c6bd470Sfengbojiang 							enabled_core_ids[i]);
8040c6bd470Sfengbojiang 			ret = write_keys(write_type);
8050c6bd470Sfengbojiang 			writer_done = 1;
8060c6bd470Sfengbojiang 
8070c6bd470Sfengbojiang 			if (ret < 0)
8080c6bd470Sfengbojiang 				goto err;
8090c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
8100c6bd470Sfengbojiang 				if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
8110c6bd470Sfengbojiang 					goto err;
8120c6bd470Sfengbojiang 
8130c6bd470Sfengbojiang 			unsigned long long cycles_per_lookup =
814*2d9fd380Sjfb8856606 				__atomic_load_n(&gread_cycles, __ATOMIC_RELAXED)
815*2d9fd380Sjfb8856606 				/ __atomic_load_n(&greads, __ATOMIC_RELAXED);
8160c6bd470Sfengbojiang 			rwc_perf_results->w_no_ks_r_miss[m][n]
8170c6bd470Sfengbojiang 						= cycles_per_lookup;
8180c6bd470Sfengbojiang 			printf("Cycles per lookup: %llu\n", cycles_per_lookup);
8190c6bd470Sfengbojiang 		}
8200c6bd470Sfengbojiang 	}
8210c6bd470Sfengbojiang 
8220c6bd470Sfengbojiang finish:
8230c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
8240c6bd470Sfengbojiang 	return 0;
8250c6bd470Sfengbojiang 
8260c6bd470Sfengbojiang err:
8270c6bd470Sfengbojiang 	rte_eal_mp_wait_lcore();
8280c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
8290c6bd470Sfengbojiang 	return -1;
8300c6bd470Sfengbojiang }
8310c6bd470Sfengbojiang 
8320c6bd470Sfengbojiang /*
8330c6bd470Sfengbojiang  * Test lookup perf:
8340c6bd470Sfengbojiang  * Reader(s) lookup keys present in the table and not likely to be on the
8350c6bd470Sfengbojiang  * shift path  while 'Main' thread adds keys causing key-shifts.
8360c6bd470Sfengbojiang  */
8370c6bd470Sfengbojiang static int
test_hash_add_ks_lookup_hit_non_sp(struct rwc_perf * rwc_perf_results,int rwc_lf,int htm,int ext_bkt)8380c6bd470Sfengbojiang test_hash_add_ks_lookup_hit_non_sp(struct rwc_perf *rwc_perf_results,
8390c6bd470Sfengbojiang 				    int rwc_lf, int htm, int ext_bkt)
8400c6bd470Sfengbojiang {
8410c6bd470Sfengbojiang 	unsigned int n, m;
8420c6bd470Sfengbojiang 	uint64_t i;
8430c6bd470Sfengbojiang 	int use_jhash = 0;
8440c6bd470Sfengbojiang 	int ret;
8450c6bd470Sfengbojiang 	uint8_t write_type;
8460c6bd470Sfengbojiang 	uint8_t read_type = READ_PASS_NON_SHIFT_PATH;
8470c6bd470Sfengbojiang 
8480c6bd470Sfengbojiang 	if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
8490c6bd470Sfengbojiang 		goto err;
8500c6bd470Sfengbojiang 	printf("\nTest: Hash add - key shift, Hash lookup - hit"
8510c6bd470Sfengbojiang 	       " (non-shift-path)\n");
8520c6bd470Sfengbojiang 	for (m = 0; m < 2; m++) {
8530c6bd470Sfengbojiang 		if (m == 1) {
8540c6bd470Sfengbojiang 			printf("\n** With bulk-lookup **\n");
8550c6bd470Sfengbojiang 			read_type |= BULK_LOOKUP;
8560c6bd470Sfengbojiang 		}
8570c6bd470Sfengbojiang 		for (n = 0; n < NUM_TEST; n++) {
8580c6bd470Sfengbojiang 			unsigned int tot_lcore = rte_lcore_count();
8590c6bd470Sfengbojiang 			if (tot_lcore < rwc_core_cnt[n] + 1)
8600c6bd470Sfengbojiang 				goto finish;
8610c6bd470Sfengbojiang 
8620c6bd470Sfengbojiang 			printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
8630c6bd470Sfengbojiang 
864*2d9fd380Sjfb8856606 			__atomic_store_n(&greads, 0, __ATOMIC_RELAXED);
865*2d9fd380Sjfb8856606 			__atomic_store_n(&gread_cycles, 0, __ATOMIC_RELAXED);
8660c6bd470Sfengbojiang 
8670c6bd470Sfengbojiang 			rte_hash_reset(tbl_rwc_test_param.h);
8680c6bd470Sfengbojiang 			writer_done = 0;
8690c6bd470Sfengbojiang 			write_type = WRITE_NO_KEY_SHIFT;
8700c6bd470Sfengbojiang 			if (write_keys(write_type) < 0)
8710c6bd470Sfengbojiang 				goto err;
8720c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
8730c6bd470Sfengbojiang 				rte_eal_remote_launch(test_rwc_reader,
8740c6bd470Sfengbojiang 						(void *)(uintptr_t)read_type,
8750c6bd470Sfengbojiang 							enabled_core_ids[i]);
8760c6bd470Sfengbojiang 			write_type = WRITE_KEY_SHIFT;
8770c6bd470Sfengbojiang 			ret = write_keys(write_type);
8780c6bd470Sfengbojiang 			writer_done = 1;
8790c6bd470Sfengbojiang 
8800c6bd470Sfengbojiang 			if (ret < 0)
8810c6bd470Sfengbojiang 				goto err;
8820c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
8830c6bd470Sfengbojiang 				if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
8840c6bd470Sfengbojiang 					goto err;
8850c6bd470Sfengbojiang 
8860c6bd470Sfengbojiang 			unsigned long long cycles_per_lookup =
887*2d9fd380Sjfb8856606 				__atomic_load_n(&gread_cycles, __ATOMIC_RELAXED)
888*2d9fd380Sjfb8856606 				/ __atomic_load_n(&greads, __ATOMIC_RELAXED);
8890c6bd470Sfengbojiang 			rwc_perf_results->w_ks_r_hit_nsp[m][n]
8900c6bd470Sfengbojiang 						= cycles_per_lookup;
8910c6bd470Sfengbojiang 			printf("Cycles per lookup: %llu\n", cycles_per_lookup);
8920c6bd470Sfengbojiang 		}
8930c6bd470Sfengbojiang 	}
8940c6bd470Sfengbojiang 
8950c6bd470Sfengbojiang finish:
8960c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
8970c6bd470Sfengbojiang 	return 0;
8980c6bd470Sfengbojiang 
8990c6bd470Sfengbojiang err:
9000c6bd470Sfengbojiang 	rte_eal_mp_wait_lcore();
9010c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
9020c6bd470Sfengbojiang 	return -1;
9030c6bd470Sfengbojiang }
9040c6bd470Sfengbojiang 
9050c6bd470Sfengbojiang /*
9060c6bd470Sfengbojiang  * Test lookup perf:
9070c6bd470Sfengbojiang  * Reader(s) lookup keys present in the table and likely on the shift-path while
9080c6bd470Sfengbojiang  * 'Main' thread adds keys causing key-shifts.
9090c6bd470Sfengbojiang  */
9100c6bd470Sfengbojiang static int
test_hash_add_ks_lookup_hit_sp(struct rwc_perf * rwc_perf_results,int rwc_lf,int htm,int ext_bkt)9110c6bd470Sfengbojiang test_hash_add_ks_lookup_hit_sp(struct rwc_perf *rwc_perf_results, int rwc_lf,
9120c6bd470Sfengbojiang 				int htm, int ext_bkt)
9130c6bd470Sfengbojiang {
9140c6bd470Sfengbojiang 	unsigned int n, m;
9150c6bd470Sfengbojiang 	uint64_t i;
9160c6bd470Sfengbojiang 	int use_jhash = 0;
9170c6bd470Sfengbojiang 	int ret;
9180c6bd470Sfengbojiang 	uint8_t write_type;
9190c6bd470Sfengbojiang 	uint8_t read_type = READ_PASS_SHIFT_PATH;
9200c6bd470Sfengbojiang 
9210c6bd470Sfengbojiang 	if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
9220c6bd470Sfengbojiang 		goto err;
9230c6bd470Sfengbojiang 	printf("\nTest: Hash add - key shift, Hash lookup - hit (shift-path)"
9240c6bd470Sfengbojiang 	       "\n");
9250c6bd470Sfengbojiang 
9260c6bd470Sfengbojiang 	for (m = 0; m < 2; m++) {
9270c6bd470Sfengbojiang 		if (m == 1) {
9280c6bd470Sfengbojiang 			printf("\n** With bulk-lookup **\n");
9290c6bd470Sfengbojiang 			read_type |= BULK_LOOKUP;
9300c6bd470Sfengbojiang 		}
9310c6bd470Sfengbojiang 		for (n = 0; n < NUM_TEST; n++) {
9320c6bd470Sfengbojiang 			unsigned int tot_lcore = rte_lcore_count();
9330c6bd470Sfengbojiang 			if (tot_lcore < rwc_core_cnt[n] + 1)
9340c6bd470Sfengbojiang 				goto finish;
9350c6bd470Sfengbojiang 
9360c6bd470Sfengbojiang 			printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
937*2d9fd380Sjfb8856606 
938*2d9fd380Sjfb8856606 			__atomic_store_n(&greads, 0, __ATOMIC_RELAXED);
939*2d9fd380Sjfb8856606 			__atomic_store_n(&gread_cycles, 0, __ATOMIC_RELAXED);
9400c6bd470Sfengbojiang 
9410c6bd470Sfengbojiang 			rte_hash_reset(tbl_rwc_test_param.h);
9420c6bd470Sfengbojiang 			writer_done = 0;
9430c6bd470Sfengbojiang 			write_type = WRITE_NO_KEY_SHIFT;
9440c6bd470Sfengbojiang 			if (write_keys(write_type) < 0)
9450c6bd470Sfengbojiang 				goto err;
9460c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
9470c6bd470Sfengbojiang 				rte_eal_remote_launch(test_rwc_reader,
9480c6bd470Sfengbojiang 						(void *)(uintptr_t)read_type,
9490c6bd470Sfengbojiang 						enabled_core_ids[i]);
9500c6bd470Sfengbojiang 			write_type = WRITE_KEY_SHIFT;
9510c6bd470Sfengbojiang 			ret = write_keys(write_type);
9520c6bd470Sfengbojiang 			writer_done = 1;
9530c6bd470Sfengbojiang 
9540c6bd470Sfengbojiang 			if (ret < 0)
9550c6bd470Sfengbojiang 				goto err;
9560c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
9570c6bd470Sfengbojiang 				if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
9580c6bd470Sfengbojiang 					goto err;
9590c6bd470Sfengbojiang 
9600c6bd470Sfengbojiang 			unsigned long long cycles_per_lookup =
961*2d9fd380Sjfb8856606 				__atomic_load_n(&gread_cycles, __ATOMIC_RELAXED)
962*2d9fd380Sjfb8856606 				/ __atomic_load_n(&greads, __ATOMIC_RELAXED);
9630c6bd470Sfengbojiang 			rwc_perf_results->w_ks_r_hit_sp[m][n]
9640c6bd470Sfengbojiang 						= cycles_per_lookup;
9650c6bd470Sfengbojiang 			printf("Cycles per lookup: %llu\n", cycles_per_lookup);
9660c6bd470Sfengbojiang 		}
9670c6bd470Sfengbojiang 	}
9680c6bd470Sfengbojiang 
9690c6bd470Sfengbojiang finish:
9700c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
9710c6bd470Sfengbojiang 	return 0;
9720c6bd470Sfengbojiang 
9730c6bd470Sfengbojiang err:
9740c6bd470Sfengbojiang 	rte_eal_mp_wait_lcore();
9750c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
9760c6bd470Sfengbojiang 	return -1;
9770c6bd470Sfengbojiang }
9780c6bd470Sfengbojiang 
9790c6bd470Sfengbojiang /*
9800c6bd470Sfengbojiang  * Test lookup perf:
9810c6bd470Sfengbojiang  * Reader(s) lookup keys absent in the table while
9820c6bd470Sfengbojiang  * 'Main' thread adds keys causing key-shifts.
9830c6bd470Sfengbojiang  */
9840c6bd470Sfengbojiang static int
test_hash_add_ks_lookup_miss(struct rwc_perf * rwc_perf_results,int rwc_lf,int htm,int ext_bkt)9850c6bd470Sfengbojiang test_hash_add_ks_lookup_miss(struct rwc_perf *rwc_perf_results, int rwc_lf, int
9860c6bd470Sfengbojiang 			     htm, int ext_bkt)
9870c6bd470Sfengbojiang {
9880c6bd470Sfengbojiang 	unsigned int n, m;
9890c6bd470Sfengbojiang 	uint64_t i;
9900c6bd470Sfengbojiang 	int use_jhash = 0;
9910c6bd470Sfengbojiang 	int ret;
9920c6bd470Sfengbojiang 	uint8_t write_type;
9930c6bd470Sfengbojiang 	uint8_t read_type = READ_FAIL;
9940c6bd470Sfengbojiang 
9950c6bd470Sfengbojiang 	if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
9960c6bd470Sfengbojiang 		goto err;
9970c6bd470Sfengbojiang 	printf("\nTest: Hash add - key shift, Hash lookup - miss\n");
9980c6bd470Sfengbojiang 	for (m = 0; m < 2; m++) {
9990c6bd470Sfengbojiang 		if (m == 1) {
10000c6bd470Sfengbojiang 			printf("\n** With bulk-lookup **\n");
10010c6bd470Sfengbojiang 			read_type |= BULK_LOOKUP;
10020c6bd470Sfengbojiang 		}
10030c6bd470Sfengbojiang 		for (n = 0; n < NUM_TEST; n++) {
10040c6bd470Sfengbojiang 			unsigned int tot_lcore = rte_lcore_count();
10050c6bd470Sfengbojiang 			if (tot_lcore < rwc_core_cnt[n] + 1)
10060c6bd470Sfengbojiang 				goto finish;
10070c6bd470Sfengbojiang 
10080c6bd470Sfengbojiang 			printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
10090c6bd470Sfengbojiang 
1010*2d9fd380Sjfb8856606 			__atomic_store_n(&greads, 0, __ATOMIC_RELAXED);
1011*2d9fd380Sjfb8856606 			__atomic_store_n(&gread_cycles, 0, __ATOMIC_RELAXED);
10120c6bd470Sfengbojiang 
10130c6bd470Sfengbojiang 			rte_hash_reset(tbl_rwc_test_param.h);
10140c6bd470Sfengbojiang 			writer_done = 0;
10150c6bd470Sfengbojiang 			write_type = WRITE_NO_KEY_SHIFT;
10160c6bd470Sfengbojiang 			if (write_keys(write_type) < 0)
10170c6bd470Sfengbojiang 				goto err;
10180c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
10190c6bd470Sfengbojiang 				rte_eal_remote_launch(test_rwc_reader,
10200c6bd470Sfengbojiang 						(void *)(uintptr_t)read_type,
10210c6bd470Sfengbojiang 							enabled_core_ids[i]);
10220c6bd470Sfengbojiang 			write_type = WRITE_KEY_SHIFT;
10230c6bd470Sfengbojiang 			ret = write_keys(write_type);
10240c6bd470Sfengbojiang 			writer_done = 1;
10250c6bd470Sfengbojiang 
10260c6bd470Sfengbojiang 			if (ret < 0)
10270c6bd470Sfengbojiang 				goto err;
10280c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
10290c6bd470Sfengbojiang 				if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
10300c6bd470Sfengbojiang 					goto err;
10310c6bd470Sfengbojiang 
10320c6bd470Sfengbojiang 			unsigned long long cycles_per_lookup =
1033*2d9fd380Sjfb8856606 				__atomic_load_n(&gread_cycles, __ATOMIC_RELAXED)
1034*2d9fd380Sjfb8856606 				/ __atomic_load_n(&greads, __ATOMIC_RELAXED);
10350c6bd470Sfengbojiang 			rwc_perf_results->w_ks_r_miss[m][n] = cycles_per_lookup;
10360c6bd470Sfengbojiang 			printf("Cycles per lookup: %llu\n", cycles_per_lookup);
10370c6bd470Sfengbojiang 		}
10380c6bd470Sfengbojiang 	}
10390c6bd470Sfengbojiang 
10400c6bd470Sfengbojiang finish:
10410c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
10420c6bd470Sfengbojiang 	return 0;
10430c6bd470Sfengbojiang 
10440c6bd470Sfengbojiang err:
10450c6bd470Sfengbojiang 	rte_eal_mp_wait_lcore();
10460c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
10470c6bd470Sfengbojiang 	return -1;
10480c6bd470Sfengbojiang }
10490c6bd470Sfengbojiang 
10500c6bd470Sfengbojiang /*
10510c6bd470Sfengbojiang  * Test lookup perf for multi-writer:
10520c6bd470Sfengbojiang  * Reader(s) lookup keys present in the table and likely on the shift-path while
10530c6bd470Sfengbojiang  * Writers add keys causing key-shiftsi.
10540c6bd470Sfengbojiang  * Writers are running in parallel, on different data plane cores.
10550c6bd470Sfengbojiang  */
10560c6bd470Sfengbojiang static int
test_hash_multi_add_lookup(struct rwc_perf * rwc_perf_results,int rwc_lf,int htm,int ext_bkt)10570c6bd470Sfengbojiang test_hash_multi_add_lookup(struct rwc_perf *rwc_perf_results, int rwc_lf,
10580c6bd470Sfengbojiang 			   int htm, int ext_bkt)
10590c6bd470Sfengbojiang {
10600c6bd470Sfengbojiang 	unsigned int n, m, k;
10610c6bd470Sfengbojiang 	uint64_t i;
10620c6bd470Sfengbojiang 	int use_jhash = 0;
10630c6bd470Sfengbojiang 	uint8_t write_type;
10640c6bd470Sfengbojiang 	uint8_t read_type = READ_PASS_SHIFT_PATH;
10650c6bd470Sfengbojiang 
10660c6bd470Sfengbojiang 	if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
10670c6bd470Sfengbojiang 		goto err;
10680c6bd470Sfengbojiang 	printf("\nTest: Multi-add-lookup\n");
10690c6bd470Sfengbojiang 	uint8_t pos_core;
10700c6bd470Sfengbojiang 	for (m = 1; m < NUM_TEST; m++) {
10710c6bd470Sfengbojiang 		/* Calculate keys added by each writer */
10720c6bd470Sfengbojiang 		tbl_rwc_test_param.single_insert =
10730c6bd470Sfengbojiang 			tbl_rwc_test_param.count_keys_ks / rwc_core_cnt[m];
10740c6bd470Sfengbojiang 		for (k = 0; k < 2; k++) {
10750c6bd470Sfengbojiang 			if (k == 1) {
10760c6bd470Sfengbojiang 				printf("\n** With bulk-lookup **\n");
10770c6bd470Sfengbojiang 				read_type |= BULK_LOOKUP;
10780c6bd470Sfengbojiang 			}
10790c6bd470Sfengbojiang 			for (n = 0; n < NUM_TEST; n++) {
10800c6bd470Sfengbojiang 				unsigned int tot_lcore	= rte_lcore_count();
10810c6bd470Sfengbojiang 				if (tot_lcore < (rwc_core_cnt[n] +
10820c6bd470Sfengbojiang 				     rwc_core_cnt[m] + 1))
10830c6bd470Sfengbojiang 					goto finish;
10840c6bd470Sfengbojiang 
10850c6bd470Sfengbojiang 				printf("\nNumber of writers: %u",
10860c6bd470Sfengbojiang 				       rwc_core_cnt[m]);
10870c6bd470Sfengbojiang 				printf("\nNumber of readers: %u\n",
10880c6bd470Sfengbojiang 				       rwc_core_cnt[n]);
10890c6bd470Sfengbojiang 
1090*2d9fd380Sjfb8856606 				__atomic_store_n(&greads, 0, __ATOMIC_RELAXED);
1091*2d9fd380Sjfb8856606 				__atomic_store_n(&gread_cycles, 0,
1092*2d9fd380Sjfb8856606 						 __ATOMIC_RELAXED);
10930c6bd470Sfengbojiang 
10940c6bd470Sfengbojiang 				rte_hash_reset(tbl_rwc_test_param.h);
10950c6bd470Sfengbojiang 				writer_done = 0;
10960c6bd470Sfengbojiang 				write_type = WRITE_NO_KEY_SHIFT;
10970c6bd470Sfengbojiang 				if (write_keys(write_type) < 0)
10980c6bd470Sfengbojiang 					goto err;
10990c6bd470Sfengbojiang 
11000c6bd470Sfengbojiang 				/* Launch reader(s) */
11010c6bd470Sfengbojiang 				for (i = 1; i <= rwc_core_cnt[n]; i++)
11020c6bd470Sfengbojiang 					rte_eal_remote_launch(test_rwc_reader,
11030c6bd470Sfengbojiang 						(void *)(uintptr_t)read_type,
11040c6bd470Sfengbojiang 						enabled_core_ids[i]);
11050c6bd470Sfengbojiang 				write_type = WRITE_KEY_SHIFT;
11060c6bd470Sfengbojiang 				pos_core = 0;
11070c6bd470Sfengbojiang 
11080c6bd470Sfengbojiang 				/* Launch writers */
11090c6bd470Sfengbojiang 				for (; i <= rwc_core_cnt[m]
11100c6bd470Sfengbojiang 				     + rwc_core_cnt[n];	i++) {
11110c6bd470Sfengbojiang 					rte_eal_remote_launch
11120c6bd470Sfengbojiang 						(test_rwc_multi_writer,
11130c6bd470Sfengbojiang 						(void *)(uintptr_t)pos_core,
11140c6bd470Sfengbojiang 						enabled_core_ids[i]);
11150c6bd470Sfengbojiang 					pos_core++;
11160c6bd470Sfengbojiang 				}
11170c6bd470Sfengbojiang 
11180c6bd470Sfengbojiang 				/* Wait for writers to complete */
11190c6bd470Sfengbojiang 				for (i = rwc_core_cnt[n] + 1;
11200c6bd470Sfengbojiang 				     i <= rwc_core_cnt[m] + rwc_core_cnt[n];
11210c6bd470Sfengbojiang 				     i++)
11220c6bd470Sfengbojiang 					rte_eal_wait_lcore(enabled_core_ids[i]);
11230c6bd470Sfengbojiang 
11240c6bd470Sfengbojiang 				writer_done = 1;
11250c6bd470Sfengbojiang 
11260c6bd470Sfengbojiang 				for (i = 1; i <= rwc_core_cnt[n]; i++)
11270c6bd470Sfengbojiang 					if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
11280c6bd470Sfengbojiang 						goto err;
11290c6bd470Sfengbojiang 
11300c6bd470Sfengbojiang 				unsigned long long cycles_per_lookup =
1131*2d9fd380Sjfb8856606 					__atomic_load_n(&gread_cycles,
1132*2d9fd380Sjfb8856606 							__ATOMIC_RELAXED) /
1133*2d9fd380Sjfb8856606 					__atomic_load_n(&greads,
1134*2d9fd380Sjfb8856606 							  __ATOMIC_RELAXED);
11350c6bd470Sfengbojiang 				rwc_perf_results->multi_rw[m][k][n]
11360c6bd470Sfengbojiang 					= cycles_per_lookup;
11370c6bd470Sfengbojiang 				printf("Cycles per lookup: %llu\n",
11380c6bd470Sfengbojiang 				       cycles_per_lookup);
11390c6bd470Sfengbojiang 			}
11400c6bd470Sfengbojiang 		}
11410c6bd470Sfengbojiang 	}
11420c6bd470Sfengbojiang 
11430c6bd470Sfengbojiang finish:
11440c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
11450c6bd470Sfengbojiang 	return 0;
11460c6bd470Sfengbojiang 
11470c6bd470Sfengbojiang err:
11480c6bd470Sfengbojiang 	rte_eal_mp_wait_lcore();
11490c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
11500c6bd470Sfengbojiang 	return -1;
11510c6bd470Sfengbojiang }
11520c6bd470Sfengbojiang 
11530c6bd470Sfengbojiang /*
11540c6bd470Sfengbojiang  * Test lookup perf:
11550c6bd470Sfengbojiang  * Reader(s) lookup keys present in the extendable bkt.
11560c6bd470Sfengbojiang  */
11570c6bd470Sfengbojiang static int
test_hash_add_ks_lookup_hit_extbkt(struct rwc_perf * rwc_perf_results,int rwc_lf,int htm,int ext_bkt)11580c6bd470Sfengbojiang test_hash_add_ks_lookup_hit_extbkt(struct rwc_perf *rwc_perf_results,
11590c6bd470Sfengbojiang 				int rwc_lf, int htm, int ext_bkt)
11600c6bd470Sfengbojiang {
11610c6bd470Sfengbojiang 	unsigned int n, m;
11620c6bd470Sfengbojiang 	uint64_t i;
11630c6bd470Sfengbojiang 	int use_jhash = 0;
11640c6bd470Sfengbojiang 	uint8_t write_type;
11650c6bd470Sfengbojiang 	uint8_t read_type = READ_PASS_KEY_SHIFTS_EXTBKT;
11660c6bd470Sfengbojiang 
11670c6bd470Sfengbojiang 	if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
11680c6bd470Sfengbojiang 		goto err;
11690c6bd470Sfengbojiang 	printf("\nTest: Hash add - key-shifts, read - hit (ext_bkt)\n");
11700c6bd470Sfengbojiang 	for (m = 0; m < 2; m++) {
11710c6bd470Sfengbojiang 		if (m == 1) {
11720c6bd470Sfengbojiang 			printf("\n** With bulk-lookup **\n");
11730c6bd470Sfengbojiang 			read_type |= BULK_LOOKUP;
11740c6bd470Sfengbojiang 		}
11750c6bd470Sfengbojiang 		for (n = 0; n < NUM_TEST; n++) {
11760c6bd470Sfengbojiang 			unsigned int tot_lcore = rte_lcore_count();
11770c6bd470Sfengbojiang 			if (tot_lcore < rwc_core_cnt[n] + 1)
11780c6bd470Sfengbojiang 				goto finish;
11790c6bd470Sfengbojiang 
11800c6bd470Sfengbojiang 			printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
11810c6bd470Sfengbojiang 
1182*2d9fd380Sjfb8856606 			__atomic_store_n(&greads, 0, __ATOMIC_RELAXED);
1183*2d9fd380Sjfb8856606 			__atomic_store_n(&gread_cycles, 0, __ATOMIC_RELAXED);
11840c6bd470Sfengbojiang 
11850c6bd470Sfengbojiang 			rte_hash_reset(tbl_rwc_test_param.h);
11860c6bd470Sfengbojiang 			write_type = WRITE_NO_KEY_SHIFT;
11870c6bd470Sfengbojiang 			if (write_keys(write_type) < 0)
11880c6bd470Sfengbojiang 				goto err;
11890c6bd470Sfengbojiang 			write_type = WRITE_KEY_SHIFT;
11900c6bd470Sfengbojiang 			if (write_keys(write_type) < 0)
11910c6bd470Sfengbojiang 				goto err;
11920c6bd470Sfengbojiang 			writer_done = 0;
11930c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
11940c6bd470Sfengbojiang 				rte_eal_remote_launch(test_rwc_reader,
11950c6bd470Sfengbojiang 						(void *)(uintptr_t)read_type,
11960c6bd470Sfengbojiang 							enabled_core_ids[i]);
11970c6bd470Sfengbojiang 			for (i = 0; i < tbl_rwc_test_param.count_keys_ks_extbkt;
11980c6bd470Sfengbojiang 			     i++) {
11990c6bd470Sfengbojiang 				if (rte_hash_del_key(tbl_rwc_test_param.h,
12000c6bd470Sfengbojiang 					tbl_rwc_test_param.keys_ks_extbkt + i)
12010c6bd470Sfengbojiang 							< 0) {
12020c6bd470Sfengbojiang 					printf("Delete Failed: %u\n",
12030c6bd470Sfengbojiang 					tbl_rwc_test_param.keys_ks_extbkt[i]);
12040c6bd470Sfengbojiang 					goto err;
12050c6bd470Sfengbojiang 				}
12060c6bd470Sfengbojiang 			}
12070c6bd470Sfengbojiang 			writer_done = 1;
12080c6bd470Sfengbojiang 
12090c6bd470Sfengbojiang 			for (i = 1; i <= rwc_core_cnt[n]; i++)
12100c6bd470Sfengbojiang 				if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
12110c6bd470Sfengbojiang 					goto err;
12120c6bd470Sfengbojiang 
12130c6bd470Sfengbojiang 			unsigned long long cycles_per_lookup =
1214*2d9fd380Sjfb8856606 				__atomic_load_n(&gread_cycles, __ATOMIC_RELAXED)
1215*2d9fd380Sjfb8856606 				/ __atomic_load_n(&greads, __ATOMIC_RELAXED);
12160c6bd470Sfengbojiang 			rwc_perf_results->w_ks_r_hit_extbkt[m][n]
12170c6bd470Sfengbojiang 						= cycles_per_lookup;
12180c6bd470Sfengbojiang 			printf("Cycles per lookup: %llu\n", cycles_per_lookup);
12190c6bd470Sfengbojiang 		}
12200c6bd470Sfengbojiang 	}
12210c6bd470Sfengbojiang 
12220c6bd470Sfengbojiang finish:
12230c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
12240c6bd470Sfengbojiang 	return 0;
12250c6bd470Sfengbojiang 
12260c6bd470Sfengbojiang err:
12270c6bd470Sfengbojiang 	rte_eal_mp_wait_lcore();
12280c6bd470Sfengbojiang 	rte_hash_free(tbl_rwc_test_param.h);
12290c6bd470Sfengbojiang 	return -1;
12300c6bd470Sfengbojiang }
12310c6bd470Sfengbojiang 
1232*2d9fd380Sjfb8856606 static struct rte_rcu_qsbr *rv;
1233*2d9fd380Sjfb8856606 
1234*2d9fd380Sjfb8856606 /*
1235*2d9fd380Sjfb8856606  * Reader thread using rte_hash data structure with RCU
1236*2d9fd380Sjfb8856606  */
1237*2d9fd380Sjfb8856606 static int
test_hash_rcu_qsbr_reader(void * arg)1238*2d9fd380Sjfb8856606 test_hash_rcu_qsbr_reader(void *arg)
1239*2d9fd380Sjfb8856606 {
1240*2d9fd380Sjfb8856606 	unsigned int i, j;
1241*2d9fd380Sjfb8856606 	uint32_t num_keys = tbl_rwc_test_param.count_keys_no_ks
1242*2d9fd380Sjfb8856606 				- QSBR_REPORTING_INTERVAL;
1243*2d9fd380Sjfb8856606 	uint32_t *keys = tbl_rwc_test_param.keys_no_ks;
1244*2d9fd380Sjfb8856606 	uint32_t lcore_id = rte_lcore_id();
1245*2d9fd380Sjfb8856606 	RTE_SET_USED(arg);
1246*2d9fd380Sjfb8856606 
1247*2d9fd380Sjfb8856606 	(void)rte_rcu_qsbr_thread_register(rv, lcore_id);
1248*2d9fd380Sjfb8856606 	rte_rcu_qsbr_thread_online(rv, lcore_id);
1249*2d9fd380Sjfb8856606 	do {
1250*2d9fd380Sjfb8856606 		for (i = 0; i < num_keys; i += j) {
1251*2d9fd380Sjfb8856606 			for (j = 0; j < QSBR_REPORTING_INTERVAL; j++)
1252*2d9fd380Sjfb8856606 				rte_hash_lookup(tbl_rwc_test_param.h,
1253*2d9fd380Sjfb8856606 						keys + i + j);
1254*2d9fd380Sjfb8856606 			/* Update quiescent state counter */
1255*2d9fd380Sjfb8856606 			rte_rcu_qsbr_quiescent(rv, lcore_id);
1256*2d9fd380Sjfb8856606 		}
1257*2d9fd380Sjfb8856606 	} while (!writer_done);
1258*2d9fd380Sjfb8856606 	rte_rcu_qsbr_thread_offline(rv, lcore_id);
1259*2d9fd380Sjfb8856606 	(void)rte_rcu_qsbr_thread_unregister(rv, lcore_id);
1260*2d9fd380Sjfb8856606 
1261*2d9fd380Sjfb8856606 	return 0;
1262*2d9fd380Sjfb8856606 }
1263*2d9fd380Sjfb8856606 
1264*2d9fd380Sjfb8856606 /*
1265*2d9fd380Sjfb8856606  * Writer thread using rte_hash data structure with RCU
1266*2d9fd380Sjfb8856606  */
1267*2d9fd380Sjfb8856606 static int
test_hash_rcu_qsbr_writer(void * arg)1268*2d9fd380Sjfb8856606 test_hash_rcu_qsbr_writer(void *arg)
1269*2d9fd380Sjfb8856606 {
1270*2d9fd380Sjfb8856606 	uint32_t i, offset;
1271*2d9fd380Sjfb8856606 	uint64_t begin, cycles;
1272*2d9fd380Sjfb8856606 	uint8_t pos_core = (uint32_t)((uintptr_t)arg);
1273*2d9fd380Sjfb8856606 	offset = pos_core * tbl_rwc_test_param.single_insert;
1274*2d9fd380Sjfb8856606 
1275*2d9fd380Sjfb8856606 	begin = rte_rdtsc_precise();
1276*2d9fd380Sjfb8856606 	for (i = offset; i < offset + tbl_rwc_test_param.single_insert; i++) {
1277*2d9fd380Sjfb8856606 		/* Delete element from the shared data structure */
1278*2d9fd380Sjfb8856606 		rte_hash_del_key(tbl_rwc_test_param.h,
1279*2d9fd380Sjfb8856606 					tbl_rwc_test_param.keys_no_ks + i);
1280*2d9fd380Sjfb8856606 		rte_hash_add_key(tbl_rwc_test_param.h,
1281*2d9fd380Sjfb8856606 				tbl_rwc_test_param.keys_no_ks + i);
1282*2d9fd380Sjfb8856606 	}
1283*2d9fd380Sjfb8856606 	cycles = rte_rdtsc_precise() - begin;
1284*2d9fd380Sjfb8856606 	__atomic_fetch_add(&gwrite_cycles, cycles, __ATOMIC_RELAXED);
1285*2d9fd380Sjfb8856606 	__atomic_fetch_add(&gwrites, tbl_rwc_test_param.single_insert,
1286*2d9fd380Sjfb8856606 			   __ATOMIC_RELAXED);
1287*2d9fd380Sjfb8856606 	return 0;
1288*2d9fd380Sjfb8856606 }
1289*2d9fd380Sjfb8856606 
1290*2d9fd380Sjfb8856606 /*
1291*2d9fd380Sjfb8856606  * Writer perf test with RCU QSBR in DQ mode:
1292*2d9fd380Sjfb8856606  * Writer(s) delete and add keys in the table.
1293*2d9fd380Sjfb8856606  * Readers lookup keys in the hash table
1294*2d9fd380Sjfb8856606  */
1295*2d9fd380Sjfb8856606 static int
test_hash_rcu_qsbr_writer_perf(struct rwc_perf * rwc_perf_results,int rwc_lf,int htm,int ext_bkt)1296*2d9fd380Sjfb8856606 test_hash_rcu_qsbr_writer_perf(struct rwc_perf *rwc_perf_results, int rwc_lf,
1297*2d9fd380Sjfb8856606 				int htm, int ext_bkt)
1298*2d9fd380Sjfb8856606 {
1299*2d9fd380Sjfb8856606 	unsigned int n;
1300*2d9fd380Sjfb8856606 	uint64_t i;
1301*2d9fd380Sjfb8856606 	uint8_t write_type;
1302*2d9fd380Sjfb8856606 	int use_jhash = 0;
1303*2d9fd380Sjfb8856606 	struct rte_hash_rcu_config rcu_config = {0};
1304*2d9fd380Sjfb8856606 	uint32_t sz;
1305*2d9fd380Sjfb8856606 	uint8_t pos_core;
1306*2d9fd380Sjfb8856606 
1307*2d9fd380Sjfb8856606 	printf("\nTest: Writer perf with integrated RCU\n");
1308*2d9fd380Sjfb8856606 
1309*2d9fd380Sjfb8856606 	if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
1310*2d9fd380Sjfb8856606 		goto err;
1311*2d9fd380Sjfb8856606 
1312*2d9fd380Sjfb8856606 	sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
1313*2d9fd380Sjfb8856606 	rv = (struct rte_rcu_qsbr *)rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
1314*2d9fd380Sjfb8856606 	rcu_config.v = rv;
1315*2d9fd380Sjfb8856606 
1316*2d9fd380Sjfb8856606 	if (rte_hash_rcu_qsbr_add(tbl_rwc_test_param.h, &rcu_config) < 0) {
1317*2d9fd380Sjfb8856606 		printf("RCU init in hash failed\n");
1318*2d9fd380Sjfb8856606 		goto err;
1319*2d9fd380Sjfb8856606 	}
1320*2d9fd380Sjfb8856606 
1321*2d9fd380Sjfb8856606 	for (n = 0; n < NUM_TEST; n++) {
1322*2d9fd380Sjfb8856606 		unsigned int tot_lcore = rte_lcore_count();
1323*2d9fd380Sjfb8856606 		if (tot_lcore < rwc_core_cnt[n] + 3)
1324*2d9fd380Sjfb8856606 			goto finish;
1325*2d9fd380Sjfb8856606 
1326*2d9fd380Sjfb8856606 		/* Calculate keys added by each writer */
1327*2d9fd380Sjfb8856606 		tbl_rwc_test_param.single_insert =
1328*2d9fd380Sjfb8856606 			tbl_rwc_test_param.count_keys_no_ks /
1329*2d9fd380Sjfb8856606 				rwc_core_cnt[n];
1330*2d9fd380Sjfb8856606 		printf("\nNumber of writers: %u\n", rwc_core_cnt[n]);
1331*2d9fd380Sjfb8856606 
1332*2d9fd380Sjfb8856606 		__atomic_store_n(&gwrites, 0, __ATOMIC_RELAXED);
1333*2d9fd380Sjfb8856606 		__atomic_store_n(&gwrite_cycles, 0, __ATOMIC_RELAXED);
1334*2d9fd380Sjfb8856606 
1335*2d9fd380Sjfb8856606 		rte_hash_reset(tbl_rwc_test_param.h);
1336*2d9fd380Sjfb8856606 		rte_rcu_qsbr_init(rv, RTE_MAX_LCORE);
1337*2d9fd380Sjfb8856606 
1338*2d9fd380Sjfb8856606 		write_type = WRITE_NO_KEY_SHIFT;
1339*2d9fd380Sjfb8856606 		if (write_keys(write_type) < 0)
1340*2d9fd380Sjfb8856606 			goto err;
1341*2d9fd380Sjfb8856606 		write_type = WRITE_KEY_SHIFT;
1342*2d9fd380Sjfb8856606 		if (write_keys(write_type) < 0)
1343*2d9fd380Sjfb8856606 			goto err;
1344*2d9fd380Sjfb8856606 
1345*2d9fd380Sjfb8856606 		/* Launch 2 readers */
1346*2d9fd380Sjfb8856606 		for (i = 1; i <= 2; i++)
1347*2d9fd380Sjfb8856606 			rte_eal_remote_launch(test_hash_rcu_qsbr_reader, NULL,
1348*2d9fd380Sjfb8856606 					      enabled_core_ids[i]);
1349*2d9fd380Sjfb8856606 		pos_core = 0;
1350*2d9fd380Sjfb8856606 		/* Launch writer(s) */
1351*2d9fd380Sjfb8856606 		for (; i <= rwc_core_cnt[n] + 2; i++) {
1352*2d9fd380Sjfb8856606 			rte_eal_remote_launch(test_hash_rcu_qsbr_writer,
1353*2d9fd380Sjfb8856606 				(void *)(uintptr_t)pos_core,
1354*2d9fd380Sjfb8856606 				enabled_core_ids[i]);
1355*2d9fd380Sjfb8856606 			pos_core++;
1356*2d9fd380Sjfb8856606 		}
1357*2d9fd380Sjfb8856606 
1358*2d9fd380Sjfb8856606 		/* Wait for writers to complete */
1359*2d9fd380Sjfb8856606 		for (i = 3; i <= rwc_core_cnt[n] + 2; i++)
1360*2d9fd380Sjfb8856606 			rte_eal_wait_lcore(enabled_core_ids[i]);
1361*2d9fd380Sjfb8856606 
1362*2d9fd380Sjfb8856606 		writer_done = 1;
1363*2d9fd380Sjfb8856606 
1364*2d9fd380Sjfb8856606 		/* Wait for readers to complete */
1365*2d9fd380Sjfb8856606 		rte_eal_mp_wait_lcore();
1366*2d9fd380Sjfb8856606 
1367*2d9fd380Sjfb8856606 		unsigned long long cycles_per_write_operation =
1368*2d9fd380Sjfb8856606 			__atomic_load_n(&gwrite_cycles, __ATOMIC_RELAXED) /
1369*2d9fd380Sjfb8856606 			__atomic_load_n(&gwrites, __ATOMIC_RELAXED);
1370*2d9fd380Sjfb8856606 		rwc_perf_results->writer_add_del[n]
1371*2d9fd380Sjfb8856606 					= cycles_per_write_operation;
1372*2d9fd380Sjfb8856606 		printf("Cycles per write operation: %llu\n",
1373*2d9fd380Sjfb8856606 				cycles_per_write_operation);
1374*2d9fd380Sjfb8856606 	}
1375*2d9fd380Sjfb8856606 
1376*2d9fd380Sjfb8856606 finish:
1377*2d9fd380Sjfb8856606 	rte_hash_free(tbl_rwc_test_param.h);
1378*2d9fd380Sjfb8856606 	rte_free(rv);
1379*2d9fd380Sjfb8856606 	return 0;
1380*2d9fd380Sjfb8856606 
1381*2d9fd380Sjfb8856606 err:
1382*2d9fd380Sjfb8856606 	writer_done = 1;
1383*2d9fd380Sjfb8856606 	rte_eal_mp_wait_lcore();
1384*2d9fd380Sjfb8856606 	rte_hash_free(tbl_rwc_test_param.h);
1385*2d9fd380Sjfb8856606 	rte_free(rv);
1386*2d9fd380Sjfb8856606 	return -1;
1387*2d9fd380Sjfb8856606 }
1388*2d9fd380Sjfb8856606 
13890c6bd470Sfengbojiang static int
test_hash_readwrite_lf_perf_main(void)13900c6bd470Sfengbojiang test_hash_readwrite_lf_perf_main(void)
13910c6bd470Sfengbojiang {
13920c6bd470Sfengbojiang 	/*
13930c6bd470Sfengbojiang 	 * Variables used to choose different tests.
13940c6bd470Sfengbojiang 	 * rwc_lf indicates if read-write concurrency lock-free support is
13950c6bd470Sfengbojiang 	 * enabled.
13960c6bd470Sfengbojiang 	 * htm indicates if Hardware transactional memory support is enabled.
13970c6bd470Sfengbojiang 	 */
13980c6bd470Sfengbojiang 	int rwc_lf = 0;
13990c6bd470Sfengbojiang 	int htm;
14000c6bd470Sfengbojiang 	int ext_bkt = 0;
14010c6bd470Sfengbojiang 
14020c6bd470Sfengbojiang 	if (rte_lcore_count() < 2) {
14030c6bd470Sfengbojiang 		printf("Not enough cores for hash_readwrite_lf_perf_autotest, expecting at least 2\n");
14040c6bd470Sfengbojiang 		return TEST_SKIPPED;
14050c6bd470Sfengbojiang 	}
14060c6bd470Sfengbojiang 
14070c6bd470Sfengbojiang 	setlocale(LC_NUMERIC, "");
14080c6bd470Sfengbojiang 
14090c6bd470Sfengbojiang 	/* Reset tbl_rwc_test_param to discard values from previous run */
14100c6bd470Sfengbojiang 	memset(&tbl_rwc_test_param, 0, sizeof(tbl_rwc_test_param));
14110c6bd470Sfengbojiang 
14120c6bd470Sfengbojiang 	if (rte_tm_supported())
14130c6bd470Sfengbojiang 		htm = 1;
14140c6bd470Sfengbojiang 	else
14150c6bd470Sfengbojiang 		htm = 0;
14160c6bd470Sfengbojiang 
14170c6bd470Sfengbojiang 	if (generate_keys() != 0)
14180c6bd470Sfengbojiang 		return -1;
14190c6bd470Sfengbojiang 	if (get_enabled_cores_list() != 0)
14200c6bd470Sfengbojiang 		return -1;
14210c6bd470Sfengbojiang 
14220c6bd470Sfengbojiang 	if (RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF) {
14230c6bd470Sfengbojiang 		rwc_lf = 1;
14240c6bd470Sfengbojiang 		ext_bkt = 1;
14250c6bd470Sfengbojiang 		printf("Test lookup with read-write concurrency lock free support"
14260c6bd470Sfengbojiang 		       " enabled\n");
14270c6bd470Sfengbojiang 		if (test_hash_add_no_ks_lookup_hit(&rwc_lf_results, rwc_lf,
14280c6bd470Sfengbojiang 							htm, ext_bkt) < 0)
14290c6bd470Sfengbojiang 			return -1;
14300c6bd470Sfengbojiang 		if (test_hash_add_no_ks_lookup_miss(&rwc_lf_results, rwc_lf,
14310c6bd470Sfengbojiang 							htm, ext_bkt) < 0)
14320c6bd470Sfengbojiang 			return -1;
14330c6bd470Sfengbojiang 		if (test_hash_add_ks_lookup_hit_non_sp(&rwc_lf_results, rwc_lf,
14340c6bd470Sfengbojiang 							htm, ext_bkt) < 0)
14350c6bd470Sfengbojiang 			return -1;
14360c6bd470Sfengbojiang 		if (test_hash_add_ks_lookup_hit_sp(&rwc_lf_results, rwc_lf,
14370c6bd470Sfengbojiang 							htm, ext_bkt) < 0)
14380c6bd470Sfengbojiang 			return -1;
14390c6bd470Sfengbojiang 		if (test_hash_add_ks_lookup_miss(&rwc_lf_results, rwc_lf, htm,
14400c6bd470Sfengbojiang 						 ext_bkt) < 0)
14410c6bd470Sfengbojiang 			return -1;
14420c6bd470Sfengbojiang 		if (test_hash_multi_add_lookup(&rwc_lf_results, rwc_lf, htm,
14430c6bd470Sfengbojiang 					       ext_bkt) < 0)
14440c6bd470Sfengbojiang 			return -1;
14450c6bd470Sfengbojiang 		if (test_hash_add_ks_lookup_hit_extbkt(&rwc_lf_results, rwc_lf,
14460c6bd470Sfengbojiang 							htm, ext_bkt) < 0)
14470c6bd470Sfengbojiang 			return -1;
1448*2d9fd380Sjfb8856606 		if (test_hash_rcu_qsbr_writer_perf(&rwc_lf_results, rwc_lf,
1449*2d9fd380Sjfb8856606 						   htm, ext_bkt) < 0)
1450*2d9fd380Sjfb8856606 			return -1;
14510c6bd470Sfengbojiang 	}
14520c6bd470Sfengbojiang 	printf("\nTest lookup with read-write concurrency lock free support"
14530c6bd470Sfengbojiang 	       " disabled\n");
14540c6bd470Sfengbojiang 	rwc_lf = 0;
14550c6bd470Sfengbojiang 	if (!htm) {
14560c6bd470Sfengbojiang 		printf("With HTM Disabled\n");
14570c6bd470Sfengbojiang 		if (!RUN_WITH_HTM_DISABLED) {
14580c6bd470Sfengbojiang 			printf("Enable RUN_WITH_HTM_DISABLED to test with"
14590c6bd470Sfengbojiang 			       " lock-free disabled");
14600c6bd470Sfengbojiang 			goto results;
14610c6bd470Sfengbojiang 		}
14620c6bd470Sfengbojiang 	} else
14630c6bd470Sfengbojiang 		printf("With HTM Enabled\n");
14640c6bd470Sfengbojiang 	if (test_hash_add_no_ks_lookup_hit(&rwc_non_lf_results, rwc_lf, htm,
14650c6bd470Sfengbojiang 					   ext_bkt) < 0)
14660c6bd470Sfengbojiang 		return -1;
14670c6bd470Sfengbojiang 	if (test_hash_add_no_ks_lookup_miss(&rwc_non_lf_results, rwc_lf, htm,
14680c6bd470Sfengbojiang 						ext_bkt) < 0)
14690c6bd470Sfengbojiang 		return -1;
14700c6bd470Sfengbojiang 	if (test_hash_add_ks_lookup_hit_non_sp(&rwc_non_lf_results, rwc_lf,
14710c6bd470Sfengbojiang 						htm, ext_bkt) < 0)
14720c6bd470Sfengbojiang 		return -1;
14730c6bd470Sfengbojiang 	if (test_hash_add_ks_lookup_hit_sp(&rwc_non_lf_results, rwc_lf, htm,
14740c6bd470Sfengbojiang 						ext_bkt) < 0)
14750c6bd470Sfengbojiang 		return -1;
14760c6bd470Sfengbojiang 	if (test_hash_add_ks_lookup_miss(&rwc_non_lf_results, rwc_lf, htm,
14770c6bd470Sfengbojiang 					 ext_bkt) < 0)
14780c6bd470Sfengbojiang 		return -1;
14790c6bd470Sfengbojiang 	if (test_hash_multi_add_lookup(&rwc_non_lf_results, rwc_lf, htm,
14800c6bd470Sfengbojiang 							ext_bkt) < 0)
14810c6bd470Sfengbojiang 		return -1;
14820c6bd470Sfengbojiang 	if (test_hash_add_ks_lookup_hit_extbkt(&rwc_non_lf_results, rwc_lf,
14830c6bd470Sfengbojiang 						htm, ext_bkt) < 0)
14840c6bd470Sfengbojiang 		return -1;
14850c6bd470Sfengbojiang results:
14860c6bd470Sfengbojiang 	printf("\n\t\t\t\t\t\t********** Results summary **********\n\n");
14870c6bd470Sfengbojiang 	int i, j, k;
14880c6bd470Sfengbojiang 	for (j = 0; j < 2; j++) {
14890c6bd470Sfengbojiang 		if (j == 1)
14900c6bd470Sfengbojiang 			printf("\n\t\t\t\t\t#######********** Bulk Lookup "
14910c6bd470Sfengbojiang 			       "**********#######\n\n");
14920c6bd470Sfengbojiang 		printf("_______\t\t_______\t\t_________\t___\t\t_________\t\t"
14930c6bd470Sfengbojiang 			"\t\t\t\t_________________\n");
14940c6bd470Sfengbojiang 		printf("Writers\t\tReaders\t\tLock-free\tHTM\t\tTest-case\t\t\t"
14950c6bd470Sfengbojiang 		       "\t\t\tCycles per lookup\n");
14960c6bd470Sfengbojiang 		printf("_______\t\t_______\t\t_________\t___\t\t_________\t\t\t"
14970c6bd470Sfengbojiang 		       "\t\t\t_________________\n");
14980c6bd470Sfengbojiang 		for (i = 0; i < NUM_TEST; i++) {
14990c6bd470Sfengbojiang 			printf("%u\t\t%u\t\t", 1, rwc_core_cnt[i]);
15000c6bd470Sfengbojiang 			printf("Enabled\t\t");
15010c6bd470Sfengbojiang 			printf("N/A\t\t");
15020c6bd470Sfengbojiang 			printf("Hash add - no key-shifts, lookup - hit\t\t\t\t"
15030c6bd470Sfengbojiang 				"%u\n\t\t\t\t\t\t\t\t",
15040c6bd470Sfengbojiang 				rwc_lf_results.w_no_ks_r_hit[j][i]);
15050c6bd470Sfengbojiang 			printf("Hash add - no key-shifts, lookup - miss\t\t\t\t"
15060c6bd470Sfengbojiang 				"%u\n\t\t\t\t\t\t\t\t",
15070c6bd470Sfengbojiang 				rwc_lf_results.w_no_ks_r_miss[j][i]);
15080c6bd470Sfengbojiang 			printf("Hash add - key-shifts, lookup - hit"
15090c6bd470Sfengbojiang 			       "(non-shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
15100c6bd470Sfengbojiang 			       rwc_lf_results.w_ks_r_hit_nsp[j][i]);
15110c6bd470Sfengbojiang 			printf("Hash add - key-shifts, lookup - hit "
15120c6bd470Sfengbojiang 			       "(shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
15130c6bd470Sfengbojiang 			       rwc_lf_results.w_ks_r_hit_sp[j][i]);
15140c6bd470Sfengbojiang 			printf("Hash add - key-shifts, Hash lookup miss\t\t\t\t"
15150c6bd470Sfengbojiang 				"%u\n\t\t\t\t\t\t\t\t",
15160c6bd470Sfengbojiang 				rwc_lf_results.w_ks_r_miss[j][i]);
15170c6bd470Sfengbojiang 			printf("Hash add - key-shifts, Hash lookup hit (ext_bkt)\t\t"
15180c6bd470Sfengbojiang 				"%u\n\n\t\t\t\t",
15190c6bd470Sfengbojiang 				rwc_lf_results.w_ks_r_hit_extbkt[j][i]);
15200c6bd470Sfengbojiang 
15210c6bd470Sfengbojiang 			printf("Disabled\t");
15220c6bd470Sfengbojiang 			if (htm)
15230c6bd470Sfengbojiang 				printf("Enabled\t\t");
15240c6bd470Sfengbojiang 			else
15250c6bd470Sfengbojiang 				printf("Disabled\t");
15260c6bd470Sfengbojiang 			printf("Hash add - no key-shifts, lookup - hit\t\t\t\t"
15270c6bd470Sfengbojiang 				"%u\n\t\t\t\t\t\t\t\t",
15280c6bd470Sfengbojiang 				rwc_non_lf_results.w_no_ks_r_hit[j][i]);
15290c6bd470Sfengbojiang 			printf("Hash add - no key-shifts, lookup - miss\t\t\t\t"
15300c6bd470Sfengbojiang 				"%u\n\t\t\t\t\t\t\t\t",
15310c6bd470Sfengbojiang 				rwc_non_lf_results.w_no_ks_r_miss[j][i]);
15320c6bd470Sfengbojiang 			printf("Hash add - key-shifts, lookup - hit "
15330c6bd470Sfengbojiang 			       "(non-shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
15340c6bd470Sfengbojiang 			       rwc_non_lf_results.w_ks_r_hit_nsp[j][i]);
15350c6bd470Sfengbojiang 			printf("Hash add - key-shifts, lookup - hit "
15360c6bd470Sfengbojiang 			       "(shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
15370c6bd470Sfengbojiang 			       rwc_non_lf_results.w_ks_r_hit_sp[j][i]);
15380c6bd470Sfengbojiang 			printf("Hash add - key-shifts, Hash lookup miss\t\t\t\t"
15390c6bd470Sfengbojiang 			       "%u\n\t\t\t\t\t\t\t\t",
15400c6bd470Sfengbojiang 			       rwc_non_lf_results.w_ks_r_miss[j][i]);
15410c6bd470Sfengbojiang 			printf("Hash add - key-shifts, Hash lookup hit (ext_bkt)\t\t"
15420c6bd470Sfengbojiang 				"%u\n",
15430c6bd470Sfengbojiang 				rwc_non_lf_results.w_ks_r_hit_extbkt[j][i]);
15440c6bd470Sfengbojiang 
15450c6bd470Sfengbojiang 			printf("_______\t\t_______\t\t_________\t___\t\t"
15460c6bd470Sfengbojiang 			       "_________\t\t\t\t\t\t_________________\n");
15470c6bd470Sfengbojiang 		}
15480c6bd470Sfengbojiang 
15490c6bd470Sfengbojiang 		for (i = 1; i < NUM_TEST; i++) {
15500c6bd470Sfengbojiang 			for (k = 0; k < NUM_TEST; k++) {
15510c6bd470Sfengbojiang 				printf("%u", rwc_core_cnt[i]);
15520c6bd470Sfengbojiang 				printf("\t\t%u\t\t", rwc_core_cnt[k]);
15530c6bd470Sfengbojiang 				printf("Enabled\t\t");
15540c6bd470Sfengbojiang 				printf("N/A\t\t");
15550c6bd470Sfengbojiang 				printf("Multi-add-lookup\t\t\t\t\t\t%u\n\n\t\t"
15560c6bd470Sfengbojiang 				       "\t\t",
15570c6bd470Sfengbojiang 				       rwc_lf_results.multi_rw[i][j][k]);
15580c6bd470Sfengbojiang 				printf("Disabled\t");
15590c6bd470Sfengbojiang 				if (htm)
15600c6bd470Sfengbojiang 					printf("Enabled\t\t");
15610c6bd470Sfengbojiang 				else
15620c6bd470Sfengbojiang 					printf("Disabled\t");
15630c6bd470Sfengbojiang 				printf("Multi-add-lookup\t\t\t\t\t\t%u\n",
15640c6bd470Sfengbojiang 				       rwc_non_lf_results.multi_rw[i][j][k]);
15650c6bd470Sfengbojiang 
15660c6bd470Sfengbojiang 				printf("_______\t\t_______\t\t_________\t___"
15670c6bd470Sfengbojiang 				       "\t\t_________\t\t\t\t\t\t"
15680c6bd470Sfengbojiang 				       "_________________\n");
15690c6bd470Sfengbojiang 			}
15700c6bd470Sfengbojiang 		}
15710c6bd470Sfengbojiang 	}
15720c6bd470Sfengbojiang 	rte_free(tbl_rwc_test_param.keys);
15730c6bd470Sfengbojiang 	rte_free(tbl_rwc_test_param.keys_no_ks);
15740c6bd470Sfengbojiang 	rte_free(tbl_rwc_test_param.keys_ks);
15750c6bd470Sfengbojiang 	rte_free(tbl_rwc_test_param.keys_absent);
15760c6bd470Sfengbojiang 	rte_free(tbl_rwc_test_param.keys_shift_path);
15770c6bd470Sfengbojiang 	rte_free(tbl_rwc_test_param.keys_non_shift_path);
15780c6bd470Sfengbojiang 	rte_free(tbl_rwc_test_param.keys_ext_bkt);
15790c6bd470Sfengbojiang 	rte_free(tbl_rwc_test_param.keys_ks_extbkt);
15800c6bd470Sfengbojiang 	return 0;
15810c6bd470Sfengbojiang }
15820c6bd470Sfengbojiang 
15830c6bd470Sfengbojiang REGISTER_TEST_COMMAND(hash_readwrite_lf_perf_autotest,
15840c6bd470Sfengbojiang 	test_hash_readwrite_lf_perf_main);
1585