@@ -7,6 +7,7 @@
#include <rte_ip.h>
#include <rte_random.h>
#include <rte_malloc.h>
+#include <rte_byteorder.h>
#include "test.h"
@@ -935,6 +936,112 @@ test_adjust_tuple_mult_reta(void)
return TEST_SUCCESS;
}
+#define RETA_SZ_LOG 11
+#define RSS_KEY_SZ 40
+#define RETA_SZ (1 << RETA_SZ_LOG)
+#define NB_HASH_ITER RETA_SZ
+#define NB_TEST_ITER 10
+
+static inline void
+run_hash_calc_loop(uint8_t *key, union rte_thash_tuple *tuple,
+ unsigned int *rss_reta_hits)
+{
+ uint32_t rss_hash;
+ int i;
+
+ for (i = 0; i < NB_HASH_ITER; i++) {
+ /* variable part starts from the most significant bit */
+ tuple->v4.dport = (i << (sizeof(tuple->v4.dport) * CHAR_BIT -
+ RETA_SZ_LOG));
+ /*
+ * swap sport and dport on LE arch since rte_softrss()
+ * works with host byte order uint32_t values
+ */
+ tuple->v4.dport = rte_cpu_to_be_16(tuple->v4.dport);
+ tuple->v4.sctp_tag = rte_be_to_cpu_32(tuple->v4.sctp_tag);
+ rss_hash = rte_softrss((uint32_t *)tuple,
+ RTE_THASH_V4_L4_LEN, key);
+ /* unroll swap, required only for sport */
+ tuple->v4.sctp_tag = rte_cpu_to_be_32(tuple->v4.sctp_tag);
+ rss_reta_hits[rss_hash & (RETA_SZ - 1)]++;
+ }
+}
+
+static int
+hash_calc_iteration(unsigned int *min_before, unsigned int *max_before,
+ unsigned int *min_after, unsigned int *max_after,
+ unsigned int *min_default, unsigned int *max_default)
+{
+ uint8_t key[RSS_KEY_SZ] = {0};
+ union rte_thash_tuple tuple;
+ unsigned int rss_reta_hits_before_adjust[RETA_SZ] = {0};
+ unsigned int rss_reta_hits_after_adjust[RETA_SZ] = {0};
+ unsigned int rss_reta_hits_default_key[RETA_SZ] = {0};
+ int i;
+
+ for (i = 0; i < RSS_KEY_SZ; i++)
+ key[i] = rte_rand();
+
+ tuple.v4.src_addr = rte_rand();
+ tuple.v4.dst_addr = rte_rand();
+ tuple.v4.sport = rte_rand();
+
+ run_hash_calc_loop(key, &tuple, rss_reta_hits_before_adjust);
+
+ int ret = rte_thash_gen_key(key, RSS_KEY_SZ, RETA_SZ_LOG,
+ offsetof(union rte_thash_tuple, v4.dport)*CHAR_BIT,
+ RETA_SZ_LOG);
+
+ if (ret) {
+ printf("Can't generate key\n");
+ return -1;
+ }
+
+ run_hash_calc_loop(key, &tuple, rss_reta_hits_after_adjust);
+
+ run_hash_calc_loop(default_rss_key, &tuple, rss_reta_hits_default_key);
+
+ for (i = 0; i < RETA_SZ; i++) {
+ *min_before = RTE_MIN(*min_before, rss_reta_hits_before_adjust[i]);
+ *max_before = RTE_MAX(*max_before, rss_reta_hits_before_adjust[i]);
+ *min_after = RTE_MIN(*min_after, rss_reta_hits_after_adjust[i]);
+ *max_after = RTE_MAX(*max_after, rss_reta_hits_after_adjust[i]);
+ *min_default = RTE_MIN(*min_default, rss_reta_hits_default_key[i]);
+ *max_default = RTE_MAX(*max_default, rss_reta_hits_default_key[i]);
+ }
+
+ return 0;
+}
+
+static int
+test_keygen(void)
+{
+ int i, ret;
+ unsigned int min_before = UINT32_MAX;
+ unsigned int min_after = UINT32_MAX;
+ unsigned int min_default = UINT32_MAX;
+ unsigned int max_before = 0;
+ unsigned int max_after = 0;
+ unsigned int max_default = 0;
+
+ for (i = 0; i < NB_TEST_ITER; i++) {
+ /* calculates the worst distribution for each key */
+ ret = hash_calc_iteration(&min_before, &max_before, &min_after,
+ &max_after, &min_default, &max_default);
+ if (ret)
+ return ret;
+ }
+
+ printf("RSS before key adjustment: min=%d, max=%d\n",
+ min_before, max_before);
+ printf("RSS after key adjustment: min=%d, max=%d\n",
+ min_after, max_after);
+ printf("RSS default key: min=%d, max=%d\n",
+ min_default, max_default);
+
+ return TEST_SUCCESS;
+}
+
static struct unit_test_suite thash_tests = {
.suite_name = "thash autotest",
.setup = NULL,
@@ -956,6 +1063,7 @@ static struct unit_test_suite thash_tests = {
TEST_CASE(test_predictable_rss_multirange),
TEST_CASE(test_adjust_tuple),
TEST_CASE(test_adjust_tuple_mult_reta),
+ TEST_CASE(test_keygen),
TEST_CASES_END()
}
};