From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 96ABA42CC8; Thu, 15 Jun 2023 19:15:12 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 240B240E0F; Thu, 15 Jun 2023 19:15:12 +0200 (CEST) Received: from mail-ot1-f47.google.com (mail-ot1-f47.google.com [209.85.210.47]) by mails.dpdk.org (Postfix) with ESMTP id D854040A8B for ; Thu, 15 Jun 2023 19:15:10 +0200 (CEST) Received: by mail-ot1-f47.google.com with SMTP id 46e09a7af769-6b2993c9652so5759457a34.1 for ; Thu, 15 Jun 2023 10:15:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1686849310; x=1689441310; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=6yyzw6dgiPuyhMPF95gkhuFpTef/PERxlBxtAK7c8YU=; b=bc7r6akMaKcURB7OoktsHFGN6bzYPqkEwwWJmKylTu8MyEn0qZJw3kZZokH7mIGDyH 5GTEvNU0xawozGHfUrG8AAWFVplPr94YkGxDinq3bjjPYXNSe4oB+e5XyTaWC0byqpZV Gyt1RTOPvAf0ZTzbx6e0OQNsBwoVp24GH/9RJcn+Lh4fApBcR3Kqb9xNj7lb1UA8FNR3 Wm04pXavwZ4qlXFnRFcQCh1VVySwy3QlPov5kclGsd93oSi+mCXb+OGpgsnyrXDk6ya0 ztBrmw389NQjPgsIm0Ql0Y5bpxtNDXvrE+9XmkfUFqbjzPeVRAtTTRa+UtTZA0MVUjwg YLoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686849310; x=1689441310; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=6yyzw6dgiPuyhMPF95gkhuFpTef/PERxlBxtAK7c8YU=; b=CXs+Vv7BTVZMbFob6eAjOyt2EkCwHcJ2pDIjib9UhuOQ6l+Ysfa/eQJfAcEnbSu6QP Woszf3WaWSCjUWcNzlENxsismZ+0U4toCHUncvceJknGyyvEA3zp3S1SXXpjA+mIALNz ELzfCx/RRKxLvlhxBVnSgmNnG6IruHEIJCzn3hor+/VBPw0s/4O8LY8O/JUOtO68lNvd dDbNQBW15/k0FnyWEWTeWtvieDJYK4e1e93rZKtt2/vX1S77x6oG/5CUOgezhINZ5oDf WUGvIzPtMx5XkQhFK+xKn7C6qqXztJOYFaMfrQgGjXpvx4wBKmpQrYRzG9FnR45d3Ch+ 5u4g== X-Gm-Message-State: AC+VfDyggDJnmozWmS0u8AdTJnvktXUHKOpvXUmlQWcRijaV3wTpJOQm BAzYqpu4r+JttzPyoL4EXP/2ghiPfnolaGd/9FY= X-Google-Smtp-Source: ACHHUZ4pOYFgQeK1hg2pKbaPvnoqa4ME2BCNq19cGRPdJr5QGcj3Ti7OduNXYGLOTpPFBAEf5M//AJt87+dlV5IRD/8= X-Received: by 2002:a4a:e050:0:b0:54f:629a:f581 with SMTP id v16-20020a4ae050000000b0054f629af581mr12217208oos.7.1686849309877; Thu, 15 Jun 2023 10:15:09 -0700 (PDT) MIME-Version: 1.0 References: <20230221175529.644311-1-qobilidop@gmail.com> <20230221193710.717280-1-qobilidop@gmail.com> In-Reply-To: <20230221193710.717280-1-qobilidop@gmail.com> From: Vladimir Medvedkin Date: Thu, 15 Jun 2023 18:14:58 +0100 Message-ID: Subject: Re: [PATCH v6] hash: add XOR32 hash function To: Bili Dong Cc: vladimir.medvedkin@intel.com, dev@dpdk.org, cristian.dumitrescu@intel.com, Bruce Richardson , yipeng1.wang@intel.com, sameh.gobriel@intel.com, Thomas Monjalon Content-Type: multipart/alternative; boundary="000000000000e7a9e505fe2e354c" X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org --000000000000e7a9e505fe2e354c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Bili, The rte_hash_xor32() implementation looks a bit messy with respect to byte ordering, i.e. in case when data_len >=3D 8 init_val is byte swapped, but i= n other cases the data is byte swapped. Maybe it could be implemented like: static inline uint32_t rte_hash_xor32(const void *data, uint32_t data_len, uint32_t init_val) { const uint8_t *data8 =3D data; uint64_t hash64 =3D 0; uint32_t hash32; unsigned int i; for (i =3D 0; i < data_len / 8; i++) { hash64 ^=3D *(const uint64_t *)data8; data8 +=3D 8; } if (data_len & 0x4) { hash64 ^=3D *(const uint32_t *)data8; data8 +=3D 4; } int bit_offset =3D 0; if (data_len & 0x2) { hash64 ^=3D *(const uint16_t *)data8; bit_offset =3D 16; data8 +=3D 2; } if (data_len & 0x1) hash64 ^=3D *(const uint8_t *)data8 << bit_offset; hash32 =3D (hash64 >> 32) ^ (uint32_t)hash64; return rte_be_to_cpu_32(hash32) ^ init_val; } What do you think? Also, consider to check in hash_functions_autotest keys with length equal to 3 (or eq 3 mod 4, for example 7 or 11) =D0=B2=D1=82, 21 =D1=84=D0=B5=D0=B2=D1=80. 2023=E2=80=AF=D0=B3. =D0=B2 19:3= 7, Bili Dong : > An XOR32 hash is needed in the Software Switch (SWX) Pipeline for its > use case in P4. We implement it in this patch so it could be easily > registered in the pipeline later. > > Signed-off-by: Bili Dong > --- > .mailmap | 1 + > app/test/test_hash_functions.c | 33 +++++++++++-- > lib/hash/rte_hash_xor.h | 87 ++++++++++++++++++++++++++++++++++ > 3 files changed, 118 insertions(+), 3 deletions(-) > create mode 100644 lib/hash/rte_hash_xor.h > > diff --git a/.mailmap b/.mailmap > index a9f4f28fba..3e9bec29d5 100644 > --- a/.mailmap > +++ b/.mailmap > @@ -159,6 +159,7 @@ Bernard Iremonger > Bert van Leeuwen > Bhagyada Modali > Bharat Mota > +Bili Dong > Bill Hong > Billy McFall > Billy O'Mahony > diff --git a/app/test/test_hash_functions.c > b/app/test/test_hash_functions.c > index 76d51b6e71..53e296fec4 100644 > --- a/app/test/test_hash_functions.c > +++ b/app/test/test_hash_functions.c > @@ -15,6 +15,7 @@ > #include > #include > #include > +#include > > #include "test.h" > > @@ -22,8 +23,8 @@ > * Hash values calculated for key sizes from array "hashtest_key_lens" > * and for initial values from array "hashtest_initvals. > * Each key will be formed by increasing each byte by 1: > - * e.g.: key size =3D 4, key =3D 0x03020100 > - * key size =3D 8, key =3D 0x0706050403020100 > + * e.g.: key size =3D 4, key =3D 0x00010203 > + * key size =3D 8, key =3D 0x0001020304050607 > */ > static uint32_t hash_values_jhash[2][12] =3D {{ > 0x8ba9414b, 0xdf0d39c9, > @@ -51,6 +52,19 @@ static uint32_t hash_values_crc[2][12] =3D {{ > 0x789c104f, 0x53028d3e > } > }; > +static uint32_t hash_values_xor32[2][12] =3D {{ > + 0x00000000, 0x00010000, > + 0x00010203, 0x04040404, 0x00000000, 0x00000000, > + 0x00000000, 0x00000000, 0x0c040404, 0x000d0e0f, > + 0x04212223, 0x04040404 > +}, > +{ > + 0xdeadbeef, 0xdeacbeef, > + 0xdeacbcec, 0xdaa9baeb, 0xdeadbeef, 0xdeadbeef, > + 0xdeadbeef, 0xdeadbeef, 0xd2a9baeb, 0xdea0b0e0, > + 0xda8c9ccc, 0xdaa9baeb > +} > +}; > > > /***********************************************************************= ******** > * Hash function performance test configuration section. Each performanc= e > test > @@ -61,7 +75,7 @@ static uint32_t hash_values_crc[2][12] =3D {{ > */ > #define HASHTEST_ITERATIONS 1000000 > #define MAX_KEYSIZE 64 > -static rte_hash_function hashtest_funcs[] =3D {rte_jhash, rte_hash_crc}; > +static rte_hash_function hashtest_funcs[] =3D {rte_jhash, rte_hash_crc, > rte_hash_xor32}; > static uint32_t hashtest_initvals[] =3D {0, 0xdeadbeef}; > static uint32_t hashtest_key_lens[] =3D { > 1, 2, /* Unusual key sizes */ > @@ -85,6 +99,9 @@ get_hash_name(rte_hash_function f) > if (f =3D=3D rte_hash_crc) > return "rte_hash_crc"; > > + if (f =3D=3D rte_hash_xor32) > + return "rte_hash_xor32"; > + > return "UnknownHash"; > } > > @@ -173,6 +190,16 @@ verify_precalculated_hash_func_tests(void) > hash_values_crc[j][i], hash); > return -1; > } > + > + hash =3D rte_hash_xor32(key, hashtest_key_lens[i]= , > + hashtest_initvals[j]); > + if (hash !=3D hash_values_xor32[j][i]) { > + printf("XOR32 for %u bytes with initial > value 0x%x." > + " Expected 0x%x, but got 0x%x\n", > + hashtest_key_lens[i], > hashtest_initvals[j], > + hash_values_xor32[j][i], hash); > + return -1; > + } > } > } > > diff --git a/lib/hash/rte_hash_xor.h b/lib/hash/rte_hash_xor.h > new file mode 100644 > index 0000000000..366adbe64c > --- /dev/null > +++ b/lib/hash/rte_hash_xor.h > @@ -0,0 +1,87 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2023 Intel Corporation > + */ > + > +#ifndef _RTE_HASH_XOR_H_ > +#define _RTE_HASH_XOR_H_ > + > +/** > + * @file > + * > + * RTE XOR Hash > + */ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include > + > +#include > + > +/** > + * Calculate XOR32 hash on user-supplied byte array. > + * > + * @param data > + * Data to perform hash on. > + * @param data_len > + * How many bytes to use to calculate hash value. > + * @param init_val > + * Value to initialise hash generator. > + * @return > + * 32bit calculated hash value. > + */ > +static inline uint32_t > +rte_hash_xor32(const void *data, uint32_t data_len, uint32_t init_val) > +{ > + uint32_t hash32; > + const uint8_t *data8 =3D data; > + > + /* Minimize byte order conversions depending on data length. */ > + if (data_len >=3D 8) { > + /* For longer arrays, operate in big endian. */ > + uint64_t hash64 =3D rte_cpu_to_be_32(init_val); > + > + uint32_t i; > + for (i =3D 0; i < data_len / 8; i++) { > + hash64 ^=3D *(const uint64_t *)data8; > + data8 +=3D 8; > + } > + > + if (data_len & 0x4) { > + hash64 ^=3D *(const uint32_t *)data8; > + data8 +=3D 4; > + } > + > + hash32 =3D rte_be_to_cpu_32(hash64 ^ (hash64 >> 32)); > + } else { > + /* For shorter arrays, operate in host endian. */ > + hash32 =3D init_val; > + > + if (data_len & 0x4) { > + hash32 ^=3D rte_be_to_cpu_32(*(const uint32_t > *)data8); > + data8 +=3D 4; > + } > + } > + > + /* Deal with remaining (< 4) bytes. */ > + > + uint8_t bit_offset =3D 0; > + > + if (data_len & 0x2) { > + hash32 ^=3D (uint32_t)rte_be_to_cpu_16(*(const uint16_t > *)data8) << 16; > + data8 +=3D 2; > + bit_offset +=3D 16; > + } > + > + if (data_len & 0x1) > + hash32 ^=3D (uint32_t)(*(const uint8_t *)data8) << (24 - > bit_offset); > + > + return hash32; > +} > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif /* _RTE_HASH_XOR_H_ */ > -- > 2.34.1 > > --=20 Regards, Vladimir --000000000000e7a9e505fe2e354c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Bili,

