[dpdk-dev] [PATCH v5 4/4] test/hash: add tests for integrated RCU QSBR

Dharmik Thakkar Dharmik.Thakkar at arm.com
Wed Oct 21 06:55:46 CEST 2020



> On Oct 20, 2020, at 10:54 PM, Wang, Yipeng1 <yipeng1.wang at intel.com> wrote:
> 
>> -----Original Message-----
>> From: Dharmik Thakkar <dharmik.thakkar at arm.com>
>> Sent: Tuesday, October 20, 2020 9:13 AM
>> To: Wang, Yipeng1 <yipeng1.wang at intel.com>; Gobriel, Sameh
>> <sameh.gobriel at intel.com>; Richardson, Bruce <bruce.richardson at intel.com>
>> Cc: dev at dpdk.org; nd at arm.com; Dharmik Thakkar
>> <dharmik.thakkar at arm.com>
>> Subject: [PATCH v5 4/4] test/hash: add tests for integrated RCU QSBR
>> 
>> Add functional and performance tests for the integrated RCU QSBR.
>> 
>> Suggested-by: Honnappa Nagarahalli <honnappa.nagarahalli at arm.com>
>> Signed-off-by: Dharmik Thakkar <dharmik.thakkar at arm.com>
>> Reviewed-by: Ruifeng Wang <ruifeng.wang at arm.com>
>> ---
>> app/test/test_hash.c                   | 390 ++++++++++++++++++++++++-
>> app/test/test_hash_readwrite_lf_perf.c | 170 ++++++++++-
>> 2 files changed, 556 insertions(+), 4 deletions(-)
>> 
>> diff --git a/app/test/test_hash.c b/app/test/test_hash.c index
>> 990a1815f893..22b47b3e7728 100644
>> --- a/app/test/test_hash.c
>> +++ b/app/test/test_hash.c
>> @@ -52,7 +52,7 @@ static uint32_t hashtest_key_lens[] = {0, 2, 4, 5, 6, 7, 8, 10,
>> 11, 15, 16, 21,
>> 	}								\
>> } while(0)
>> 
>> -#define RETURN_IF_ERROR_FBK(cond, str, ...) do {
>> 	\
>> +#define RETURN_IF_ERROR_FBK(cond, str, ...) do {			\
>> 	if (cond) {							\
>> 		printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__);
>> \
>> 		if (handle) rte_fbk_hash_free(handle);			\
>> @@ -60,6 +60,20 @@ static uint32_t hashtest_key_lens[] = {0, 2, 4, 5, 6, 7, 8,
>> 10, 11, 15, 16, 21,
>> 	}								\
>> } while(0)
>> 
>> +#define RETURN_IF_ERROR_RCU_QSBR(cond, str, ...) do {
>> 	\
>> +	if (cond) {							\
>> +		printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__);
>> \
>> +		if (rcu_cfg.mode == RTE_HASH_QSBR_MODE_SYNC) {
>> 	\
>> +			writer_done = 1;				\
>> +			/* Wait until reader exited. */			\
>> +			rte_eal_mp_wait_lcore();			\
>> +		}							\
>> +		if (g_handle) rte_hash_free(g_handle);			\
>> +		if (g_qsv) rte_free(g_qsv);				\
>> +		return -1;						\
>> +	}								\
>> +} while(0)
>> +
>> /* 5-tuple key type */
>> struct flow_key {
>> 	uint32_t ip_src;
>> @@ -1801,6 +1815,365 @@ test_hash_add_delete_jhash_3word(void)
>> 	return ret;
>> }
>> 
>> +static struct rte_hash *g_handle;
>> +static struct rte_rcu_qsbr *g_qsv;
>> +static volatile uint8_t writer_done;
>> +struct flow_key g_rand_keys[9];
>> +/*
>> + * rte_hash_rcu_qsbr_add positive and negative tests.
>> + *  - Add RCU QSBR variable to Hash
>> + *  - Add another RCU QSBR variable to Hash
>> + *  - Check returns
>> + */
>> +static int
>> +test_hash_rcu_qsbr_add(void)
>> +{
>> +	size_t sz;
>> +	struct rte_rcu_qsbr *qsv2 = NULL;
>> +	int32_t status;
>> +	struct rte_hash_rcu_config rcu_cfg = {0};
>> +
>> +	struct rte_hash_parameters params;
>> +
>> +	printf("\n# Running RCU QSBR add tests\n");
>> +	memcpy(&params, &ut_params, sizeof(params));
>> +	params.name = "test_hash_rcu_qsbr_add";
>> +	params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF
>> |
>> +
>> 	RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
>> +	g_handle = rte_hash_create(&params);
>> +	RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation
>> failed");
>> +
>> +	/* Create RCU QSBR variable */
>> +	sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
>> +	g_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
>> +					RTE_CACHE_LINE_SIZE,
>> SOCKET_ID_ANY);
>> +	RETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL,
>> +				 "RCU QSBR variable creation failed");
>> +
>> +	status = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE);
> [Wang, Yipeng] It reminds me that could we hide this function in the rte_cuckoo_hash.c as well?
> I saw most of the rcu related functions are hidden in the hash implementation, it would be less confusing if we hide this one as well.

Yes, I think this can be hidden within rte_hash_reset() and rte_hash_rcu_qsbr_add()

> 
>> +	RETURN_IF_ERROR_RCU_QSBR(status != 0,
>> +				 "RCU QSBR variable initialization failed");
>> +
>> +	rcu_cfg.v = g_qsv;
>> +	/* Invalid QSBR mode */
>> +	rcu_cfg.mode = 2;
> [Wang, Yipeng] Any other way rather than hardcode 2 here? Maybe just a large number like 0xff?

Yes, I can use 0xxff

> 
>> +	status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);
>> +	RETURN_IF_ERROR_RCU_QSBR(status == 0, "Invalid QSBR mode test
>> +failed");
>> +
>> +	rcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ;
> [Wang, Yipeng] This reminds me that if there is an explanation on the difference of the two modes for users to easy to choose?

It is available within rte_hash.h

>  
> 
>> +	/* Attach RCU QSBR to hash table */
>> +	status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);
>> +	RETURN_IF_ERROR_RCU_QSBR(status != 0,
>> +				 "Attach RCU QSBR to hash table failed");
>> +
>> +	/* Create and attach another RCU QSBR to hash table */
>> +	qsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
>> +					RTE_CACHE_LINE_SIZE,
>> SOCKET_ID_ANY);
>> +	RETURN_IF_ERROR_RCU_QSBR(qsv2 == NULL,
>> +				 "RCU QSBR variable creation failed");
>> +
>> +	rcu_cfg.v = qsv2;
>> +	rcu_cfg.mode = RTE_HASH_QSBR_MODE_SYNC;
>> +	status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);
>> +	rte_free(qsv2);
>> +	RETURN_IF_ERROR_RCU_QSBR(status == 0,
>> +			"Attach RCU QSBR to hash table succeeded where
>> failure"
>> +			" is expected");
>> +
>> +	rte_hash_free(g_handle);
>> +	rte_free(g_qsv);
>> +
>> +	return 0;
>> +}
> <...>



More information about the dev mailing list