<div dir="ltr">The reported <a href="http://mails.dpdk.org/archives/test-report/2023-February/357697.html">performance issue</a> is a mystery to me. Does anyone have an idea what's going on?<div><br></div><div>Thanks,</div><div>Bili</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Feb 21, 2023 at 11:37 AM Bili Dong <<a href="mailto:qobilidop@gmail.com">qobilidop@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">An XOR32 hash is needed in the Software Switch (SWX) Pipeline for its<br>
use case in P4. We implement it in this patch so it could be easily<br>
registered in the pipeline later.<br>
<br>
Signed-off-by: Bili Dong <<a href="mailto:qobilidop@gmail.com" target="_blank">qobilidop@gmail.com</a>><br>
---<br>
.mailmap | 1 +<br>
app/test/test_hash_functions.c | 33 +++++++++++--<br>
lib/hash/rte_hash_xor.h | 87 ++++++++++++++++++++++++++++++++++<br>
3 files changed, 118 insertions(+), 3 deletions(-)<br>
create mode 100644 lib/hash/rte_hash_xor.h<br>
<br>
diff --git a/.mailmap b/.mailmap<br>
index a9f4f28fba..3e9bec29d5 100644<br>
--- a/.mailmap<br>
+++ b/.mailmap<br>
@@ -159,6 +159,7 @@ Bernard Iremonger <<a href="mailto:bernard.iremonger@intel.com" target="_blank">bernard.iremonger@intel.com</a>><br>
Bert van Leeuwen <<a href="mailto:bert.vanleeuwen@netronome.com" target="_blank">bert.vanleeuwen@netronome.com</a>><br>
Bhagyada Modali <<a href="mailto:bhagyada.modali@amd.com" target="_blank">bhagyada.modali@amd.com</a>><br>
Bharat Mota <<a href="mailto:bmota@vmware.com" target="_blank">bmota@vmware.com</a>><br>
+Bili Dong <<a href="mailto:qobilidop@gmail.com" target="_blank">qobilidop@gmail.com</a>><br>
Bill Hong <<a href="mailto:bhong@brocade.com" target="_blank">bhong@brocade.com</a>><br>
Billy McFall <<a href="mailto:bmcfall@redhat.com" target="_blank">bmcfall@redhat.com</a>><br>
Billy O'Mahony <<a href="mailto:billy.o.mahony@intel.com" target="_blank">billy.o.mahony@intel.com</a>><br>
diff --git a/app/test/test_hash_functions.c b/app/test/test_hash_functions.c<br>
index 76d51b6e71..53e296fec4 100644<br>
--- a/app/test/test_hash_functions.c<br>
+++ b/app/test/test_hash_functions.c<br>
@@ -15,6 +15,7 @@<br>
#include <rte_hash.h><br>
#include <rte_jhash.h><br>
#include <rte_hash_crc.h><br>
+#include <rte_hash_xor.h><br>
<br>
#include "test.h"<br>
<br>
@@ -22,8 +23,8 @@<br>
* Hash values calculated for key sizes from array "hashtest_key_lens"<br>
* and for initial values from array "hashtest_initvals.<br>
* Each key will be formed by increasing each byte by 1:<br>
- * e.g.: key size = 4, key = 0x03020100<br>
- * key size = 8, key = 0x0706050403020100<br>
+ * e.g.: key size = 4, key = 0x00010203<br>
+ * key size = 8, key = 0x0001020304050607<br>
*/<br>
static uint32_t hash_values_jhash[2][12] = {{<br>
0x8ba9414b, 0xdf0d39c9,<br>
@@ -51,6 +52,19 @@ static uint32_t hash_values_crc[2][12] = {{<br>
0x789c104f, 0x53028d3e<br>
}<br>
};<br>
+static uint32_t hash_values_xor32[2][12] = {{<br>
+ 0x00000000, 0x00010000,<br>
+ 0x00010203, 0x04040404, 0x00000000, 0x00000000,<br>
+ 0x00000000, 0x00000000, 0x0c040404, 0x000d0e0f,<br>
+ 0x04212223, 0x04040404<br>
+},<br>
+{<br>
+ 0xdeadbeef, 0xdeacbeef,<br>
+ 0xdeacbcec, 0xdaa9baeb, 0xdeadbeef, 0xdeadbeef,<br>
+ 0xdeadbeef, 0xdeadbeef, 0xd2a9baeb, 0xdea0b0e0,<br>
+ 0xda8c9ccc, 0xdaa9baeb<br>
+}<br>
+};<br>
<br>
/*******************************************************************************<br>
* Hash function performance test configuration section. Each performance test<br>
@@ -61,7 +75,7 @@ static uint32_t hash_values_crc[2][12] = {{<br>
*/<br>
#define HASHTEST_ITERATIONS 1000000<br>
#define MAX_KEYSIZE 64<br>
-static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc};<br>
+static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc, rte_hash_xor32};<br>
static uint32_t hashtest_initvals[] = {0, 0xdeadbeef};<br>
static uint32_t hashtest_key_lens[] = {<br>
1, 2, /* Unusual key sizes */<br>
@@ -85,6 +99,9 @@ get_hash_name(rte_hash_function f)<br>
if (f == rte_hash_crc)<br>
return "rte_hash_crc";<br>
<br>
+ if (f == rte_hash_xor32)<br>
+ return "rte_hash_xor32";<br>
+<br>
return "UnknownHash";<br>
}<br>
<br>
@@ -173,6 +190,16 @@ verify_precalculated_hash_func_tests(void)<br>
hash_values_crc[j][i], hash);<br>
return -1;<br>
}<br>
+<br>
+ hash = rte_hash_xor32(key, hashtest_key_lens[i],<br>
+ hashtest_initvals[j]);<br>
+ if (hash != hash_values_xor32[j][i]) {<br>
+ printf("XOR32 for %u bytes with initial value 0x%x."<br>
+ " Expected 0x%x, but got 0x%x\n",<br>
+ hashtest_key_lens[i], hashtest_initvals[j],<br>
+ hash_values_xor32[j][i], hash);<br>
+ return -1;<br>
+ }<br>
}<br>
}<br>
<br>
diff --git a/lib/hash/rte_hash_xor.h b/lib/hash/rte_hash_xor.h<br>
new file mode 100644<br>
index 0000000000..366adbe64c<br>
--- /dev/null<br>
+++ b/lib/hash/rte_hash_xor.h<br>
@@ -0,0 +1,87 @@<br>
+/* SPDX-License-Identifier: BSD-3-Clause<br>
+ * Copyright(c) 2023 Intel Corporation<br>
+ */<br>
+<br>
+#ifndef _RTE_HASH_XOR_H_<br>
+#define _RTE_HASH_XOR_H_<br>
+<br>
+/**<br>
+ * @file<br>
+ *<br>
+ * RTE XOR Hash<br>
+ */<br>
+<br>
+#ifdef __cplusplus<br>
+extern "C" {<br>
+#endif<br>
+<br>
+#include <stdint.h><br>
+<br>
+#include <rte_byteorder.h><br>
+<br>
+/**<br>
+ * Calculate XOR32 hash on user-supplied byte array.<br>
+ *<br>
+ * @param data<br>
+ * Data to perform hash on.<br>
+ * @param data_len<br>
+ * How many bytes to use to calculate hash value.<br>
+ * @param init_val<br>
+ * Value to initialise hash generator.<br>
+ * @return<br>
+ * 32bit calculated hash value.<br>
+ */<br>
+static inline uint32_t<br>
+rte_hash_xor32(const void *data, uint32_t data_len, uint32_t init_val)<br>
+{<br>
+ uint32_t hash32;<br>
+ const uint8_t *data8 = data;<br>
+<br>
+ /* Minimize byte order conversions depending on data length. */<br>
+ if (data_len >= 8) {<br>
+ /* For longer arrays, operate in big endian. */<br>
+ uint64_t hash64 = rte_cpu_to_be_32(init_val);<br>
+<br>
+ uint32_t i;<br>
+ for (i = 0; i < data_len / 8; i++) {<br>
+ hash64 ^= *(const uint64_t *)data8;<br>
+ data8 += 8;<br>
+ }<br>
+<br>
+ if (data_len & 0x4) {<br>
+ hash64 ^= *(const uint32_t *)data8;<br>
+ data8 += 4;<br>
+ }<br>
+<br>
+ hash32 = rte_be_to_cpu_32(hash64 ^ (hash64 >> 32));<br>
+ } else {<br>
+ /* For shorter arrays, operate in host endian. */<br>
+ hash32 = init_val;<br>
+<br>
+ if (data_len & 0x4) {<br>
+ hash32 ^= rte_be_to_cpu_32(*(const uint32_t *)data8);<br>
+ data8 += 4;<br>
+ }<br>
+ }<br>
+<br>
+ /* Deal with remaining (< 4) bytes. */<br>
+<br>
+ uint8_t bit_offset = 0;<br>
+<br>
+ if (data_len & 0x2) {<br>
+ hash32 ^= (uint32_t)rte_be_to_cpu_16(*(const uint16_t *)data8) << 16;<br>
+ data8 += 2;<br>
+ bit_offset += 16;<br>
+ }<br>
+<br>
+ if (data_len & 0x1)<br>
+ hash32 ^= (uint32_t)(*(const uint8_t *)data8) << (24 - bit_offset);<br>
+<br>
+ return hash32;<br>
+}<br>
+<br>
+#ifdef __cplusplus<br>
+}<br>
+#endif<br>
+<br>
+#endif /* _RTE_HASH_XOR_H_ */<br>
-- <br>
2.34.1<br>
<br>
</blockquote></div>