The rte_hash_xor32(= ) implementation looks a bit messy with respect to byte ordering, i.e. in c= ase when data_len >=3D 8 init_val is byte swapped, but in other cases th= e data is byte swapped.
Maybe it could be implemented like:
=

static inline uint32_t
rte_hash_xor32(const void *da= ta, uint32_t data_len, uint32_t init_val)
{
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 const uint8_t *data8 =3D data;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t = hash64 =3D 0;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint32_t hash32;
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 unsigned int i;

=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (i= =3D 0; i < data_len / 8; i++) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 hash64 ^=3D *(const uint64_t *)data8;
=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 data8 +=3D 8;
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 }

=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (data_len & 0x4) = {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 hash64 ^=3D *(= const uint32_t *)data8;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 data8 +=3D 4;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

=C2=A0 =C2=A0= =C2=A0 =C2=A0 int bit_offset =3D 0;

=C2=A0 =C2=A0 =C2=A0 =C2=A0 if = (data_len & 0x2) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 hash64 ^=3D *(const uint16_t *)data8;
=C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 bit_offset =3D 16;
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 data8 +=3D 2;
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 }

=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (data_len & 0x1)
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 hash64 ^=3D *(const uint8_= t *)data8 << bit_offset;

=C2=A0 =C2=A0 =C2=A0 =C2=A0 hash32 = =3D (hash64 >> 32) ^ (uint32_t)hash64;

