xref: /dpdk/app/test/test_thash.c (revision 89398ecec0486f91e1d9302ae2fb454f3b2dd012)
10c6c8320SVladimir Medvedkin /* SPDX-License-Identifier: BSD-3-Clause
20c6c8320SVladimir Medvedkin  * Copyright(c) 2015-2019 Vladimir Medvedkin <medvedkinv@gmail.com>
3a9de470cSBruce Richardson  */
4a9de470cSBruce Richardson 
5a9de470cSBruce Richardson #include <rte_common.h>
6a9de470cSBruce Richardson #include <rte_eal.h>
7a9de470cSBruce Richardson #include <rte_ip.h>
828ebff11SVladimir Medvedkin #include <rte_random.h>
94fd8c4cbSVladimir Medvedkin #include <rte_malloc.h>
10*89398eceSVladimir Medvedkin #include <rte_byteorder.h>
11a9de470cSBruce Richardson 
12a9de470cSBruce Richardson #include "test.h"
13a9de470cSBruce Richardson 
14a9de470cSBruce Richardson #include <rte_thash.h>
15a9de470cSBruce Richardson 
1628ebff11SVladimir Medvedkin #define HASH_MSK(reta_sz)	((1 << reta_sz) - 1)
1728ebff11SVladimir Medvedkin #define TUPLE_SZ	(RTE_THASH_V4_L4_LEN * 4)
1828ebff11SVladimir Medvedkin 
19a9de470cSBruce Richardson struct test_thash_v4 {
20a9de470cSBruce Richardson 	uint32_t	dst_ip;
21a9de470cSBruce Richardson 	uint32_t	src_ip;
22a9de470cSBruce Richardson 	uint16_t	dst_port;
23a9de470cSBruce Richardson 	uint16_t	src_port;
24a9de470cSBruce Richardson 	uint32_t	hash_l3;
25a9de470cSBruce Richardson 	uint32_t	hash_l3l4;
26a9de470cSBruce Richardson };
27a9de470cSBruce Richardson 
28a9de470cSBruce Richardson struct test_thash_v6 {
29431e6b9aSRobin Jarry 	struct rte_ipv6_addr dst_ip;
30431e6b9aSRobin Jarry 	struct rte_ipv6_addr src_ip;
31a9de470cSBruce Richardson 	uint16_t	dst_port;
32a9de470cSBruce Richardson 	uint16_t	src_port;
33a9de470cSBruce Richardson 	uint32_t	hash_l3;
34a9de470cSBruce Richardson 	uint32_t	hash_l3l4;
35a9de470cSBruce Richardson };
36a9de470cSBruce Richardson 
37a9de470cSBruce Richardson /*From 82599 Datasheet 7.1.2.8.3 RSS Verification Suite*/
38a9de470cSBruce Richardson struct test_thash_v4 v4_tbl[] = {
390c9da755SDavid Marchand {RTE_IPV4(161, 142, 100, 80), RTE_IPV4(66, 9, 149, 187),
40a9de470cSBruce Richardson 	1766, 2794, 0x323e8fc2, 0x51ccc178},
410c9da755SDavid Marchand {RTE_IPV4(65, 69, 140, 83), RTE_IPV4(199, 92, 111, 2),
42a9de470cSBruce Richardson 	4739, 14230, 0xd718262a, 0xc626b0ea},
430c9da755SDavid Marchand {RTE_IPV4(12, 22, 207, 184), RTE_IPV4(24, 19, 198, 95),
44a9de470cSBruce Richardson 	38024, 12898, 0xd2d0a5de, 0x5c2b394a},
450c9da755SDavid Marchand {RTE_IPV4(209, 142, 163, 6), RTE_IPV4(38, 27, 205, 30),
46a9de470cSBruce Richardson 	2217, 48228, 0x82989176, 0xafc7327f},
470c9da755SDavid Marchand {RTE_IPV4(202, 188, 127, 2), RTE_IPV4(153, 39, 163, 191),
48a9de470cSBruce Richardson 	1303, 44251, 0x5d1809c5, 0x10e828a2},
49a9de470cSBruce Richardson };
50a9de470cSBruce Richardson 
51a9de470cSBruce Richardson struct test_thash_v6 v6_tbl[] = {
52a9de470cSBruce Richardson /*3ffe:2501:200:3::1*/
53431e6b9aSRobin Jarry {RTE_IPV6(0x3ffe, 0x2501, 0x0200, 0x0003, 0, 0, 0, 0x0001),
54a9de470cSBruce Richardson /*3ffe:2501:200:1fff::7*/
55431e6b9aSRobin Jarry RTE_IPV6(0x3ffe, 0x2501, 0x0200, 0x1fff, 0, 0, 0, 0x0007),
56a9de470cSBruce Richardson 1766, 2794, 0x2cc18cd5, 0x40207d3d},
57a9de470cSBruce Richardson /*ff02::1*/
58431e6b9aSRobin Jarry {RTE_IPV6(0xff02, 0, 0, 0, 0, 0, 0, 0x0001),
59a9de470cSBruce Richardson /*3ffe:501:8::260:97ff:fe40:efab*/
60431e6b9aSRobin Jarry RTE_IPV6(0x3ffe, 0x0501, 0x0008, 0, 0x0260, 0x97ff, 0xfe40, 0xefab),
61a9de470cSBruce Richardson 4739, 14230, 0x0f0c461c, 0xdde51bbf},
62a9de470cSBruce Richardson /*fe80::200:f8ff:fe21:67cf*/
63431e6b9aSRobin Jarry {RTE_IPV6(0xfe80, 0, 0, 0, 0x0200, 0xf8ff, 0xfe21, 0x67cf),
64a9de470cSBruce Richardson /*3ffe:1900:4545:3:200:f8ff:fe21:67cf*/
65431e6b9aSRobin Jarry RTE_IPV6(0x3ffe, 0x1900, 0x4545, 0x0003, 0x0200, 0xf8ff, 0xfe21, 0x67cf),
66a9de470cSBruce Richardson 38024, 44251, 0x4b61e985, 0x02d1feef},
67a9de470cSBruce Richardson };
68a9de470cSBruce Richardson 
69a9de470cSBruce Richardson uint8_t default_rss_key[] = {
70a9de470cSBruce Richardson 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
71a9de470cSBruce Richardson 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
72a9de470cSBruce Richardson 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
73a9de470cSBruce Richardson 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
74a9de470cSBruce Richardson 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
75a9de470cSBruce Richardson };
76a9de470cSBruce Richardson 
774fd8c4cbSVladimir Medvedkin static const uint8_t big_rss_key[] = {
784fd8c4cbSVladimir Medvedkin 	0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
794fd8c4cbSVladimir Medvedkin 	0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
804fd8c4cbSVladimir Medvedkin 	0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
814fd8c4cbSVladimir Medvedkin 	0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
824fd8c4cbSVladimir Medvedkin 	0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
834fd8c4cbSVladimir Medvedkin 	0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
844fd8c4cbSVladimir Medvedkin 	0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
854fd8c4cbSVladimir Medvedkin 	0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
864fd8c4cbSVladimir Medvedkin 	0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
874fd8c4cbSVladimir Medvedkin 	0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
884fd8c4cbSVladimir Medvedkin 	0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
894fd8c4cbSVladimir Medvedkin 	0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
904fd8c4cbSVladimir Medvedkin 	0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
914fd8c4cbSVladimir Medvedkin 	0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
924fd8c4cbSVladimir Medvedkin 	0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
934fd8c4cbSVladimir Medvedkin 	0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
944fd8c4cbSVladimir Medvedkin 	0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
954fd8c4cbSVladimir Medvedkin 	0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
964fd8c4cbSVladimir Medvedkin 	0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
974fd8c4cbSVladimir Medvedkin 	0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
984fd8c4cbSVladimir Medvedkin 	0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
994fd8c4cbSVladimir Medvedkin 	0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
1004fd8c4cbSVladimir Medvedkin 	0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
1014fd8c4cbSVladimir Medvedkin 	0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
1024fd8c4cbSVladimir Medvedkin 	0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
1034fd8c4cbSVladimir Medvedkin };
1044fd8c4cbSVladimir Medvedkin 
105a9de470cSBruce Richardson static int
10628ebff11SVladimir Medvedkin test_toeplitz_hash_calc(void)
107a9de470cSBruce Richardson {
108431e6b9aSRobin Jarry 	uint32_t i;
109a9de470cSBruce Richardson 	union rte_thash_tuple tuple;
110a9de470cSBruce Richardson 	uint32_t rss_l3, rss_l3l4;
111a9de470cSBruce Richardson 	uint8_t rss_key_be[RTE_DIM(default_rss_key)];
112a7c528e5SOlivier Matz 	struct rte_ipv6_hdr ipv6_hdr;
113a9de470cSBruce Richardson 
114a9de470cSBruce Richardson 	/* Convert RSS key*/
115a9de470cSBruce Richardson 	rte_convert_rss_key((uint32_t *)&default_rss_key,
116a9de470cSBruce Richardson 		(uint32_t *)rss_key_be, RTE_DIM(default_rss_key));
117a9de470cSBruce Richardson 
118a9de470cSBruce Richardson 
119a9de470cSBruce Richardson 	for (i = 0; i < RTE_DIM(v4_tbl); i++) {
120a9de470cSBruce Richardson 		tuple.v4.src_addr = v4_tbl[i].src_ip;
121a9de470cSBruce Richardson 		tuple.v4.dst_addr = v4_tbl[i].dst_ip;
122a9de470cSBruce Richardson 		tuple.v4.sport = v4_tbl[i].src_port;
123a9de470cSBruce Richardson 		tuple.v4.dport = v4_tbl[i].dst_port;
124a9de470cSBruce Richardson 		/*Calculate hash with original key*/
125a9de470cSBruce Richardson 		rss_l3 = rte_softrss((uint32_t *)&tuple,
126a9de470cSBruce Richardson 				RTE_THASH_V4_L3_LEN, default_rss_key);
127a9de470cSBruce Richardson 		rss_l3l4 = rte_softrss((uint32_t *)&tuple,
128a9de470cSBruce Richardson 				RTE_THASH_V4_L4_LEN, default_rss_key);
129a9de470cSBruce Richardson 		if ((rss_l3 != v4_tbl[i].hash_l3) ||
130a9de470cSBruce Richardson 				(rss_l3l4 != v4_tbl[i].hash_l3l4))
13128ebff11SVladimir Medvedkin 			return -TEST_FAILED;
132a9de470cSBruce Richardson 		/*Calculate hash with converted key*/
133a9de470cSBruce Richardson 		rss_l3 = rte_softrss_be((uint32_t *)&tuple,
134a9de470cSBruce Richardson 				RTE_THASH_V4_L3_LEN, rss_key_be);
135a9de470cSBruce Richardson 		rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
136a9de470cSBruce Richardson 				RTE_THASH_V4_L4_LEN, rss_key_be);
137a9de470cSBruce Richardson 		if ((rss_l3 != v4_tbl[i].hash_l3) ||
138a9de470cSBruce Richardson 				(rss_l3l4 != v4_tbl[i].hash_l3l4))
13928ebff11SVladimir Medvedkin 			return -TEST_FAILED;
140a9de470cSBruce Richardson 	}
141a9de470cSBruce Richardson 	for (i = 0; i < RTE_DIM(v6_tbl); i++) {
142a9de470cSBruce Richardson 		/*Fill ipv6 hdr*/
143431e6b9aSRobin Jarry 		ipv6_hdr.src_addr = v6_tbl[i].src_ip;
144431e6b9aSRobin Jarry 		ipv6_hdr.dst_addr = v6_tbl[i].dst_ip;
145a9de470cSBruce Richardson 		/*Load and convert ipv6 address into tuple*/
146a9de470cSBruce Richardson 		rte_thash_load_v6_addrs(&ipv6_hdr, &tuple);
147a9de470cSBruce Richardson 		tuple.v6.sport = v6_tbl[i].src_port;
148a9de470cSBruce Richardson 		tuple.v6.dport = v6_tbl[i].dst_port;
149a9de470cSBruce Richardson 		/*Calculate hash with original key*/
150a9de470cSBruce Richardson 		rss_l3 = rte_softrss((uint32_t *)&tuple,
151a9de470cSBruce Richardson 				RTE_THASH_V6_L3_LEN, default_rss_key);
152a9de470cSBruce Richardson 		rss_l3l4 = rte_softrss((uint32_t *)&tuple,
153a9de470cSBruce Richardson 				RTE_THASH_V6_L4_LEN, default_rss_key);
154a9de470cSBruce Richardson 		if ((rss_l3 != v6_tbl[i].hash_l3) ||
155a9de470cSBruce Richardson 				(rss_l3l4 != v6_tbl[i].hash_l3l4))
15628ebff11SVladimir Medvedkin 			return -TEST_FAILED;
157a9de470cSBruce Richardson 		/*Calculate hash with converted key*/
158a9de470cSBruce Richardson 		rss_l3 = rte_softrss_be((uint32_t *)&tuple,
159a9de470cSBruce Richardson 				RTE_THASH_V6_L3_LEN, rss_key_be);
160a9de470cSBruce Richardson 		rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
161a9de470cSBruce Richardson 				RTE_THASH_V6_L4_LEN, rss_key_be);
162a9de470cSBruce Richardson 		if ((rss_l3 != v6_tbl[i].hash_l3) ||
163a9de470cSBruce Richardson 				(rss_l3l4 != v6_tbl[i].hash_l3l4))
16428ebff11SVladimir Medvedkin 			return -TEST_FAILED;
165a9de470cSBruce Richardson 	}
16628ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
16728ebff11SVladimir Medvedkin }
16828ebff11SVladimir Medvedkin 
16928ebff11SVladimir Medvedkin static int
1704fd8c4cbSVladimir Medvedkin test_toeplitz_hash_gfni(void)
1714fd8c4cbSVladimir Medvedkin {
172431e6b9aSRobin Jarry 	uint32_t i;
1734fd8c4cbSVladimir Medvedkin 	union rte_thash_tuple tuple;
1744fd8c4cbSVladimir Medvedkin 	uint32_t rss_l3, rss_l3l4;
1754fd8c4cbSVladimir Medvedkin 	uint64_t rss_key_matrixes[RTE_DIM(default_rss_key)];
1764fd8c4cbSVladimir Medvedkin 
1774fd8c4cbSVladimir Medvedkin 	if (!rte_thash_gfni_supported())
1784fd8c4cbSVladimir Medvedkin 		return TEST_SKIPPED;
1794fd8c4cbSVladimir Medvedkin 
1804fd8c4cbSVladimir Medvedkin 	/* Convert RSS key into matrixes */
1814fd8c4cbSVladimir Medvedkin 	rte_thash_complete_matrix(rss_key_matrixes, default_rss_key,
1824fd8c4cbSVladimir Medvedkin 		RTE_DIM(default_rss_key));
1834fd8c4cbSVladimir Medvedkin 
1844fd8c4cbSVladimir Medvedkin 	for (i = 0; i < RTE_DIM(v4_tbl); i++) {
1854fd8c4cbSVladimir Medvedkin 		tuple.v4.src_addr = rte_cpu_to_be_32(v4_tbl[i].src_ip);
1864fd8c4cbSVladimir Medvedkin 		tuple.v4.dst_addr = rte_cpu_to_be_32(v4_tbl[i].dst_ip);
1874fd8c4cbSVladimir Medvedkin 		tuple.v4.sport = rte_cpu_to_be_16(v4_tbl[i].dst_port);
1884fd8c4cbSVladimir Medvedkin 		tuple.v4.dport = rte_cpu_to_be_16(v4_tbl[i].src_port);
1894fd8c4cbSVladimir Medvedkin 
1904fd8c4cbSVladimir Medvedkin 		rss_l3 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)&tuple,
1914fd8c4cbSVladimir Medvedkin 				RTE_THASH_V4_L3_LEN * 4);
1924fd8c4cbSVladimir Medvedkin 		rss_l3l4 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)&tuple,
1934fd8c4cbSVladimir Medvedkin 				RTE_THASH_V4_L4_LEN * 4);
1944fd8c4cbSVladimir Medvedkin 		if ((rss_l3 != v4_tbl[i].hash_l3) ||
1954fd8c4cbSVladimir Medvedkin 				(rss_l3l4 != v4_tbl[i].hash_l3l4))
1964fd8c4cbSVladimir Medvedkin 			return -TEST_FAILED;
1974fd8c4cbSVladimir Medvedkin 	}
1984fd8c4cbSVladimir Medvedkin 
1994fd8c4cbSVladimir Medvedkin 	for (i = 0; i < RTE_DIM(v6_tbl); i++) {
200431e6b9aSRobin Jarry 		tuple.v6.src_addr = v6_tbl[i].src_ip;
201431e6b9aSRobin Jarry 		tuple.v6.dst_addr = v6_tbl[i].dst_ip;
2024fd8c4cbSVladimir Medvedkin 		tuple.v6.sport = rte_cpu_to_be_16(v6_tbl[i].dst_port);
2034fd8c4cbSVladimir Medvedkin 		tuple.v6.dport = rte_cpu_to_be_16(v6_tbl[i].src_port);
2044fd8c4cbSVladimir Medvedkin 		rss_l3 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)&tuple,
2054fd8c4cbSVladimir Medvedkin 				RTE_THASH_V6_L3_LEN * 4);
2064fd8c4cbSVladimir Medvedkin 		rss_l3l4 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)&tuple,
2074fd8c4cbSVladimir Medvedkin 				RTE_THASH_V6_L4_LEN * 4);
2084fd8c4cbSVladimir Medvedkin 		if ((rss_l3 != v6_tbl[i].hash_l3) ||
2094fd8c4cbSVladimir Medvedkin 				(rss_l3l4 != v6_tbl[i].hash_l3l4))
2104fd8c4cbSVladimir Medvedkin 			return -TEST_FAILED;
2114fd8c4cbSVladimir Medvedkin 	}
2124fd8c4cbSVladimir Medvedkin 
2134fd8c4cbSVladimir Medvedkin 	return TEST_SUCCESS;
2144fd8c4cbSVladimir Medvedkin }
2154fd8c4cbSVladimir Medvedkin 
2164fd8c4cbSVladimir Medvedkin #define DATA_SZ		4
2174fd8c4cbSVladimir Medvedkin #define ITER		1000
2184fd8c4cbSVladimir Medvedkin 
2194fd8c4cbSVladimir Medvedkin enum {
2204fd8c4cbSVladimir Medvedkin 	SCALAR_DATA_BUF_1_HASH_IDX = 0,
2214fd8c4cbSVladimir Medvedkin 	SCALAR_DATA_BUF_2_HASH_IDX,
2224fd8c4cbSVladimir Medvedkin 	GFNI_DATA_BUF_1_HASH_IDX,
2234fd8c4cbSVladimir Medvedkin 	GFNI_DATA_BUF_2_HASH_IDX,
22431d7c069SVladimir Medvedkin 	GFNI_BULK_DATA_BUF_1_HASH_IDX,
22531d7c069SVladimir Medvedkin 	GFNI_BULK_DATA_BUF_2_HASH_IDX,
2264fd8c4cbSVladimir Medvedkin 	HASH_IDXES
2274fd8c4cbSVladimir Medvedkin };
2284fd8c4cbSVladimir Medvedkin 
2294fd8c4cbSVladimir Medvedkin static int
2304fd8c4cbSVladimir Medvedkin test_toeplitz_hash_rand_data(void)
2314fd8c4cbSVladimir Medvedkin {
2324fd8c4cbSVladimir Medvedkin 	uint32_t data[2][DATA_SZ];
2334fd8c4cbSVladimir Medvedkin 	uint32_t scalar_data[2][DATA_SZ];
2344fd8c4cbSVladimir Medvedkin 	uint32_t hash[HASH_IDXES] = { 0 };
2354fd8c4cbSVladimir Medvedkin 	uint64_t rss_key_matrixes[RTE_DIM(default_rss_key)];
2364fd8c4cbSVladimir Medvedkin 	int i, j;
23731d7c069SVladimir Medvedkin 	uint8_t *bulk_data[2];
2384fd8c4cbSVladimir Medvedkin 
2394fd8c4cbSVladimir Medvedkin 	if (!rte_thash_gfni_supported())
2404fd8c4cbSVladimir Medvedkin 		return TEST_SKIPPED;
2414fd8c4cbSVladimir Medvedkin 
2424fd8c4cbSVladimir Medvedkin 	rte_thash_complete_matrix(rss_key_matrixes, default_rss_key,
2434fd8c4cbSVladimir Medvedkin 		RTE_DIM(default_rss_key));
2444fd8c4cbSVladimir Medvedkin 
24531d7c069SVladimir Medvedkin 	for (i = 0; i < 2; i++)
24631d7c069SVladimir Medvedkin 		bulk_data[i] = (uint8_t *)data[i];
24731d7c069SVladimir Medvedkin 
2484fd8c4cbSVladimir Medvedkin 	for (i = 0; i < ITER; i++) {
2494fd8c4cbSVladimir Medvedkin 		for (j = 0; j < DATA_SZ; j++) {
2504fd8c4cbSVladimir Medvedkin 			data[0][j] = rte_rand();
2514fd8c4cbSVladimir Medvedkin 			data[1][j] = rte_rand();
2524fd8c4cbSVladimir Medvedkin 			scalar_data[0][j] = rte_cpu_to_be_32(data[0][j]);
2534fd8c4cbSVladimir Medvedkin 			scalar_data[1][j] = rte_cpu_to_be_32(data[1][j]);
2544fd8c4cbSVladimir Medvedkin 		}
2554fd8c4cbSVladimir Medvedkin 
2564fd8c4cbSVladimir Medvedkin 		hash[SCALAR_DATA_BUF_1_HASH_IDX] = rte_softrss(scalar_data[0],
2574fd8c4cbSVladimir Medvedkin 			DATA_SZ, default_rss_key);
2584fd8c4cbSVladimir Medvedkin 		hash[SCALAR_DATA_BUF_2_HASH_IDX] = rte_softrss(scalar_data[1],
2594fd8c4cbSVladimir Medvedkin 			DATA_SZ, default_rss_key);
2604fd8c4cbSVladimir Medvedkin 		hash[GFNI_DATA_BUF_1_HASH_IDX] = rte_thash_gfni(
2614fd8c4cbSVladimir Medvedkin 			rss_key_matrixes, (uint8_t *)data[0],
2624fd8c4cbSVladimir Medvedkin 			DATA_SZ * sizeof(uint32_t));
2634fd8c4cbSVladimir Medvedkin 		hash[GFNI_DATA_BUF_2_HASH_IDX] = rte_thash_gfni(
2644fd8c4cbSVladimir Medvedkin 			rss_key_matrixes, (uint8_t *)data[1],
2654fd8c4cbSVladimir Medvedkin 			DATA_SZ * sizeof(uint32_t));
26631d7c069SVladimir Medvedkin 		rte_thash_gfni_bulk(rss_key_matrixes,
26731d7c069SVladimir Medvedkin 			DATA_SZ * sizeof(uint32_t), bulk_data,
26831d7c069SVladimir Medvedkin 			&hash[GFNI_BULK_DATA_BUF_1_HASH_IDX], 2);
2694fd8c4cbSVladimir Medvedkin 
2704fd8c4cbSVladimir Medvedkin 		if ((hash[SCALAR_DATA_BUF_1_HASH_IDX] !=
2714fd8c4cbSVladimir Medvedkin 				hash[GFNI_DATA_BUF_1_HASH_IDX]) ||
27231d7c069SVladimir Medvedkin 				(hash[SCALAR_DATA_BUF_1_HASH_IDX] !=
27331d7c069SVladimir Medvedkin 				hash[GFNI_BULK_DATA_BUF_1_HASH_IDX]) ||
2744fd8c4cbSVladimir Medvedkin 				(hash[SCALAR_DATA_BUF_2_HASH_IDX] !=
27531d7c069SVladimir Medvedkin 				hash[GFNI_DATA_BUF_2_HASH_IDX]) ||
27631d7c069SVladimir Medvedkin 				(hash[SCALAR_DATA_BUF_2_HASH_IDX] !=
27731d7c069SVladimir Medvedkin 				hash[GFNI_BULK_DATA_BUF_2_HASH_IDX]))
2784fd8c4cbSVladimir Medvedkin 
2794fd8c4cbSVladimir Medvedkin 			return -TEST_FAILED;
2804fd8c4cbSVladimir Medvedkin 	}
2814fd8c4cbSVladimir Medvedkin 
2824fd8c4cbSVladimir Medvedkin 	return TEST_SUCCESS;
2834fd8c4cbSVladimir Medvedkin }
2844fd8c4cbSVladimir Medvedkin 
2854fd8c4cbSVladimir Medvedkin enum {
2864fd8c4cbSVladimir Medvedkin 	RSS_V4_IDX,
2874fd8c4cbSVladimir Medvedkin 	RSS_V6_IDX
2884fd8c4cbSVladimir Medvedkin };
2894fd8c4cbSVladimir Medvedkin 
2904fd8c4cbSVladimir Medvedkin static int
29131d7c069SVladimir Medvedkin test_toeplitz_hash_gfni_bulk(void)
29231d7c069SVladimir Medvedkin {
293431e6b9aSRobin Jarry 	uint32_t i;
29431d7c069SVladimir Medvedkin 	union rte_thash_tuple tuple[2];
29531d7c069SVladimir Medvedkin 	uint8_t *tuples[2];
29631d7c069SVladimir Medvedkin 	uint32_t rss[2] = { 0 };
29731d7c069SVladimir Medvedkin 	uint64_t rss_key_matrixes[RTE_DIM(default_rss_key)];
29831d7c069SVladimir Medvedkin 
29931d7c069SVladimir Medvedkin 	if (!rte_thash_gfni_supported())
30031d7c069SVladimir Medvedkin 		return TEST_SKIPPED;
30131d7c069SVladimir Medvedkin 
30231d7c069SVladimir Medvedkin 	/* Convert RSS key into matrixes */
30331d7c069SVladimir Medvedkin 	rte_thash_complete_matrix(rss_key_matrixes, default_rss_key,
30431d7c069SVladimir Medvedkin 		RTE_DIM(default_rss_key));
30531d7c069SVladimir Medvedkin 
30631d7c069SVladimir Medvedkin 	for (i = 0; i < RTE_DIM(tuples); i++) {
30731d7c069SVladimir Medvedkin 		/* allocate memory enough for a biggest tuple */
30831d7c069SVladimir Medvedkin 		tuples[i] = rte_zmalloc(NULL, RTE_THASH_V6_L4_LEN * 4, 0);
30931d7c069SVladimir Medvedkin 		if (tuples[i] == NULL)
31031d7c069SVladimir Medvedkin 			return -TEST_FAILED;
31131d7c069SVladimir Medvedkin 	}
31231d7c069SVladimir Medvedkin 
31331d7c069SVladimir Medvedkin 	for (i = 0; i < RTE_MIN(RTE_DIM(v4_tbl), RTE_DIM(v6_tbl)); i++) {
31431d7c069SVladimir Medvedkin 		/*Load IPv4 headers and copy it into the corresponding tuple*/
31531d7c069SVladimir Medvedkin 		tuple[0].v4.src_addr = rte_cpu_to_be_32(v4_tbl[i].src_ip);
31631d7c069SVladimir Medvedkin 		tuple[0].v4.dst_addr = rte_cpu_to_be_32(v4_tbl[i].dst_ip);
31731d7c069SVladimir Medvedkin 		tuple[0].v4.sport = rte_cpu_to_be_16(v4_tbl[i].dst_port);
31831d7c069SVladimir Medvedkin 		tuple[0].v4.dport = rte_cpu_to_be_16(v4_tbl[i].src_port);
31931d7c069SVladimir Medvedkin 		rte_memcpy(tuples[0], &tuple[0], RTE_THASH_V4_L4_LEN * 4);
32031d7c069SVladimir Medvedkin 
32131d7c069SVladimir Medvedkin 		/*Load IPv6 headers and copy it into the corresponding tuple*/
322431e6b9aSRobin Jarry 		tuple[1].v6.src_addr = v6_tbl[i].src_ip;
323431e6b9aSRobin Jarry 		tuple[1].v6.dst_addr = v6_tbl[i].dst_ip;
32431d7c069SVladimir Medvedkin 		tuple[1].v6.sport = rte_cpu_to_be_16(v6_tbl[i].dst_port);
32531d7c069SVladimir Medvedkin 		tuple[1].v6.dport = rte_cpu_to_be_16(v6_tbl[i].src_port);
32631d7c069SVladimir Medvedkin 		rte_memcpy(tuples[1], &tuple[1], RTE_THASH_V6_L4_LEN * 4);
32731d7c069SVladimir Medvedkin 
32831d7c069SVladimir Medvedkin 		rte_thash_gfni_bulk(rss_key_matrixes, RTE_THASH_V6_L4_LEN * 4,
32931d7c069SVladimir Medvedkin 			tuples, rss, 2);
33031d7c069SVladimir Medvedkin 
33131d7c069SVladimir Medvedkin 		if ((rss[RSS_V4_IDX] != v4_tbl[i].hash_l3l4) ||
33231d7c069SVladimir Medvedkin 				(rss[RSS_V6_IDX] != v6_tbl[i].hash_l3l4))
33331d7c069SVladimir Medvedkin 			return -TEST_FAILED;
33431d7c069SVladimir Medvedkin 	}
33531d7c069SVladimir Medvedkin 
33631d7c069SVladimir Medvedkin 	return TEST_SUCCESS;
33731d7c069SVladimir Medvedkin }
33831d7c069SVladimir Medvedkin 
33931d7c069SVladimir Medvedkin static int
3404fd8c4cbSVladimir Medvedkin test_big_tuple_gfni(void)
3414fd8c4cbSVladimir Medvedkin {
3424fd8c4cbSVladimir Medvedkin 	uint32_t arr[16];
3434fd8c4cbSVladimir Medvedkin 	uint32_t arr_softrss[16];
3444fd8c4cbSVladimir Medvedkin 	uint32_t hash_1, hash_2;
3454fd8c4cbSVladimir Medvedkin 	uint64_t rss_key_matrixes[RTE_DIM(big_rss_key)];
3464fd8c4cbSVladimir Medvedkin 	unsigned int i, size = RTE_DIM(arr) * sizeof(uint32_t);
3474fd8c4cbSVladimir Medvedkin 
3484fd8c4cbSVladimir Medvedkin 	if (!rte_thash_gfni_supported())
3494fd8c4cbSVladimir Medvedkin 		return TEST_SKIPPED;
3504fd8c4cbSVladimir Medvedkin 
3514fd8c4cbSVladimir Medvedkin 	/* Convert RSS key into matrixes */
3524fd8c4cbSVladimir Medvedkin 	rte_thash_complete_matrix(rss_key_matrixes, big_rss_key,
3534fd8c4cbSVladimir Medvedkin 		RTE_DIM(big_rss_key));
3544fd8c4cbSVladimir Medvedkin 
3554fd8c4cbSVladimir Medvedkin 	for (i = 0; i < RTE_DIM(arr); i++) {
3564fd8c4cbSVladimir Medvedkin 		arr[i] = rte_rand();
3574fd8c4cbSVladimir Medvedkin 		arr_softrss[i] = rte_be_to_cpu_32(arr[i]);
3584fd8c4cbSVladimir Medvedkin 	}
3594fd8c4cbSVladimir Medvedkin 
3604fd8c4cbSVladimir Medvedkin 	hash_1 = rte_softrss(arr_softrss, RTE_DIM(arr), big_rss_key);
3614fd8c4cbSVladimir Medvedkin 	hash_2 = rte_thash_gfni(rss_key_matrixes, (uint8_t *)arr, size);
3624fd8c4cbSVladimir Medvedkin 
3634fd8c4cbSVladimir Medvedkin 	if (hash_1 != hash_2)
3644fd8c4cbSVladimir Medvedkin 		return -TEST_FAILED;
3654fd8c4cbSVladimir Medvedkin 
3664fd8c4cbSVladimir Medvedkin 	return TEST_SUCCESS;
3674fd8c4cbSVladimir Medvedkin }
3684fd8c4cbSVladimir Medvedkin 
3694fd8c4cbSVladimir Medvedkin static int
37028ebff11SVladimir Medvedkin test_create_invalid(void)
37128ebff11SVladimir Medvedkin {
37228ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
37328ebff11SVladimir Medvedkin 	int key_len = 40;
37428ebff11SVladimir Medvedkin 	int reta_sz = 7;
37528ebff11SVladimir Medvedkin 
37628ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx(NULL, key_len, reta_sz, NULL, 0);
37728ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx == NULL,
37828ebff11SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
37928ebff11SVladimir Medvedkin 
38028ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", 0, reta_sz, NULL, 0);
38128ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx == NULL,
38228ebff11SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
38328ebff11SVladimir Medvedkin 
38428ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx(NULL, key_len, 1, NULL, 0);
38528ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx == NULL,
38628ebff11SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
38728ebff11SVladimir Medvedkin 
38828ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx(NULL, key_len, 17, NULL, 0);
38928ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx == NULL,
39028ebff11SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
39128ebff11SVladimir Medvedkin 
39228ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
39328ebff11SVladimir Medvedkin }
39428ebff11SVladimir Medvedkin 
39528ebff11SVladimir Medvedkin static int
39628ebff11SVladimir Medvedkin test_multiple_create(void)
39728ebff11SVladimir Medvedkin {
39828ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
39928ebff11SVladimir Medvedkin 	int key_len = 40;
40028ebff11SVladimir Medvedkin 	int reta_sz = 7;
40128ebff11SVladimir Medvedkin 	int i;
40228ebff11SVladimir Medvedkin 
40328ebff11SVladimir Medvedkin 	for (i = 0; i < 100; i++) {
40428ebff11SVladimir Medvedkin 		ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
40528ebff11SVladimir Medvedkin 		RTE_TEST_ASSERT(ctx != NULL, "Can not create CTX\n");
40628ebff11SVladimir Medvedkin 
40728ebff11SVladimir Medvedkin 		rte_thash_free_ctx(ctx);
40828ebff11SVladimir Medvedkin 	}
40928ebff11SVladimir Medvedkin 
41028ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
41128ebff11SVladimir Medvedkin }
41228ebff11SVladimir Medvedkin 
41328ebff11SVladimir Medvedkin static int
41428ebff11SVladimir Medvedkin test_free_null(void)
41528ebff11SVladimir Medvedkin {
41628ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
41728ebff11SVladimir Medvedkin 
41828ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", 40, 7, NULL, 0);
41928ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "Can not create CTX\n");
42028ebff11SVladimir Medvedkin 
42128ebff11SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
42228ebff11SVladimir Medvedkin 	rte_thash_free_ctx(NULL);
42328ebff11SVladimir Medvedkin 
42428ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
42528ebff11SVladimir Medvedkin }
42628ebff11SVladimir Medvedkin 
42728ebff11SVladimir Medvedkin static int
42828ebff11SVladimir Medvedkin test_add_invalid_helper(void)
42928ebff11SVladimir Medvedkin {
43028ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
43128ebff11SVladimir Medvedkin 	const int key_len = 40;
43228ebff11SVladimir Medvedkin 	int reta_sz = 7;
43328ebff11SVladimir Medvedkin 	int ret;
43428ebff11SVladimir Medvedkin 
43528ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
43628ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
43728ebff11SVladimir Medvedkin 
43828ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(NULL, "test", reta_sz, 0);
43928ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == -EINVAL,
44028ebff11SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
44128ebff11SVladimir Medvedkin 
44228ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, NULL, reta_sz, 0);
44328ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == -EINVAL,
44428ebff11SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
44528ebff11SVladimir Medvedkin 
44628ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "test", reta_sz - 1, 0);
44728ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == -EINVAL,
44828ebff11SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
44928ebff11SVladimir Medvedkin 
45028ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "test", reta_sz, key_len * 8);
45128ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == -EINVAL,
45228ebff11SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
45328ebff11SVladimir Medvedkin 
45428ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "first_range", reta_sz, 0);
45528ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
45628ebff11SVladimir Medvedkin 
45728ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "first_range", reta_sz, 0);
45828ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == -EEXIST,
45928ebff11SVladimir Medvedkin 		"Call succeeded with duplicated name\n");
46028ebff11SVladimir Medvedkin 
46128ebff11SVladimir Medvedkin 	/*
46228ebff11SVladimir Medvedkin 	 * Create second helper with offset 3 * reta_sz.
46328ebff11SVladimir Medvedkin 	 * Note first_range helper created range in key:
46428ebff11SVladimir Medvedkin 	 * [0, 32 + length{= reta_sz} - 1), i.e [0, 37).
46528ebff11SVladimir Medvedkin 	 * second range is [44, 81)
46628ebff11SVladimir Medvedkin 	 */
46728ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "second_range", reta_sz,
46828ebff11SVladimir Medvedkin 		32 +  2 * reta_sz);
46928ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
47028ebff11SVladimir Medvedkin 
47128ebff11SVladimir Medvedkin 	/*
47228ebff11SVladimir Medvedkin 	 * Try to create overlapping with first_ and second_ ranges,
47328ebff11SVladimir Medvedkin 	 * i.e. [6, 49)
47428ebff11SVladimir Medvedkin 	 */
47528ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "third_range", 2 * reta_sz, reta_sz);
47628ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == -EEXIST,
47728ebff11SVladimir Medvedkin 		"Call succeeded with overlapping ranges\n");
47828ebff11SVladimir Medvedkin 
47928ebff11SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
48028ebff11SVladimir Medvedkin 
48128ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
48228ebff11SVladimir Medvedkin }
48328ebff11SVladimir Medvedkin 
48428ebff11SVladimir Medvedkin static int
48528ebff11SVladimir Medvedkin test_find_existing(void)
48628ebff11SVladimir Medvedkin {
48728ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx, *ret_ctx;
48828ebff11SVladimir Medvedkin 
48928ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", 40, 7, NULL, 0);
49028ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
49128ebff11SVladimir Medvedkin 
49228ebff11SVladimir Medvedkin 	ret_ctx = rte_thash_find_existing("test");
49328ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret_ctx != NULL, "can not find existing ctx\n");
49428ebff11SVladimir Medvedkin 
49528ebff11SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
49628ebff11SVladimir Medvedkin 
49728ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
49828ebff11SVladimir Medvedkin }
49928ebff11SVladimir Medvedkin 
50028ebff11SVladimir Medvedkin static int
50128ebff11SVladimir Medvedkin test_get_helper(void)
50228ebff11SVladimir Medvedkin {
50328ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
50428ebff11SVladimir Medvedkin 	struct rte_thash_subtuple_helper *h;
50528ebff11SVladimir Medvedkin 	int ret;
50628ebff11SVladimir Medvedkin 
50728ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", 40, 7, NULL, 0);
50828ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "Can not create thash ctx\n");
50928ebff11SVladimir Medvedkin 
51028ebff11SVladimir Medvedkin 	h = rte_thash_get_helper(NULL, "first_range");
51128ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(h == NULL, "Call succeeded with invalid parameters\n");
51228ebff11SVladimir Medvedkin 
51328ebff11SVladimir Medvedkin 	h = rte_thash_get_helper(ctx, NULL);
51428ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(h == NULL, "Call succeeded with invalid parameters\n");
51528ebff11SVladimir Medvedkin 
51628ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "first_range", 8, 0);
51728ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
51828ebff11SVladimir Medvedkin 
51928ebff11SVladimir Medvedkin 	h = rte_thash_get_helper(ctx, "first_range");
52028ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(h != NULL, "Can not find helper\n");
52128ebff11SVladimir Medvedkin 
52228ebff11SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
52328ebff11SVladimir Medvedkin 
52428ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
52528ebff11SVladimir Medvedkin }
52628ebff11SVladimir Medvedkin 
52728ebff11SVladimir Medvedkin static int
52828ebff11SVladimir Medvedkin test_period_overflow(void)
52928ebff11SVladimir Medvedkin {
53028ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
53128ebff11SVladimir Medvedkin 	int reta_sz = 7; /* reflects polynomial degree */
53228ebff11SVladimir Medvedkin 	int ret;
53328ebff11SVladimir Medvedkin 
53428ebff11SVladimir Medvedkin 	/* first create without RTE_THASH_IGNORE_PERIOD_OVERFLOW flag */
53528ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", 40, reta_sz, NULL, 0);
53628ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "Can not create thash ctx\n");
53728ebff11SVladimir Medvedkin 
53828ebff11SVladimir Medvedkin 	/* requested range > (2^reta_sz) - 1 */
53928ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "test", (1 << reta_sz), 0);
54028ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == -ENOSPC,
54128ebff11SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
54228ebff11SVladimir Medvedkin 
54328ebff11SVladimir Medvedkin 	/* requested range == len + 32 - 1, smaller than (2^reta_sz) - 1 */
54428ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "test", (1 << reta_sz) - 32, 0);
54528ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
54628ebff11SVladimir Medvedkin 
54728ebff11SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
54828ebff11SVladimir Medvedkin 
54928ebff11SVladimir Medvedkin 	/* create with RTE_THASH_IGNORE_PERIOD_OVERFLOW flag */
55028ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", 40, reta_sz, NULL,
55128ebff11SVladimir Medvedkin 		RTE_THASH_IGNORE_PERIOD_OVERFLOW);
55228ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "Can not create thash ctx\n");
55328ebff11SVladimir Medvedkin 
55428ebff11SVladimir Medvedkin 	/* requested range > (2^reta_sz - 1) */
55528ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "test", (1 << reta_sz) + 10, 0);
55628ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "Can not create helper\n");
55728ebff11SVladimir Medvedkin 
55828ebff11SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
55928ebff11SVladimir Medvedkin 
56028ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
56128ebff11SVladimir Medvedkin }
56228ebff11SVladimir Medvedkin 
56328ebff11SVladimir Medvedkin static int
56428ebff11SVladimir Medvedkin test_predictable_rss_min_seq(void)
56528ebff11SVladimir Medvedkin {
56628ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
56728ebff11SVladimir Medvedkin 	struct rte_thash_subtuple_helper *h;
56828ebff11SVladimir Medvedkin 	const int key_len = 40;
56928ebff11SVladimir Medvedkin 	int reta_sz = 6;
57028ebff11SVladimir Medvedkin 	uint8_t initial_key[key_len];
57128ebff11SVladimir Medvedkin 	const uint8_t *new_key;
57228ebff11SVladimir Medvedkin 	int ret;
57328ebff11SVladimir Medvedkin 	union rte_thash_tuple tuple;
57428ebff11SVladimir Medvedkin 	uint32_t orig_hash, adj_hash, adj;
57528ebff11SVladimir Medvedkin 	unsigned int desired_value = 27 & HASH_MSK(reta_sz);
57628ebff11SVladimir Medvedkin 	uint16_t port_value = 22;
57728ebff11SVladimir Medvedkin 
57828ebff11SVladimir Medvedkin 	memset(initial_key, 0, key_len);
57928ebff11SVladimir Medvedkin 
58028ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", key_len, reta_sz, initial_key,
58128ebff11SVladimir Medvedkin 		RTE_THASH_MINIMAL_SEQ);
58228ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
58328ebff11SVladimir Medvedkin 
58428ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "snat", sizeof(uint16_t) * 8,
58528ebff11SVladimir Medvedkin 		offsetof(union rte_thash_tuple, v4.sport) * 8);
58628ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "can not add helper, ret %d\n", ret);
58728ebff11SVladimir Medvedkin 
58828ebff11SVladimir Medvedkin 	h = rte_thash_get_helper(ctx, "snat");
58928ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(h != NULL, "can not find helper\n");
59028ebff11SVladimir Medvedkin 
59128ebff11SVladimir Medvedkin 	new_key = rte_thash_get_key(ctx);
59228ebff11SVladimir Medvedkin 	tuple.v4.src_addr = RTE_IPV4(0, 0, 0, 0);
59328ebff11SVladimir Medvedkin 	tuple.v4.dst_addr = RTE_IPV4(0, 0, 0, 0);
59428ebff11SVladimir Medvedkin 	tuple.v4.sport = 0;
59528ebff11SVladimir Medvedkin 	tuple.v4.sport = rte_cpu_to_be_16(port_value);
59628ebff11SVladimir Medvedkin 	tuple.v4.dport = 0;
59728ebff11SVladimir Medvedkin 	tuple.v4.sctp_tag = rte_be_to_cpu_32(tuple.v4.sctp_tag);
59828ebff11SVladimir Medvedkin 
59928ebff11SVladimir Medvedkin 	orig_hash = rte_softrss((uint32_t *)&tuple,
60028ebff11SVladimir Medvedkin 		RTE_THASH_V4_L4_LEN, new_key);
60128ebff11SVladimir Medvedkin 	adj = rte_thash_get_complement(h, orig_hash, desired_value);
60228ebff11SVladimir Medvedkin 
60328ebff11SVladimir Medvedkin 	tuple.v4.sctp_tag = rte_cpu_to_be_32(tuple.v4.sctp_tag);
60428ebff11SVladimir Medvedkin 	tuple.v4.sport ^= rte_cpu_to_be_16(adj);
60528ebff11SVladimir Medvedkin 	tuple.v4.sctp_tag = rte_be_to_cpu_32(tuple.v4.sctp_tag);
60628ebff11SVladimir Medvedkin 
60728ebff11SVladimir Medvedkin 	adj_hash = rte_softrss((uint32_t *)&tuple,
60828ebff11SVladimir Medvedkin 		RTE_THASH_V4_L4_LEN, new_key);
60928ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT((adj_hash & HASH_MSK(reta_sz)) ==
61028ebff11SVladimir Medvedkin 		desired_value, "bad desired value\n");
61128ebff11SVladimir Medvedkin 
61228ebff11SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
61328ebff11SVladimir Medvedkin 
61428ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
61528ebff11SVladimir Medvedkin }
61628ebff11SVladimir Medvedkin 
61728ebff11SVladimir Medvedkin /*
61828ebff11SVladimir Medvedkin  * This test creates 7 subranges in the following order:
61928ebff11SVladimir Medvedkin  * range_one	= [56, 95),	len = 8, offset = 56
62028ebff11SVladimir Medvedkin  * range_two	= [64, 103),	len = 8, offset = 64
62128ebff11SVladimir Medvedkin  * range_three	= [120, 159),	len = 8, offset = 120
62228ebff11SVladimir Medvedkin  * range_four	= [48, 87),	len = 8, offset = 48
62328ebff11SVladimir Medvedkin  * range_five	= [57, 95),	len = 7, offset = 57
62428ebff11SVladimir Medvedkin  * range_six	= [40, 111),	len = 40, offset = 40
62528ebff11SVladimir Medvedkin  * range_seven	= [0, 39),	len = 8, offset = 0
62628ebff11SVladimir Medvedkin  */
62728ebff11SVladimir Medvedkin struct range {
62828ebff11SVladimir Medvedkin 	const char *name;
62928ebff11SVladimir Medvedkin 	int len;
63028ebff11SVladimir Medvedkin 	int offset;
63128ebff11SVladimir Medvedkin 	int byte_idx;
63228ebff11SVladimir Medvedkin };
63328ebff11SVladimir Medvedkin 
63428ebff11SVladimir Medvedkin struct range rng_arr[] = {
63528ebff11SVladimir Medvedkin 	{"one",   8,  56,  7},
63628ebff11SVladimir Medvedkin 	{"two",   8,  64,  8},
63728ebff11SVladimir Medvedkin 	{"three", 8,  120, 15},
63828ebff11SVladimir Medvedkin 	{"four",  8,  48,  6},
63928ebff11SVladimir Medvedkin 	{"six",   40, 40,  9},
64028ebff11SVladimir Medvedkin 	{"five",  7,  57,  7},
64128ebff11SVladimir Medvedkin 	{"seven", 8,  0,   0}
64228ebff11SVladimir Medvedkin };
64328ebff11SVladimir Medvedkin 
64428ebff11SVladimir Medvedkin static int
64528ebff11SVladimir Medvedkin test_predictable_rss_multirange(void)
64628ebff11SVladimir Medvedkin {
64728ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
64828ebff11SVladimir Medvedkin 	struct rte_thash_subtuple_helper *h[RTE_DIM(rng_arr)];
64928ebff11SVladimir Medvedkin 	const uint8_t *new_key;
65028ebff11SVladimir Medvedkin 	const int key_len = 40;
65128ebff11SVladimir Medvedkin 	int reta_sz = 7;
65228ebff11SVladimir Medvedkin 	unsigned int i, j, k;
65328ebff11SVladimir Medvedkin 	int ret;
65428ebff11SVladimir Medvedkin 	uint32_t desired_value = rte_rand() & HASH_MSK(reta_sz);
65528ebff11SVladimir Medvedkin 	uint8_t tuples[RTE_DIM(rng_arr)][16] = { {0} };
65628ebff11SVladimir Medvedkin 	uint32_t *ptr;
65728ebff11SVladimir Medvedkin 	uint32_t hashes[RTE_DIM(rng_arr)];
65828ebff11SVladimir Medvedkin 	uint32_t adj_hashes[RTE_DIM(rng_arr)];
65928ebff11SVladimir Medvedkin 	uint32_t adj;
66028ebff11SVladimir Medvedkin 
66128ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
66228ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
66328ebff11SVladimir Medvedkin 
66428ebff11SVladimir Medvedkin 	for (i = 0; i < RTE_DIM(rng_arr); i++) {
66528ebff11SVladimir Medvedkin 		ret = rte_thash_add_helper(ctx, rng_arr[i].name,
66628ebff11SVladimir Medvedkin 			rng_arr[i].len, rng_arr[i].offset);
66728ebff11SVladimir Medvedkin 		RTE_TEST_ASSERT(ret == 0, "can not add helper\n");
66828ebff11SVladimir Medvedkin 
66928ebff11SVladimir Medvedkin 		h[i] = rte_thash_get_helper(ctx, rng_arr[i].name);
67028ebff11SVladimir Medvedkin 		RTE_TEST_ASSERT(h[i] != NULL, "can not find helper\n");
67128ebff11SVladimir Medvedkin 	}
67228ebff11SVladimir Medvedkin 	new_key = rte_thash_get_key(ctx);
67328ebff11SVladimir Medvedkin 
67428ebff11SVladimir Medvedkin 	/*
67528ebff11SVladimir Medvedkin 	 * calculate hashes, complements, then adjust keys with
6767be78d02SJosh Soref 	 * complements and recalculate hashes
67728ebff11SVladimir Medvedkin 	 */
67828ebff11SVladimir Medvedkin 	for (i = 0; i < RTE_DIM(rng_arr); i++) {
67928ebff11SVladimir Medvedkin 		for (k = 0; k < 100; k++) {
68028ebff11SVladimir Medvedkin 			/* init with random keys */
68128ebff11SVladimir Medvedkin 			ptr = (uint32_t *)&tuples[i][0];
68228ebff11SVladimir Medvedkin 			for (j = 0; j < 4; j++)
68328ebff11SVladimir Medvedkin 				ptr[j] = rte_rand();
68428ebff11SVladimir Medvedkin 			/* convert keys from BE to CPU byte order */
68528ebff11SVladimir Medvedkin 			for (j = 0; j < 4; j++)
68628ebff11SVladimir Medvedkin 				ptr[j] = rte_be_to_cpu_32(ptr[j]);
68728ebff11SVladimir Medvedkin 
68828ebff11SVladimir Medvedkin 			hashes[i] = rte_softrss(ptr, 4, new_key);
68928ebff11SVladimir Medvedkin 			adj = rte_thash_get_complement(h[i], hashes[i],
69028ebff11SVladimir Medvedkin 				desired_value);
69128ebff11SVladimir Medvedkin 			/* convert back to BE to adjust the value */
69228ebff11SVladimir Medvedkin 			for (j = 0; j < 4; j++)
69328ebff11SVladimir Medvedkin 				ptr[j] = rte_cpu_to_be_32(ptr[j]);
69428ebff11SVladimir Medvedkin 
69528ebff11SVladimir Medvedkin 			tuples[i][rng_arr[i].byte_idx] ^= adj;
69628ebff11SVladimir Medvedkin 
69728ebff11SVladimir Medvedkin 			for (j = 0; j < 4; j++)
69828ebff11SVladimir Medvedkin 				ptr[j] = rte_be_to_cpu_32(ptr[j]);
69928ebff11SVladimir Medvedkin 
70028ebff11SVladimir Medvedkin 			adj_hashes[i] = rte_softrss(ptr, 4, new_key);
70128ebff11SVladimir Medvedkin 			RTE_TEST_ASSERT((adj_hashes[i] & HASH_MSK(reta_sz)) ==
70228ebff11SVladimir Medvedkin 				desired_value,
70328ebff11SVladimir Medvedkin 				"bad desired value for %d tuple\n", i);
70428ebff11SVladimir Medvedkin 		}
70528ebff11SVladimir Medvedkin 	}
70628ebff11SVladimir Medvedkin 
70728ebff11SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
70828ebff11SVladimir Medvedkin 
70928ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
71028ebff11SVladimir Medvedkin }
71128ebff11SVladimir Medvedkin 
71228ebff11SVladimir Medvedkin static int
71328ebff11SVladimir Medvedkin cmp_tuple_eq(void *userdata, uint8_t *tuple)
71428ebff11SVladimir Medvedkin {
71528ebff11SVladimir Medvedkin 	return memcmp(userdata, tuple, TUPLE_SZ);
71628ebff11SVladimir Medvedkin }
71728ebff11SVladimir Medvedkin 
71828ebff11SVladimir Medvedkin static int
71928ebff11SVladimir Medvedkin test_adjust_tuple(void)
72028ebff11SVladimir Medvedkin {
72128ebff11SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
72228ebff11SVladimir Medvedkin 	struct rte_thash_subtuple_helper *h;
72328ebff11SVladimir Medvedkin 	const int key_len = 40;
72428ebff11SVladimir Medvedkin 	const uint8_t *new_key;
72528ebff11SVladimir Medvedkin 	uint8_t tuple[TUPLE_SZ];
72628ebff11SVladimir Medvedkin 	uint32_t tmp_tuple[TUPLE_SZ / sizeof(uint32_t)];
72728ebff11SVladimir Medvedkin 	uint32_t tuple_copy[TUPLE_SZ / sizeof(uint32_t)];
72828ebff11SVladimir Medvedkin 	uint32_t hash;
72928ebff11SVladimir Medvedkin 	int reta_sz = CHAR_BIT;
73028ebff11SVladimir Medvedkin 	int ret;
73128ebff11SVladimir Medvedkin 	unsigned int i, desired_value = rte_rand() & HASH_MSK(reta_sz);
73228ebff11SVladimir Medvedkin 
73328ebff11SVladimir Medvedkin 	memset(tuple, 0xab, TUPLE_SZ);
73428ebff11SVladimir Medvedkin 
73528ebff11SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
73628ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
73728ebff11SVladimir Medvedkin 
73828ebff11SVladimir Medvedkin 	/*
73928ebff11SVladimir Medvedkin 	 * set offset to be in the middle of a byte
74028ebff11SVladimir Medvedkin 	 * set size of the subtuple to be 2 * rets_sz
74128ebff11SVladimir Medvedkin 	 * to have the room for random bits
74228ebff11SVladimir Medvedkin 	 */
74328ebff11SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "test", reta_sz * 2,
74428ebff11SVladimir Medvedkin 		(5 * CHAR_BIT) + 4);
74528ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "can not add helper, ret %d\n", ret);
74628ebff11SVladimir Medvedkin 
74728ebff11SVladimir Medvedkin 	new_key = rte_thash_get_key(ctx);
74828ebff11SVladimir Medvedkin 
74928ebff11SVladimir Medvedkin 	h = rte_thash_get_helper(ctx, "test");
75028ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(h != NULL, "can not find helper\n");
75128ebff11SVladimir Medvedkin 
75228ebff11SVladimir Medvedkin 	ret = rte_thash_adjust_tuple(ctx, h, tuple, TUPLE_SZ, desired_value,
75328ebff11SVladimir Medvedkin 		1, NULL, NULL);
75428ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "can not adjust tuple, ret %d\n", ret);
75528ebff11SVladimir Medvedkin 
75628ebff11SVladimir Medvedkin 	for (i = 0; i < (TUPLE_SZ / 4); i++)
75728ebff11SVladimir Medvedkin 		tmp_tuple[i] =
75828ebff11SVladimir Medvedkin 			rte_be_to_cpu_32(*(uint32_t *)&tuple[i * 4]);
75928ebff11SVladimir Medvedkin 
76028ebff11SVladimir Medvedkin 	hash = rte_softrss(tmp_tuple, TUPLE_SZ / 4, new_key);
76128ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT((hash & HASH_MSK(reta_sz)) ==
76228ebff11SVladimir Medvedkin 		desired_value, "bad desired value\n");
76328ebff11SVladimir Medvedkin 
76428ebff11SVladimir Medvedkin 
76528ebff11SVladimir Medvedkin 	/* Pass previously calculated tuple to callback function */
76628ebff11SVladimir Medvedkin 	memcpy(tuple_copy, tuple, TUPLE_SZ);
76728ebff11SVladimir Medvedkin 
76828ebff11SVladimir Medvedkin 	memset(tuple, 0xab, TUPLE_SZ);
76928ebff11SVladimir Medvedkin 	ret = rte_thash_adjust_tuple(ctx, h, tuple, TUPLE_SZ, desired_value,
77028ebff11SVladimir Medvedkin 		1, cmp_tuple_eq, tuple_copy);
77128ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == -EEXIST,
77228ebff11SVladimir Medvedkin 		"adjust tuple didn't indicate collision\n");
77328ebff11SVladimir Medvedkin 
77428ebff11SVladimir Medvedkin 	/*
77528ebff11SVladimir Medvedkin 	 * Make the function to generate random bits into subtuple
77628ebff11SVladimir Medvedkin 	 * after first adjustment attempt.
77728ebff11SVladimir Medvedkin 	 */
77828ebff11SVladimir Medvedkin 	memset(tuple, 0xab, TUPLE_SZ);
77928ebff11SVladimir Medvedkin 	ret = rte_thash_adjust_tuple(ctx, h, tuple, TUPLE_SZ, desired_value,
78028ebff11SVladimir Medvedkin 		2, cmp_tuple_eq, tuple_copy);
78128ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "can not adjust tuple, ret %d\n", ret);
78228ebff11SVladimir Medvedkin 
78328ebff11SVladimir Medvedkin 	for (i = 0; i < (TUPLE_SZ / 4); i++)
78428ebff11SVladimir Medvedkin 		tmp_tuple[i] =
78528ebff11SVladimir Medvedkin 			rte_be_to_cpu_32(*(uint32_t *)&tuple[i * 4]);
78628ebff11SVladimir Medvedkin 
78728ebff11SVladimir Medvedkin 	hash = rte_softrss(tmp_tuple, TUPLE_SZ / 4, new_key);
78828ebff11SVladimir Medvedkin 	RTE_TEST_ASSERT((hash & HASH_MSK(reta_sz)) ==
78928ebff11SVladimir Medvedkin 		desired_value, "bad desired value\n");
79028ebff11SVladimir Medvedkin 
79128ebff11SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
79228ebff11SVladimir Medvedkin 
79328ebff11SVladimir Medvedkin 	return TEST_SUCCESS;
79428ebff11SVladimir Medvedkin }
79528ebff11SVladimir Medvedkin 
796ed4f8e02SVladimir Medvedkin static uint32_t
797ed4f8e02SVladimir Medvedkin calc_tuple_hash(const uint8_t tuple[TUPLE_SZ], const uint8_t *key)
798ed4f8e02SVladimir Medvedkin {
799ed4f8e02SVladimir Medvedkin 	uint32_t i, hash;
800ed4f8e02SVladimir Medvedkin 	uint32_t tmp[TUPLE_SZ / sizeof(uint32_t)];
801ed4f8e02SVladimir Medvedkin 
802ed4f8e02SVladimir Medvedkin 	for (i = 0; i < RTE_DIM(tmp); i++)
803ed4f8e02SVladimir Medvedkin 		tmp[i] = rte_be_to_cpu_32(
804ed4f8e02SVladimir Medvedkin 			*(const uint32_t *)&tuple[i * sizeof(uint32_t)]);
805ed4f8e02SVladimir Medvedkin 
806ed4f8e02SVladimir Medvedkin 	hash = rte_softrss(tmp, RTE_DIM(tmp), key);
807ed4f8e02SVladimir Medvedkin 	return hash;
808ed4f8e02SVladimir Medvedkin }
809ed4f8e02SVladimir Medvedkin 
810ed4f8e02SVladimir Medvedkin static int
811ed4f8e02SVladimir Medvedkin check_adj_tuple(const uint8_t tuple[TUPLE_SZ], const uint8_t *key,
812ed4f8e02SVladimir Medvedkin 		uint32_t dhv, uint32_t ohv, uint32_t adjust, uint32_t reta_sz,
813ed4f8e02SVladimir Medvedkin 		const char *prefix)
814ed4f8e02SVladimir Medvedkin {
815ed4f8e02SVladimir Medvedkin 	uint32_t hash, hashlsb;
816ed4f8e02SVladimir Medvedkin 
817ed4f8e02SVladimir Medvedkin 	hash = calc_tuple_hash(tuple, key);
818ed4f8e02SVladimir Medvedkin 	hashlsb = hash & HASH_MSK(reta_sz);
819ed4f8e02SVladimir Medvedkin 
820ed4f8e02SVladimir Medvedkin 	printf("%s(%s) for tuple:\n", __func__, prefix);
821ed4f8e02SVladimir Medvedkin 	rte_memdump(stdout, NULL, tuple, TUPLE_SZ);
822ed4f8e02SVladimir Medvedkin 	printf("\treta_sz: %u,\n"
823ed4f8e02SVladimir Medvedkin 		"\torig hash: %#x,\n"
824ed4f8e02SVladimir Medvedkin 		"\tdesired: %#x,\n"
825ed4f8e02SVladimir Medvedkin 		"\tadjust: %#x,\n"
826ed4f8e02SVladimir Medvedkin 		"\tactual: %#x,\n",
827ed4f8e02SVladimir Medvedkin 	       reta_sz, ohv, dhv, adjust, hashlsb);
828ed4f8e02SVladimir Medvedkin 
829ed4f8e02SVladimir Medvedkin 	if (dhv == hashlsb) {
830ed4f8e02SVladimir Medvedkin 		printf("\t***Succeeded\n");
831ed4f8e02SVladimir Medvedkin 		return 0;
832ed4f8e02SVladimir Medvedkin 	}
833ed4f8e02SVladimir Medvedkin 
834ed4f8e02SVladimir Medvedkin 	printf("\t***Failed\n");
835ed4f8e02SVladimir Medvedkin 	return -1;
836ed4f8e02SVladimir Medvedkin }
837ed4f8e02SVladimir Medvedkin 
838ed4f8e02SVladimir Medvedkin static int
839ed4f8e02SVladimir Medvedkin test_adjust_tuple_mb(uint32_t reta_sz, uint32_t bofs)
840ed4f8e02SVladimir Medvedkin {
841ed4f8e02SVladimir Medvedkin 	struct rte_thash_ctx *ctx;
842ed4f8e02SVladimir Medvedkin 	struct rte_thash_subtuple_helper *h;
843ed4f8e02SVladimir Medvedkin 	const int key_len = 40;
844ed4f8e02SVladimir Medvedkin 	const uint8_t *new_key;
845ed4f8e02SVladimir Medvedkin 	uint8_t orig_tuple[TUPLE_SZ];
846ed4f8e02SVladimir Medvedkin 	uint8_t tuple_1[TUPLE_SZ];
847ed4f8e02SVladimir Medvedkin 	uint8_t tuple_2[TUPLE_SZ];
848ed4f8e02SVladimir Medvedkin 	uint32_t orig_hash;
849ed4f8e02SVladimir Medvedkin 	int rc, ret;
850ed4f8e02SVladimir Medvedkin 	uint32_t adj_bits;
851ed4f8e02SVladimir Medvedkin 	unsigned int random = rte_rand();
852ed4f8e02SVladimir Medvedkin 	unsigned int desired_value = random & HASH_MSK(reta_sz);
853ed4f8e02SVladimir Medvedkin 
854ed4f8e02SVladimir Medvedkin 	const uint32_t h_offset = offsetof(union rte_thash_tuple, v4.dport) * CHAR_BIT;
855ed4f8e02SVladimir Medvedkin 	const uint32_t h_size = sizeof(uint16_t) * CHAR_BIT - bofs;
856ed4f8e02SVladimir Medvedkin 
857ed4f8e02SVladimir Medvedkin 	printf("===%s(reta_sz=%u,bofs=%u)===\n", __func__, reta_sz, bofs);
858ed4f8e02SVladimir Medvedkin 
859ed4f8e02SVladimir Medvedkin 	memset(orig_tuple, 0xab, sizeof(orig_tuple));
860ed4f8e02SVladimir Medvedkin 
861ed4f8e02SVladimir Medvedkin 	ctx = rte_thash_init_ctx("test", key_len, reta_sz, NULL, 0);
862ed4f8e02SVladimir Medvedkin 	RTE_TEST_ASSERT(ctx != NULL, "can not create thash ctx\n");
863ed4f8e02SVladimir Medvedkin 
864ed4f8e02SVladimir Medvedkin 	ret = rte_thash_add_helper(ctx, "test", h_size, h_offset);
865ed4f8e02SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "can not add helper, ret %d\n", ret);
866ed4f8e02SVladimir Medvedkin 
867ed4f8e02SVladimir Medvedkin 	new_key = rte_thash_get_key(ctx);
868ed4f8e02SVladimir Medvedkin 
869ed4f8e02SVladimir Medvedkin 	h = rte_thash_get_helper(ctx, "test");
870ed4f8e02SVladimir Medvedkin 
871ed4f8e02SVladimir Medvedkin 	orig_hash = calc_tuple_hash(orig_tuple, new_key);
872ed4f8e02SVladimir Medvedkin 
873ed4f8e02SVladimir Medvedkin 	adj_bits = rte_thash_get_complement(h, orig_hash, desired_value);
874ed4f8e02SVladimir Medvedkin 
875ed4f8e02SVladimir Medvedkin 	/* use method #1, update tuple manually */
876ed4f8e02SVladimir Medvedkin 	memcpy(tuple_1, orig_tuple, sizeof(tuple_1));
877ed4f8e02SVladimir Medvedkin 	{
878ed4f8e02SVladimir Medvedkin 		uint16_t nv, ov, *p;
879ed4f8e02SVladimir Medvedkin 
880ed4f8e02SVladimir Medvedkin 		p = (uint16_t *)(tuple_1 + h_offset / CHAR_BIT);
881ed4f8e02SVladimir Medvedkin 		ov = p[0];
882ed4f8e02SVladimir Medvedkin 		nv = ov ^ rte_cpu_to_be_16(adj_bits << bofs);
883ed4f8e02SVladimir Medvedkin 		printf("%s#%d: ov=%#hx, nv=%#hx, adj=%#x;\n",
884ed4f8e02SVladimir Medvedkin 			__func__, __LINE__, ov, nv, adj_bits);
885ed4f8e02SVladimir Medvedkin 		p[0] = nv;
886ed4f8e02SVladimir Medvedkin 	}
887ed4f8e02SVladimir Medvedkin 
888ed4f8e02SVladimir Medvedkin 	rc = check_adj_tuple(tuple_1, new_key, desired_value, orig_hash,
889ed4f8e02SVladimir Medvedkin 		adj_bits, reta_sz, "method #1");
890ed4f8e02SVladimir Medvedkin 	if (h_offset % CHAR_BIT == 0)
891ed4f8e02SVladimir Medvedkin 		ret |= rc;
892ed4f8e02SVladimir Medvedkin 
893ed4f8e02SVladimir Medvedkin 	/* use method #2, use library function to adjust tuple */
894ed4f8e02SVladimir Medvedkin 	memcpy(tuple_2, orig_tuple, sizeof(tuple_2));
895ed4f8e02SVladimir Medvedkin 
896ed4f8e02SVladimir Medvedkin 	rte_thash_adjust_tuple(ctx, h, tuple_2, sizeof(tuple_2),
897ed4f8e02SVladimir Medvedkin 		desired_value, 1, NULL, NULL);
898ed4f8e02SVladimir Medvedkin 	ret |= check_adj_tuple(tuple_2, new_key, desired_value, orig_hash,
899ed4f8e02SVladimir Medvedkin 		adj_bits, reta_sz, "method #2");
900ed4f8e02SVladimir Medvedkin 
901ed4f8e02SVladimir Medvedkin 	rte_thash_free_ctx(ctx);
902ed4f8e02SVladimir Medvedkin 
903ed4f8e02SVladimir Medvedkin 	ret |= memcmp(tuple_1, tuple_2, sizeof(tuple_1));
904ed4f8e02SVladimir Medvedkin 
905ed4f8e02SVladimir Medvedkin 	printf("%s EXIT=======\n", __func__);
906ed4f8e02SVladimir Medvedkin 	return ret;
907ed4f8e02SVladimir Medvedkin }
908ed4f8e02SVladimir Medvedkin 
909ed4f8e02SVladimir Medvedkin static int
910ed4f8e02SVladimir Medvedkin test_adjust_tuple_mult_reta(void)
911ed4f8e02SVladimir Medvedkin {
912ed4f8e02SVladimir Medvedkin 	uint32_t i, j, np, nt;
913ed4f8e02SVladimir Medvedkin 
914ed4f8e02SVladimir Medvedkin 	nt = 0, np = 0;
915ed4f8e02SVladimir Medvedkin 	for (i = 0; i < CHAR_BIT; i++) {
916ed4f8e02SVladimir Medvedkin 		for (j = 6; j <= RTE_THASH_RETA_SZ_MAX - i; j++) {
917ed4f8e02SVladimir Medvedkin 			np += (test_adjust_tuple_mb(j, i) == 0);
918ed4f8e02SVladimir Medvedkin 			nt++;
919ed4f8e02SVladimir Medvedkin 		}
920ed4f8e02SVladimir Medvedkin 	}
921ed4f8e02SVladimir Medvedkin 
922ed4f8e02SVladimir Medvedkin 	printf("%s: tests executed: %u, test passed: %u\n", __func__, nt, np);
923ed4f8e02SVladimir Medvedkin 	RTE_TEST_ASSERT(nt == np, "%u subtests failed", nt - np);
924ed4f8e02SVladimir Medvedkin 	return TEST_SUCCESS;
925ed4f8e02SVladimir Medvedkin }
926ed4f8e02SVladimir Medvedkin 
927*89398eceSVladimir Medvedkin #define RETA_SZ_LOG		11
928*89398eceSVladimir Medvedkin #define RSS_KEY_SZ		40
929*89398eceSVladimir Medvedkin #define RETA_SZ			(1 << RETA_SZ_LOG)
930*89398eceSVladimir Medvedkin #define NB_HASH_ITER	RETA_SZ
931*89398eceSVladimir Medvedkin #define NB_TEST_ITER	10
932*89398eceSVladimir Medvedkin 
933*89398eceSVladimir Medvedkin static inline void
934*89398eceSVladimir Medvedkin run_hash_calc_loop(uint8_t *key, union rte_thash_tuple *tuple,
935*89398eceSVladimir Medvedkin 					unsigned int *rss_reta_hits)
936*89398eceSVladimir Medvedkin {
937*89398eceSVladimir Medvedkin 	uint32_t rss_hash;
938*89398eceSVladimir Medvedkin 	int i;
939*89398eceSVladimir Medvedkin 
940*89398eceSVladimir Medvedkin 	for (i = 0; i < NB_HASH_ITER; i++) {
941*89398eceSVladimir Medvedkin 		/* variable part starts from the most significant bit */
942*89398eceSVladimir Medvedkin 		tuple->v4.dport = (i << (sizeof(tuple->v4.dport) * CHAR_BIT -
943*89398eceSVladimir Medvedkin 			RETA_SZ_LOG));
944*89398eceSVladimir Medvedkin 		/*
945*89398eceSVladimir Medvedkin 		 * swap sport and dport on LE arch since rte_softrss()
946*89398eceSVladimir Medvedkin 		 * works with host byte order uint32_t values
947*89398eceSVladimir Medvedkin 		 */
948*89398eceSVladimir Medvedkin 		tuple->v4.dport = rte_cpu_to_be_16(tuple->v4.dport);
949*89398eceSVladimir Medvedkin 		tuple->v4.sctp_tag = rte_be_to_cpu_32(tuple->v4.sctp_tag);
950*89398eceSVladimir Medvedkin 		rss_hash = rte_softrss((uint32_t *)tuple,
951*89398eceSVladimir Medvedkin 				RTE_THASH_V4_L4_LEN, key);
952*89398eceSVladimir Medvedkin 		/* unroll swap, required only for sport */
953*89398eceSVladimir Medvedkin 		tuple->v4.sctp_tag = rte_cpu_to_be_32(tuple->v4.sctp_tag);
954*89398eceSVladimir Medvedkin 		rss_reta_hits[rss_hash & (RETA_SZ - 1)]++;
955*89398eceSVladimir Medvedkin 	}
956*89398eceSVladimir Medvedkin }
957*89398eceSVladimir Medvedkin 
958*89398eceSVladimir Medvedkin static int
959*89398eceSVladimir Medvedkin hash_calc_iteration(unsigned int *min_before, unsigned int *max_before,
960*89398eceSVladimir Medvedkin 		unsigned int *min_after, unsigned int *max_after,
961*89398eceSVladimir Medvedkin 		unsigned int *min_default, unsigned int *max_default)
962*89398eceSVladimir Medvedkin {
963*89398eceSVladimir Medvedkin 	uint8_t key[RSS_KEY_SZ] = {0};
964*89398eceSVladimir Medvedkin 	union rte_thash_tuple tuple;
965*89398eceSVladimir Medvedkin 	unsigned int rss_reta_hits_before_adjust[RETA_SZ] = {0};
966*89398eceSVladimir Medvedkin 	unsigned int rss_reta_hits_after_adjust[RETA_SZ] = {0};
967*89398eceSVladimir Medvedkin 	unsigned int rss_reta_hits_default_key[RETA_SZ] = {0};
968*89398eceSVladimir Medvedkin 	int i;
969*89398eceSVladimir Medvedkin 
970*89398eceSVladimir Medvedkin 	for (i = 0; i < RSS_KEY_SZ; i++)
971*89398eceSVladimir Medvedkin 		key[i] = rte_rand();
972*89398eceSVladimir Medvedkin 
973*89398eceSVladimir Medvedkin 	tuple.v4.src_addr = rte_rand();
974*89398eceSVladimir Medvedkin 	tuple.v4.dst_addr = rte_rand();
975*89398eceSVladimir Medvedkin 	tuple.v4.sport = rte_rand();
976*89398eceSVladimir Medvedkin 
977*89398eceSVladimir Medvedkin 	run_hash_calc_loop(key, &tuple, rss_reta_hits_before_adjust);
978*89398eceSVladimir Medvedkin 
979*89398eceSVladimir Medvedkin 	int ret = rte_thash_gen_key(key, RSS_KEY_SZ, RETA_SZ_LOG,
980*89398eceSVladimir Medvedkin 		offsetof(union rte_thash_tuple, v4.dport)*CHAR_BIT,
981*89398eceSVladimir Medvedkin 		RETA_SZ_LOG);
982*89398eceSVladimir Medvedkin 
983*89398eceSVladimir Medvedkin 	if (ret) {
984*89398eceSVladimir Medvedkin 		printf("Can't generate key\n");
985*89398eceSVladimir Medvedkin 		return -1;
986*89398eceSVladimir Medvedkin 	}
987*89398eceSVladimir Medvedkin 
988*89398eceSVladimir Medvedkin 	run_hash_calc_loop(key, &tuple, rss_reta_hits_after_adjust);
989*89398eceSVladimir Medvedkin 
990*89398eceSVladimir Medvedkin 	run_hash_calc_loop(default_rss_key, &tuple, rss_reta_hits_default_key);
991*89398eceSVladimir Medvedkin 
992*89398eceSVladimir Medvedkin 	for (i = 0; i < RETA_SZ; i++) {
993*89398eceSVladimir Medvedkin 		*min_before = RTE_MIN(*min_before, rss_reta_hits_before_adjust[i]);
994*89398eceSVladimir Medvedkin 		*max_before = RTE_MAX(*max_before, rss_reta_hits_before_adjust[i]);
995*89398eceSVladimir Medvedkin 		*min_after = RTE_MIN(*min_after, rss_reta_hits_after_adjust[i]);
996*89398eceSVladimir Medvedkin 		*max_after = RTE_MAX(*max_after, rss_reta_hits_after_adjust[i]);
997*89398eceSVladimir Medvedkin 		*min_default = RTE_MIN(*min_default, rss_reta_hits_default_key[i]);
998*89398eceSVladimir Medvedkin 		*max_default = RTE_MAX(*max_default, rss_reta_hits_default_key[i]);
999*89398eceSVladimir Medvedkin 	}
1000*89398eceSVladimir Medvedkin 
1001*89398eceSVladimir Medvedkin 	return 0;
1002*89398eceSVladimir Medvedkin }
1003*89398eceSVladimir Medvedkin 
1004*89398eceSVladimir Medvedkin static int
1005*89398eceSVladimir Medvedkin test_keygen(void)
1006*89398eceSVladimir Medvedkin {
1007*89398eceSVladimir Medvedkin 	int i, ret;
1008*89398eceSVladimir Medvedkin 	unsigned int min_before = UINT32_MAX;
1009*89398eceSVladimir Medvedkin 	unsigned int min_after = UINT32_MAX;
1010*89398eceSVladimir Medvedkin 	unsigned int min_default = UINT32_MAX;
1011*89398eceSVladimir Medvedkin 	unsigned int max_before = 0;
1012*89398eceSVladimir Medvedkin 	unsigned int max_after = 0;
1013*89398eceSVladimir Medvedkin 	unsigned int max_default = 0;
1014*89398eceSVladimir Medvedkin 
1015*89398eceSVladimir Medvedkin 	for (i = 0; i < NB_TEST_ITER; i++) {
1016*89398eceSVladimir Medvedkin 		/* calculates the worst distribution for each key */
1017*89398eceSVladimir Medvedkin 		ret = hash_calc_iteration(&min_before, &max_before, &min_after,
1018*89398eceSVladimir Medvedkin 			&max_after, &min_default, &max_default);
1019*89398eceSVladimir Medvedkin 		if (ret)
1020*89398eceSVladimir Medvedkin 			return ret;
1021*89398eceSVladimir Medvedkin 	}
1022*89398eceSVladimir Medvedkin 
1023*89398eceSVladimir Medvedkin 	printf("RSS before key adjustment: min=%d, max=%d\n",
1024*89398eceSVladimir Medvedkin 		min_before, max_before);
1025*89398eceSVladimir Medvedkin 	printf("RSS after key adjustment: min=%d, max=%d\n",
1026*89398eceSVladimir Medvedkin 		min_after, max_after);
1027*89398eceSVladimir Medvedkin 	printf("RSS default key: min=%d, max=%d\n",
1028*89398eceSVladimir Medvedkin 		min_default, max_default);
1029*89398eceSVladimir Medvedkin 
1030*89398eceSVladimir Medvedkin 	return TEST_SUCCESS;
1031*89398eceSVladimir Medvedkin }
1032*89398eceSVladimir Medvedkin 
103328ebff11SVladimir Medvedkin static struct unit_test_suite thash_tests = {
103428ebff11SVladimir Medvedkin 	.suite_name = "thash autotest",
103528ebff11SVladimir Medvedkin 	.setup = NULL,
103628ebff11SVladimir Medvedkin 	.teardown = NULL,
103728ebff11SVladimir Medvedkin 	.unit_test_cases = {
103828ebff11SVladimir Medvedkin 	TEST_CASE(test_toeplitz_hash_calc),
10394fd8c4cbSVladimir Medvedkin 	TEST_CASE(test_toeplitz_hash_gfni),
10404fd8c4cbSVladimir Medvedkin 	TEST_CASE(test_toeplitz_hash_rand_data),
104131d7c069SVladimir Medvedkin 	TEST_CASE(test_toeplitz_hash_gfni_bulk),
10424fd8c4cbSVladimir Medvedkin 	TEST_CASE(test_big_tuple_gfni),
104328ebff11SVladimir Medvedkin 	TEST_CASE(test_create_invalid),
104428ebff11SVladimir Medvedkin 	TEST_CASE(test_multiple_create),
104528ebff11SVladimir Medvedkin 	TEST_CASE(test_free_null),
104628ebff11SVladimir Medvedkin 	TEST_CASE(test_add_invalid_helper),
104728ebff11SVladimir Medvedkin 	TEST_CASE(test_find_existing),
104828ebff11SVladimir Medvedkin 	TEST_CASE(test_get_helper),
104928ebff11SVladimir Medvedkin 	TEST_CASE(test_period_overflow),
105028ebff11SVladimir Medvedkin 	TEST_CASE(test_predictable_rss_min_seq),
105128ebff11SVladimir Medvedkin 	TEST_CASE(test_predictable_rss_multirange),
105228ebff11SVladimir Medvedkin 	TEST_CASE(test_adjust_tuple),
1053ed4f8e02SVladimir Medvedkin 	TEST_CASE(test_adjust_tuple_mult_reta),
1054*89398eceSVladimir Medvedkin 	TEST_CASE(test_keygen),
105528ebff11SVladimir Medvedkin 	TEST_CASES_END()
105628ebff11SVladimir Medvedkin 	}
105728ebff11SVladimir Medvedkin };
105828ebff11SVladimir Medvedkin 
105928ebff11SVladimir Medvedkin static int
106028ebff11SVladimir Medvedkin test_thash(void)
106128ebff11SVladimir Medvedkin {
106228ebff11SVladimir Medvedkin 	return unit_test_suite_runner(&thash_tests);
1063a9de470cSBruce Richardson }
1064a9de470cSBruce Richardson 
1065e0a8442cSBruce Richardson REGISTER_FAST_TEST(thash_autotest, true, true, test_thash);
1066