=C2=A0 =C2=A0 =C2=A0 = =C2=A0 return rte_be_to_cpu_32(hash32) ^ init_val;
}

<= /div>
What do you think?

Also, consider to che= ck in=C2=A0hash_functions_autotest keys with length equal to 3 (or eq 3 mod= 4, for example 7 or 11)

=D0=B2=D1=82, 21 =D1=84=D0=B5=D0=B2=D1=80. 2023=E2= =80=AF=D0=B3. =D0=B2 19:37, Bili Dong <qobilidop@gmail.com>:
An XOR32 hash is needed in the Software Switch (SWX) Pip= eline for its
use case in P4. We implement it in this patch so it could be easily
registered in the pipeline later.

Signed-off-by: Bili Dong <qobilidop@gmail.com>
---
=C2=A0.mailmap=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 1 +
=C2=A0app/test/test_hash_functions.c | 33 +++++++++++--
=C2=A0lib/hash/rte_hash_xor.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 | 87 +++++++++++++= +++++++++++++++++++++
=C2=A03 files changed, 118 insertions(+), 3 deletions(-)
=C2=A0create mode 100644 lib/hash/rte_hash_xor.h

diff --git a/.mailmap b/.mailmap
index a9f4f28fba..3e9bec29d5 100644
--- a/.mailmap
+++ b/.mailmap
@@ -159,6 +159,7 @@ Bernard Iremonger <bernard.iremonger@intel.com>
=C2=A0Bert van Leeuwen <bert.vanleeuwen@netronome.com>
=C2=A0Bhagyada Modali <bhagyada.modali@amd.com>
=C2=A0Bharat Mota <bmota@vmware.com>
+Bili Dong <qob= ilidop@gmail.com>
=C2=A0Bill Hong <= bhong@brocade.com>
=C2=A0Billy McFall <bmcfall@redhat.com>
=C2=A0Billy O'Mahony <billy.o.mahony@intel.com>
diff --git a/app/test/test_hash_functions.c b/app/test/test_hash_functions.= c
index 76d51b6e71..53e296fec4 100644
--- a/app/test/test_hash_functions.c
+++ b/app/test/test_hash_functions.c
@@ -15,6 +15,7 @@
=C2=A0#include <rte_hash.h>
=C2=A0#include <rte_jhash.h>
=C2=A0#include <rte_hash_crc.h>
+#include <rte_hash_xor.h>

=C2=A0#include "test.h"

@@ -22,8 +23,8 @@
=C2=A0 * Hash values calculated for key sizes from array "hashtest_key= _lens"
=C2=A0 * and for initial values from array "hashtest_initvals.
=C2=A0 * Each key will be formed by increasing each byte by 1:
- * e.g.: key size =3D 4, key =3D 0x03020100
- *=C2=A0 =C2=A0 =C2=A0 =C2=A0key size =3D 8, key =3D 0x0706050403020100 + * e.g.: key size =3D 4, key =3D 0x00010203
+ *=C2=A0 =C2=A0 =C2=A0 =C2=A0key size =3D 8, key =3D 0x0001020304050607 =C2=A0 */
=C2=A0static uint32_t hash_values_jhash[2][12] =3D {{
=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x8ba9414b, 0xdf0d39c9,
@@ -51,6 +52,19 @@ static uint32_t hash_values_crc[2][12] =3D {{
=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x789c104f, 0x53028d3e
=C2=A0}
=C2=A0};
+static uint32_t hash_values_xor32[2][12] =3D {{
+=C2=A0 =C2=A0 =C2=A0 =C2=A00x00000000, 0x00010000,
+=C2=A0 =C2=A0 =C2=A0 =C2=A00x00010203, 0x04040404, 0x00000000, 0x00000000,=
+=C2=A0 =C2=A0 =C2=A0 =C2=A00x00000000, 0x00000000, 0x0c040404, 0x000d0e0f,=
+=C2=A0 =C2=A0 =C2=A0 =C2=A00x04212223, 0x04040404
+},
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A00xdeadbeef, 0xdeacbeef,
+=C2=A0 =C2=A0 =C2=A0 =C2=A00xdeacbcec, 0xdaa9baeb, 0xdeadbeef, 0xdeadbeef,=
+=C2=A0 =C2=A0 =C2=A0 =C2=A00xdeadbeef, 0xdeadbeef, 0xd2a9baeb, 0xdea0b0e0,=
+=C2=A0 =C2=A0 =C2=A0 =C2=A00xda8c9ccc, 0xdaa9baeb
+}
+};

=C2=A0/********************************************************************= ***********
=C2=A0 * Hash function performance test configuration section. Each perform= ance test
@@ -61,7 +75,7 @@ static uint32_t hash_values_crc[2][12] =3D {{
=C2=A0 */
=C2=A0#define HASHTEST_ITERATIONS 1000000
=C2=A0#define MAX_KEYSIZE 64
-static rte_hash_function hashtest_funcs[] =3D {rte_jhash, rte_hash_crc}; +static rte_hash_function hashtest_funcs[] =3D {rte_jhash, rte_hash_crc, rt= e_hash_xor32};
=C2=A0static uint32_t hashtest_initvals[] =3D {0, 0xdeadbeef};
=C2=A0static uint32_t hashtest_key_lens[] =3D {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 1, 2,=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0/* Unusual key sizes */
@@ -85,6 +99,9 @@ get_hash_name(rte_hash_function f)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (f =3D=3D rte_hash_crc)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return "rte_ha= sh_crc";

+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (f =3D=3D rte_hash_xor32)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return "rte_ha= sh_xor32";
+
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return "UnknownHash";
=C2=A0}

@@ -173,6 +190,16 @@ verify_precalculated_hash_func_tests(void)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0hash_valu= es_crc[j][i], hash);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return -1;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 }
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0hash =3D rte_hash_xor32(key, hashtest_key_lens[i],
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0hashtest_= initvals[j]);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0if (hash !=3D hash_values_xor32[j][i]) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0printf("XOR32 for %u bytes with = initial value 0x%x."
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 " Expected= 0x%x, but got 0x%x\n",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 hashtest_key_le= ns[i], hashtest_initvals[j],
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 hash_values_xor= 32[j][i], hash);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return -1;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0}
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

diff --git a/lib/hash/rte_hash_xor.h b/lib/hash/rte_hash_xor.h
new file mode 100644
index 0000000000..366adbe64c
--- /dev/null
+++ b/lib/hash/rte_hash_xor.h
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Intel Corporation
+ */
+
+#ifndef _RTE_HASH_XOR_H_
+#define _RTE_HASH_XOR_H_
+
+/**
+ * @file
+ *
+ * RTE XOR Hash
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include <rte_byteorder.h>
+
+/**
+ * Calculate XOR32 hash on user-supplied byte array.
+ *
+ * @param data
+ *=C2=A0 =C2=A0Data to perform hash on.
+ * @param data_len
+ *=C2=A0 =C2=A0How many bytes to use to calculate hash value.
+ * @param init_val
+ *=C2=A0 =C2=A0Value to initialise hash generator.
+ * @return
+ *=C2=A0 =C2=A032bit calculated hash value.
+ */
+static inline uint32_t
+rte_hash_xor32(const void *data, uint32_t data_len, uint32_t init_val)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0uint32_t hash32;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0const uint8_t *data8 =3D data;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* Minimize byte order conversions depending on= data length. */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (data_len >=3D 8) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* For longer array= s, operate in big endian. */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0uint64_t hash64 =3D= rte_cpu_to_be_32(init_val);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0uint32_t i;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0for (i =3D 0; i <= ; data_len / 8; i++) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0hash64 ^=3D *(const uint64_t *)data8;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0data8 +=3D 8;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (data_len & = 0x4) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0hash64 ^=3D *(const uint32_t *)data8;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0data8 +=3D 4;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0hash32 =3D rte_be_t= o_cpu_32(hash64 ^ (hash64 >> 32));
+=C2=A0 =C2=A0 =C2=A0 =C2=A0} else {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* For shorter arra= ys, operate in host endian. */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0hash32 =3D init_val= ;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (data_len & = 0x4) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0hash32 ^=3D rte_be_to_cpu_32(*(const uint32_t *)data8);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0data8 +=3D 4;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* Deal with remaining (< 4) bytes. */
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0uint8_t bit_offset =3D 0;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (data_len & 0x2) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0hash32 ^=3D (uint32= _t)rte_be_to_cpu_16(*(const uint16_t *)data8) << 16;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0data8 +=3D 2;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0bit_offset +=3D 16;=
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (data_len & 0x1)
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0hash32 ^=3D (uint32= _t)(*(const uint8_t *)data8) << (24 - bit_offset);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return hash32;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_HASH_XOR_H_ */
--
2.34.1



--
Regards,
Vladimir
--000000000000e7a9e505fe2e354c--