DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH] Add toeplitz hash algorithm
@ 2015-04-08 19:06 Vladimir Medvedkin
  2015-04-08 22:24 ` Stephen Hemminger
                   ` (2 more replies)
  0 siblings, 3 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-04-08 19:06 UTC (permalink / raw)
  To: dev

Software implementation of the Toeplitz hash function used by RSS.
Can be used either for packet distribution on single queue NIC
or for simulating of RSS computation on specific NIC (for example
after GRE header decapsulating).

Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
---
 lib/librte_hash/Makefile    |   1 +
 lib/librte_hash/rte_thash.h | 179 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 180 insertions(+)
 create mode 100644 lib/librte_hash/rte_thash.h

diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
index 3696cb1..083a9e5 100644
--- a/lib/librte_hash/Makefile
+++ b/lib/librte_hash/Makefile
@@ -50,6 +50,7 @@ SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
 
 # this lib needs eal
 DEPDIRS-$(CONFIG_RTE_LIBRTE_HASH) += lib/librte_eal lib/librte_malloc
diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
new file mode 100644
index 0000000..1acfa3a
--- /dev/null
+++ b/lib/librte_hash/rte_thash.h
@@ -0,0 +1,179 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_THASH_H
+#define _RTE_THASH_H
+
+/**
+ * @file
+ *
+ * toeplitz hash functions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Software implementation of the Toeplitz hash function used by RSS.
+ * Can be used either for packet distribution on single queue NIC
+ * or for simulating of RSS computation on specific NIC (for example
+ * after GRE header decapsulating)
+ */
+
+#include <stdint.h>
+#include <rte_byteorder.h>
+
+enum rte_thash_flag {
+	RTE_THASH_L3 = 0,	//calculate hash tacking into account only l3 header
+	RTE_THASH_L4		//calculate hash tacking into account l4 + l4 headers
+};
+
+/**
+ * Prepare special converted key to use with rte_softrss_be()
+ * @param orig
+ *   pointer to original RSS key
+ * @param targ
+ *   pointer to target RSS key
+ */
+
+static inline void
+rte_convert_rss_key(uint32_t *orig, uint32_t *targ)
+{
+	int i;
+	for (i = 0; i < 10; i++) {
+		targ[i] = rte_be_to_cpu_32(orig[i]);
+	}
+}
+
+/**
+ * Generic implementation. Can be used with original rss_key
+ * All ip's and ports have to be CPU byte order.
+ * @param sip
+ *   Source ip address.
+ * @param dip
+ *   Destination ip address.
+ * @param sp
+ *   Source TCP|UDP port.
+ * @param dp
+ *   Destination TCP|UDP port.
+ * @param flag
+ *   RTE_THASH_L3:	calculate hash tacking into account only sip and dip
+ *   RTE_THASH_L4:	calculate hash tacking into account sip, dip, sp and dp
+ * @param *rss_key
+ *   Pointer to 40-byte RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+
+static inline uint32_t
+rte_softrss(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp, enum rte_thash_flag flag, uint32_t *rss_key)
+{
+	uint32_t ret = 0;
+	int i;
+	for (i = 0; i < 32; i++) {
+		if (sip & (1 << (31 - i))) {
+			ret ^= (rte_cpu_to_be_32(*rss_key) << i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
+		}
+	}
+	rss_key++;
+	for (i = 0; i < 32; i++) {
+		if (dip & (1 << (31 - i))) {
+			ret ^= (rte_cpu_to_be_32(*rss_key) << i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
+		}
+	}
+        if (flag == RTE_THASH_L4) {
+		rss_key++;
+		for (i = 0; i < 32; i++) {
+			if (((sp<<16)|dp) & (1 << (31 - i))) {
+				ret ^= (rte_cpu_to_be_32(*rss_key) << i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+/**
+ * Optimized implementation.
+ * If you want the calculated hash value matches NIC RSS value
+ * you have to use special converted key.
+ * All ip's and ports have to be CPU byte order.
+ * @param sip
+ *   Source ip address.
+ * @param dip
+ *   Destination ip address.
+ * @param sp
+ *   Source TCP|UDP port.
+ * @param dp
+ *   Destination TCP|UDP port.
+ * @param flag
+ *   RTE_THASH_L3:	calculate hash tacking into account only sip and dip
+ *   RTE_THASH_L4:	calculate hash tacking into account sip, dip, sp and dp
+ * @param *rss_key
+ *   Pointer to 40-byte RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+
+static inline uint32_t
+rte_softrss_be(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp, enum rte_thash_flag flag, uint32_t *rss_key)
+{
+	uint32_t ret = 0;
+	int i;
+	for (i = 0; i < 32; i++) {
+		if (sip & (1 << (31 - i))) {
+			ret ^= (*rss_key << i)|(uint32_t)((uint64_t)*(rss_key + 1) >> (32 - i));
+		}
+	}
+	rss_key++;
+	for (i = 0; i < 32; i++) {
+		if (dip & (1 << (31 - i))) {
+			ret ^= (*rss_key << i)|(uint32_t)((uint64_t)*(rss_key + 1) >> (32 - i));
+		}
+	}
+        if (flag == RTE_THASH_L4) {
+		rss_key++;
+		for (i = 0; i < 32; i++) {
+			if (((sp<<16)|dp) & (1 << (31 - i))) {
+				ret ^= (*rss_key << i)|(uint32_t)((uint64_t)*(rss_key + 1) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_THASH_H */
-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH] Add toeplitz hash algorithm
  2015-04-08 19:06 [dpdk-dev] [PATCH] Add toeplitz hash algorithm Vladimir Medvedkin
@ 2015-04-08 22:24 ` Stephen Hemminger
  2015-04-09 12:50   ` Vladimir Medvedkin
  2015-04-09  6:37 ` Gleb Natapov
  2015-05-05 13:20 ` [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS Vladimir Medvedkin
  2 siblings, 1 reply; 37+ messages in thread
From: Stephen Hemminger @ 2015-04-08 22:24 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

On Wed,  8 Apr 2015 15:06:13 -0400
Vladimir Medvedkin <medvedkinv@gmail.com> wrote:

> Software implementation of the Toeplitz hash function used by RSS.
> Can be used either for packet distribution on single queue NIC
> or for simulating of RSS computation on specific NIC (for example
> after GRE header decapsulating).
> 
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>

> +enum rte_thash_flag {
> +	RTE_THASH_L3 = 0,	//calculate hash tacking into account only l3 header
> +	RTE_THASH_L4		//calculate hash tacking into account l4 + l4 headers
> +};
> +
> +/**
> + * Prepare special converted key to use with rte_softrss_be()
> + * @param orig
> + *   pointer to original RSS key
> + * @param targ
> + *   pointer to target RSS key
> + */
> +
> +static inline void
> +rte_convert_rss_key(uint32_t *orig, uint32_t *targ)
orig should be const

> +{
> +	int i;
> +	for (i = 0; i < 10; i++) {
> +		targ[i] = rte_be_to_cpu_32(orig[i]);
> +	}
> +}

> +static inline uint32_t
> +rte_softrss(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp, enum rte_thash_flag flag, uint32_t *rss_key)

rss_key should be const

> +{
> +	uint32_t ret = 0;
> +	int i;
> +	for (i = 0; i < 32; i++) {
blank line after declaration please

> +		if (sip & (1 << (31 - i))) {
> +			ret ^= (rte_cpu_to_be_32(*rss_key) << i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));

Long expression > 80 characters.
Repeated multiple times (should be inline)
Extra parens ()
Extension to 64 bits is only to avoid compiler warning?


> +		}
> +	}
> +	rss_key++;
> +	for (i = 0; i < 32; i++) {
> +		if (dip & (1 << (31 - i))) {
> +			ret ^= (rte_cpu_to_be_32(*rss_key) << i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> +		}
> +	}
> +        if (flag == RTE_THASH_L4) {
> +		rss_key++;
> +		for (i = 0; i < 32; i++) {
> +			if (((sp<<16)|dp) & (1 << (31 - i))) {
> +				ret ^= (rte_cpu_to_be_32(*rss_key) << i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> +			}
> +		}
> +	}
> +	return ret;
> +}
> +
> +/**
> + * Optimized implementation.
> + * If you want the calculated hash value matches NIC RSS value
> + * you have to use special converted key.
> + * All ip's and ports have to be CPU byte order.
> + * @param sip
> + *   Source ip address.
> + * @param dip
> + *   Destination ip address.
> + * @param sp
> + *   Source TCP|UDP port.
> + * @param dp
> + *   Destination TCP|UDP port.
> + * @param flag
> + *   RTE_THASH_L3:	calculate hash tacking into account only sip and dip
> + *   RTE_THASH_L4:	calculate hash tacking into account sip, dip, sp and dp
> + * @param *rss_key
> + *   Pointer to 40-byte RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +
> +static inline uint32_t
> +rte_softrss_be(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp, enum rte_thash_flag flag, uint32_t *rss_key)
> +{

Same problems as previous code.
Also lots of copy paste (see Do Not Repeat Yourself principle).

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH] Add toeplitz hash algorithm
  2015-04-08 19:06 [dpdk-dev] [PATCH] Add toeplitz hash algorithm Vladimir Medvedkin
  2015-04-08 22:24 ` Stephen Hemminger
@ 2015-04-09  6:37 ` Gleb Natapov
  2015-04-09 12:57   ` Vladimir Medvedkin
  2015-05-05 13:20 ` [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS Vladimir Medvedkin
  2 siblings, 1 reply; 37+ messages in thread
From: Gleb Natapov @ 2015-04-09  6:37 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

On Wed, Apr 08, 2015 at 03:06:13PM -0400, Vladimir Medvedkin wrote:
> Software implementation of the Toeplitz hash function used by RSS.
> Can be used either for packet distribution on single queue NIC
> or for simulating of RSS computation on specific NIC (for example
> after GRE header decapsulating).
> 
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> ---
>  lib/librte_hash/Makefile    |   1 +
>  lib/librte_hash/rte_thash.h | 179 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 180 insertions(+)
>  create mode 100644 lib/librte_hash/rte_thash.h
> 
> diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
> index 3696cb1..083a9e5 100644
> --- a/lib/librte_hash/Makefile
> +++ b/lib/librte_hash/Makefile
> @@ -50,6 +50,7 @@ SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
> +SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
>  
>  # this lib needs eal
>  DEPDIRS-$(CONFIG_RTE_LIBRTE_HASH) += lib/librte_eal lib/librte_malloc
> diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
> new file mode 100644
> index 0000000..1acfa3a
> --- /dev/null
> +++ b/lib/librte_hash/rte_thash.h
> @@ -0,0 +1,179 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef _RTE_THASH_H
> +#define _RTE_THASH_H
> +
> +/**
> + * @file
> + *
> + * toeplitz hash functions.
> + */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Software implementation of the Toeplitz hash function used by RSS.
> + * Can be used either for packet distribution on single queue NIC
> + * or for simulating of RSS computation on specific NIC (for example
> + * after GRE header decapsulating)
> + */
> +
> +#include <stdint.h>
> +#include <rte_byteorder.h>
> +
> +enum rte_thash_flag {
> +	RTE_THASH_L3 = 0,	//calculate hash tacking into account only l3 header
> +	RTE_THASH_L4		//calculate hash tacking into account l4 + l4 headers
> +};
> +
> +/**
> + * Prepare special converted key to use with rte_softrss_be()
> + * @param orig
> + *   pointer to original RSS key
> + * @param targ
> + *   pointer to target RSS key
> + */
> +
> +static inline void
> +rte_convert_rss_key(uint32_t *orig, uint32_t *targ)
> +{
> +	int i;
> +	for (i = 0; i < 10; i++) {
> +		targ[i] = rte_be_to_cpu_32(orig[i]);
> +	}
> +}
> +
> +/**
> + * Generic implementation. Can be used with original rss_key
> + * All ip's and ports have to be CPU byte order.
> + * @param sip
> + *   Source ip address.
> + * @param dip
> + *   Destination ip address.
ipv4, what about ipv6? Why not define rss function that works on byte
buffer and let caller build it according to whatever fields it want to
hash?

> + * @param sp
> + *   Source TCP|UDP port.
> + * @param dp
> + *   Destination TCP|UDP port.
> + * @param flag
> + *   RTE_THASH_L3:	calculate hash tacking into account only sip and dip
> + *   RTE_THASH_L4:	calculate hash tacking into account sip, dip, sp and dp
> + * @param *rss_key
> + *   Pointer to 40-byte RSS hash key.
i40e has 52 byte RSS hash key.

> + * @return
> + *   Calculated hash value.
> + */
> +
> +static inline uint32_t
> +rte_softrss(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp, enum rte_thash_flag flag, uint32_t *rss_key)
> +{
> +	uint32_t ret = 0;
> +	int i;
> +	for (i = 0; i < 32; i++) {
> +		if (sip & (1 << (31 - i))) {
> +			ret ^= (rte_cpu_to_be_32(*rss_key) << i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> +		}
> +	}
> +	rss_key++;
> +	for (i = 0; i < 32; i++) {
> +		if (dip & (1 << (31 - i))) {
> +			ret ^= (rte_cpu_to_be_32(*rss_key) << i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> +		}
> +	}
> +        if (flag == RTE_THASH_L4) {
> +		rss_key++;
> +		for (i = 0; i < 32; i++) {
> +			if (((sp<<16)|dp) & (1 << (31 - i))) {
> +				ret ^= (rte_cpu_to_be_32(*rss_key) << i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> +			}
> +		}
> +	}
> +	return ret;
> +}
> +
> +/**
> + * Optimized implementation.
> + * If you want the calculated hash value matches NIC RSS value
> + * you have to use special converted key.
> + * All ip's and ports have to be CPU byte order.
> + * @param sip
> + *   Source ip address.
> + * @param dip
> + *   Destination ip address.
> + * @param sp
> + *   Source TCP|UDP port.
> + * @param dp
> + *   Destination TCP|UDP port.
> + * @param flag
> + *   RTE_THASH_L3:	calculate hash tacking into account only sip and dip
> + *   RTE_THASH_L4:	calculate hash tacking into account sip, dip, sp and dp
> + * @param *rss_key
> + *   Pointer to 40-byte RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +
> +static inline uint32_t
> +rte_softrss_be(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp, enum rte_thash_flag flag, uint32_t *rss_key)
> +{
> +	uint32_t ret = 0;
> +	int i;
> +	for (i = 0; i < 32; i++) {
> +		if (sip & (1 << (31 - i))) {
> +			ret ^= (*rss_key << i)|(uint32_t)((uint64_t)*(rss_key + 1) >> (32 - i));
> +		}
> +	}
> +	rss_key++;
> +	for (i = 0; i < 32; i++) {
> +		if (dip & (1 << (31 - i))) {
> +			ret ^= (*rss_key << i)|(uint32_t)((uint64_t)*(rss_key + 1) >> (32 - i));
> +		}
> +	}
> +        if (flag == RTE_THASH_L4) {
> +		rss_key++;
> +		for (i = 0; i < 32; i++) {
> +			if (((sp<<16)|dp) & (1 << (31 - i))) {
> +				ret ^= (*rss_key << i)|(uint32_t)((uint64_t)*(rss_key + 1) >> (32 - i));
> +			}
> +		}
> +	}
> +	return ret;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_THASH_H */
> -- 
> 1.8.3.2
> 

--
			Gleb.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH] Add toeplitz hash algorithm
  2015-04-08 22:24 ` Stephen Hemminger
@ 2015-04-09 12:50   ` Vladimir Medvedkin
  0 siblings, 0 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-04-09 12:50 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

Hi Stephen,



2015-04-09 1:24 GMT+03:00 Stephen Hemminger <stephen@networkplumber.org>:

> On Wed,  8 Apr 2015 15:06:13 -0400
> Vladimir Medvedkin <medvedkinv@gmail.com> wrote:
>
> > Software implementation of the Toeplitz hash function used by RSS.
> > Can be used either for packet distribution on single queue NIC
> > or for simulating of RSS computation on specific NIC (for example
> > after GRE header decapsulating).
> >
> > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
>
> > +enum rte_thash_flag {
> > +     RTE_THASH_L3 = 0,       //calculate hash tacking into account only
> l3 header
> > +     RTE_THASH_L4            //calculate hash tacking into account l4 +
> l4 headers
> > +};
> > +
> > +/**
> > + * Prepare special converted key to use with rte_softrss_be()
> > + * @param orig
> > + *   pointer to original RSS key
> > + * @param targ
> > + *   pointer to target RSS key
> > + */
> > +
> > +static inline void
> > +rte_convert_rss_key(uint32_t *orig, uint32_t *targ)
> orig should be const
>
> > +{
> > +     int i;
> > +     for (i = 0; i < 10; i++) {
> > +             targ[i] = rte_be_to_cpu_32(orig[i]);
> > +     }
> > +}
>
> > +static inline uint32_t
> > +rte_softrss(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp, enum
> rte_thash_flag flag, uint32_t *rss_key)
>
> rss_key should be const
>
> > +{
> > +     uint32_t ret = 0;
> > +     int i;
> > +     for (i = 0; i < 32; i++) {
> blank line after declaration please
>
> > +             if (sip & (1 << (31 - i))) {
> > +                     ret ^= (rte_cpu_to_be_32(*rss_key) <<
> i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
>
> Long expression > 80 characters.
> Repeated multiple times (should be inline)
> Extra parens ()
>
Thanks for remarks, I'll fix it.

> Extension to 64 bits is only to avoid compiler warning?
>
No, in case when i = 0 we shift uint32_t left by 32 bits, which leads to
undefined behaviour. In fact, shift counter just masked to 5 bits, so count
range is limited to 0 to 31.

>
>
> > +             }
> > +     }
> > +     rss_key++;
> > +     for (i = 0; i < 32; i++) {
> > +             if (dip & (1 << (31 - i))) {
> > +                     ret ^= (rte_cpu_to_be_32(*rss_key) <<
> i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> > +             }
> > +     }
> > +        if (flag == RTE_THASH_L4) {
> > +             rss_key++;
> > +             for (i = 0; i < 32; i++) {
> > +                     if (((sp<<16)|dp) & (1 << (31 - i))) {
> > +                             ret ^= (rte_cpu_to_be_32(*rss_key) <<
> i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> > +                     }
> > +             }
> > +     }
> > +     return ret;
> > +}
> > +
> > +/**
> > + * Optimized implementation.
> > + * If you want the calculated hash value matches NIC RSS value
> > + * you have to use special converted key.
> > + * All ip's and ports have to be CPU byte order.
> > + * @param sip
> > + *   Source ip address.
> > + * @param dip
> > + *   Destination ip address.
> > + * @param sp
> > + *   Source TCP|UDP port.
> > + * @param dp
> > + *   Destination TCP|UDP port.
> > + * @param flag
> > + *   RTE_THASH_L3:   calculate hash tacking into account only sip and
> dip
> > + *   RTE_THASH_L4:   calculate hash tacking into account sip, dip, sp
> and dp
> > + * @param *rss_key
> > + *   Pointer to 40-byte RSS hash key.
> > + * @return
> > + *   Calculated hash value.
> > + */
> > +
> > +static inline uint32_t
> > +rte_softrss_be(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp,
> enum rte_thash_flag flag, uint32_t *rss_key)
> > +{
>
> Same problems as previous code.
> Also lots of copy paste (see Do Not Repeat Yourself principle).
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH] Add toeplitz hash algorithm
  2015-04-09  6:37 ` Gleb Natapov
@ 2015-04-09 12:57   ` Vladimir Medvedkin
  0 siblings, 0 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-04-09 12:57 UTC (permalink / raw)
  To: Gleb Natapov; +Cc: dev

Hi Gleb,


2015-04-09 9:37 GMT+03:00 Gleb Natapov <gleb@cloudius-systems.com>:

> On Wed, Apr 08, 2015 at 03:06:13PM -0400, Vladimir Medvedkin wrote:
> > Software implementation of the Toeplitz hash function used by RSS.
> > Can be used either for packet distribution on single queue NIC
> > or for simulating of RSS computation on specific NIC (for example
> > after GRE header decapsulating).
> >
> > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> > ---
> >  lib/librte_hash/Makefile    |   1 +
> >  lib/librte_hash/rte_thash.h | 179
> ++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 180 insertions(+)
> >  create mode 100644 lib/librte_hash/rte_thash.h
> >
> > diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
> > index 3696cb1..083a9e5 100644
> > --- a/lib/librte_hash/Makefile
> > +++ b/lib/librte_hash/Makefile
> > @@ -50,6 +50,7 @@ SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
> >  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
> >  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
> >  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
> > +SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
> >
> >  # this lib needs eal
> >  DEPDIRS-$(CONFIG_RTE_LIBRTE_HASH) += lib/librte_eal lib/librte_malloc
> > diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
> > new file mode 100644
> > index 0000000..1acfa3a
> > --- /dev/null
> > +++ b/lib/librte_hash/rte_thash.h
> > @@ -0,0 +1,179 @@
> > +/*-
> > + *   BSD LICENSE
> > + *
> > + *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
> > + *   All rights reserved.
> > + *
> > + *   Redistribution and use in source and binary forms, with or without
> > + *   modification, are permitted provided that the following conditions
> > + *   are met:
> > + *
> > + *     * Redistributions of source code must retain the above copyright
> > + *       notice, this list of conditions and the following disclaimer.
> > + *     * Redistributions in binary form must reproduce the above
> copyright
> > + *       notice, this list of conditions and the following disclaimer in
> > + *       the documentation and/or other materials provided with the
> > + *       distribution.
> > + *     * Neither the name of Intel Corporation nor the names of its
> > + *       contributors may be used to endorse or promote products derived
> > + *       from this software without specific prior written permission.
> > + *
> > + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> > + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> > + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> FOR
> > + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> > + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> > + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> > + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
> USE,
> > + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> ANY
> > + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> USE
> > + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> > + */
> > +
> > +#ifndef _RTE_THASH_H
> > +#define _RTE_THASH_H
> > +
> > +/**
> > + * @file
> > + *
> > + * toeplitz hash functions.
> > + */
> > +
> > +#ifdef __cplusplus
> > +extern "C" {
> > +#endif
> > +
> > +/**
> > + * Software implementation of the Toeplitz hash function used by RSS.
> > + * Can be used either for packet distribution on single queue NIC
> > + * or for simulating of RSS computation on specific NIC (for example
> > + * after GRE header decapsulating)
> > + */
> > +
> > +#include <stdint.h>
> > +#include <rte_byteorder.h>
> > +
> > +enum rte_thash_flag {
> > +     RTE_THASH_L3 = 0,       //calculate hash tacking into account only
> l3 header
> > +     RTE_THASH_L4            //calculate hash tacking into account l4 +
> l4 headers
> > +};
> > +
> > +/**
> > + * Prepare special converted key to use with rte_softrss_be()
> > + * @param orig
> > + *   pointer to original RSS key
> > + * @param targ
> > + *   pointer to target RSS key
> > + */
> > +
> > +static inline void
> > +rte_convert_rss_key(uint32_t *orig, uint32_t *targ)
> > +{
> > +     int i;
> > +     for (i = 0; i < 10; i++) {
> > +             targ[i] = rte_be_to_cpu_32(orig[i]);
> > +     }
> > +}
> > +
> > +/**
> > + * Generic implementation. Can be used with original rss_key
> > + * All ip's and ports have to be CPU byte order.
> > + * @param sip
> > + *   Source ip address.
> > + * @param dip
> > + *   Destination ip address.
> ipv4, what about ipv6? Why not define rss function that works on byte
> buffer and let caller build it according to whatever fields it want to
> hash?
>
Good idea, I will think about it.


>
> > + * @param sp
> > + *   Source TCP|UDP port.
> > + * @param dp
> > + *   Destination TCP|UDP port.
> > + * @param flag
> > + *   RTE_THASH_L3:   calculate hash tacking into account only sip and
> dip
> > + *   RTE_THASH_L4:   calculate hash tacking into account sip, dip, sp
> and dp
> > + * @param *rss_key
> > + *   Pointer to 40-byte RSS hash key.
> i40e has 52 byte RSS hash key.
>

> > + * @return
> > + *   Calculated hash value.
> > + */
> > +
> > +static inline uint32_t
> > +rte_softrss(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp, enum
> rte_thash_flag flag, uint32_t *rss_key)
> > +{
> > +     uint32_t ret = 0;
> > +     int i;
> > +     for (i = 0; i < 32; i++) {
> > +             if (sip & (1 << (31 - i))) {
> > +                     ret ^= (rte_cpu_to_be_32(*rss_key) <<
> i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> > +             }
> > +     }
> > +     rss_key++;
> > +     for (i = 0; i < 32; i++) {
> > +             if (dip & (1 << (31 - i))) {
> > +                     ret ^= (rte_cpu_to_be_32(*rss_key) <<
> i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> > +             }
> > +     }
> > +        if (flag == RTE_THASH_L4) {
> > +             rss_key++;
> > +             for (i = 0; i < 32; i++) {
> > +                     if (((sp<<16)|dp) & (1 << (31 - i))) {
> > +                             ret ^= (rte_cpu_to_be_32(*rss_key) <<
> i)|(uint32_t)((uint64_t)(rte_cpu_to_be_32(*(rss_key + 1))) >> (32 - i));
> > +                     }
> > +             }
> > +     }
> > +     return ret;
> > +}
> > +
> > +/**
> > + * Optimized implementation.
> > + * If you want the calculated hash value matches NIC RSS value
> > + * you have to use special converted key.
> > + * All ip's and ports have to be CPU byte order.
> > + * @param sip
> > + *   Source ip address.
> > + * @param dip
> > + *   Destination ip address.
> > + * @param sp
> > + *   Source TCP|UDP port.
> > + * @param dp
> > + *   Destination TCP|UDP port.
> > + * @param flag
> > + *   RTE_THASH_L3:   calculate hash tacking into account only sip and
> dip
> > + *   RTE_THASH_L4:   calculate hash tacking into account sip, dip, sp
> and dp
> > + * @param *rss_key
> > + *   Pointer to 40-byte RSS hash key.
> > + * @return
> > + *   Calculated hash value.
> > + */
> > +
> > +static inline uint32_t
> > +rte_softrss_be(uint32_t sip, uint32_t dip, uint16_t sp, uint16_t dp,
> enum rte_thash_flag flag, uint32_t *rss_key)
> > +{
> > +     uint32_t ret = 0;
> > +     int i;
> > +     for (i = 0; i < 32; i++) {
> > +             if (sip & (1 << (31 - i))) {
> > +                     ret ^= (*rss_key <<
> i)|(uint32_t)((uint64_t)*(rss_key + 1) >> (32 - i));
> > +             }
> > +     }
> > +     rss_key++;
> > +     for (i = 0; i < 32; i++) {
> > +             if (dip & (1 << (31 - i))) {
> > +                     ret ^= (*rss_key <<
> i)|(uint32_t)((uint64_t)*(rss_key + 1) >> (32 - i));
> > +             }
> > +     }
> > +        if (flag == RTE_THASH_L4) {
> > +             rss_key++;
> > +             for (i = 0; i < 32; i++) {
> > +                     if (((sp<<16)|dp) & (1 << (31 - i))) {
> > +                             ret ^= (*rss_key <<
> i)|(uint32_t)((uint64_t)*(rss_key + 1) >> (32 - i));
> > +                     }
> > +             }
> > +     }
> > +     return ret;
> > +}
> > +
> > +#ifdef __cplusplus
> > +}
> > +#endif
> > +
> > +#endif /* _RTE_THASH_H */
> > --
> > 1.8.3.2
> >
>
> --
>                         Gleb.
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-04-08 19:06 [dpdk-dev] [PATCH] Add toeplitz hash algorithm Vladimir Medvedkin
  2015-04-08 22:24 ` Stephen Hemminger
  2015-04-09  6:37 ` Gleb Natapov
@ 2015-05-05 13:20 ` Vladimir Medvedkin
  2015-05-05 16:03   ` Chilikin, Andrey
  2015-05-08 14:58   ` Vladimir Medvedkin
  2 siblings, 2 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-05-05 13:20 UTC (permalink / raw)
  To: dev

Software implementation of the Toeplitz hash function used by RSS.
Can be used either for packet distribution on single queue NIC
or for simulating of RSS computation on specific NIC (for example
after GRE header decapsulating).

v2 changes
- Add ipv6 support
- Various style fixes

Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
---
 lib/librte_hash/Makefile    |   1 +
 lib/librte_hash/rte_thash.h | 209 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 210 insertions(+)
 create mode 100644 lib/librte_hash/rte_thash.h

diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
index 3696cb1..981230b 100644
--- a/lib/librte_hash/Makefile
+++ b/lib/librte_hash/Makefile
@@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
 
 # this lib needs eal
diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
new file mode 100644
index 0000000..42c7bf6
--- /dev/null
+++ b/lib/librte_hash/rte_thash.h
@@ -0,0 +1,209 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_THASH_H
+#define _RTE_THASH_H
+
+/**
+ * @file
+ *
+ * toeplitz hash functions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Software implementation of the Toeplitz hash function used by RSS.
+ * Can be used either for packet distribution on single queue NIC
+ * or for simulating of RSS computation on specific NIC (for example
+ * after GRE header decapsulating)
+ */
+
+#include <stdint.h>
+#include <rte_byteorder.h>
+#include <rte_vect.h>
+
+#ifdef __SSE3__
+static const __m128i bswap_mask = {0x0405060700010203, 0x0C0D0E0F08090A0B};
+#endif
+
+enum rte_thash_len {
+	RTE_THASH_V4_L3	= 2,	/*calculate hash of ipv4 header only*/
+	RTE_THASH_V4_L4	= 3,	/*calculate hash of ipv4 + transport headers*/
+	RTE_THASH_V6_L3	= 8,	/*calculate hash of ipv6 header only */
+	RTE_THASH_V6_L4	= 9,	/*calculate hash of ipv6 + transport headers */
+};
+
+/**
+ * IPv4 tuple
+ * addreses and ports have to be CPU byte order
+ */
+struct rte_ipv4_tuple {
+	uint32_t	src_addr;
+	uint32_t	dst_addr;
+	uint16_t	dport;
+	uint16_t	sport;
+};
+
+/**
+ * IPv6 tuple
+ * Addresses have to be filled by rte_thash_load_v6_addr()
+ * ports have to be CPU byte order
+ */
+struct rte_ipv6_tuple {
+	uint8_t		src_addr[16];
+	uint8_t		dst_addr[16];
+	uint16_t	dport;
+	uint16_t	sport;
+};
+
+union rte_thash_tuple {
+	struct rte_ipv4_tuple	v4;
+	struct rte_ipv6_tuple	v6;
+} __attribute__((aligned(16)));
+
+/**
+ * Prepare special converted key to use with rte_softrss_be()
+ * @param orig
+ *   pointer to original RSS key
+ * @param targ
+ *   pointer to target RSS key
+ * @param len
+ *   RSS key length
+ */
+static inline void
+rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
+{
+	int i;
+
+	for (i = 0; i < (len >> 2); i++) {
+		targ[i] = rte_be_to_cpu_32(orig[i]);
+	}
+}
+
+/**
+ * Prepare and load IPv6 address
+ * @param orig
+ *   Pointer to ipv6 address inside ipv6_hdr
+ * @param targ
+ *   Pointer to ipv6 address inside rte_ipv6_tuple
+ */
+static inline void
+rte_thash_load_v6_addr(const uint8_t *orig, uint8_t *targ)
+{
+#ifdef __SSE3__
+	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig);
+	*(__m128i *)targ = _mm_shuffle_epi8(ipv6, bswap_mask);
+#else
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		*((uint32_t *)targ + i) =
+			rte_be_to_cpu_32(*((const uint32_t *)orig + i));
+	}
+#endif
+}
+
+/**
+ * Generic implementation. Can be used with original rss_key
+ * @param input_tuple
+ *   Pointer to rte_thash_tuple union
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ *   RTE_THASH_V4_L3:	calculate hash of IPv4 src address and IPv4 dst address
+ *   RTE_THASH_V4_L4	calculate hash of IPv4 adresses and TCP|UDP ports
+ *   RTE_THASH_V6_L3:	calculate hash of IPv6 src address and IPv4 dst address
+ *   RTE_THASH_V6_L4	calculate hash of IPv6 adresses and TCP|UDP ports
+ * @param rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss(union rte_thash_tuple *input_tuple, enum rte_thash_len input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (((uint32_t *)input_tuple)[j] & (1 << (31 - i))) {
+				ret ^= rte_cpu_to_be_32(((const uint32_t *)rss_key)[j]) << i |
+					(uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t *)rss_key)[j + 1])) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+/**
+ * Optimized implementation.
+ * If you want the calculated hash value matches NIC RSS value
+ * you have to use special converted key.
+ * @param input_tuple
+ *   Pointer to rte_thash_tuple union
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ *   RTE_THASH_V4_L3:	calculate hash of IPv4 src address and IPv4 dst address
+ *   RTE_THASH_V4_L4	calculate hash of IPv4 adresses and TCP|UDP ports
+ *   RTE_THASH_V6_L3:	calculate hash of IPv6 src address and IPv4 dst address
+ *   RTE_THASH_V6_L4	calculate hash of IPv6 adresses and TCP|UDP ports
+ * @param *rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss_be(union rte_thash_tuple *input_tuple, enum rte_thash_len input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (((uint32_t *)input_tuple)[j] & (1 << (31 - i))) {
+				ret ^= ((const uint32_t *)rss_key)[j] << i |
+					(uint32_t)((uint64_t)(((const uint32_t *)rss_key)[j + 1]) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_THASH_H */
-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-05-05 13:20 ` [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS Vladimir Medvedkin
@ 2015-05-05 16:03   ` Chilikin, Andrey
  2015-05-07 10:28     ` Vladimir Medvedkin
  2015-05-08 14:58   ` Vladimir Medvedkin
  1 sibling, 1 reply; 37+ messages in thread
From: Chilikin, Andrey @ 2015-05-05 16:03 UTC (permalink / raw)
  To: Vladimir Medvedkin, dev

Hi Vladimir,

Why limit Toeplitz hash calculation to predefined tuples and length? Should it be more general, something like
rte_softrss_be(void *input, uint32_t input_len, const uint8_t *rss_key) to enable hash calculation for an input of any size? It would be useful for distributing packets using some non-standard tuples, like hashing on QinQ or adding IP protocol to hash calculation to separate UDP and TCP flows or even some other fields from a packet, for example, tunnel ID from VXLAN headers. By the way, i40e already supports RSS for SCTP in addition to TCP and UDP and includes Verification Tag as well as SCTP source and destination ports for RSS hash.

Regards,
Andrey

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Vladimir
> Medvedkin
> Sent: Tuesday, May 5, 2015 2:20 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
> 
> Software implementation of the Toeplitz hash function used by RSS.
> Can be used either for packet distribution on single queue NIC or for
> simulating of RSS computation on specific NIC (for example after GRE header
> decapsulating).
> 
> v2 changes
> - Add ipv6 support
> - Various style fixes
> 
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> ---
>  lib/librte_hash/Makefile    |   1 +
>  lib/librte_hash/rte_thash.h | 209
> ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 210 insertions(+)
>  create mode 100644 lib/librte_hash/rte_thash.h
> 
> diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile index
> 3696cb1..981230b 100644
> --- a/lib/librte_hash/Makefile
> +++ b/lib/librte_hash/Makefile
> @@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
> SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h  SYMLINK-
> $(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h  SYMLINK-
> $(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
> +SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
> 
>  # this lib needs eal
> diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h new file
> mode 100644 index 0000000..42c7bf6
> --- /dev/null
> +++ b/lib/librte_hash/rte_thash.h
> @@ -0,0 +1,209 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> + */
> +
> +#ifndef _RTE_THASH_H
> +#define _RTE_THASH_H
> +
> +/**
> + * @file
> + *
> + * toeplitz hash functions.
> + */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Software implementation of the Toeplitz hash function used by RSS.
> + * Can be used either for packet distribution on single queue NIC
> + * or for simulating of RSS computation on specific NIC (for example
> + * after GRE header decapsulating)
> + */
> +
> +#include <stdint.h>
> +#include <rte_byteorder.h>
> +#include <rte_vect.h>
> +
> +#ifdef __SSE3__
> +static const __m128i bswap_mask = {0x0405060700010203,
> +0x0C0D0E0F08090A0B}; #endif
> +
> +enum rte_thash_len {
> +	RTE_THASH_V4_L3	= 2,	/*calculate hash of ipv4 header
> only*/
> +	RTE_THASH_V4_L4	= 3,	/*calculate hash of ipv4 + transport
> headers*/
> +	RTE_THASH_V6_L3	= 8,	/*calculate hash of ipv6 header only
> */
> +	RTE_THASH_V6_L4	= 9,	/*calculate hash of ipv6 + transport
> headers */
> +};
> +
> +/**
> + * IPv4 tuple
> + * addreses and ports have to be CPU byte order  */ struct
> +rte_ipv4_tuple {
> +	uint32_t	src_addr;
> +	uint32_t	dst_addr;
> +	uint16_t	dport;
> +	uint16_t	sport;
> +};
> +
> +/**
> + * IPv6 tuple
> + * Addresses have to be filled by rte_thash_load_v6_addr()
> + * ports have to be CPU byte order
> + */
> +struct rte_ipv6_tuple {
> +	uint8_t		src_addr[16];
> +	uint8_t		dst_addr[16];
> +	uint16_t	dport;
> +	uint16_t	sport;
> +};
> +
> +union rte_thash_tuple {
> +	struct rte_ipv4_tuple	v4;
> +	struct rte_ipv6_tuple	v6;
> +} __attribute__((aligned(16)));
> +
> +/**
> + * Prepare special converted key to use with rte_softrss_be()
> + * @param orig
> + *   pointer to original RSS key
> + * @param targ
> + *   pointer to target RSS key
> + * @param len
> + *   RSS key length
> + */
> +static inline void
> +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len) {
> +	int i;
> +
> +	for (i = 0; i < (len >> 2); i++) {
> +		targ[i] = rte_be_to_cpu_32(orig[i]);
> +	}
> +}
> +
> +/**
> + * Prepare and load IPv6 address
> + * @param orig
> + *   Pointer to ipv6 address inside ipv6_hdr
> + * @param targ
> + *   Pointer to ipv6 address inside rte_ipv6_tuple
> + */
> +static inline void
> +rte_thash_load_v6_addr(const uint8_t *orig, uint8_t *targ) { #ifdef
> +__SSE3__
> +	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig);
> +	*(__m128i *)targ = _mm_shuffle_epi8(ipv6, bswap_mask); #else
> +	int i;
> +
> +	for (i = 0; i < 4; i++) {
> +		*((uint32_t *)targ + i) =
> +			rte_be_to_cpu_32(*((const uint32_t *)orig + i));
> +	}
> +#endif
> +}
> +
> +/**
> + * Generic implementation. Can be used with original rss_key
> + * @param input_tuple
> + *   Pointer to rte_thash_tuple union
> + * @param input_len
> + *   Length of input_tuple in 4-bytes chunks
> + *   RTE_THASH_V4_L3:	calculate hash of IPv4 src address and IPv4 dst
> address
> + *   RTE_THASH_V4_L4	calculate hash of IPv4 adresses and TCP|UDP
> ports
> + *   RTE_THASH_V6_L3:	calculate hash of IPv6 src address and IPv4 dst
> address
> + *   RTE_THASH_V6_L4	calculate hash of IPv6 adresses and TCP|UDP
> ports
> + * @param rss_key
> + *   Pointer to RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +static inline uint32_t
> +rte_softrss(union rte_thash_tuple *input_tuple, enum rte_thash_len
> input_len,
> +		const uint8_t *rss_key)
> +{
> +	uint32_t i, j, ret = 0;
> +
> +	for (j = 0; j < input_len; j++) {
> +		for (i = 0; i < 32; i++) {
> +			if (((uint32_t *)input_tuple)[j] & (1 << (31 - i))) {
> +				ret ^= rte_cpu_to_be_32(((const uint32_t
> *)rss_key)[j]) << i |
> +
> 	(uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t
> *)rss_key)[j + 1])) >> (32 - i));
> +			}
> +		}
> +	}
> +	return ret;
> +}
> +
> +/**
> + * Optimized implementation.
> + * If you want the calculated hash value matches NIC RSS value
> + * you have to use special converted key.
> + * @param input_tuple
> + *   Pointer to rte_thash_tuple union
> + * @param input_len
> + *   Length of input_tuple in 4-bytes chunks
> + *   RTE_THASH_V4_L3:	calculate hash of IPv4 src address and IPv4 dst
> address
> + *   RTE_THASH_V4_L4	calculate hash of IPv4 adresses and TCP|UDP
> ports
> + *   RTE_THASH_V6_L3:	calculate hash of IPv6 src address and IPv4 dst
> address
> + *   RTE_THASH_V6_L4	calculate hash of IPv6 adresses and TCP|UDP
> ports
> + * @param *rss_key
> + *   Pointer to RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +static inline uint32_t
> +rte_softrss_be(union rte_thash_tuple *input_tuple, enum rte_thash_len
> input_len,
> +		const uint8_t *rss_key)
> +{
> +	uint32_t i, j, ret = 0;
> +
> +	for (j = 0; j < input_len; j++) {
> +		for (i = 0; i < 32; i++) {
> +			if (((uint32_t *)input_tuple)[j] & (1 << (31 - i))) {
> +				ret ^= ((const uint32_t *)rss_key)[j] << i |
> +					(uint32_t)((uint64_t)(((const uint32_t
> *)rss_key)[j + 1]) >> (32 - i));
> +			}
> +		}
> +	}
> +	return ret;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_THASH_H */
> --
> 1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-05-05 16:03   ` Chilikin, Andrey
@ 2015-05-07 10:28     ` Vladimir Medvedkin
  2015-05-07 11:38       ` Chilikin, Andrey
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-05-07 10:28 UTC (permalink / raw)
  To: Chilikin, Andrey; +Cc: dev

Hi Andrey,

The main goal of this new functions is to calculate the hash which is equal
to the hash of the NIC.
According to XL710 datasheet table 7-5 for sctp input set consists of
IP4-S, IP4-D, SCTP-Verification-Tag. I don't see any NIC that uses QinQ or
single vlan tag, ip proto number, tunnel id, vxlan, etc for calculating RSS
hash. If it appear we can always update union rte_thash_tuple.
I think it should be like:
struct rte_ports {
        uint16_t dport;
        uint16_t sport;
};

union rte_thash_l4 {
        struct          rte_ports ports;
        uint32_t        sctp_tag;
};
struct rte_ipv4_tuple {
        uint32_t        src_addr;
        uint32_t        dst_addr;
        union rte_thash_l4 l4;
};
If it is necessary to distribute packets according to non standart tuples I
think it's more appropriate to use crc32 or jhash because of speed.
rte_softrss_be consumes 400-500 clocks for each 4-byte input at E3
1230v1@3.2GHz. This means for ipv4+tcp it consumes ~1500 clocks.
If you or someone still think you need general toeplitz hash I'll add it.

Regards,
Vladimir


2015-05-05 19:03 GMT+03:00 Chilikin, Andrey <andrey.chilikin@intel.com>:

> Hi Vladimir,
>
> Why limit Toeplitz hash calculation to predefined tuples and length?
> Should it be more general, something like
> rte_softrss_be(void *input, uint32_t input_len, const uint8_t *rss_key) to
> enable hash calculation for an input of any size? It would be useful for
> distributing packets using some non-standard tuples, like hashing on QinQ
> or adding IP protocol to hash calculation to separate UDP and TCP flows or
> even some other fields from a packet, for example, tunnel ID from VXLAN
> headers. By the way, i40e already supports RSS for SCTP in addition to TCP
> and UDP and includes Verification Tag as well as SCTP source and
> destination ports for RSS hash.
>
> Regards,
> Andrey
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Vladimir
> > Medvedkin
> > Sent: Tuesday, May 5, 2015 2:20 PM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
> >
> > Software implementation of the Toeplitz hash function used by RSS.
> > Can be used either for packet distribution on single queue NIC or for
> > simulating of RSS computation on specific NIC (for example after GRE
> header
> > decapsulating).
> >
> > v2 changes
> > - Add ipv6 support
> > - Various style fixes
> >
> > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> > ---
> >  lib/librte_hash/Makefile    |   1 +
> >  lib/librte_hash/rte_thash.h | 209
> > ++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 210 insertions(+)
> >  create mode 100644 lib/librte_hash/rte_thash.h
> >
> > diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile index
> > 3696cb1..981230b 100644
> > --- a/lib/librte_hash/Makefile
> > +++ b/lib/librte_hash/Makefile
> > @@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
> > SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h  SYMLINK-
> > $(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h  SYMLINK-
> > $(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
> > +SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
> >  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
> >
> >  # this lib needs eal
> > diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
> new file
> > mode 100644 index 0000000..42c7bf6
> > --- /dev/null
> > +++ b/lib/librte_hash/rte_thash.h
> > @@ -0,0 +1,209 @@
> > +/*-
> > + *   BSD LICENSE
> > + *
> > + *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
> > + *   All rights reserved.
> > + *
> > + *   Redistribution and use in source and binary forms, with or without
> > + *   modification, are permitted provided that the following conditions
> > + *   are met:
> > + *
> > + *     * Redistributions of source code must retain the above copyright
> > + *       notice, this list of conditions and the following disclaimer.
> > + *     * Redistributions in binary form must reproduce the above
> copyright
> > + *       notice, this list of conditions and the following disclaimer in
> > + *       the documentation and/or other materials provided with the
> > + *       distribution.
> > + *     * Neither the name of Intel Corporation nor the names of its
> > + *       contributors may be used to endorse or promote products derived
> > + *       from this software without specific prior written permission.
> > + *
> > + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > CONTRIBUTORS
> > + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> > NOT
> > + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> > FITNESS FOR
> > + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> > COPYRIGHT
> > + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> > INCIDENTAL,
> > + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > NOT
> > + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> > OF USE,
> > + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> > AND ON ANY
> > + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> > TORT
> > + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> > THE USE
> > + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> > DAMAGE.
> > + */
> > +
> > +#ifndef _RTE_THASH_H
> > +#define _RTE_THASH_H
> > +
> > +/**
> > + * @file
> > + *
> > + * toeplitz hash functions.
> > + */
> > +
> > +#ifdef __cplusplus
> > +extern "C" {
> > +#endif
> > +
> > +/**
> > + * Software implementation of the Toeplitz hash function used by RSS.
> > + * Can be used either for packet distribution on single queue NIC
> > + * or for simulating of RSS computation on specific NIC (for example
> > + * after GRE header decapsulating)
> > + */
> > +
> > +#include <stdint.h>
> > +#include <rte_byteorder.h>
> > +#include <rte_vect.h>
> > +
> > +#ifdef __SSE3__
> > +static const __m128i bswap_mask = {0x0405060700010203,
> > +0x0C0D0E0F08090A0B}; #endif
> > +
> > +enum rte_thash_len {
> > +     RTE_THASH_V4_L3 = 2,    /*calculate hash of ipv4 header
> > only*/
> > +     RTE_THASH_V4_L4 = 3,    /*calculate hash of ipv4 + transport
> > headers*/
> > +     RTE_THASH_V6_L3 = 8,    /*calculate hash of ipv6 header only
> > */
> > +     RTE_THASH_V6_L4 = 9,    /*calculate hash of ipv6 + transport
> > headers */
> > +};
> > +
> > +/**
> > + * IPv4 tuple
> > + * addreses and ports have to be CPU byte order  */ struct
> > +rte_ipv4_tuple {
> > +     uint32_t        src_addr;
> > +     uint32_t        dst_addr;
> > +     uint16_t        dport;
> > +     uint16_t        sport;
> > +};
> > +
> > +/**
> > + * IPv6 tuple
> > + * Addresses have to be filled by rte_thash_load_v6_addr()
> > + * ports have to be CPU byte order
> > + */
> > +struct rte_ipv6_tuple {
> > +     uint8_t         src_addr[16];
> > +     uint8_t         dst_addr[16];
> > +     uint16_t        dport;
> > +     uint16_t        sport;
> > +};
> > +
> > +union rte_thash_tuple {
> > +     struct rte_ipv4_tuple   v4;
> > +     struct rte_ipv6_tuple   v6;
> > +} __attribute__((aligned(16)));
> > +
> > +/**
> > + * Prepare special converted key to use with rte_softrss_be()
> > + * @param orig
> > + *   pointer to original RSS key
> > + * @param targ
> > + *   pointer to target RSS key
> > + * @param len
> > + *   RSS key length
> > + */
> > +static inline void
> > +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len) {
> > +     int i;
> > +
> > +     for (i = 0; i < (len >> 2); i++) {
> > +             targ[i] = rte_be_to_cpu_32(orig[i]);
> > +     }
> > +}
> > +
> > +/**
> > + * Prepare and load IPv6 address
> > + * @param orig
> > + *   Pointer to ipv6 address inside ipv6_hdr
> > + * @param targ
> > + *   Pointer to ipv6 address inside rte_ipv6_tuple
> > + */
> > +static inline void
> > +rte_thash_load_v6_addr(const uint8_t *orig, uint8_t *targ) { #ifdef
> > +__SSE3__
> > +     __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig);
> > +     *(__m128i *)targ = _mm_shuffle_epi8(ipv6, bswap_mask); #else
> > +     int i;
> > +
> > +     for (i = 0; i < 4; i++) {
> > +             *((uint32_t *)targ + i) =
> > +                     rte_be_to_cpu_32(*((const uint32_t *)orig + i));
> > +     }
> > +#endif
> > +}
> > +
> > +/**
> > + * Generic implementation. Can be used with original rss_key
> > + * @param input_tuple
> > + *   Pointer to rte_thash_tuple union
> > + * @param input_len
> > + *   Length of input_tuple in 4-bytes chunks
> > + *   RTE_THASH_V4_L3:        calculate hash of IPv4 src address and
> IPv4 dst
> > address
> > + *   RTE_THASH_V4_L4 calculate hash of IPv4 adresses and TCP|UDP
> > ports
> > + *   RTE_THASH_V6_L3:        calculate hash of IPv6 src address and
> IPv4 dst
> > address
> > + *   RTE_THASH_V6_L4 calculate hash of IPv6 adresses and TCP|UDP
> > ports
> > + * @param rss_key
> > + *   Pointer to RSS hash key.
> > + * @return
> > + *   Calculated hash value.
> > + */
> > +static inline uint32_t
> > +rte_softrss(union rte_thash_tuple *input_tuple, enum rte_thash_len
> > input_len,
> > +             const uint8_t *rss_key)
> > +{
> > +     uint32_t i, j, ret = 0;
> > +
> > +     for (j = 0; j < input_len; j++) {
> > +             for (i = 0; i < 32; i++) {
> > +                     if (((uint32_t *)input_tuple)[j] & (1 << (31 -
> i))) {
> > +                             ret ^= rte_cpu_to_be_32(((const uint32_t
> > *)rss_key)[j]) << i |
> > +
> >       (uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t
> > *)rss_key)[j + 1])) >> (32 - i));
> > +                     }
> > +             }
> > +     }
> > +     return ret;
> > +}
> > +
> > +/**
> > + * Optimized implementation.
> > + * If you want the calculated hash value matches NIC RSS value
> > + * you have to use special converted key.
> > + * @param input_tuple
> > + *   Pointer to rte_thash_tuple union
> > + * @param input_len
> > + *   Length of input_tuple in 4-bytes chunks
> > + *   RTE_THASH_V4_L3:        calculate hash of IPv4 src address and
> IPv4 dst
> > address
> > + *   RTE_THASH_V4_L4 calculate hash of IPv4 adresses and TCP|UDP
> > ports
> > + *   RTE_THASH_V6_L3:        calculate hash of IPv6 src address and
> IPv4 dst
> > address
> > + *   RTE_THASH_V6_L4 calculate hash of IPv6 adresses and TCP|UDP
> > ports
> > + * @param *rss_key
> > + *   Pointer to RSS hash key.
> > + * @return
> > + *   Calculated hash value.
> > + */
> > +static inline uint32_t
> > +rte_softrss_be(union rte_thash_tuple *input_tuple, enum rte_thash_len
> > input_len,
> > +             const uint8_t *rss_key)
> > +{
> > +     uint32_t i, j, ret = 0;
> > +
> > +     for (j = 0; j < input_len; j++) {
> > +             for (i = 0; i < 32; i++) {
> > +                     if (((uint32_t *)input_tuple)[j] & (1 << (31 -
> i))) {
> > +                             ret ^= ((const uint32_t *)rss_key)[j] << i
> |
> > +                                     (uint32_t)((uint64_t)(((const
> uint32_t
> > *)rss_key)[j + 1]) >> (32 - i));
> > +                     }
> > +             }
> > +     }
> > +     return ret;
> > +}
> > +
> > +#ifdef __cplusplus
> > +}
> > +#endif
> > +
> > +#endif /* _RTE_THASH_H */
> > --
> > 1.8.3.2
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-05-07 10:28     ` Vladimir Medvedkin
@ 2015-05-07 11:38       ` Chilikin, Andrey
  2015-05-08 14:58         ` Vladimir Medvedkin
  0 siblings, 1 reply; 37+ messages in thread
From: Chilikin, Andrey @ 2015-05-07 11:38 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

Hi Vladimir,

Yes, at the moment NICs support limited input sets for hash calculation, but why limit SW for the same sets if it can be done in more general way and be easily scalable for HW updates? Using limited input set for RSS is not a feature of Toeplitz hash, but limitation of HW. I believe that general Toeplitz function will be more appropriate – it will cover input sets currently supported by HW and also will be easily scalable for future HW. Also, talking about different NICs – Niantic and Fortville, for example, have hash keys of different length, so rte_softrss() function should take into account hash key’s length as well.
Regards,
Andrey


From: Vladimir Medvedkin [mailto:medvedkinv@gmail.com]
Sent: Thursday, May 7, 2015 11:28 AM
To: Chilikin, Andrey
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS

Hi Andrey,

The main goal of this new functions is to calculate the hash which is equal to the hash of the NIC.
According to XL710 datasheet table 7-5 for sctp input set consists of IP4-S, IP4-D, SCTP-Verification-Tag. I don't see any NIC that uses QinQ or single vlan tag, ip proto number, tunnel id, vxlan, etc for calculating RSS hash. If it appear we can always update union rte_thash_tuple.
I think it should be like:
struct rte_ports {
        uint16_t dport;
        uint16_t sport;
};

union rte_thash_l4 {
        struct          rte_ports ports;
        uint32_t        sctp_tag;
};
struct rte_ipv4_tuple {
        uint32_t        src_addr;
        uint32_t        dst_addr;
        union rte_thash_l4 l4;
};
If it is necessary to distribute packets according to non standart tuples I think it's more appropriate to use crc32 or jhash because of speed. rte_softrss_be consumes 400-500 clocks for each 4-byte input at E3 1230v1@3.2GHz<mailto:1230v1@3.2GHz>. This means for ipv4+tcp it consumes ~1500 clocks.
If you or someone still think you need general toeplitz hash I'll add it.
Regards,
Vladimir


2015-05-05 19:03 GMT+03:00 Chilikin, Andrey <andrey.chilikin@intel.com<mailto:andrey.chilikin@intel.com>>:
Hi Vladimir,

Why limit Toeplitz hash calculation to predefined tuples and length? Should it be more general, something like
rte_softrss_be(void *input, uint32_t input_len, const uint8_t *rss_key) to enable hash calculation for an input of any size? It would be useful for distributing packets using some non-standard tuples, like hashing on QinQ or adding IP protocol to hash calculation to separate UDP and TCP flows or even some other fields from a packet, for example, tunnel ID from VXLAN headers. By the way, i40e already supports RSS for SCTP in addition to TCP and UDP and includes Verification Tag as well as SCTP source and destination ports for RSS hash.

Regards,
Andrey

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org<mailto:dev-bounces@dpdk.org>] On Behalf Of Vladimir
> Medvedkin
> Sent: Tuesday, May 5, 2015 2:20 PM
> To: dev@dpdk.org<mailto:dev@dpdk.org>
> Subject: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
>
> Software implementation of the Toeplitz hash function used by RSS.
> Can be used either for packet distribution on single queue NIC or for
> simulating of RSS computation on specific NIC (for example after GRE header
> decapsulating).
>
> v2 changes
> - Add ipv6 support
> - Various style fixes
>
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com<mailto:medvedkinv@gmail.com>>
> ---
>  lib/librte_hash/Makefile    |   1 +
>  lib/librte_hash/rte_thash.h | 209
> ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 210 insertions(+)
>  create mode 100644 lib/librte_hash/rte_thash.h
>
> diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile index
> 3696cb1..981230b 100644
> --- a/lib/librte_hash/Makefile
> +++ b/lib/librte_hash/Makefile
> @@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
> SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h  SYMLINK-
> $(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h  SYMLINK-
> $(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
> +SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
>
>  # this lib needs eal
> diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h new file
> mode 100644 index 0000000..42c7bf6
> --- /dev/null
> +++ b/lib/librte_hash/rte_thash.h
> @@ -0,0 +1,209 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> + */
> +
> +#ifndef _RTE_THASH_H
> +#define _RTE_THASH_H
> +
> +/**
> + * @file
> + *
> + * toeplitz hash functions.
> + */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Software implementation of the Toeplitz hash function used by RSS.
> + * Can be used either for packet distribution on single queue NIC
> + * or for simulating of RSS computation on specific NIC (for example
> + * after GRE header decapsulating)
> + */
> +
> +#include <stdint.h>
> +#include <rte_byteorder.h>
> +#include <rte_vect.h>
> +
> +#ifdef __SSE3__
> +static const __m128i bswap_mask = {0x0405060700010203,
> +0x0C0D0E0F08090A0B}; #endif
> +
> +enum rte_thash_len {
> +     RTE_THASH_V4_L3 = 2,    /*calculate hash of ipv4 header
> only*/
> +     RTE_THASH_V4_L4 = 3,    /*calculate hash of ipv4 + transport
> headers*/
> +     RTE_THASH_V6_L3 = 8,    /*calculate hash of ipv6 header only
> */
> +     RTE_THASH_V6_L4 = 9,    /*calculate hash of ipv6 + transport
> headers */
> +};
> +
> +/**
> + * IPv4 tuple
> + * addreses and ports have to be CPU byte order  */ struct
> +rte_ipv4_tuple {
> +     uint32_t        src_addr;
> +     uint32_t        dst_addr;
> +     uint16_t        dport;
> +     uint16_t        sport;
> +};
> +
> +/**
> + * IPv6 tuple
> + * Addresses have to be filled by rte_thash_load_v6_addr()
> + * ports have to be CPU byte order
> + */
> +struct rte_ipv6_tuple {
> +     uint8_t         src_addr[16];
> +     uint8_t         dst_addr[16];
> +     uint16_t        dport;
> +     uint16_t        sport;
> +};
> +
> +union rte_thash_tuple {
> +     struct rte_ipv4_tuple   v4;
> +     struct rte_ipv6_tuple   v6;
> +} __attribute__((aligned(16)));
> +
> +/**
> + * Prepare special converted key to use with rte_softrss_be()
> + * @param orig
> + *   pointer to original RSS key
> + * @param targ
> + *   pointer to target RSS key
> + * @param len
> + *   RSS key length
> + */
> +static inline void
> +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len) {
> +     int i;
> +
> +     for (i = 0; i < (len >> 2); i++) {
> +             targ[i] = rte_be_to_cpu_32(orig[i]);
> +     }
> +}
> +
> +/**
> + * Prepare and load IPv6 address
> + * @param orig
> + *   Pointer to ipv6 address inside ipv6_hdr
> + * @param targ
> + *   Pointer to ipv6 address inside rte_ipv6_tuple
> + */
> +static inline void
> +rte_thash_load_v6_addr(const uint8_t *orig, uint8_t *targ) { #ifdef
> +__SSE3__
> +     __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig);
> +     *(__m128i *)targ = _mm_shuffle_epi8(ipv6, bswap_mask); #else
> +     int i;
> +
> +     for (i = 0; i < 4; i++) {
> +             *((uint32_t *)targ + i) =
> +                     rte_be_to_cpu_32(*((const uint32_t *)orig + i));
> +     }
> +#endif
> +}
> +
> +/**
> + * Generic implementation. Can be used with original rss_key
> + * @param input_tuple
> + *   Pointer to rte_thash_tuple union
> + * @param input_len
> + *   Length of input_tuple in 4-bytes chunks
> + *   RTE_THASH_V4_L3:        calculate hash of IPv4 src address and IPv4 dst
> address
> + *   RTE_THASH_V4_L4 calculate hash of IPv4 adresses and TCP|UDP
> ports
> + *   RTE_THASH_V6_L3:        calculate hash of IPv6 src address and IPv4 dst
> address
> + *   RTE_THASH_V6_L4 calculate hash of IPv6 adresses and TCP|UDP
> ports
> + * @param rss_key
> + *   Pointer to RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +static inline uint32_t
> +rte_softrss(union rte_thash_tuple *input_tuple, enum rte_thash_len
> input_len,
> +             const uint8_t *rss_key)
> +{
> +     uint32_t i, j, ret = 0;
> +
> +     for (j = 0; j < input_len; j++) {
> +             for (i = 0; i < 32; i++) {
> +                     if (((uint32_t *)input_tuple)[j] & (1 << (31 - i))) {
> +                             ret ^= rte_cpu_to_be_32(((const uint32_t
> *)rss_key)[j]) << i |
> +
>       (uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t
> *)rss_key)[j + 1])) >> (32 - i));
> +                     }
> +             }
> +     }
> +     return ret;
> +}
> +
> +/**
> + * Optimized implementation.
> + * If you want the calculated hash value matches NIC RSS value
> + * you have to use special converted key.
> + * @param input_tuple
> + *   Pointer to rte_thash_tuple union
> + * @param input_len
> + *   Length of input_tuple in 4-bytes chunks
> + *   RTE_THASH_V4_L3:        calculate hash of IPv4 src address and IPv4 dst
> address
> + *   RTE_THASH_V4_L4 calculate hash of IPv4 adresses and TCP|UDP
> ports
> + *   RTE_THASH_V6_L3:        calculate hash of IPv6 src address and IPv4 dst
> address
> + *   RTE_THASH_V6_L4 calculate hash of IPv6 adresses and TCP|UDP
> ports
> + * @param *rss_key
> + *   Pointer to RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +static inline uint32_t
> +rte_softrss_be(union rte_thash_tuple *input_tuple, enum rte_thash_len
> input_len,
> +             const uint8_t *rss_key)
> +{
> +     uint32_t i, j, ret = 0;
> +
> +     for (j = 0; j < input_len; j++) {
> +             for (i = 0; i < 32; i++) {
> +                     if (((uint32_t *)input_tuple)[j] & (1 << (31 - i))) {
> +                             ret ^= ((const uint32_t *)rss_key)[j] << i |
> +                                     (uint32_t)((uint64_t)(((const uint32_t
> *)rss_key)[j + 1]) >> (32 - i));
> +                     }
> +             }
> +     }
> +     return ret;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_THASH_H */
> --
> 1.8.3.2


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-05-05 13:20 ` [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS Vladimir Medvedkin
  2015-05-05 16:03   ` Chilikin, Andrey
@ 2015-05-08 14:58   ` Vladimir Medvedkin
  2015-06-03 14:07     ` Thomas Monjalon
                       ` (2 more replies)
  1 sibling, 3 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-05-08 14:58 UTC (permalink / raw)
  To: dev

Software implementation of the Toeplitz hash function used by RSS.
Can be used either for packet distribution on single queue NIC
or for simulating of RSS computation on specific NIC (for example
after GRE header decapsulating).

v3 changes
- Rework API to be more generic
- Add sctp_tag into tuple

v2 changes
- Add ipv6 support
- Various style fixes

Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
---
 lib/librte_hash/Makefile    |   1 +
 lib/librte_hash/rte_thash.h | 207 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 208 insertions(+)
 create mode 100644 lib/librte_hash/rte_thash.h

diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
index 3696cb1..981230b 100644
--- a/lib/librte_hash/Makefile
+++ b/lib/librte_hash/Makefile
@@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
 
 # this lib needs eal
diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
new file mode 100644
index 0000000..5d5111b
--- /dev/null
+++ b/lib/librte_hash/rte_thash.h
@@ -0,0 +1,207 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_THASH_H
+#define _RTE_THASH_H
+
+/**
+ * @file
+ *
+ * toeplitz hash functions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Software implementation of the Toeplitz hash function used by RSS.
+ * Can be used either for packet distribution on single queue NIC
+ * or for simulating of RSS computation on specific NIC (for example
+ * after GRE header decapsulating)
+ */
+
+#include <stdint.h>
+#include <rte_byteorder.h>
+#include <rte_vect.h>
+
+#ifdef __SSE3__
+static const __m128i bswap_mask = {0x0405060700010203, 0x0C0D0E0F08090A0B};
+#endif
+
+#define RTE_THASH_V4_L3	 2	/*calculate hash of ipv4 header only*/
+#define RTE_THASH_V4_L4	 3	/*calculate hash of ipv4 + transport headers*/
+#define RTE_THASH_V6_L3	 8	/*calculate hash of ipv6 header only */
+#define RTE_THASH_V6_L4	 9	/*calculate hash of ipv6 + transport headers */
+
+struct rte_ports {
+        uint16_t dport;
+        uint16_t sport;
+};
+
+union rte_thash_l4 {
+        struct          rte_ports ports;
+        uint32_t        sctp_tag;
+};
+
+/**
+ * IPv4 tuple
+ * addreses and ports/sctp_tag have to be CPU byte order
+ */
+struct rte_ipv4_tuple {
+	uint32_t	src_addr;
+	uint32_t	dst_addr;
+	union rte_thash_l4 l4;
+};
+
+/**
+ * IPv6 tuple
+ * Addresses have to be filled by rte_thash_load_v6_addr()
+ * ports/sctp_tag have to be CPU byte order
+ */
+struct rte_ipv6_tuple {
+	uint8_t		src_addr[16];
+	uint8_t		dst_addr[16];
+	union rte_thash_l4 l4;
+};
+
+union rte_thash_tuple {
+	struct rte_ipv4_tuple	v4;
+	struct rte_ipv6_tuple	v6;
+} __attribute__((aligned(16)));
+
+/**
+ * Prepare special converted key to use with rte_softrss_be()
+ * @param orig
+ *   pointer to original RSS key
+ * @param targ
+ *   pointer to target RSS key
+ * @param len
+ *   RSS key length
+ */
+static inline void
+rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
+{
+	int i;
+
+	for (i = 0; i < (len >> 2); i++) {
+		targ[i] = rte_be_to_cpu_32(orig[i]);
+	}
+}
+
+/**
+ * Prepare and load IPv6 address
+ * @param orig
+ *   Pointer to ipv6 address inside ipv6_hdr
+ * @param targ
+ *   Pointer to ipv6 address inside rte_ipv6_tuple
+ */
+static inline void
+rte_thash_load_v6_addr(const uint8_t *orig, uint8_t *targ)
+{
+#ifdef __SSE3__
+	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig);
+	*(__m128i *)targ = _mm_shuffle_epi8(ipv6, bswap_mask);
+#else
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		*((uint32_t *)targ + i) =
+			rte_be_to_cpu_32(*((const uint32_t *)orig + i));
+	}
+#endif
+}
+
+/**
+ * Generic implementation. Can be used with original rss_key
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss(uint32_t *input_tuple, uint32_t input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (input_tuple[j] & (1 << (31 - i))) {
+				ret ^= rte_cpu_to_be_32(((const uint32_t *)rss_key)[j]) << i |
+					(uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t *)rss_key)[j + 1])) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+/**
+ * Optimized implementation.
+ * If you want the calculated hash value matches NIC RSS value
+ * you have to use special converted key.
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param *rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (input_tuple[j] & (1 << (31 - i))) {
+				ret ^= ((const uint32_t *)rss_key)[j] << i |
+					(uint32_t)((uint64_t)(((const uint32_t *)rss_key)[j + 1]) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_THASH_H */
-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-05-07 11:38       ` Chilikin, Andrey
@ 2015-05-08 14:58         ` Vladimir Medvedkin
  0 siblings, 0 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-05-08 14:58 UTC (permalink / raw)
  To: Chilikin, Andrey; +Cc: dev

Hi Andrey,

OK, so be it. Thus in case you want to distribute (or just calculate hash
based on non standart tuple) - use your own tuple and own hash key (length
of tuple and key - responsible of the programmer). In case you want to
emulate NIC RSS - use union rte_thash_tuple (still needs to be updated with
new NICs input tuples) and NIC RSS hash key.
P.S Thanks for reviews.

Regards,
Vladimir

2015-05-07 14:38 GMT+03:00 Chilikin, Andrey <andrey.chilikin@intel.com>:

>  Hi Vladimir,
>
>
>
> Yes, at the moment NICs support limited input sets for hash calculation,
> but why limit SW for the same sets if it can be done in more general way
> and be easily scalable for HW updates? Using limited input set for RSS is
> not a feature of Toeplitz hash, but limitation of HW. I believe that
> general Toeplitz function will be more appropriate – it will cover input
> sets currently supported by HW and also will be easily scalable for future
> HW. Also, talking about different NICs – Niantic and Fortville, for
> example, have hash keys of different length, so rte_softrss() function
> should take into account hash key’s length as well.
>
>  Regards,
>
> Andrey
>
>
>
>
>
> *From:* Vladimir Medvedkin [mailto:medvedkinv@gmail.com]
> *Sent:* Thursday, May 7, 2015 11:28 AM
> *To:* Chilikin, Andrey
> *Cc:* dev@dpdk.org
> *Subject:* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by
> RSS
>
>
>
> Hi Andrey,
>
> The main goal of this new functions is to calculate the hash which is
> equal to the hash of the NIC.
> According to XL710 datasheet table 7-5 for sctp input set consists of
> IP4-S, IP4-D, SCTP-Verification-Tag. I don't see any NIC that uses QinQ or
> single vlan tag, ip proto number, tunnel id, vxlan, etc for calculating RSS
> hash. If it appear we can always update union rte_thash_tuple.
> I think it should be like:
>
> struct rte_ports {
>         uint16_t dport;
>         uint16_t sport;
> };
>
> union rte_thash_l4 {
>         struct          rte_ports ports;
>         uint32_t        sctp_tag;
> };
> struct rte_ipv4_tuple {
>         uint32_t        src_addr;
>         uint32_t        dst_addr;
>         union rte_thash_l4 l4;
> };
>
> If it is necessary to distribute packets according to non standart tuples
> I think it's more appropriate to use crc32 or jhash because of speed.
> rte_softrss_be consumes 400-500 clocks for each 4-byte input at E3
> 1230v1@3.2GHz. This means for ipv4+tcp it consumes ~1500 clocks.
>
> If you or someone still think you need general toeplitz hash I'll add it.
>
> Regards,
>
> Vladimir
>
>
>
>
>
> 2015-05-05 19:03 GMT+03:00 Chilikin, Andrey <andrey.chilikin@intel.com>:
>
> Hi Vladimir,
>
> Why limit Toeplitz hash calculation to predefined tuples and length?
> Should it be more general, something like
> rte_softrss_be(void *input, uint32_t input_len, const uint8_t *rss_key) to
> enable hash calculation for an input of any size? It would be useful for
> distributing packets using some non-standard tuples, like hashing on QinQ
> or adding IP protocol to hash calculation to separate UDP and TCP flows or
> even some other fields from a packet, for example, tunnel ID from VXLAN
> headers. By the way, i40e already supports RSS for SCTP in addition to TCP
> and UDP and includes Verification Tag as well as SCTP source and
> destination ports for RSS hash.
>
> Regards,
> Andrey
>
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Vladimir
> > Medvedkin
> > Sent: Tuesday, May 5, 2015 2:20 PM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
> >
> > Software implementation of the Toeplitz hash function used by RSS.
> > Can be used either for packet distribution on single queue NIC or for
> > simulating of RSS computation on specific NIC (for example after GRE
> header
> > decapsulating).
> >
> > v2 changes
> > - Add ipv6 support
> > - Various style fixes
> >
> > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> > ---
> >  lib/librte_hash/Makefile    |   1 +
> >  lib/librte_hash/rte_thash.h | 209
> > ++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 210 insertions(+)
> >  create mode 100644 lib/librte_hash/rte_thash.h
> >
> > diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile index
> > 3696cb1..981230b 100644
> > --- a/lib/librte_hash/Makefile
> > +++ b/lib/librte_hash/Makefile
> > @@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
> > SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h  SYMLINK-
> > $(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h  SYMLINK-
> > $(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
> > +SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
> >  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
> >
> >  # this lib needs eal
> > diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
> new file
> > mode 100644 index 0000000..42c7bf6
> > --- /dev/null
> > +++ b/lib/librte_hash/rte_thash.h
> > @@ -0,0 +1,209 @@
> > +/*-
> > + *   BSD LICENSE
> > + *
> > + *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
> > + *   All rights reserved.
> > + *
> > + *   Redistribution and use in source and binary forms, with or without
> > + *   modification, are permitted provided that the following conditions
> > + *   are met:
> > + *
> > + *     * Redistributions of source code must retain the above copyright
> > + *       notice, this list of conditions and the following disclaimer.
> > + *     * Redistributions in binary form must reproduce the above
> copyright
> > + *       notice, this list of conditions and the following disclaimer in
> > + *       the documentation and/or other materials provided with the
> > + *       distribution.
> > + *     * Neither the name of Intel Corporation nor the names of its
> > + *       contributors may be used to endorse or promote products derived
> > + *       from this software without specific prior written permission.
> > + *
> > + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > CONTRIBUTORS
> > + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> > NOT
> > + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> > FITNESS FOR
> > + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> > COPYRIGHT
> > + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> > INCIDENTAL,
> > + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > NOT
> > + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> > OF USE,
> > + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> > AND ON ANY
> > + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> > TORT
> > + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> > THE USE
> > + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> > DAMAGE.
> > + */
> > +
> > +#ifndef _RTE_THASH_H
> > +#define _RTE_THASH_H
> > +
> > +/**
> > + * @file
> > + *
> > + * toeplitz hash functions.
> > + */
> > +
> > +#ifdef __cplusplus
> > +extern "C" {
> > +#endif
> > +
> > +/**
> > + * Software implementation of the Toeplitz hash function used by RSS.
> > + * Can be used either for packet distribution on single queue NIC
> > + * or for simulating of RSS computation on specific NIC (for example
> > + * after GRE header decapsulating)
> > + */
> > +
> > +#include <stdint.h>
> > +#include <rte_byteorder.h>
> > +#include <rte_vect.h>
> > +
> > +#ifdef __SSE3__
> > +static const __m128i bswap_mask = {0x0405060700010203,
>
> > +0x0C0D0E0F08090A0B}; #endif
> > +
> > +enum rte_thash_len {
> > +     RTE_THASH_V4_L3 = 2,    /*calculate hash of ipv4 header
> > only*/
> > +     RTE_THASH_V4_L4 = 3,    /*calculate hash of ipv4 + transport
> > headers*/
> > +     RTE_THASH_V6_L3 = 8,    /*calculate hash of ipv6 header only
> > */
> > +     RTE_THASH_V6_L4 = 9,    /*calculate hash of ipv6 + transport
> > headers */
> > +};
> > +
> > +/**
> > + * IPv4 tuple
> > + * addreses and ports have to be CPU byte order  */ struct
> > +rte_ipv4_tuple {
>
> > +     uint32_t        src_addr;
> > +     uint32_t        dst_addr;
> > +     uint16_t        dport;
> > +     uint16_t        sport;
> > +};
> > +
> > +/**
> > + * IPv6 tuple
> > + * Addresses have to be filled by rte_thash_load_v6_addr()
> > + * ports have to be CPU byte order
> > + */
> > +struct rte_ipv6_tuple {
> > +     uint8_t         src_addr[16];
> > +     uint8_t         dst_addr[16];
> > +     uint16_t        dport;
> > +     uint16_t        sport;
> > +};
> > +
> > +union rte_thash_tuple {
> > +     struct rte_ipv4_tuple   v4;
> > +     struct rte_ipv6_tuple   v6;
> > +} __attribute__((aligned(16)));
> > +
> > +/**
> > + * Prepare special converted key to use with rte_softrss_be()
> > + * @param orig
> > + *   pointer to original RSS key
> > + * @param targ
> > + *   pointer to target RSS key
> > + * @param len
> > + *   RSS key length
> > + */
> > +static inline void
> > +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len) {
>
> > +     int i;
> > +
> > +     for (i = 0; i < (len >> 2); i++) {
> > +             targ[i] = rte_be_to_cpu_32(orig[i]);
> > +     }
> > +}
> > +
> > +/**
> > + * Prepare and load IPv6 address
> > + * @param orig
> > + *   Pointer to ipv6 address inside ipv6_hdr
> > + * @param targ
> > + *   Pointer to ipv6 address inside rte_ipv6_tuple
> > + */
> > +static inline void
> > +rte_thash_load_v6_addr(const uint8_t *orig, uint8_t *targ) { #ifdef
> > +__SSE3__
> > +     __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig);
> > +     *(__m128i *)targ = _mm_shuffle_epi8(ipv6, bswap_mask); #else
>
> > +     int i;
> > +
> > +     for (i = 0; i < 4; i++) {
> > +             *((uint32_t *)targ + i) =
> > +                     rte_be_to_cpu_32(*((const uint32_t *)orig + i));
> > +     }
> > +#endif
> > +}
> > +
> > +/**
> > + * Generic implementation. Can be used with original rss_key
> > + * @param input_tuple
> > + *   Pointer to rte_thash_tuple union
> > + * @param input_len
> > + *   Length of input_tuple in 4-bytes chunks
> > + *   RTE_THASH_V4_L3:        calculate hash of IPv4 src address and
> IPv4 dst
> > address
> > + *   RTE_THASH_V4_L4 calculate hash of IPv4 adresses and TCP|UDP
> > ports
> > + *   RTE_THASH_V6_L3:        calculate hash of IPv6 src address and
> IPv4 dst
> > address
> > + *   RTE_THASH_V6_L4 calculate hash of IPv6 adresses and TCP|UDP
> > ports
> > + * @param rss_key
> > + *   Pointer to RSS hash key.
> > + * @return
> > + *   Calculated hash value.
> > + */
> > +static inline uint32_t
> > +rte_softrss(union rte_thash_tuple *input_tuple, enum rte_thash_len
> > input_len,
> > +             const uint8_t *rss_key)
> > +{
> > +     uint32_t i, j, ret = 0;
> > +
> > +     for (j = 0; j < input_len; j++) {
> > +             for (i = 0; i < 32; i++) {
> > +                     if (((uint32_t *)input_tuple)[j] & (1 << (31 -
> i))) {
> > +                             ret ^= rte_cpu_to_be_32(((const uint32_t
> > *)rss_key)[j]) << i |
> > +
> >       (uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t
> > *)rss_key)[j + 1])) >> (32 - i));
> > +                     }
> > +             }
> > +     }
> > +     return ret;
> > +}
> > +
> > +/**
> > + * Optimized implementation.
> > + * If you want the calculated hash value matches NIC RSS value
> > + * you have to use special converted key.
> > + * @param input_tuple
> > + *   Pointer to rte_thash_tuple union
> > + * @param input_len
> > + *   Length of input_tuple in 4-bytes chunks
> > + *   RTE_THASH_V4_L3:        calculate hash of IPv4 src address and
> IPv4 dst
> > address
> > + *   RTE_THASH_V4_L4 calculate hash of IPv4 adresses and TCP|UDP
> > ports
> > + *   RTE_THASH_V6_L3:        calculate hash of IPv6 src address and
> IPv4 dst
> > address
> > + *   RTE_THASH_V6_L4 calculate hash of IPv6 adresses and TCP|UDP
> > ports
> > + * @param *rss_key
> > + *   Pointer to RSS hash key.
> > + * @return
> > + *   Calculated hash value.
> > + */
> > +static inline uint32_t
> > +rte_softrss_be(union rte_thash_tuple *input_tuple, enum rte_thash_len
> > input_len,
> > +             const uint8_t *rss_key)
> > +{
> > +     uint32_t i, j, ret = 0;
> > +
> > +     for (j = 0; j < input_len; j++) {
> > +             for (i = 0; i < 32; i++) {
> > +                     if (((uint32_t *)input_tuple)[j] & (1 << (31 -
> i))) {
> > +                             ret ^= ((const uint32_t *)rss_key)[j] << i
> |
> > +                                     (uint32_t)((uint64_t)(((const
> uint32_t
> > *)rss_key)[j + 1]) >> (32 - i));
> > +                     }
> > +             }
> > +     }
> > +     return ret;
> > +}
> > +
> > +#ifdef __cplusplus
> > +}
> > +#endif
> > +
> > +#endif /* _RTE_THASH_H */
> > --
> > 1.8.3.2
>
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-05-08 14:58   ` Vladimir Medvedkin
@ 2015-06-03 14:07     ` Thomas Monjalon
  2015-06-16  9:07       ` Thomas Monjalon
  2015-06-16 12:29     ` Bruce Richardson
  2015-06-19 14:55     ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
  2 siblings, 1 reply; 37+ messages in thread
From: Thomas Monjalon @ 2015-06-03 14:07 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

2015-05-08 10:58, Vladimir Medvedkin:
> Software implementation of the Toeplitz hash function used by RSS.
> Can be used either for packet distribution on single queue NIC
> or for simulating of RSS computation on specific NIC (for example
> after GRE header decapsulating).
> 
> v3 changes
> - Rework API to be more generic
> - Add sctp_tag into tuple
> 
> v2 changes
> - Add ipv6 support
> - Various style fixes
> 
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> ---
>  lib/librte_hash/Makefile    |   1 +
>  lib/librte_hash/rte_thash.h | 207 ++++++++++++++++++++++++++++++++++++++++++++

Without any comment, it seems this v3 is approved.
Maybe that this patch would be even better by implementing some unit tests.
I wonder if the hash chapter of the prog guide could list the different
algorithms and why/when use them?

Thanks

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-06-03 14:07     ` Thomas Monjalon
@ 2015-06-16  9:07       ` Thomas Monjalon
  2015-06-16 10:36         ` Bruce Richardson
  0 siblings, 1 reply; 37+ messages in thread
From: Thomas Monjalon @ 2015-06-16  9:07 UTC (permalink / raw)
  To: bruce.richardson; +Cc: dev

2015-06-03 16:07, Thomas Monjalon:
> 2015-05-08 10:58, Vladimir Medvedkin:
> > Software implementation of the Toeplitz hash function used by RSS.
> > Can be used either for packet distribution on single queue NIC
> > or for simulating of RSS computation on specific NIC (for example
> > after GRE header decapsulating).
> > 
> > v3 changes
> > - Rework API to be more generic
> > - Add sctp_tag into tuple
> > 
> > v2 changes
> > - Add ipv6 support
> > - Various style fixes
> > 
> > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> > ---
> >  lib/librte_hash/Makefile    |   1 +
> >  lib/librte_hash/rte_thash.h | 207 ++++++++++++++++++++++++++++++++++++++++++++
> 
> Without any comment, it seems this v3 is approved.
> Maybe that this patch would be even better by implementing some unit tests.
> I wonder if the hash chapter of the prog guide could list the different
> algorithms and why/when use them?

Bruce, any opinion?
Don't you think that unit tests are required?

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-06-16  9:07       ` Thomas Monjalon
@ 2015-06-16 10:36         ` Bruce Richardson
  0 siblings, 0 replies; 37+ messages in thread
From: Bruce Richardson @ 2015-06-16 10:36 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

On Tue, Jun 16, 2015 at 11:07:28AM +0200, Thomas Monjalon wrote:
> 2015-06-03 16:07, Thomas Monjalon:
> > 2015-05-08 10:58, Vladimir Medvedkin:
> > > Software implementation of the Toeplitz hash function used by RSS.
> > > Can be used either for packet distribution on single queue NIC
> > > or for simulating of RSS computation on specific NIC (for example
> > > after GRE header decapsulating).
> > > 
> > > v3 changes
> > > - Rework API to be more generic
> > > - Add sctp_tag into tuple
> > > 
> > > v2 changes
> > > - Add ipv6 support
> > > - Various style fixes
> > > 
> > > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> > > ---
> > >  lib/librte_hash/Makefile    |   1 +
> > >  lib/librte_hash/rte_thash.h | 207 ++++++++++++++++++++++++++++++++++++++++++++
> > 
> > Without any comment, it seems this v3 is approved.
> > Maybe that this patch would be even better by implementing some unit tests.
> > I wonder if the hash chapter of the prog guide could list the different
> > algorithms and why/when use them?
> 
> Bruce, any opinion?
> Don't you think that unit tests are required?

Sorry, I missed this patch set. I'll take a look at it today.

/Bruce

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-05-08 14:58   ` Vladimir Medvedkin
  2015-06-03 14:07     ` Thomas Monjalon
@ 2015-06-16 12:29     ` Bruce Richardson
  2015-06-16 19:26       ` Vladimir Medvedkin
  2015-06-19 14:55     ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
  2 siblings, 1 reply; 37+ messages in thread
From: Bruce Richardson @ 2015-06-16 12:29 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

On Fri, May 08, 2015 at 10:58:12AM -0400, Vladimir Medvedkin wrote:
> Software implementation of the Toeplitz hash function used by RSS.
> Can be used either for packet distribution on single queue NIC
> or for simulating of RSS computation on specific NIC (for example
> after GRE header decapsulating).
> 
> v3 changes
> - Rework API to be more generic
> - Add sctp_tag into tuple
> 
> v2 changes
> - Add ipv6 support
> - Various style fixes
> 
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>

Hi Vladimir,

first off, thanks for this patch, it looks like something we want into DPDK.
However, as Thomas has already pointed out, I think we could really do with
some unit tests for this code. As it stands right now, we don't even know if this
header compiles, as the header file is not used by any C file in DPDK.

Some other comments are inline below.

Regards,
/Bruce
> ---
>  lib/librte_hash/Makefile    |   1 +
>  lib/librte_hash/rte_thash.h | 207 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 208 insertions(+)
>  create mode 100644 lib/librte_hash/rte_thash.h
> 
> diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
> index 3696cb1..981230b 100644
> --- a/lib/librte_hash/Makefile
> +++ b/lib/librte_hash/Makefile
> @@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
>  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
> +SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
>  
>  # this lib needs eal
> diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
> new file mode 100644
> index 0000000..5d5111b
> --- /dev/null
> +++ b/lib/librte_hash/rte_thash.h
> @@ -0,0 +1,207 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.

Date and copyright owner look to need update here.

> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifndef _RTE_THASH_H
> +#define _RTE_THASH_H
> +
> +/**
> + * @file
> + *
> + * toeplitz hash functions.
> + */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Software implementation of the Toeplitz hash function used by RSS.
> + * Can be used either for packet distribution on single queue NIC
> + * or for simulating of RSS computation on specific NIC (for example
> + * after GRE header decapsulating)
> + */
> +
> +#include <stdint.h>
> +#include <rte_byteorder.h>
> +#include <rte_vect.h>
> +
> +#ifdef __SSE3__
> +static const __m128i bswap_mask = {0x0405060700010203, 0x0C0D0E0F08090A0B};
> +#endif

I think a more descriptive name for this might help. Yes, it's a mask for
byteswapping, but I think the name could do with being more descriptive. I see
below it's used for IPv6 IP extraction, so maybe that could be put in the name
somehow. A comment should also be added on what it is used for.
Finally, since this is a public symbol in the including C file, it should have
an rte_ prefix - or perhaps just an underscore prefix "_".

> +
> +#define RTE_THASH_V4_L3	 2	/*calculate hash of ipv4 header only*/
> +#define RTE_THASH_V4_L4	 3	/*calculate hash of ipv4 + transport headers*/
> +#define RTE_THASH_V6_L3	 8	/*calculate hash of ipv6 header only */
> +#define RTE_THASH_V6_L4	 9	/*calculate hash of ipv6 + transport headers */
> +

Are these #defines used anywhere? If not, they should be removed.

> +struct rte_ports {
> +        uint16_t dport;
> +        uint16_t sport;
> +};
> +
> +union rte_thash_l4 {
> +        struct          rte_ports ports;
> +        uint32_t        sctp_tag;
> +};
> +

Any reason for the rte_ports struct being separated out from the rte_thash_l4
structure?

> +/**
> + * IPv4 tuple
> + * addreses and ports/sctp_tag have to be CPU byte order
> + */
> +struct rte_ipv4_tuple {
> +	uint32_t	src_addr;
> +	uint32_t	dst_addr;
> +	union rte_thash_l4 l4;
> +};
> +
> +/**
> + * IPv6 tuple
> + * Addresses have to be filled by rte_thash_load_v6_addr()
> + * ports/sctp_tag have to be CPU byte order
> + */
> +struct rte_ipv6_tuple {
> +	uint8_t		src_addr[16];
> +	uint8_t		dst_addr[16];
> +	union rte_thash_l4 l4;
> +};
> +
> +union rte_thash_tuple {
> +	struct rte_ipv4_tuple	v4;
> +	struct rte_ipv6_tuple	v6;
> +} __attribute__((aligned(16)));
> +

I can see the reason for these structure, but they are not actually used
anywhere in the code below. Should some of the functions, e.g. load_v6_addr fn
not use these as type parameters?

> +/**
> + * Prepare special converted key to use with rte_softrss_be()
> + * @param orig
> + *   pointer to original RSS key
> + * @param targ
> + *   pointer to target RSS key
> + * @param len
> + *   RSS key length
> + */
> +static inline void
> +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
> +{
> +	int i;
> +
> +	for (i = 0; i < (len >> 2); i++) {
> +		targ[i] = rte_be_to_cpu_32(orig[i]);
> +	}
> +}
> +
> +/**
> + * Prepare and load IPv6 address
> + * @param orig
> + *   Pointer to ipv6 address inside ipv6_hdr
> + * @param targ
> + *   Pointer to ipv6 address inside rte_ipv6_tuple
> + */
> +static inline void
> +rte_thash_load_v6_addr(const uint8_t *orig, uint8_t *targ)

Why not take a struct ipv6_hdr (from ip.h) and struct rte_ipv6_tuple parameters
directly, rather than uint8_t parameters to somewhere in the middle of the
structures? Specifying that way allows the compile to check the user is doing
things correctly.

> +{
> +#ifdef __SSE3__

I actually think the minimum supported SSE instruction set level for DPDK is
SSE3, so perhaps these #idefs could be removed.

> +	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig);
> +	*(__m128i *)targ = _mm_shuffle_epi8(ipv6, bswap_mask);
> +#else
> +	int i;
> +
> +	for (i = 0; i < 4; i++) {
> +		*((uint32_t *)targ + i) =
> +			rte_be_to_cpu_32(*((const uint32_t *)orig + i));
> +	}
> +#endif
> +}
> +
> +/**
> + * Generic implementation. Can be used with original rss_key
> + * @param input_tuple
> + *   Pointer to input tuple
> + * @param input_len
> + *   Length of input_tuple in 4-bytes chunks
> + * @param rss_key
> + *   Pointer to RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +static inline uint32_t
> +rte_softrss(uint32_t *input_tuple, uint32_t input_len,
> +		const uint8_t *rss_key)
> +{
> +	uint32_t i, j, ret = 0;
> +
> +	for (j = 0; j < input_len; j++) {
> +		for (i = 0; i < 32; i++) {
> +			if (input_tuple[j] & (1 << (31 - i))) {
> +				ret ^= rte_cpu_to_be_32(((const uint32_t *)rss_key)[j]) << i |
> +					(uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t *)rss_key)[j + 1])) >> (32 - i));

Line is rather long and not terribly readable. Can it be split up into a number
of easier to read statements (without affecting performance)?

> +			}
> +		}
> +	}
> +	return ret;
> +}
> +
> +/**
> + * Optimized implementation.
> + * If you want the calculated hash value matches NIC RSS value
> + * you have to use special converted key.

Put in reference to function used for the conversion.
Can you also document when you might want to use this version over the 
previous one?

> + * @param input_tuple
> + *   Pointer to input tuple
> + * @param input_len
> + *   Length of input_tuple in 4-bytes chunks
> + * @param *rss_key
> + *   Pointer to RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +static inline uint32_t
> +rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
> +		const uint8_t *rss_key)
> +{
> +	uint32_t i, j, ret = 0;
> +
> +	for (j = 0; j < input_len; j++) {
> +		for (i = 0; i < 32; i++) {
> +			if (input_tuple[j] & (1 << (31 - i))) {
> +				ret ^= ((const uint32_t *)rss_key)[j] << i |
> +					(uint32_t)((uint64_t)(((const uint32_t *)rss_key)[j + 1]) >> (32 - i));
> +			}
> +		}
> +	}
> +	return ret;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_THASH_H */
> -- 
> 1.8.3.2
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS
  2015-06-16 12:29     ` Bruce Richardson
@ 2015-06-16 19:26       ` Vladimir Medvedkin
  0 siblings, 0 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-06-16 19:26 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

Hi Bruce,

2015-06-16 15:29 GMT+03:00 Bruce Richardson <bruce.richardson@intel.com>:

> On Fri, May 08, 2015 at 10:58:12AM -0400, Vladimir Medvedkin wrote:
> > Software implementation of the Toeplitz hash function used by RSS.
> > Can be used either for packet distribution on single queue NIC
> > or for simulating of RSS computation on specific NIC (for example
> > after GRE header decapsulating).
> >
> > v3 changes
> > - Rework API to be more generic
> > - Add sctp_tag into tuple
> >
> > v2 changes
> > - Add ipv6 support
> > - Various style fixes
> >
> > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
>
> Hi Vladimir,
>
> first off, thanks for this patch, it looks like something we want into
> DPDK.
> However, as Thomas has already pointed out, I think we could really do with
> some unit tests for this code. As it stands right now, we don't even know
> if this
> header compiles, as the header file is not used by any C file in DPDK.
>
I'll try to make a unit test this week

>
> Some other comments are inline below.
>
> Regards,
> /Bruce
> > ---
> >  lib/librte_hash/Makefile    |   1 +
> >  lib/librte_hash/rte_thash.h | 207
> ++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 208 insertions(+)
> >  create mode 100644 lib/librte_hash/rte_thash.h
> >
> > diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
> > index 3696cb1..981230b 100644
> > --- a/lib/librte_hash/Makefile
> > +++ b/lib/librte_hash/Makefile
> > @@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
> >  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
> >  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
> >  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
> > +SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
> >  SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
> >
> >  # this lib needs eal
> > diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
> > new file mode 100644
> > index 0000000..5d5111b
> > --- /dev/null
> > +++ b/lib/librte_hash/rte_thash.h
> > @@ -0,0 +1,207 @@
> > +/*-
> > + *   BSD LICENSE
> > + *
> > + *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
>
> Date and copyright owner look to need update here.
>
> > + *   All rights reserved.
> > + *
> > + *   Redistribution and use in source and binary forms, with or without
> > + *   modification, are permitted provided that the following conditions
> > + *   are met:
> > + *
> > + *     * Redistributions of source code must retain the above copyright
> > + *       notice, this list of conditions and the following disclaimer.
> > + *     * Redistributions in binary form must reproduce the above
> copyright
> > + *       notice, this list of conditions and the following disclaimer in
> > + *       the documentation and/or other materials provided with the
> > + *       distribution.
> > + *     * Neither the name of Intel Corporation nor the names of its
> > + *       contributors may be used to endorse or promote products derived
> > + *       from this software without specific prior written permission.
> > + *
> > + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> > + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> > + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> FOR
> > + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> > + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> > + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> > + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
> USE,
> > + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> ANY
> > + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> USE
> > + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> > + */
> > +
> > +#ifndef _RTE_THASH_H
> > +#define _RTE_THASH_H
> > +
> > +/**
> > + * @file
> > + *
> > + * toeplitz hash functions.
> > + */
> > +
> > +#ifdef __cplusplus
> > +extern "C" {
> > +#endif
> > +
> > +/**
> > + * Software implementation of the Toeplitz hash function used by RSS.
> > + * Can be used either for packet distribution on single queue NIC
> > + * or for simulating of RSS computation on specific NIC (for example
> > + * after GRE header decapsulating)
> > + */
> > +
> > +#include <stdint.h>
> > +#include <rte_byteorder.h>
> > +#include <rte_vect.h>
> > +
> > +#ifdef __SSE3__
> > +static const __m128i bswap_mask = {0x0405060700010203,
> 0x0C0D0E0F08090A0B};
> > +#endif
>
> I think a more descriptive name for this might help. Yes, it's a mask for
> byteswapping, but I think the name could do with being more descriptive. I
> see
> below it's used for IPv6 IP extraction, so maybe that could be put in the
> name
> somehow. A comment should also be added on what it is used for.
> Finally, since this is a public symbol in the including C file, it should
> have
> an rte_ prefix - or perhaps just an underscore prefix "_".
>
> I think rte_thash_ipv6_bswap_maskwill be more appropriate

> > +
> > +#define RTE_THASH_V4_L3       2      /*calculate hash of ipv4 header
> only*/
> > +#define RTE_THASH_V4_L4       3      /*calculate hash of ipv4 +
> transport headers*/
> > +#define RTE_THASH_V6_L3       8      /*calculate hash of ipv6 header
> only */
> > +#define RTE_THASH_V6_L4       9      /*calculate hash of ipv6 +
> transport headers */
> > +
>
> Are these #defines used anywhere? If not, they should be removed.
>
It can be used in code that uses this library.

>
> > +struct rte_ports {
> > +        uint16_t dport;
> > +        uint16_t sport;
> > +};
> > +
> > +union rte_thash_l4 {
> > +        struct          rte_ports ports;
> > +        uint32_t        sctp_tag;
> > +};
> > +
>
> Any reason for the rte_ports struct being separated out from the
> rte_thash_l4
> structure?
>
You're right, no reason, I'll make unnamed struct field.

>
> > +/**
> > + * IPv4 tuple
> > + * addreses and ports/sctp_tag have to be CPU byte order
> > + */
> > +struct rte_ipv4_tuple {
> > +     uint32_t        src_addr;
> > +     uint32_t        dst_addr;
> > +     union rte_thash_l4 l4;
> > +};
> > +
> > +/**
> > + * IPv6 tuple
> > + * Addresses have to be filled by rte_thash_load_v6_addr()
> > + * ports/sctp_tag have to be CPU byte order
> > + */
> > +struct rte_ipv6_tuple {
> > +     uint8_t         src_addr[16];
> > +     uint8_t         dst_addr[16];
> > +     union rte_thash_l4 l4;
> > +};
> > +
> > +union rte_thash_tuple {
> > +     struct rte_ipv4_tuple   v4;
> > +     struct rte_ipv6_tuple   v6;
> > +} __attribute__((aligned(16)));
> > +
>
> I can see the reason for these structure, but they are not actually used
> anywhere in the code below. Should some of the functions, e.g.
> load_v6_addr fn
> not use these as type parameters?
>
Agree

>
> > +/**
> > + * Prepare special converted key to use with rte_softrss_be()
> > + * @param orig
> > + *   pointer to original RSS key
> > + * @param targ
> > + *   pointer to target RSS key
> > + * @param len
> > + *   RSS key length
> > + */
> > +static inline void
> > +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
> > +{
> > +     int i;
> > +
> > +     for (i = 0; i < (len >> 2); i++) {
> > +             targ[i] = rte_be_to_cpu_32(orig[i]);
> > +     }
> > +}
> > +
> > +/**
> > + * Prepare and load IPv6 address
> > + * @param orig
> > + *   Pointer to ipv6 address inside ipv6_hdr
> > + * @param targ
> > + *   Pointer to ipv6 address inside rte_ipv6_tuple
> > + */
> > +static inline void
> > +rte_thash_load_v6_addr(const uint8_t *orig, uint8_t *targ)
>
> Why not take a struct ipv6_hdr (from ip.h) and struct rte_ipv6_tuple
> parameters
> directly, rather than uint8_t parameters to somewhere in the middle of the
> structures? Specifying that way allows the compile to check the user is
> doing
> things correctly.
>
Agree too. I think it shoul be like rte_thash_load_v6_addr(const struct
ipv6_hdr *orig, union rte_thash_tuple *targ)

>
> > +{
> > +#ifdef __SSE3__
>
> I actually think the minimum supported SSE instruction set level for DPDK
> is
> SSE3, so perhaps these #idefs could be removed.
>
> > +     __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig);
> > +     *(__m128i *)targ = _mm_shuffle_epi8(ipv6, bswap_mask);
> > +#else
> > +     int i;
> > +
> > +     for (i = 0; i < 4; i++) {
> > +             *((uint32_t *)targ + i) =
> > +                     rte_be_to_cpu_32(*((const uint32_t *)orig + i));
> > +     }
> > +#endif
> > +}
> > +
> > +/**
> > + * Generic implementation. Can be used with original rss_key
> > + * @param input_tuple
> > + *   Pointer to input tuple
> > + * @param input_len
> > + *   Length of input_tuple in 4-bytes chunks
> > + * @param rss_key
> > + *   Pointer to RSS hash key.
> > + * @return
> > + *   Calculated hash value.
> > + */
> > +static inline uint32_t
> > +rte_softrss(uint32_t *input_tuple, uint32_t input_len,
> > +             const uint8_t *rss_key)
> > +{
> > +     uint32_t i, j, ret = 0;
> > +
> > +     for (j = 0; j < input_len; j++) {
> > +             for (i = 0; i < 32; i++) {
> > +                     if (input_tuple[j] & (1 << (31 - i))) {
> > +                             ret ^= rte_cpu_to_be_32(((const uint32_t
> *)rss_key)[j]) << i |
> > +
>  (uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t *)rss_key)[j +
> 1])) >> (32 - i));
>
> Line is rather long and not terribly readable. Can it be split up into a
> number
> of easier to read statements (without affecting performance)?
>
I don't see how it can be done

>
> > +                     }
> > +             }
> > +     }
> > +     return ret;
> > +}
> > +
> > +/**
> > + * Optimized implementation.
> > + * If you want the calculated hash value matches NIC RSS value
> > + * you have to use special converted key.
>
> Put in reference to function used for the conversion.
> Can you also document when you might want to use this version over the
> previous one?
>
> > + * @param input_tuple
> > + *   Pointer to input tuple
> > + * @param input_len
> > + *   Length of input_tuple in 4-bytes chunks
> > + * @param *rss_key
> > + *   Pointer to RSS hash key.
> > + * @return
> > + *   Calculated hash value.
> > + */
> > +static inline uint32_t
> > +rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
> > +             const uint8_t *rss_key)
> > +{
> > +     uint32_t i, j, ret = 0;
> > +
> > +     for (j = 0; j < input_len; j++) {
> > +             for (i = 0; i < 32; i++) {
> > +                     if (input_tuple[j] & (1 << (31 - i))) {
> > +                             ret ^= ((const uint32_t *)rss_key)[j] << i
> |
> > +                                     (uint32_t)((uint64_t)(((const
> uint32_t *)rss_key)[j + 1]) >> (32 - i));
> > +                     }
> > +             }
> > +     }
> > +     return ret;
> > +}
> > +
> > +#ifdef __cplusplus
> > +}
> > +#endif
> > +
> > +#endif /* _RTE_THASH_H */
> > --
> > 1.8.3.2
> >
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [dpdk-dev] [PATCH v4] Add toeplitz hash algorithm used by RSS
  2015-05-08 14:58   ` Vladimir Medvedkin
  2015-06-03 14:07     ` Thomas Monjalon
  2015-06-16 12:29     ` Bruce Richardson
@ 2015-06-19 14:55     ` Vladimir Medvedkin
  2015-06-19 15:59       ` Richardson, Bruce
                         ` (2 more replies)
  2 siblings, 3 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-06-19 14:55 UTC (permalink / raw)
  To: dev

v4 changes
- Fix copyright
- rename bswap_mask constant, add rte_ prefix
- change rte_ipv[46]_tuple struct
- change rte_thash_load_v6_addr prototype

v3 changes
- Rework API to be more generic
- Add sctp_tag into tuple

v2 changes
- Add ipv6 support
- Various style fixes

---
 lib/librte_hash/Makefile    |   1 +
 lib/librte_hash/rte_thash.h | 202 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 203 insertions(+)
 create mode 100644 lib/librte_hash/rte_thash.h

diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
index 3696cb1..981230b 100644
--- a/lib/librte_hash/Makefile
+++ b/lib/librte_hash/Makefile
@@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
 
 # this lib needs eal
diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
new file mode 100644
index 0000000..7b3cc52
--- /dev/null
+++ b/lib/librte_hash/rte_thash.h
@@ -0,0 +1,202 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com>
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_THASH_H
+#define _RTE_THASH_H
+
+/**
+ * @file
+ *
+ * toeplitz hash functions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Software implementation of the Toeplitz hash function used by RSS.
+ * Can be used either for packet distribution on single queue NIC
+ * or for simulating of RSS computation on specific NIC (for example
+ * after GRE header decapsulating)
+ */
+
+#include <stdint.h>
+#include <rte_byteorder.h>
+#include <rte_vect.h>
+#include <rte_ip.h>
+
+/* Byte swap mask used for converting IPv6 address 4-byte chunks to CPU byte order */
+static const __m128i rte_thash_ipv6_bswap_mask = {0x0405060700010203, 0x0C0D0E0F08090A0B};
+
+#define RTE_THASH_V4_L3	 2	/*calculate hash of ipv4 header only*/
+#define RTE_THASH_V4_L4	 3	/*calculate hash of ipv4 + transport headers*/
+#define RTE_THASH_V6_L3	 8	/*calculate hash of ipv6 header only */
+#define RTE_THASH_V6_L4	 9	/*calculate hash of ipv6 + transport headers */
+
+/**
+ * IPv4 tuple
+ * addreses and ports/sctp_tag have to be CPU byte order
+ */
+struct rte_ipv4_tuple {
+	uint32_t	src_addr;
+	uint32_t	dst_addr;
+	union {
+		struct {
+			uint16_t dport;
+			uint16_t sport;
+		};
+		uint32_t        sctp_tag;
+	};
+};
+
+/**
+ * IPv6 tuple
+ * Addresses have to be filled by rte_thash_load_v6_addr()
+ * ports/sctp_tag have to be CPU byte order
+ */
+struct rte_ipv6_tuple {
+	uint8_t		src_addr[16];
+	uint8_t		dst_addr[16];
+	union {
+		struct {
+			uint16_t dport;
+			uint16_t sport;
+		};
+		uint32_t        sctp_tag;
+	};
+};
+
+union rte_thash_tuple {
+	struct rte_ipv4_tuple	v4;
+	struct rte_ipv6_tuple	v6;
+} __attribute__((aligned(16)));
+
+/**
+ * Prepare special converted key to use with rte_softrss_be()
+ * @param orig
+ *   pointer to original RSS key
+ * @param targ
+ *   pointer to target RSS key
+ * @param len
+ *   RSS key length
+ */
+static inline void
+rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
+{
+	int i;
+
+	for (i = 0; i < (len >> 2); i++) {
+		targ[i] = rte_be_to_cpu_32(orig[i]);
+	}
+}
+
+/**
+ * Prepare and load IPv6 address
+ * @param orig
+ *   Pointer to ipv6 header of the original packet
+ * @param targ
+ *   Pointer to rte_ipv6_tuple structure
+ */
+static inline void
+rte_thash_load_v6_addr(const struct ipv6_hdr *orig, union rte_thash_tuple *targ)
+{
+	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
+	*(__m128i *)targ->v6.src_addr = _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
+	ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
+	*(__m128i *)targ->v6.dst_addr = _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
+}
+
+/**
+ * Generic implementation. Can be used with original rss_key
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss(uint32_t *input_tuple, uint32_t input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (input_tuple[j] & (1 << (31 - i))) {
+				ret ^= rte_cpu_to_be_32(((const uint32_t *)rss_key)[j]) << i |
+					(uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t *)rss_key)[j + 1])) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+/**
+ * Optimized implementation.
+ * If you want the calculated hash value matches NIC RSS value
+ * you have to use special converted key with rte_convert_rss_key() fn.
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param *rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (input_tuple[j] & (1 << (31 - i))) {
+				ret ^= ((const uint32_t *)rss_key)[j] << i |
+					(uint32_t)((uint64_t)(((const uint32_t *)rss_key)[j + 1]) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_THASH_H */
-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v4] Add toeplitz hash algorithm used by RSS
  2015-06-19 14:55     ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
@ 2015-06-19 15:59       ` Richardson, Bruce
  2015-06-19 16:14         ` Vladimir Medvedkin
  2015-06-19 16:33         ` Mcnamara, John
  2015-06-19 17:31       ` [dpdk-dev] [PATCH v5] " Vladimir Medvedkin
  2015-06-19 17:32       ` [dpdk-dev] [PATCH v3] Add unit test for thash library Vladimir Medvedkin
  2 siblings, 2 replies; 37+ messages in thread
From: Richardson, Bruce @ 2015-06-19 15:59 UTC (permalink / raw)
  To: Vladimir Medvedkin, dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Vladimir Medvedkin
> Sent: Friday, June 19, 2015 3:56 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v4] Add toeplitz hash algorithm used by RSS
> 
> v4 changes
> - Fix copyright
> - rename bswap_mask constant, add rte_ prefix
> - change rte_ipv[46]_tuple struct
> - change rte_thash_load_v6_addr prototype
> 
> v3 changes
> - Rework API to be more generic
> - Add sctp_tag into tuple
> 
> v2 changes
> - Add ipv6 support
> - Various style fixes
> 

Missing signoff line.

> ---
>  lib/librte_hash/Makefile    |   1 +
>  lib/librte_hash/rte_thash.h | 202
> ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 203 insertions(+)
>  create mode 100644 lib/librte_hash/rte_thash.h
> 
<...snip...>
> +
> +/* Byte swap mask used for converting IPv6 address 4-byte chunks to CPU
> byte order */
> +static const __m128i rte_thash_ipv6_bswap_mask = {0x0405060700010203,
> 0x0C0D0E0F08090A0B};
> +
> +#define RTE_THASH_V4_L3	 2	/*calculate hash of ipv4 header only*/
> +#define RTE_THASH_V4_L4	 3	/*calculate hash of ipv4 + transport
> headers*/
> +#define RTE_THASH_V6_L3	 8	/*calculate hash of ipv6 header only
> */
> +#define RTE_THASH_V6_L4	 9	/*calculate hash of ipv6 + transport
> headers */

I'm still not seeing why these values need to be defined here, rather than in a specific app.
Also, the choice of values for these defines seems strange to me? How were they chosen?

/Bruce

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v4] Add toeplitz hash algorithm used by RSS
  2015-06-19 15:59       ` Richardson, Bruce
@ 2015-06-19 16:14         ` Vladimir Medvedkin
  2015-06-29 12:18           ` Bruce Richardson
  2015-06-19 16:33         ` Mcnamara, John
  1 sibling, 1 reply; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-06-19 16:14 UTC (permalink / raw)
  To: Richardson, Bruce; +Cc: dev

Hi Bruce,

2015-06-19 18:59 GMT+03:00 Richardson, Bruce <bruce.richardson@intel.com>:

>
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Vladimir Medvedkin
> > Sent: Friday, June 19, 2015 3:56 PM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v4] Add toeplitz hash algorithm used by RSS
> >
> > v4 changes
> > - Fix copyright
> > - rename bswap_mask constant, add rte_ prefix
> > - change rte_ipv[46]_tuple struct
> > - change rte_thash_load_v6_addr prototype
> >
> > v3 changes
> > - Rework API to be more generic
> > - Add sctp_tag into tuple
> >
> > v2 changes
> > - Add ipv6 support
> > - Various style fixes
> >
>
> Missing signoff line.
>
> > ---
> >  lib/librte_hash/Makefile    |   1 +
> >  lib/librte_hash/rte_thash.h | 202
> > ++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 203 insertions(+)
> >  create mode 100644 lib/librte_hash/rte_thash.h
> >
> <...snip...>
> > +
> > +/* Byte swap mask used for converting IPv6 address 4-byte chunks to CPU
> > byte order */
> > +static const __m128i rte_thash_ipv6_bswap_mask = {0x0405060700010203,
> > 0x0C0D0E0F08090A0B};
> > +
> > +#define RTE_THASH_V4_L3       2      /*calculate hash of ipv4 header
> only*/
> > +#define RTE_THASH_V4_L4       3      /*calculate hash of ipv4 +
> transport
> > headers*/
> > +#define RTE_THASH_V6_L3       8      /*calculate hash of ipv6 header
> only
> > */
> > +#define RTE_THASH_V6_L4       9      /*calculate hash of ipv6 +
> transport
> > headers */
>
> I'm still not seeing why these values need to be defined here, rather than
> in a specific app.
> Also, the choice of values for these defines seems strange to me? How were
> they chosen?
>
This is a predefined values. They mean the length (in 4-bytes) of the
input data
in hashing. I think it's like defines in rte_ip.h, for example.

>
> /Bruce
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v4] Add toeplitz hash algorithm used by RSS
  2015-06-19 15:59       ` Richardson, Bruce
  2015-06-19 16:14         ` Vladimir Medvedkin
@ 2015-06-19 16:33         ` Mcnamara, John
  1 sibling, 0 replies; 37+ messages in thread
From: Mcnamara, John @ 2015-06-19 16:33 UTC (permalink / raw)
  To: Vladimir Medvedkin, dev

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Richardson, Bruce
> Sent: Friday, June 19, 2015 5:00 PM
> To: Vladimir Medvedkin; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v4] Add toeplitz hash algorithm used by RSS
> 
> Missing signoff line.
> 

Hi,

It would also be worth running Linux checkpatch against the patch, which would have caught the missing signoff. It also shows a lot of warnings in the patch which indicates conflicts with the coding guidelines.

John 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [dpdk-dev] [PATCH v5] Add toeplitz hash algorithm used by RSS
  2015-06-19 14:55     ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
  2015-06-19 15:59       ` Richardson, Bruce
@ 2015-06-19 17:31       ` Vladimir Medvedkin
  2015-06-29 12:40         ` Bruce Richardson
  2015-06-30 23:40         ` [dpdk-dev] [PATCH v6] " Vladimir Medvedkin
  2015-06-19 17:32       ` [dpdk-dev] [PATCH v3] Add unit test for thash library Vladimir Medvedkin
  2 siblings, 2 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-06-19 17:31 UTC (permalink / raw)
  To: dev

Software implementation of the Toeplitz hash function used by RSS.
Can be used either for packet distribution on single queue NIC
or for simulating of RSS computation on specific NIC (for example
after GRE header decapsulating).

v5 changes
- Fix errors reported by checkpatch.pl

v4 changes
- Fix copyright
- rename bswap_mask constant, add rte_ prefix
- change rte_ipv[46]_tuple struct
- change rte_thash_load_v6_addr prototype

v3 changes
- Rework API to be more generic
- Add sctp_tag into tuple

v2 changes
- Add ipv6 support
- Various style fixes

Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
---
 lib/librte_hash/Makefile    |   1 +
 lib/librte_hash/rte_thash.h | 207 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 208 insertions(+)
 create mode 100644 lib/librte_hash/rte_thash.h

diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
index 3696cb1..981230b 100644
--- a/lib/librte_hash/Makefile
+++ b/lib/librte_hash/Makefile
@@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
 
 # this lib needs eal
diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
new file mode 100644
index 0000000..877bd50
--- /dev/null
+++ b/lib/librte_hash/rte_thash.h
@@ -0,0 +1,207 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com>
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_THASH_H
+#define _RTE_THASH_H
+
+/**
+ * @file
+ *
+ * toeplitz hash functions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Software implementation of the Toeplitz hash function used by RSS.
+ * Can be used either for packet distribution on single queue NIC
+ * or for simulating of RSS computation on specific NIC (for example
+ * after GRE header decapsulating)
+ */
+
+#include <stdint.h>
+#include <rte_byteorder.h>
+#include <rte_vect.h>
+#include <rte_ip.h>
+
+/* Byte swap mask used for converting IPv6 address
+ * 4-byte chunks to CPU byte order
+ */
+static const __m128i rte_thash_ipv6_bswap_mask = {
+		0x0405060700010203, 0x0C0D0E0F08090A0B};
+
+#define RTE_THASH_V4_L3	 2	/*calculate hash of ipv4 header only*/
+#define RTE_THASH_V4_L4	 3	/*calculate hash of ipv4 + transport headers*/
+#define RTE_THASH_V6_L3	 8	/*calculate hash of ipv6 header only */
+#define RTE_THASH_V6_L4	 9	/*calculate hash of ipv6 + transport headers */
+
+/**
+ * IPv4 tuple
+ * addreses and ports/sctp_tag have to be CPU byte order
+ */
+struct rte_ipv4_tuple {
+	uint32_t	src_addr;
+	uint32_t	dst_addr;
+	union {
+		struct {
+			uint16_t dport;
+			uint16_t sport;
+		};
+		uint32_t        sctp_tag;
+	};
+};
+
+/**
+ * IPv6 tuple
+ * Addresses have to be filled by rte_thash_load_v6_addr()
+ * ports/sctp_tag have to be CPU byte order
+ */
+struct rte_ipv6_tuple {
+	uint8_t		src_addr[16];
+	uint8_t		dst_addr[16];
+	union {
+		struct {
+			uint16_t dport;
+			uint16_t sport;
+		};
+		uint32_t        sctp_tag;
+	};
+};
+
+union rte_thash_tuple {
+	struct rte_ipv4_tuple	v4;
+	struct rte_ipv6_tuple	v6;
+} __aligned(size);
+
+/**
+ * Prepare special converted key to use with rte_softrss_be()
+ * @param orig
+ *   pointer to original RSS key
+ * @param targ
+ *   pointer to target RSS key
+ * @param len
+ *   RSS key length
+ */
+static inline void
+rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
+{
+	int i;
+
+	for (i = 0; i < (len >> 2); i++)
+		targ[i] = rte_be_to_cpu_32(orig[i]);
+}
+
+/**
+ * Prepare and load IPv6 address
+ * @param orig
+ *   Pointer to ipv6 header of the original packet
+ * @param targ
+ *   Pointer to rte_ipv6_tuple structure
+ */
+static inline void
+rte_thash_load_v6_addr(const struct ipv6_hdr *orig, union rte_thash_tuple *targ)
+{
+	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
+	*(__m128i *)targ->v6.src_addr =
+			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
+	ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
+	*(__m128i *)targ->v6.dst_addr =
+			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
+}
+
+/**
+ * Generic implementation. Can be used with original rss_key
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss(uint32_t *input_tuple, uint32_t input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (input_tuple[j] & (1 << (31 - i))) {
+				ret ^= rte_cpu_to_be_32(((const uint32_t *)rss_key)[j]) << i |
+					(uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t *)rss_key)[j + 1])) >>
+					(32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+/**
+ * Optimized implementation.
+ * If you want the calculated hash value matches NIC RSS value
+ * you have to use special converted key with rte_convert_rss_key() fn.
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param *rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (input_tuple[j] & (1 << (31 - i))) {
+				ret ^= ((const uint32_t *)rss_key)[j] << i |
+					(uint32_t)((uint64_t)(((const uint32_t *)rss_key)[j + 1]) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_THASH_H */
-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [dpdk-dev] [PATCH v3] Add unit test for thash library
  2015-06-19 14:55     ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
  2015-06-19 15:59       ` Richardson, Bruce
  2015-06-19 17:31       ` [dpdk-dev] [PATCH v5] " Vladimir Medvedkin
@ 2015-06-19 17:32       ` Vladimir Medvedkin
  2015-06-29 12:42         ` Bruce Richardson
  2015-06-30 23:41         ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
  2 siblings, 2 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-06-19 17:32 UTC (permalink / raw)
  To: dev

Add unit test for thash library

v3 changes
- Fix checkpatch errors

v2 changes
- fix typo
- remove unnecessary comments

Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
---
 app/test/Makefile         |   2 +
 app/test/autotest_data.py |  13 ++++
 app/test/test_thash.c     | 176 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 191 insertions(+)
 create mode 100644 app/test/test_thash.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 2e2758c..22e0052 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -86,6 +86,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_perf.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_functions.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_scaling.c
 
+SRCS-y += test_thash.c
+
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm.c
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6.c
 
diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py
index 0c3802b..7653f09 100644
--- a/app/test/autotest_data.py
+++ b/app/test/autotest_data.py
@@ -475,6 +475,19 @@ non_parallel_test_group_list = [
 		},
 	]
 },
+{
+	"Prefix" :	"thash",
+	"Memory" :	"32",
+	"Tests" :
+	[
+		{
+                 "Name" :       "Thash autotest",
+                 "Command" :    "thash_autotest",
+                 "Func" :       default_autotest,
+                 "Report" :     None,
+                },
+	]
+},
 
 #
 # Please always make sure that ring_perf is the last test!
diff --git a/app/test/test_thash.c b/app/test/test_thash.c
new file mode 100644
index 0000000..2a9eb28
--- /dev/null
+++ b/app/test/test_thash.c
@@ -0,0 +1,176 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com>
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_common.h>
+#include <rte_eal.h>
+#include <rte_ip.h>
+
+#include "test.h"
+
+#include <rte_thash.h>
+
+struct test_thash_v4 {
+	uint32_t	dst_ip;
+	uint32_t	src_ip;
+	uint16_t	dst_port;
+	uint16_t	src_port;
+	uint32_t	hash_l3;
+	uint32_t	hash_l3l4;
+};
+
+struct test_thash_v6 {
+	uint8_t		dst_ip[16];
+	uint8_t		src_ip[16];
+	uint16_t	dst_port;
+	uint16_t	src_port;
+	uint32_t	hash_l3;
+	uint32_t	hash_l3l4;
+};
+
+/*From 82599 Datasheet 7.1.2.8.3 RSS Verification Suite*/
+struct test_thash_v4 v4_tbl[] = {
+{IPv4(161, 142, 100, 80), IPv4(66, 9, 149, 187),
+	1766, 2794, 0x323e8fc2, 0x51ccc178},
+{IPv4(65, 69, 140, 83), IPv4(199, 92, 111, 2),
+	4739, 14230, 0xd718262a, 0xc626b0ea},
+{IPv4(12, 22, 207, 184), IPv4(24, 19, 198, 95),
+	38024, 12898, 0xd2d0a5de, 0x5c2b394a},
+{IPv4(209, 142, 163, 6), IPv4(38, 27, 205, 30),
+	2217, 48228, 0x82989176, 0xafc7327f},
+{IPv4(202, 188, 127, 2), IPv4(153, 39, 163, 191),
+	1303, 44251, 0x5d1809c5, 0x10e828a2},
+};
+
+struct test_thash_v6 v6_tbl[] = {
+/*3ffe:2501:200:3::1*/
+{{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x00, 0x03,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
+/*3ffe:2501:200:1fff::7*/
+{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x1f, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,},
+1766, 2794, 0x2cc18cd5, 0x40207d3d},
+/*ff02::1*/
+{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
+/*3ffe:501:8::260:97ff:fe40:efab*/
+{0x3f, 0xfe, 0x05, 0x01, 0x00, 0x08, 0x00, 0x00,
+0x02, 0x60, 0x97, 0xff, 0xfe, 0x40, 0xef, 0xab,},
+4739, 14230, 0x0f0c461c, 0xdde51bbf},
+/*fe80::200:f8ff:fe21:67cf*/
+{{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
+/*3ffe:1900:4545:3:200:f8ff:fe21:67cf*/
+{0x3f, 0xfe, 0x19, 0x00, 0x45, 0x45, 0x00, 0x03,
+0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
+38024, 44251, 0x4b61e985, 0x02d1feef},
+};
+
+uint8_t default_rss_key[] = {
+0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
+0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
+0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
+0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
+};
+
+static int
+test_thash(void)
+{
+	uint32_t i, j;
+	union rte_thash_tuple tuple;
+	uint32_t rss_l3, rss_l3l4;
+	uint8_t rss_key_be[RTE_DIM(default_rss_key)];
+	struct ipv6_hdr ipv6_hdr;
+
+	/* Convert RSS key*/
+	rte_convert_rss_key((uint32_t *)&default_rss_key,
+		(uint32_t *)rss_key_be, RTE_DIM(default_rss_key));
+
+
+	for (i = 0; i < RTE_DIM(v4_tbl); i++) {
+		tuple.v4.src_addr = v4_tbl[i].src_ip;
+		tuple.v4.dst_addr = v4_tbl[i].dst_ip;
+		tuple.v4.sport = v4_tbl[i].src_port;
+		tuple.v4.dport = v4_tbl[i].dst_port;
+		/*Calculate hash with original key*/
+		rss_l3 = rte_softrss((uint32_t *)&tuple,
+				RTE_THASH_V4_L3, default_rss_key);
+		rss_l3l4 = rte_softrss((uint32_t *)&tuple,
+				RTE_THASH_V4_L4, default_rss_key);
+		if ((rss_l3 != v4_tbl[i].hash_l3) ||
+				(rss_l3l4 != v4_tbl[i].hash_l3l4))
+			return -1;
+		/*Calculate hash with converted key*/
+		rss_l3 = rte_softrss_be((uint32_t *)&tuple,
+				RTE_THASH_V4_L3, rss_key_be);
+		rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
+				RTE_THASH_V4_L4, rss_key_be);
+		if ((rss_l3 != v4_tbl[i].hash_l3) ||
+				(rss_l3l4 != v4_tbl[i].hash_l3l4))
+			return -1;
+	}
+	for (i = 0; i < RTE_DIM(v6_tbl); i++) {
+		/*Fill ipv6 hdr*/
+		for (j = 0; j < RTE_DIM(ipv6_hdr.src_addr); j++)
+			ipv6_hdr.src_addr[j] = v6_tbl[i].src_ip[j];
+		for (j = 0; j < RTE_DIM(ipv6_hdr.dst_addr); j++)
+			ipv6_hdr.dst_addr[j] = v6_tbl[i].dst_ip[j];
+		/*Load and convert ipv6 address into tuple*/
+		rte_thash_load_v6_addr(&ipv6_hdr, &tuple);
+		tuple.v6.sport = v6_tbl[i].src_port;
+		tuple.v6.dport = v6_tbl[i].dst_port;
+		/*Calculate hash with original key*/
+		rss_l3 = rte_softrss((uint32_t *)&tuple,
+				RTE_THASH_V6_L3, default_rss_key);
+		rss_l3l4 = rte_softrss((uint32_t *)&tuple,
+				RTE_THASH_V6_L4, default_rss_key);
+		if ((rss_l3 != v6_tbl[i].hash_l3) ||
+				(rss_l3l4 != v6_tbl[i].hash_l3l4))
+			return -1;
+		/*Calculate hash with converted key*/
+		rss_l3 = rte_softrss_be((uint32_t *)&tuple,
+				RTE_THASH_V6_L3, rss_key_be);
+		rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
+				RTE_THASH_V6_L4, rss_key_be);
+		if ((rss_l3 != v6_tbl[i].hash_l3) ||
+				(rss_l3l4 != v6_tbl[i].hash_l3l4))
+			return -1;
+	}
+	return 0;
+}
+
+static struct test_command thash_cmd = {
+	.command = "thash_autotest",
+	.callback = test_thash,
+};
+REGISTER_TEST_COMMAND(thash_cmd);
-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v4] Add toeplitz hash algorithm used by RSS
  2015-06-19 16:14         ` Vladimir Medvedkin
@ 2015-06-29 12:18           ` Bruce Richardson
  0 siblings, 0 replies; 37+ messages in thread
From: Bruce Richardson @ 2015-06-29 12:18 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

On Fri, Jun 19, 2015 at 07:14:15PM +0300, Vladimir Medvedkin wrote:
> Hi Bruce,
> 
> 2015-06-19 18:59 GMT+03:00 Richardson, Bruce <bruce.richardson@intel.com>:
> 
> >
> >
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Vladimir Medvedkin
> > > Sent: Friday, June 19, 2015 3:56 PM
> > > To: dev@dpdk.org
> > > Subject: [dpdk-dev] [PATCH v4] Add toeplitz hash algorithm used by RSS
> > >
> > > v4 changes
> > > - Fix copyright
> > > - rename bswap_mask constant, add rte_ prefix
> > > - change rte_ipv[46]_tuple struct
> > > - change rte_thash_load_v6_addr prototype
> > >
> > > v3 changes
> > > - Rework API to be more generic
> > > - Add sctp_tag into tuple
> > >
> > > v2 changes
> > > - Add ipv6 support
> > > - Various style fixes
> > >
> >
> > Missing signoff line.
> >
> > > ---
> > >  lib/librte_hash/Makefile    |   1 +
> > >  lib/librte_hash/rte_thash.h | 202
> > > ++++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 203 insertions(+)
> > >  create mode 100644 lib/librte_hash/rte_thash.h
> > >
> > <...snip...>
> > > +
> > > +/* Byte swap mask used for converting IPv6 address 4-byte chunks to CPU
> > > byte order */
> > > +static const __m128i rte_thash_ipv6_bswap_mask = {0x0405060700010203,
> > > 0x0C0D0E0F08090A0B};
> > > +
> > > +#define RTE_THASH_V4_L3       2      /*calculate hash of ipv4 header
> > only*/
> > > +#define RTE_THASH_V4_L4       3      /*calculate hash of ipv4 +
> > transport
> > > headers*/
> > > +#define RTE_THASH_V6_L3       8      /*calculate hash of ipv6 header
> > only
> > > */
> > > +#define RTE_THASH_V6_L4       9      /*calculate hash of ipv6 +
> > transport
> > > headers */
> >
> > I'm still not seeing why these values need to be defined here, rather than
> > in a specific app.
> > Also, the choice of values for these defines seems strange to me? How were
> > they chosen?
> >
> This is a predefined values. They mean the length (in 4-bytes) of the
> input data
> in hashing. I think it's like defines in rte_ip.h, for example.
> 

I'm still not convined of the need for them in this file. If they are to be
kept though, they should instead have "LEN" in the name to indicate that they
are the lengths of the different keys. You could also make this clearer by
changing the L4 values to be computed using "sizeof()" given that the appropriate
tuple structures are present later in the header file to allow the sizes to be
correctly calculated.

/Bruce

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v5] Add toeplitz hash algorithm used by RSS
  2015-06-19 17:31       ` [dpdk-dev] [PATCH v5] " Vladimir Medvedkin
@ 2015-06-29 12:40         ` Bruce Richardson
  2015-06-30 12:14           ` Vladimir Medvedkin
  2015-06-30 23:40         ` [dpdk-dev] [PATCH v6] " Vladimir Medvedkin
  1 sibling, 1 reply; 37+ messages in thread
From: Bruce Richardson @ 2015-06-29 12:40 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

On Fri, Jun 19, 2015 at 01:31:13PM -0400, Vladimir Medvedkin wrote:
> Software implementation of the Toeplitz hash function used by RSS.
> Can be used either for packet distribution on single queue NIC
> or for simulating of RSS computation on specific NIC (for example
> after GRE header decapsulating).
> 
> v5 changes
> - Fix errors reported by checkpatch.pl
> 
> v4 changes
> - Fix copyright
> - rename bswap_mask constant, add rte_ prefix
> - change rte_ipv[46]_tuple struct
> - change rte_thash_load_v6_addr prototype
> 
> v3 changes
> - Rework API to be more generic
> - Add sctp_tag into tuple
> 
> v2 changes
> - Add ipv6 support
> - Various style fixes
> 
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> ---
>  lib/librte_hash/Makefile    |   1 +
>  lib/librte_hash/rte_thash.h | 207 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 208 insertions(+)
>  create mode 100644 lib/librte_hash/rte_thash.h
>
<snip>
> +static const __m128i rte_thash_ipv6_bswap_mask = {
> +		0x0405060700010203, 0x0C0D0E0F08090A0B};
> +
> +#define RTE_THASH_V4_L3	 2	/*calculate hash of ipv4 header only*/
> +#define RTE_THASH_V4_L4	 3	/*calculate hash of ipv4 + transport headers*/
> +#define RTE_THASH_V6_L3	 8	/*calculate hash of ipv6 header only */
> +#define RTE_THASH_V6_L4	 9	/*calculate hash of ipv6 + transport headers */
> +

Comment as on V4 patch - add LEN to name to make it clear they are lengths
in quadwords.

> +/**
> + * IPv4 tuple
> + * addreses and ports/sctp_tag have to be CPU byte order
> + */
> +struct rte_ipv4_tuple {
> +	uint32_t	src_addr;
> +	uint32_t	dst_addr;
> +	union {
> +		struct {
> +			uint16_t dport;
> +			uint16_t sport;
> +		};
> +		uint32_t        sctp_tag;
> +	};
> +};
> +
> +/**
> + * IPv6 tuple
> + * Addresses have to be filled by rte_thash_load_v6_addr()
> + * ports/sctp_tag have to be CPU byte order
> + */
> +struct rte_ipv6_tuple {
> +	uint8_t		src_addr[16];
> +	uint8_t		dst_addr[16];
> +	union {
> +		struct {
> +			uint16_t dport;
> +			uint16_t sport;
> +		};
> +		uint32_t        sctp_tag;
> +	};
> +};
> +
> +union rte_thash_tuple {
> +	struct rte_ipv4_tuple	v4;
> +	struct rte_ipv6_tuple	v6;
> +} __aligned(size);
> +
This throws an error on compilation [with unit test patch also applied].

In file included from /home/bruce/dpdk.org/app/test/test_thash.c:40:0:
/home/bruce/dpdk.org/x86_64-native-linuxapp-gcc/include/rte_thash.h:106:1: error: parameter names (without types) in function declaration [-Werror]
 } __aligned(size);
  ^

> +/**
> + * Prepare special converted key to use with rte_softrss_be()
> + * @param orig
> + *   pointer to original RSS key
> + * @param targ
> + *   pointer to target RSS key
> + * @param len
> + *   RSS key length
> + */
> +static inline void
> +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
> +{
> +	int i;
> +
> +	for (i = 0; i < (len >> 2); i++)
> +		targ[i] = rte_be_to_cpu_32(orig[i]);
> +}
> +
> +/**
> + * Prepare and load IPv6 address
> + * @param orig
> + *   Pointer to ipv6 header of the original packet
> + * @param targ
> + *   Pointer to rte_ipv6_tuple structure
> + */
> +static inline void
> +rte_thash_load_v6_addr(const struct ipv6_hdr *orig, union rte_thash_tuple *targ)
> +{
> +	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
> +	*(__m128i *)targ->v6.src_addr =
> +			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
> +	ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
> +	*(__m128i *)targ->v6.dst_addr =
> +			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
> +}

I think the function name needs to be pluralized, and the comment updated to make
it clear that it is not just one IPv6 address that is loaded, but rather both
source and destination.

Regards,
/Bruce

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v3] Add unit test for thash library
  2015-06-19 17:32       ` [dpdk-dev] [PATCH v3] Add unit test for thash library Vladimir Medvedkin
@ 2015-06-29 12:42         ` Bruce Richardson
  2015-06-30 23:41         ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
  1 sibling, 0 replies; 37+ messages in thread
From: Bruce Richardson @ 2015-06-29 12:42 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

On Fri, Jun 19, 2015 at 01:32:05PM -0400, Vladimir Medvedkin wrote:
> Add unit test for thash library
> 
> v3 changes
> - Fix checkpatch errors
> 
> v2 changes
> - fix typo
> - remove unnecessary comments
> 
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>

Patch obviously depends on the thash patch which is sent out separately. However,
this patch is itself fine.

Acked-by: Bruce Richardson <bruce.richardson@intel.com>

> ---
>  app/test/Makefile         |   2 +
>  app/test/autotest_data.py |  13 ++++
>  app/test/test_thash.c     | 176 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 191 insertions(+)
>  create mode 100644 app/test/test_thash.c
> 
> diff --git a/app/test/Makefile b/app/test/Makefile
> index 2e2758c..22e0052 100644
> --- a/app/test/Makefile
> +++ b/app/test/Makefile
> @@ -86,6 +86,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_perf.c
>  SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_functions.c
>  SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_scaling.c
>  
> +SRCS-y += test_thash.c
> +
>  SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm.c
>  SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6.c
>  
> diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py
> index 0c3802b..7653f09 100644
> --- a/app/test/autotest_data.py
> +++ b/app/test/autotest_data.py
> @@ -475,6 +475,19 @@ non_parallel_test_group_list = [
>  		},
>  	]
>  },
> +{
> +	"Prefix" :	"thash",
> +	"Memory" :	"32",
> +	"Tests" :
> +	[
> +		{
> +                 "Name" :       "Thash autotest",
> +                 "Command" :    "thash_autotest",
> +                 "Func" :       default_autotest,
> +                 "Report" :     None,
> +                },
> +	]
> +},
>  
>  #
>  # Please always make sure that ring_perf is the last test!
> diff --git a/app/test/test_thash.c b/app/test/test_thash.c
> new file mode 100644
> index 0000000..2a9eb28
> --- /dev/null
> +++ b/app/test/test_thash.c
> @@ -0,0 +1,176 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com>
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <rte_common.h>
> +#include <rte_eal.h>
> +#include <rte_ip.h>
> +
> +#include "test.h"
> +
> +#include <rte_thash.h>
> +
> +struct test_thash_v4 {
> +	uint32_t	dst_ip;
> +	uint32_t	src_ip;
> +	uint16_t	dst_port;
> +	uint16_t	src_port;
> +	uint32_t	hash_l3;
> +	uint32_t	hash_l3l4;
> +};
> +
> +struct test_thash_v6 {
> +	uint8_t		dst_ip[16];
> +	uint8_t		src_ip[16];
> +	uint16_t	dst_port;
> +	uint16_t	src_port;
> +	uint32_t	hash_l3;
> +	uint32_t	hash_l3l4;
> +};
> +
> +/*From 82599 Datasheet 7.1.2.8.3 RSS Verification Suite*/
> +struct test_thash_v4 v4_tbl[] = {
> +{IPv4(161, 142, 100, 80), IPv4(66, 9, 149, 187),
> +	1766, 2794, 0x323e8fc2, 0x51ccc178},
> +{IPv4(65, 69, 140, 83), IPv4(199, 92, 111, 2),
> +	4739, 14230, 0xd718262a, 0xc626b0ea},
> +{IPv4(12, 22, 207, 184), IPv4(24, 19, 198, 95),
> +	38024, 12898, 0xd2d0a5de, 0x5c2b394a},
> +{IPv4(209, 142, 163, 6), IPv4(38, 27, 205, 30),
> +	2217, 48228, 0x82989176, 0xafc7327f},
> +{IPv4(202, 188, 127, 2), IPv4(153, 39, 163, 191),
> +	1303, 44251, 0x5d1809c5, 0x10e828a2},
> +};
> +
> +struct test_thash_v6 v6_tbl[] = {
> +/*3ffe:2501:200:3::1*/
> +{{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x00, 0x03,
> +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
> +/*3ffe:2501:200:1fff::7*/
> +{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x1f, 0xff,
> +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,},
> +1766, 2794, 0x2cc18cd5, 0x40207d3d},
> +/*ff02::1*/
> +{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
> +/*3ffe:501:8::260:97ff:fe40:efab*/
> +{0x3f, 0xfe, 0x05, 0x01, 0x00, 0x08, 0x00, 0x00,
> +0x02, 0x60, 0x97, 0xff, 0xfe, 0x40, 0xef, 0xab,},
> +4739, 14230, 0x0f0c461c, 0xdde51bbf},
> +/*fe80::200:f8ff:fe21:67cf*/
> +{{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
> +/*3ffe:1900:4545:3:200:f8ff:fe21:67cf*/
> +{0x3f, 0xfe, 0x19, 0x00, 0x45, 0x45, 0x00, 0x03,
> +0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
> +38024, 44251, 0x4b61e985, 0x02d1feef},
> +};
> +
> +uint8_t default_rss_key[] = {
> +0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
> +0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
> +0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
> +0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
> +0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
> +};
> +
> +static int
> +test_thash(void)
> +{
> +	uint32_t i, j;
> +	union rte_thash_tuple tuple;
> +	uint32_t rss_l3, rss_l3l4;
> +	uint8_t rss_key_be[RTE_DIM(default_rss_key)];
> +	struct ipv6_hdr ipv6_hdr;
> +
> +	/* Convert RSS key*/
> +	rte_convert_rss_key((uint32_t *)&default_rss_key,
> +		(uint32_t *)rss_key_be, RTE_DIM(default_rss_key));
> +
> +
> +	for (i = 0; i < RTE_DIM(v4_tbl); i++) {
> +		tuple.v4.src_addr = v4_tbl[i].src_ip;
> +		tuple.v4.dst_addr = v4_tbl[i].dst_ip;
> +		tuple.v4.sport = v4_tbl[i].src_port;
> +		tuple.v4.dport = v4_tbl[i].dst_port;
> +		/*Calculate hash with original key*/
> +		rss_l3 = rte_softrss((uint32_t *)&tuple,
> +				RTE_THASH_V4_L3, default_rss_key);
> +		rss_l3l4 = rte_softrss((uint32_t *)&tuple,
> +				RTE_THASH_V4_L4, default_rss_key);
> +		if ((rss_l3 != v4_tbl[i].hash_l3) ||
> +				(rss_l3l4 != v4_tbl[i].hash_l3l4))
> +			return -1;
> +		/*Calculate hash with converted key*/
> +		rss_l3 = rte_softrss_be((uint32_t *)&tuple,
> +				RTE_THASH_V4_L3, rss_key_be);
> +		rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
> +				RTE_THASH_V4_L4, rss_key_be);
> +		if ((rss_l3 != v4_tbl[i].hash_l3) ||
> +				(rss_l3l4 != v4_tbl[i].hash_l3l4))
> +			return -1;
> +	}
> +	for (i = 0; i < RTE_DIM(v6_tbl); i++) {
> +		/*Fill ipv6 hdr*/
> +		for (j = 0; j < RTE_DIM(ipv6_hdr.src_addr); j++)
> +			ipv6_hdr.src_addr[j] = v6_tbl[i].src_ip[j];
> +		for (j = 0; j < RTE_DIM(ipv6_hdr.dst_addr); j++)
> +			ipv6_hdr.dst_addr[j] = v6_tbl[i].dst_ip[j];
> +		/*Load and convert ipv6 address into tuple*/
> +		rte_thash_load_v6_addr(&ipv6_hdr, &tuple);
> +		tuple.v6.sport = v6_tbl[i].src_port;
> +		tuple.v6.dport = v6_tbl[i].dst_port;
> +		/*Calculate hash with original key*/
> +		rss_l3 = rte_softrss((uint32_t *)&tuple,
> +				RTE_THASH_V6_L3, default_rss_key);
> +		rss_l3l4 = rte_softrss((uint32_t *)&tuple,
> +				RTE_THASH_V6_L4, default_rss_key);
> +		if ((rss_l3 != v6_tbl[i].hash_l3) ||
> +				(rss_l3l4 != v6_tbl[i].hash_l3l4))
> +			return -1;
> +		/*Calculate hash with converted key*/
> +		rss_l3 = rte_softrss_be((uint32_t *)&tuple,
> +				RTE_THASH_V6_L3, rss_key_be);
> +		rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
> +				RTE_THASH_V6_L4, rss_key_be);
> +		if ((rss_l3 != v6_tbl[i].hash_l3) ||
> +				(rss_l3l4 != v6_tbl[i].hash_l3l4))
> +			return -1;
> +	}
> +	return 0;
> +}
> +
> +static struct test_command thash_cmd = {
> +	.command = "thash_autotest",
> +	.callback = test_thash,
> +};
> +REGISTER_TEST_COMMAND(thash_cmd);
> -- 
> 1.8.3.2
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v5] Add toeplitz hash algorithm used by RSS
  2015-06-29 12:40         ` Bruce Richardson
@ 2015-06-30 12:14           ` Vladimir Medvedkin
  2015-06-30 12:48             ` Bruce Richardson
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-06-30 12:14 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev

Hi Bruce,

2015-06-29 15:40 GMT+03:00 Bruce Richardson <bruce.richardson@intel.com>:

> On Fri, Jun 19, 2015 at 01:31:13PM -0400, Vladimir Medvedkin wrote:
> > Software implementation of the Toeplitz hash function used by RSS.
> > Can be used either for packet distribution on single queue NIC
> > or for simulating of RSS computation on specific NIC (for example
> > after GRE header decapsulating).
> >
> > v5 changes
> > - Fix errors reported by checkpatch.pl
> >
> > v4 changes
> > - Fix copyright
> > - rename bswap_mask constant, add rte_ prefix
> > - change rte_ipv[46]_tuple struct
> > - change rte_thash_load_v6_addr prototype
> >
> > v3 changes
> > - Rework API to be more generic
> > - Add sctp_tag into tuple
> >
> > v2 changes
> > - Add ipv6 support
> > - Various style fixes
> >
> > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> > ---
> >  lib/librte_hash/Makefile    |   1 +
> >  lib/librte_hash/rte_thash.h | 207
> ++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 208 insertions(+)
> >  create mode 100644 lib/librte_hash/rte_thash.h
> >
> <snip>
> > +static const __m128i rte_thash_ipv6_bswap_mask = {
> > +             0x0405060700010203, 0x0C0D0E0F08090A0B};
> > +
> > +#define RTE_THASH_V4_L3       2      /*calculate hash of ipv4 header
> only*/
> > +#define RTE_THASH_V4_L4       3      /*calculate hash of ipv4 +
> transport headers*/
> > +#define RTE_THASH_V6_L3       8      /*calculate hash of ipv6 header
> only */
> > +#define RTE_THASH_V6_L4       9      /*calculate hash of ipv6 +
> transport headers */
> > +
>
> Comment as on V4 patch - add LEN to name to make it clear they are lengths
> in quadwords.
>
Agree, but length dwords

>
> > +/**
> > + * IPv4 tuple
> > + * addreses and ports/sctp_tag have to be CPU byte order
> > + */
> > +struct rte_ipv4_tuple {
> > +     uint32_t        src_addr;
> > +     uint32_t        dst_addr;
> > +     union {
> > +             struct {
> > +                     uint16_t dport;
> > +                     uint16_t sport;
> > +             };
> > +             uint32_t        sctp_tag;
> > +     };
> > +};
> > +
> > +/**
> > + * IPv6 tuple
> > + * Addresses have to be filled by rte_thash_load_v6_addr()
> > + * ports/sctp_tag have to be CPU byte order
> > + */
> > +struct rte_ipv6_tuple {
> > +     uint8_t         src_addr[16];
> > +     uint8_t         dst_addr[16];
> > +     union {
> > +             struct {
> > +                     uint16_t dport;
> > +                     uint16_t sport;
> > +             };
> > +             uint32_t        sctp_tag;
> > +     };
> > +};
> > +
> > +union rte_thash_tuple {
> > +     struct rte_ipv4_tuple   v4;
> > +     struct rte_ipv6_tuple   v6;
> > +} __aligned(size);
> > +
> This throws an error on compilation [with unit test patch also applied].
>
I will never copy paste
I will never copy paste
I will never... =)

>
> In file included from /home/bruce/dpdk.org/app/test/test_thash.c:40:0:
> /home/bruce/dpdk.org/x86_64-native-linuxapp-gcc/include/rte_thash.h:106:1:
> error: parameter names (without types) in function declaration [-Werror]
>  } __aligned(size);
>   ^
>
> +/**
> > + * Prepare special converted key to use with rte_softrss_be()
> > + * @param orig
> > + *   pointer to original RSS key
> > + * @param targ
> > + *   pointer to target RSS key
> > + * @param len
> > + *   RSS key length
> > + */
> > +static inline void
> > +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
> > +{
> > +     int i;
> > +
> > +     for (i = 0; i < (len >> 2); i++)
> > +             targ[i] = rte_be_to_cpu_32(orig[i]);
> > +}
> > +
> > +/**
> > + * Prepare and load IPv6 address
> > + * @param orig
> > + *   Pointer to ipv6 header of the original packet
> > + * @param targ
> > + *   Pointer to rte_ipv6_tuple structure
> > + */
> > +static inline void
> > +rte_thash_load_v6_addr(const struct ipv6_hdr *orig, union
> rte_thash_tuple *targ)
> > +{
> > +     __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
> > +     *(__m128i *)targ->v6.src_addr =
> > +                     _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
> > +     ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
> > +     *(__m128i *)targ->v6.dst_addr =
> > +                     _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
> > +}
>
> I think the function name needs to be pluralized, and the comment updated
> to make
> it clear that it is not just one IPv6 address that is loaded, but rather
> both
> source and destination.
>
I think no need to make too long function name like
rte_thash_load_v6_addresses(), instead I'll make comment more clear.
Is it enough?

>
> Regards,
> /Bruce
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v5] Add toeplitz hash algorithm used by RSS
  2015-06-30 12:14           ` Vladimir Medvedkin
@ 2015-06-30 12:48             ` Bruce Richardson
  0 siblings, 0 replies; 37+ messages in thread
From: Bruce Richardson @ 2015-06-30 12:48 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

On Tue, Jun 30, 2015 at 03:14:55PM +0300, Vladimir Medvedkin wrote:
> Hi Bruce,
> 
> 2015-06-29 15:40 GMT+03:00 Bruce Richardson <bruce.richardson@intel.com>:
> 
> > On Fri, Jun 19, 2015 at 01:31:13PM -0400, Vladimir Medvedkin wrote:
> > > Software implementation of the Toeplitz hash function used by RSS.
> > > Can be used either for packet distribution on single queue NIC
> > > or for simulating of RSS computation on specific NIC (for example
> > > after GRE header decapsulating).
> > >
> > > v5 changes
> > > - Fix errors reported by checkpatch.pl
> > >
> > > v4 changes
> > > - Fix copyright
> > > - rename bswap_mask constant, add rte_ prefix
> > > - change rte_ipv[46]_tuple struct
> > > - change rte_thash_load_v6_addr prototype
> > >
> > > v3 changes
> > > - Rework API to be more generic
> > > - Add sctp_tag into tuple
> > >
> > > v2 changes
> > > - Add ipv6 support
> > > - Various style fixes
> > >
> > > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> > > ---
> > >  lib/librte_hash/Makefile    |   1 +
> > >  lib/librte_hash/rte_thash.h | 207
> > ++++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 208 insertions(+)
> > >  create mode 100644 lib/librte_hash/rte_thash.h
> > >
> > <snip>
> > > +static const __m128i rte_thash_ipv6_bswap_mask = {
> > > +             0x0405060700010203, 0x0C0D0E0F08090A0B};
> > > +
> > > +#define RTE_THASH_V4_L3       2      /*calculate hash of ipv4 header
> > only*/
> > > +#define RTE_THASH_V4_L4       3      /*calculate hash of ipv4 +
> > transport headers*/
> > > +#define RTE_THASH_V6_L3       8      /*calculate hash of ipv6 header
> > only */
> > > +#define RTE_THASH_V6_L4       9      /*calculate hash of ipv6 +
> > transport headers */
> > > +
> >
> > Comment as on V4 patch - add LEN to name to make it clear they are lengths
> > in quadwords.
> >
> Agree, but length dwords
> 
Yes, my mistake.

> >
> > > +/**
> > > + * IPv4 tuple
> > > + * addreses and ports/sctp_tag have to be CPU byte order
> > > + */
> > > +struct rte_ipv4_tuple {
> > > +     uint32_t        src_addr;
> > > +     uint32_t        dst_addr;
> > > +     union {
> > > +             struct {
> > > +                     uint16_t dport;
> > > +                     uint16_t sport;
> > > +             };
> > > +             uint32_t        sctp_tag;
> > > +     };
> > > +};
> > > +
> > > +/**
> > > + * IPv6 tuple
> > > + * Addresses have to be filled by rte_thash_load_v6_addr()
> > > + * ports/sctp_tag have to be CPU byte order
> > > + */
> > > +struct rte_ipv6_tuple {
> > > +     uint8_t         src_addr[16];
> > > +     uint8_t         dst_addr[16];
> > > +     union {
> > > +             struct {
> > > +                     uint16_t dport;
> > > +                     uint16_t sport;
> > > +             };
> > > +             uint32_t        sctp_tag;
> > > +     };
> > > +};
> > > +
> > > +union rte_thash_tuple {
> > > +     struct rte_ipv4_tuple   v4;
> > > +     struct rte_ipv6_tuple   v6;
> > > +} __aligned(size);
> > > +
> > This throws an error on compilation [with unit test patch also applied].
> >
> I will never copy paste
> I will never copy paste
> I will never... =)
> 
> >
> > In file included from /home/bruce/dpdk.org/app/test/test_thash.c:40:0:
> > /home/bruce/dpdk.org/x86_64-native-linuxapp-gcc/include/rte_thash.h:106:1:
> > error: parameter names (without types) in function declaration [-Werror]
> >  } __aligned(size);
> >   ^
> >
> > +/**
> > > + * Prepare special converted key to use with rte_softrss_be()
> > > + * @param orig
> > > + *   pointer to original RSS key
> > > + * @param targ
> > > + *   pointer to target RSS key
> > > + * @param len
> > > + *   RSS key length
> > > + */
> > > +static inline void
> > > +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
> > > +{
> > > +     int i;
> > > +
> > > +     for (i = 0; i < (len >> 2); i++)
> > > +             targ[i] = rte_be_to_cpu_32(orig[i]);
> > > +}
> > > +
> > > +/**
> > > + * Prepare and load IPv6 address
> > > + * @param orig
> > > + *   Pointer to ipv6 header of the original packet
> > > + * @param targ
> > > + *   Pointer to rte_ipv6_tuple structure
> > > + */
> > > +static inline void
> > > +rte_thash_load_v6_addr(const struct ipv6_hdr *orig, union
> > rte_thash_tuple *targ)
> > > +{
> > > +     __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
> > > +     *(__m128i *)targ->v6.src_addr =
> > > +                     _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
> > > +     ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
> > > +     *(__m128i *)targ->v6.dst_addr =
> > > +                     _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
> > > +}
> >
> > I think the function name needs to be pluralized, and the comment updated
> > to make
> > it clear that it is not just one IPv6 address that is loaded, but rather
> > both
> > source and destination.
> >
> I think no need to make too long function name like
> rte_thash_load_v6_addresses(), instead I'll make comment more clear.
> Is it enough?

I was actually thinking "addrs" rather than full "addresses" in the name. The extra
"s" should be enough to make it appear as plural. Please make the comment clear 
anyway.

/Bruce

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
  2015-06-19 17:31       ` [dpdk-dev] [PATCH v5] " Vladimir Medvedkin
  2015-06-29 12:40         ` Bruce Richardson
@ 2015-06-30 23:40         ` Vladimir Medvedkin
  2015-07-01 15:29           ` Bruce Richardson
  2015-07-22  7:55           ` Tony Lu
  1 sibling, 2 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-06-30 23:40 UTC (permalink / raw)
  To: dev

Software implementation of the Toeplitz hash function used by RSS.
Can be used either for packet distribution on single queue NIC
or for simulating of RSS computation on specific NIC (for example
after GRE header decapsulating).

v6 changes
- Fix compilation error
- Rename some defines and function

v5 changes
- Fix errors reported by checkpatch.pl

v4 changes
- Fix copyright
- rename bswap_mask constant, add rte_ prefix
- change rte_ipv[46]_tuple struct
- change rte_thash_load_v6_addr prototype

v3 changes
- Rework API to be more generic
- Add sctp_tag into tuple

v2 changes
- Add ipv6 support
- Various style fixes

Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
---
 lib/librte_hash/Makefile    |   1 +
 lib/librte_hash/rte_thash.h | 231 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 232 insertions(+)
 create mode 100644 lib/librte_hash/rte_thash.h

diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile
index 3696cb1..981230b 100644
--- a/lib/librte_hash/Makefile
+++ b/lib/librte_hash/Makefile
@@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
 
 # this lib needs eal
diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h
new file mode 100644
index 0000000..1808f47
--- /dev/null
+++ b/lib/librte_hash/rte_thash.h
@@ -0,0 +1,231 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com>
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_THASH_H
+#define _RTE_THASH_H
+
+/**
+ * @file
+ *
+ * toeplitz hash functions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Software implementation of the Toeplitz hash function used by RSS.
+ * Can be used either for packet distribution on single queue NIC
+ * or for simulating of RSS computation on specific NIC (for example
+ * after GRE header decapsulating)
+ */
+
+#include <stdint.h>
+#include <rte_byteorder.h>
+#include <rte_vect.h>
+#include <rte_ip.h>
+
+/* Byte swap mask used for converting IPv6 address
+ * 4-byte chunks to CPU byte order
+ */
+static const __m128i rte_thash_ipv6_bswap_mask = {
+		0x0405060700010203, 0x0C0D0E0F08090A0B};
+
+/**
+ * length in dwords of input tuple to
+ * calculate hash of ipv4 header only
+ */
+#define RTE_THASH_V4_L3_LEN	((sizeof(struct rte_ipv4_tuple) -	\
+			sizeof(((struct rte_ipv4_tuple *)0)->sctp_tag)) / 4)
+
+/**
+ * length in dwords of input tuple to
+ * calculate hash of ipv4 header +
+ * transport header
+ */
+#define RTE_THASH_V4_L4_LEN	 ((sizeof(struct rte_ipv4_tuple)) / 4)
+
+/**
+ * length in dwords of input tuple to
+ * calculate hash of ipv6 header only
+ */
+#define RTE_THASH_V6_L3_LEN	((sizeof(struct rte_ipv6_tuple) -       \
+			sizeof(((struct rte_ipv6_tuple *)0)->sctp_tag)) / 4)
+
+/**
+ * length in dwords of input tuple to
+ * calculate hash of ipv6 header +
+ * transport header
+ */
+#define RTE_THASH_V6_L4_LEN	((sizeof(struct rte_ipv6_tuple)) / 4)
+
+/**
+ * IPv4 tuple
+ * addreses and ports/sctp_tag have to be CPU byte order
+ */
+struct rte_ipv4_tuple {
+	uint32_t	src_addr;
+	uint32_t	dst_addr;
+	union {
+		struct {
+			uint16_t dport;
+			uint16_t sport;
+		};
+		uint32_t        sctp_tag;
+	};
+};
+
+/**
+ * IPv6 tuple
+ * Addresses have to be filled by rte_thash_load_v6_addr()
+ * ports/sctp_tag have to be CPU byte order
+ */
+struct rte_ipv6_tuple {
+	uint8_t		src_addr[16];
+	uint8_t		dst_addr[16];
+	union {
+		struct {
+			uint16_t dport;
+			uint16_t sport;
+		};
+		uint32_t        sctp_tag;
+	};
+};
+
+union rte_thash_tuple {
+	struct rte_ipv4_tuple	v4;
+	struct rte_ipv6_tuple	v6;
+} __attribute__((aligned(XMM_SIZE)));
+
+/**
+ * Prepare special converted key to use with rte_softrss_be()
+ * @param orig
+ *   pointer to original RSS key
+ * @param targ
+ *   pointer to target RSS key
+ * @param len
+ *   RSS key length
+ */
+static inline void
+rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len)
+{
+	int i;
+
+	for (i = 0; i < (len >> 2); i++)
+		targ[i] = rte_be_to_cpu_32(orig[i]);
+}
+
+/**
+ * Prepare and load IPv6 addresses (src and dst)
+ * into target tuple
+ * @param orig
+ *   Pointer to ipv6 header of the original packet
+ * @param targ
+ *   Pointer to rte_ipv6_tuple structure
+ */
+static inline void
+rte_thash_load_v6_addrs(const struct ipv6_hdr *orig, union rte_thash_tuple *targ)
+{
+	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
+	*(__m128i *)targ->v6.src_addr =
+			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
+	ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
+	*(__m128i *)targ->v6.dst_addr =
+			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
+}
+
+/**
+ * Generic implementation. Can be used with original rss_key
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss(uint32_t *input_tuple, uint32_t input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (input_tuple[j] & (1 << (31 - i))) {
+				ret ^= rte_cpu_to_be_32(((const uint32_t *)rss_key)[j]) << i |
+					(uint32_t)((uint64_t)(rte_cpu_to_be_32(((const uint32_t *)rss_key)[j + 1])) >>
+					(32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+/**
+ * Optimized implementation.
+ * If you want the calculated hash value matches NIC RSS value
+ * you have to use special converted key with rte_convert_rss_key() fn.
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param *rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
+		const uint8_t *rss_key)
+{
+	uint32_t i, j, ret = 0;
+
+	for (j = 0; j < input_len; j++) {
+		for (i = 0; i < 32; i++) {
+			if (input_tuple[j] & (1 << (31 - i))) {
+				ret ^= ((const uint32_t *)rss_key)[j] << i |
+					(uint32_t)((uint64_t)(((const uint32_t *)rss_key)[j + 1]) >> (32 - i));
+			}
+		}
+	}
+	return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_THASH_H */
-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [dpdk-dev] [PATCH v4] Add unit test for thash library
  2015-06-19 17:32       ` [dpdk-dev] [PATCH v3] Add unit test for thash library Vladimir Medvedkin
  2015-06-29 12:42         ` Bruce Richardson
@ 2015-06-30 23:41         ` Vladimir Medvedkin
  2015-07-01 15:30           ` Bruce Richardson
  1 sibling, 1 reply; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-06-30 23:41 UTC (permalink / raw)
  To: dev

Add unit test for thash library

v4 changes
- Reflect rte_thash.h changes

v3 changes
- Fix checkpatch errors

v2 changes
- fix typo
- remove unnecessary comments

Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
---
 app/test/Makefile     |   1 +
 app/test/test_thash.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 177 insertions(+)
 create mode 100644 app/test/test_thash.c

diff --git a/app/test/Makefile b/app/test/Makefile
index 2e2758c..caa359c 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -82,6 +82,7 @@ SRCS-y += test_memcpy.c
 SRCS-y += test_memcpy_perf.c
 
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash.c
+SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_thash.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_perf.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_functions.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_scaling.c
diff --git a/app/test/test_thash.c b/app/test/test_thash.c
new file mode 100644
index 0000000..8e9dca0
--- /dev/null
+++ b/app/test/test_thash.c
@@ -0,0 +1,176 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com>
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_common.h>
+#include <rte_eal.h>
+#include <rte_ip.h>
+
+#include "test.h"
+
+#include <rte_thash.h>
+
+struct test_thash_v4 {
+	uint32_t	dst_ip;
+	uint32_t	src_ip;
+	uint16_t	dst_port;
+	uint16_t	src_port;
+	uint32_t	hash_l3;
+	uint32_t	hash_l3l4;
+};
+
+struct test_thash_v6 {
+	uint8_t		dst_ip[16];
+	uint8_t		src_ip[16];
+	uint16_t	dst_port;
+	uint16_t	src_port;
+	uint32_t	hash_l3;
+	uint32_t	hash_l3l4;
+};
+
+/*From 82599 Datasheet 7.1.2.8.3 RSS Verification Suite*/
+struct test_thash_v4 v4_tbl[] = {
+{IPv4(161, 142, 100, 80), IPv4(66, 9, 149, 187),
+	1766, 2794, 0x323e8fc2, 0x51ccc178},
+{IPv4(65, 69, 140, 83), IPv4(199, 92, 111, 2),
+	4739, 14230, 0xd718262a, 0xc626b0ea},
+{IPv4(12, 22, 207, 184), IPv4(24, 19, 198, 95),
+	38024, 12898, 0xd2d0a5de, 0x5c2b394a},
+{IPv4(209, 142, 163, 6), IPv4(38, 27, 205, 30),
+	2217, 48228, 0x82989176, 0xafc7327f},
+{IPv4(202, 188, 127, 2), IPv4(153, 39, 163, 191),
+	1303, 44251, 0x5d1809c5, 0x10e828a2},
+};
+
+struct test_thash_v6 v6_tbl[] = {
+/*3ffe:2501:200:3::1*/
+{{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x00, 0x03,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
+/*3ffe:2501:200:1fff::7*/
+{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x1f, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,},
+1766, 2794, 0x2cc18cd5, 0x40207d3d},
+/*ff02::1*/
+{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
+/*3ffe:501:8::260:97ff:fe40:efab*/
+{0x3f, 0xfe, 0x05, 0x01, 0x00, 0x08, 0x00, 0x00,
+0x02, 0x60, 0x97, 0xff, 0xfe, 0x40, 0xef, 0xab,},
+4739, 14230, 0x0f0c461c, 0xdde51bbf},
+/*fe80::200:f8ff:fe21:67cf*/
+{{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
+/*3ffe:1900:4545:3:200:f8ff:fe21:67cf*/
+{0x3f, 0xfe, 0x19, 0x00, 0x45, 0x45, 0x00, 0x03,
+0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
+38024, 44251, 0x4b61e985, 0x02d1feef},
+};
+
+uint8_t default_rss_key[] = {
+0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
+0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
+0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
+0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
+};
+
+static int
+test_thash(void)
+{
+	uint32_t i, j;
+	union rte_thash_tuple tuple;
+	uint32_t rss_l3, rss_l3l4;
+	uint8_t rss_key_be[RTE_DIM(default_rss_key)];
+	struct ipv6_hdr ipv6_hdr;
+
+	/* Convert RSS key*/
+	rte_convert_rss_key((uint32_t *)&default_rss_key,
+		(uint32_t *)rss_key_be, RTE_DIM(default_rss_key));
+
+
+	for (i = 0; i < RTE_DIM(v4_tbl); i++) {
+		tuple.v4.src_addr = v4_tbl[i].src_ip;
+		tuple.v4.dst_addr = v4_tbl[i].dst_ip;
+		tuple.v4.sport = v4_tbl[i].src_port;
+		tuple.v4.dport = v4_tbl[i].dst_port;
+		/*Calculate hash with original key*/
+		rss_l3 = rte_softrss((uint32_t *)&tuple,
+				RTE_THASH_V4_L3_LEN, default_rss_key);
+		rss_l3l4 = rte_softrss((uint32_t *)&tuple,
+				RTE_THASH_V4_L4_LEN, default_rss_key);
+		if ((rss_l3 != v4_tbl[i].hash_l3) ||
+				(rss_l3l4 != v4_tbl[i].hash_l3l4))
+			return -1;
+		/*Calculate hash with converted key*/
+		rss_l3 = rte_softrss_be((uint32_t *)&tuple,
+				RTE_THASH_V4_L3_LEN, rss_key_be);
+		rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
+				RTE_THASH_V4_L4_LEN, rss_key_be);
+		if ((rss_l3 != v4_tbl[i].hash_l3) ||
+				(rss_l3l4 != v4_tbl[i].hash_l3l4))
+			return -1;
+	}
+	for (i = 0; i < RTE_DIM(v6_tbl); i++) {
+		/*Fill ipv6 hdr*/
+		for (j = 0; j < RTE_DIM(ipv6_hdr.src_addr); j++)
+			ipv6_hdr.src_addr[j] = v6_tbl[i].src_ip[j];
+		for (j = 0; j < RTE_DIM(ipv6_hdr.dst_addr); j++)
+			ipv6_hdr.dst_addr[j] = v6_tbl[i].dst_ip[j];
+		/*Load and convert ipv6 address into tuple*/
+		rte_thash_load_v6_addrs(&ipv6_hdr, &tuple);
+		tuple.v6.sport = v6_tbl[i].src_port;
+		tuple.v6.dport = v6_tbl[i].dst_port;
+		/*Calculate hash with original key*/
+		rss_l3 = rte_softrss((uint32_t *)&tuple,
+				RTE_THASH_V6_L3_LEN, default_rss_key);
+		rss_l3l4 = rte_softrss((uint32_t *)&tuple,
+				RTE_THASH_V6_L4_LEN, default_rss_key);
+		if ((rss_l3 != v6_tbl[i].hash_l3) ||
+				(rss_l3l4 != v6_tbl[i].hash_l3l4))
+			return -1;
+		/*Calculate hash with converted key*/
+		rss_l3 = rte_softrss_be((uint32_t *)&tuple,
+				RTE_THASH_V6_L3_LEN, rss_key_be);
+		rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
+				RTE_THASH_V6_L4_LEN, rss_key_be);
+		if ((rss_l3 != v6_tbl[i].hash_l3) ||
+				(rss_l3l4 != v6_tbl[i].hash_l3l4))
+			return -1;
+	}
+	return 0;
+}
+
+static struct test_command thash_cmd = {
+	.command = "thash_autotest",
+	.callback = test_thash,
+};
+REGISTER_TEST_COMMAND(thash_cmd);
-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
  2015-06-30 23:40         ` [dpdk-dev] [PATCH v6] " Vladimir Medvedkin
@ 2015-07-01 15:29           ` Bruce Richardson
  2015-07-01 21:23             ` Thomas Monjalon
  2015-07-22  7:55           ` Tony Lu
  1 sibling, 1 reply; 37+ messages in thread
From: Bruce Richardson @ 2015-07-01 15:29 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

On Tue, Jun 30, 2015 at 07:40:20PM -0400, Vladimir Medvedkin wrote:
> Software implementation of the Toeplitz hash function used by RSS.
> Can be used either for packet distribution on single queue NIC
> or for simulating of RSS computation on specific NIC (for example
> after GRE header decapsulating).
> 
> v6 changes
> - Fix compilation error
> - Rename some defines and function
> 
> v5 changes
> - Fix errors reported by checkpatch.pl
> 
> v4 changes
> - Fix copyright
> - rename bswap_mask constant, add rte_ prefix
> - change rte_ipv[46]_tuple struct
> - change rte_thash_load_v6_addr prototype
> 
> v3 changes
> - Rework API to be more generic
> - Add sctp_tag into tuple
> 
> v2 changes
> - Add ipv6 support
> - Various style fixes
> 
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>

Acked-by: Bruce Richardson <bruce.richardson@intel.com>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v4] Add unit test for thash library
  2015-06-30 23:41         ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
@ 2015-07-01 15:30           ` Bruce Richardson
  2015-07-01 21:28             ` Thomas Monjalon
  0 siblings, 1 reply; 37+ messages in thread
From: Bruce Richardson @ 2015-07-01 15:30 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

On Tue, Jun 30, 2015 at 07:41:13PM -0400, Vladimir Medvedkin wrote:
> Add unit test for thash library
> 
> v4 changes
> - Reflect rte_thash.h changes
> 
> v3 changes
> - Fix checkpatch errors
> 
> v2 changes
> - fix typo
> - remove unnecessary comments
> 
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>

Acked-by: Bruce Richardson <bruce.richardson@intel.com>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
  2015-07-01 15:29           ` Bruce Richardson
@ 2015-07-01 21:23             ` Thomas Monjalon
  0 siblings, 0 replies; 37+ messages in thread
From: Thomas Monjalon @ 2015-07-01 21:23 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

2015-07-01 16:29, Bruce Richardson:
> On Tue, Jun 30, 2015 at 07:40:20PM -0400, Vladimir Medvedkin wrote:
> > Software implementation of the Toeplitz hash function used by RSS.
> > Can be used either for packet distribution on single queue NIC
> > or for simulating of RSS computation on specific NIC (for example
> > after GRE header decapsulating).
> > 
> > v6 changes
> > - Fix compilation error
> > - Rename some defines and function
> > 
> > v5 changes
> > - Fix errors reported by checkpatch.pl
> > 
> > v4 changes
> > - Fix copyright
> > - rename bswap_mask constant, add rte_ prefix
> > - change rte_ipv[46]_tuple struct
> > - change rte_thash_load_v6_addr prototype
> > 
> > v3 changes
> > - Rework API to be more generic
> > - Add sctp_tag into tuple
> > 
> > v2 changes
> > - Add ipv6 support
> > - Various style fixes
> > 
> > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> 
> Acked-by: Bruce Richardson <bruce.richardson@intel.com>

Applied, thanks

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v4] Add unit test for thash library
  2015-07-01 15:30           ` Bruce Richardson
@ 2015-07-01 21:28             ` Thomas Monjalon
  0 siblings, 0 replies; 37+ messages in thread
From: Thomas Monjalon @ 2015-07-01 21:28 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

2015-07-01 16:30, Bruce Richardson:
> On Tue, Jun 30, 2015 at 07:41:13PM -0400, Vladimir Medvedkin wrote:
> > Add unit test for thash library
> > 
> > v4 changes
> > - Reflect rte_thash.h changes
> > 
> > v3 changes
> > - Fix checkpatch errors
> > 
> > v2 changes
> > - fix typo
> > - remove unnecessary comments
> > 
> > Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> 
> Acked-by: Bruce Richardson <bruce.richardson@intel.com>

Applied, thanks

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
  2015-06-30 23:40         ` [dpdk-dev] [PATCH v6] " Vladimir Medvedkin
  2015-07-01 15:29           ` Bruce Richardson
@ 2015-07-22  7:55           ` Tony Lu
  2015-07-27 11:57             ` Vladimir Medvedkin
  1 sibling, 1 reply; 37+ messages in thread
From: Tony Lu @ 2015-07-22  7:55 UTC (permalink / raw)
  To: 'Vladimir Medvedkin', dev

Hi, Vladimir

When compiling thash for no-X86 arches, it fails with the following errors.
I wonder if
it is possible to make the thash library arch-independent?

== Build app/test
  CC test_thash.o
In file included from /u/zlu.bjg/git/dpdk.org/app/test/test_thash.c:40:
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:56:22:
error: rte_vect.h: No such file or directory
In file included from /u/zlu.bjg/git/dpdk.org/app/test/test_thash.c:40:
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:62:
error: expected '=', ',', ';', 'asm' or '__attribute__' before
'rte_thash_ipv6_bswap_mask'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:129:
error: requested alignment is not a constant
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h: In
function 'rte_thash_load_v6_addrs':
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
error: '__m128i' undeclared (first use in this function)
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
error: (Each undeclared identifier is reported only once
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
error: for each function it appears in.)
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
error: expected ';' before 'ipv6'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:161:
error: expected expression before ')' token
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
error: 'ipv6' undeclared (first use in this function)
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
warning: implicit declaration of function '_mm_loadu_si128'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
warning: nested extern declaration of '_mm_loadu_si128'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
error: expected ')' before '__m128i'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
warning: type defaults to 'int' in declaration of 'type name'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
warning: cast from pointer to integer of different size
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:164:
error: expected expression before ')' token
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:158:
warning: unused parameter 'targ'
make[3]: *** [test_thash.o] Error 1
make[2]: *** [test] Error 2
make[1]: *** [app] Error 2
make: *** [all] Error 2

Thanks
-Zhigang Lu

>-----Original Message-----
>From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Vladimir Medvedkin
>Sent: Wednesday, July 01, 2015 7:40 AM
>To: dev@dpdk.org
>Subject: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
>
>Software implementation of the Toeplitz hash function used by RSS.
>Can be used either for packet distribution on single queue NIC or for
simulating
>of RSS computation on specific NIC (for example after GRE header
>decapsulating).
>
>v6 changes
>- Fix compilation error
>- Rename some defines and function
>
>v5 changes
>- Fix errors reported by checkpatch.pl
>
>v4 changes
>- Fix copyright
>- rename bswap_mask constant, add rte_ prefix
>- change rte_ipv[46]_tuple struct
>- change rte_thash_load_v6_addr prototype
>
>v3 changes
>- Rework API to be more generic
>- Add sctp_tag into tuple
>
>v2 changes
>- Add ipv6 support
>- Various style fixes
>
>Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
>---
> lib/librte_hash/Makefile    |   1 +
> lib/librte_hash/rte_thash.h | 231
>++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 232 insertions(+)
> create mode 100644 lib/librte_hash/rte_thash.h
>
>diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile index
>3696cb1..981230b 100644
>--- a/lib/librte_hash/Makefile
>+++ b/lib/librte_hash/Makefile
>@@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
>SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
>SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
>SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
>+SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
> SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
>
> # this lib needs eal
>diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h new
file
>mode 100644 index 0000000..1808f47
>--- /dev/null
>+++ b/lib/librte_hash/rte_thash.h
>@@ -0,0 +1,231 @@
>+/*-
>+ *   BSD LICENSE
>+ *
>+ *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com>
>+ *   All rights reserved.
>+ *
>+ *   Redistribution and use in source and binary forms, with or without
>+ *   modification, are permitted provided that the following conditions
>+ *   are met:
>+ *
>+ *     * Redistributions of source code must retain the above copyright
>+ *       notice, this list of conditions and the following disclaimer.
>+ *     * Redistributions in binary form must reproduce the above copyright
>+ *       notice, this list of conditions and the following disclaimer in
>+ *       the documentation and/or other materials provided with the
>+ *       distribution.
>+ *     * Neither the name of Intel Corporation nor the names of its
>+ *       contributors may be used to endorse or promote products derived
>+ *       from this software without specific prior written permission.
>+ *
>+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
>CONTRIBUTORS
>+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
>NOT
>+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
>FITNESS FOR
>+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
>COPYRIGHT
>+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
>INCIDENTAL,
>+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
>NOT
>+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
>OF USE,
>+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
>AND ON ANY
>+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
>TORT
>+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
>THE USE
>+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
>DAMAGE.
>+ */
>+
>+#ifndef _RTE_THASH_H
>+#define _RTE_THASH_H
>+
>+/**
>+ * @file
>+ *
>+ * toeplitz hash functions.
>+ */
>+
>+#ifdef __cplusplus
>+extern "C" {
>+#endif
>+
>+/**
>+ * Software implementation of the Toeplitz hash function used by RSS.
>+ * Can be used either for packet distribution on single queue NIC
>+ * or for simulating of RSS computation on specific NIC (for example
>+ * after GRE header decapsulating)
>+ */
>+
>+#include <stdint.h>
>+#include <rte_byteorder.h>
>+#include <rte_vect.h>
>+#include <rte_ip.h>
>+
>+/* Byte swap mask used for converting IPv6 address
>+ * 4-byte chunks to CPU byte order
>+ */
>+static const __m128i rte_thash_ipv6_bswap_mask = {
>+		0x0405060700010203, 0x0C0D0E0F08090A0B};
>+
>+/**
>+ * length in dwords of input tuple to
>+ * calculate hash of ipv4 header only
>+ */
>+#define RTE_THASH_V4_L3_LEN	((sizeof(struct rte_ipv4_tuple) -	\
>+			sizeof(((struct rte_ipv4_tuple *)0)->sctp_tag)) / 4)
>+
>+/**
>+ * length in dwords of input tuple to
>+ * calculate hash of ipv4 header +
>+ * transport header
>+ */
>+#define RTE_THASH_V4_L4_LEN	 ((sizeof(struct rte_ipv4_tuple)) / 4)
>+
>+/**
>+ * length in dwords of input tuple to
>+ * calculate hash of ipv6 header only
>+ */
>+#define RTE_THASH_V6_L3_LEN	((sizeof(struct rte_ipv6_tuple) -       \
>+			sizeof(((struct rte_ipv6_tuple *)0)->sctp_tag)) / 4)
>+
>+/**
>+ * length in dwords of input tuple to
>+ * calculate hash of ipv6 header +
>+ * transport header
>+ */
>+#define RTE_THASH_V6_L4_LEN	((sizeof(struct rte_ipv6_tuple)) / 4)
>+
>+/**
>+ * IPv4 tuple
>+ * addreses and ports/sctp_tag have to be CPU byte order  */ struct
>+rte_ipv4_tuple {
>+	uint32_t	src_addr;
>+	uint32_t	dst_addr;
>+	union {
>+		struct {
>+			uint16_t dport;
>+			uint16_t sport;
>+		};
>+		uint32_t        sctp_tag;
>+	};
>+};
>+
>+/**
>+ * IPv6 tuple
>+ * Addresses have to be filled by rte_thash_load_v6_addr()
>+ * ports/sctp_tag have to be CPU byte order  */ struct rte_ipv6_tuple {
>+	uint8_t		src_addr[16];
>+	uint8_t		dst_addr[16];
>+	union {
>+		struct {
>+			uint16_t dport;
>+			uint16_t sport;
>+		};
>+		uint32_t        sctp_tag;
>+	};
>+};
>+
>+union rte_thash_tuple {
>+	struct rte_ipv4_tuple	v4;
>+	struct rte_ipv6_tuple	v6;
>+} __attribute__((aligned(XMM_SIZE)));
>+
>+/**
>+ * Prepare special converted key to use with rte_softrss_be()
>+ * @param orig
>+ *   pointer to original RSS key
>+ * @param targ
>+ *   pointer to target RSS key
>+ * @param len
>+ *   RSS key length
>+ */
>+static inline void
>+rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len) {
>+	int i;
>+
>+	for (i = 0; i < (len >> 2); i++)
>+		targ[i] = rte_be_to_cpu_32(orig[i]);
>+}
>+
>+/**
>+ * Prepare and load IPv6 addresses (src and dst)
>+ * into target tuple
>+ * @param orig
>+ *   Pointer to ipv6 header of the original packet
>+ * @param targ
>+ *   Pointer to rte_ipv6_tuple structure
>+ */
>+static inline void
>+rte_thash_load_v6_addrs(const struct ipv6_hdr *orig, union
>+rte_thash_tuple *targ) {
>+	__m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
>+	*(__m128i *)targ->v6.src_addr =
>+			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
>+	ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
>+	*(__m128i *)targ->v6.dst_addr =
>+			_mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask); }
>+
>+/**
>+ * Generic implementation. Can be used with original rss_key
>+ * @param input_tuple
>+ *   Pointer to input tuple
>+ * @param input_len
>+ *   Length of input_tuple in 4-bytes chunks
>+ * @param rss_key
>+ *   Pointer to RSS hash key.
>+ * @return
>+ *   Calculated hash value.
>+ */
>+static inline uint32_t
>+rte_softrss(uint32_t *input_tuple, uint32_t input_len,
>+		const uint8_t *rss_key)
>+{
>+	uint32_t i, j, ret = 0;
>+
>+	for (j = 0; j < input_len; j++) {
>+		for (i = 0; i < 32; i++) {
>+			if (input_tuple[j] & (1 << (31 - i))) {
>+				ret ^= rte_cpu_to_be_32(((const uint32_t
*)rss_key)[j]) << i
>|
>+
(uint32_t)((uint64_t)(rte_cpu_to_be_32(((const
>uint32_t *)rss_key)[j + 1])) >>
>+					(32 - i));
>+			}
>+		}
>+	}
>+	return ret;
>+}
>+
>+/**
>+ * Optimized implementation.
>+ * If you want the calculated hash value matches NIC RSS value
>+ * you have to use special converted key with rte_convert_rss_key() fn.
>+ * @param input_tuple
>+ *   Pointer to input tuple
>+ * @param input_len
>+ *   Length of input_tuple in 4-bytes chunks
>+ * @param *rss_key
>+ *   Pointer to RSS hash key.
>+ * @return
>+ *   Calculated hash value.
>+ */
>+static inline uint32_t
>+rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
>+		const uint8_t *rss_key)
>+{
>+	uint32_t i, j, ret = 0;
>+
>+	for (j = 0; j < input_len; j++) {
>+		for (i = 0; i < 32; i++) {
>+			if (input_tuple[j] & (1 << (31 - i))) {
>+				ret ^= ((const uint32_t *)rss_key)[j] << i |
>+					(uint32_t)((uint64_t)(((const
uint32_t *)rss_key)[j +
>1]) >> (32 - i));
>+			}
>+		}
>+	}
>+	return ret;
>+}
>+
>+#ifdef __cplusplus
>+}
>+#endif
>+
>+#endif /* _RTE_THASH_H */
>--
>1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
  2015-07-22  7:55           ` Tony Lu
@ 2015-07-27 11:57             ` Vladimir Medvedkin
  2015-07-29  5:01               ` Qiu, Michael
  0 siblings, 1 reply; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-07-27 11:57 UTC (permalink / raw)
  To: Tony Lu; +Cc: dev

Hi Tony,

Sorry for the late reply, I was on vacation.
I'll prepare patch soon.

Regards,
Vladimir

2015-07-22 10:55 GMT+03:00 Tony Lu <zlu@ezchip.com>:

> Hi, Vladimir
>
> When compiling thash for no-X86 arches, it fails with the following errors.
> I wonder if
> it is possible to make the thash library arch-independent?
>
> == Build app/test
>   CC test_thash.o
> In file included from /u/zlu.bjg/git/dpdk.org/app/test/test_thash.c:40:
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:56:22
> :
> error: rte_vect.h: No such file or directory
> In file included from /u/zlu.bjg/git/dpdk.org/app/test/test_thash.c:40:
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:62:
> error: expected '=', ',', ';', 'asm' or '__attribute__' before
> 'rte_thash_ipv6_bswap_mask'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:129:
> error: requested alignment is not a constant
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h: In
> function 'rte_thash_load_v6_addrs':
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
> error: '__m128i' undeclared (first use in this function)
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
> error: (Each undeclared identifier is reported only once
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
> error: for each function it appears in.)
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
> error: expected ';' before 'ipv6'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:161:
> error: expected expression before ')' token
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> error: 'ipv6' undeclared (first use in this function)
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> warning: implicit declaration of function '_mm_loadu_si128'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> warning: nested extern declaration of '_mm_loadu_si128'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> error: expected ')' before '__m128i'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> warning: type defaults to 'int' in declaration of 'type name'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> warning: cast from pointer to integer of different size
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:164:
> error: expected expression before ')' token
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:158:
> warning: unused parameter 'targ'
> make[3]: *** [test_thash.o] Error 1
> make[2]: *** [test] Error 2
> make[1]: *** [app] Error 2
> make: *** [all] Error 2
>
> Thanks
> -Zhigang Lu
>
> >-----Original Message-----
> >From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Vladimir Medvedkin
> >Sent: Wednesday, July 01, 2015 7:40 AM
> >To: dev@dpdk.org
> >Subject: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
> >
> >Software implementation of the Toeplitz hash function used by RSS.
> >Can be used either for packet distribution on single queue NIC or for
> simulating
> >of RSS computation on specific NIC (for example after GRE header
> >decapsulating).
> >
> >v6 changes
> >- Fix compilation error
> >- Rename some defines and function
> >
> >v5 changes
> >- Fix errors reported by checkpatch.pl
> >
> >v4 changes
> >- Fix copyright
> >- rename bswap_mask constant, add rte_ prefix
> >- change rte_ipv[46]_tuple struct
> >- change rte_thash_load_v6_addr prototype
> >
> >v3 changes
> >- Rework API to be more generic
> >- Add sctp_tag into tuple
> >
> >v2 changes
> >- Add ipv6 support
> >- Various style fixes
> >
> >Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com>
> >---
> > lib/librte_hash/Makefile    |   1 +
> > lib/librte_hash/rte_thash.h | 231
> >++++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 232 insertions(+)
> > create mode 100644 lib/librte_hash/rte_thash.h
> >
> >diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile index
> >3696cb1..981230b 100644
> >--- a/lib/librte_hash/Makefile
> >+++ b/lib/librte_hash/Makefile
> >@@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
> >SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
> >SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
> >SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
> >+SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
> > SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
> >
> > # this lib needs eal
> >diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h new
> file
> >mode 100644 index 0000000..1808f47
> >--- /dev/null
> >+++ b/lib/librte_hash/rte_thash.h
> >@@ -0,0 +1,231 @@
> >+/*-
> >+ *   BSD LICENSE
> >+ *
> >+ *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com>
> >+ *   All rights reserved.
> >+ *
> >+ *   Redistribution and use in source and binary forms, with or without
> >+ *   modification, are permitted provided that the following conditions
> >+ *   are met:
> >+ *
> >+ *     * Redistributions of source code must retain the above copyright
> >+ *       notice, this list of conditions and the following disclaimer.
> >+ *     * Redistributions in binary form must reproduce the above
> copyright
> >+ *       notice, this list of conditions and the following disclaimer in
> >+ *       the documentation and/or other materials provided with the
> >+ *       distribution.
> >+ *     * Neither the name of Intel Corporation nor the names of its
> >+ *       contributors may be used to endorse or promote products derived
> >+ *       from this software without specific prior written permission.
> >+ *
> >+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> >CONTRIBUTORS
> >+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> >NOT
> >+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> >FITNESS FOR
> >+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> >COPYRIGHT
> >+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> >INCIDENTAL,
> >+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> >NOT
> >+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> >OF USE,
> >+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> >AND ON ANY
> >+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> >TORT
> >+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> >THE USE
> >+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> >DAMAGE.
> >+ */
> >+
> >+#ifndef _RTE_THASH_H
> >+#define _RTE_THASH_H
> >+
> >+/**
> >+ * @file
> >+ *
> >+ * toeplitz hash functions.
> >+ */
> >+
> >+#ifdef __cplusplus
> >+extern "C" {
> >+#endif
> >+
> >+/**
> >+ * Software implementation of the Toeplitz hash function used by RSS.
> >+ * Can be used either for packet distribution on single queue NIC
> >+ * or for simulating of RSS computation on specific NIC (for example
> >+ * after GRE header decapsulating)
> >+ */
> >+
> >+#include <stdint.h>
> >+#include <rte_byteorder.h>
> >+#include <rte_vect.h>
> >+#include <rte_ip.h>
> >+
> >+/* Byte swap mask used for converting IPv6 address
> >+ * 4-byte chunks to CPU byte order
> >+ */
> >+static const __m128i rte_thash_ipv6_bswap_mask = {
> >+              0x0405060700010203, 0x0C0D0E0F08090A0B};
> >+
> >+/**
> >+ * length in dwords of input tuple to
> >+ * calculate hash of ipv4 header only
> >+ */
> >+#define RTE_THASH_V4_L3_LEN   ((sizeof(struct rte_ipv4_tuple) -       \
> >+                      sizeof(((struct rte_ipv4_tuple *)0)->sctp_tag)) /
> 4)
> >+
> >+/**
> >+ * length in dwords of input tuple to
> >+ * calculate hash of ipv4 header +
> >+ * transport header
> >+ */
> >+#define RTE_THASH_V4_L4_LEN    ((sizeof(struct rte_ipv4_tuple)) / 4)
> >+
> >+/**
> >+ * length in dwords of input tuple to
> >+ * calculate hash of ipv6 header only
> >+ */
> >+#define RTE_THASH_V6_L3_LEN   ((sizeof(struct rte_ipv6_tuple) -       \
> >+                      sizeof(((struct rte_ipv6_tuple *)0)->sctp_tag)) /
> 4)
> >+
> >+/**
> >+ * length in dwords of input tuple to
> >+ * calculate hash of ipv6 header +
> >+ * transport header
> >+ */
> >+#define RTE_THASH_V6_L4_LEN   ((sizeof(struct rte_ipv6_tuple)) / 4)
> >+
> >+/**
> >+ * IPv4 tuple
> >+ * addreses and ports/sctp_tag have to be CPU byte order  */ struct
> >+rte_ipv4_tuple {
> >+      uint32_t        src_addr;
> >+      uint32_t        dst_addr;
> >+      union {
> >+              struct {
> >+                      uint16_t dport;
> >+                      uint16_t sport;
> >+              };
> >+              uint32_t        sctp_tag;
> >+      };
> >+};
> >+
> >+/**
> >+ * IPv6 tuple
> >+ * Addresses have to be filled by rte_thash_load_v6_addr()
> >+ * ports/sctp_tag have to be CPU byte order  */ struct rte_ipv6_tuple {
> >+      uint8_t         src_addr[16];
> >+      uint8_t         dst_addr[16];
> >+      union {
> >+              struct {
> >+                      uint16_t dport;
> >+                      uint16_t sport;
> >+              };
> >+              uint32_t        sctp_tag;
> >+      };
> >+};
> >+
> >+union rte_thash_tuple {
> >+      struct rte_ipv4_tuple   v4;
> >+      struct rte_ipv6_tuple   v6;
> >+} __attribute__((aligned(XMM_SIZE)));
> >+
> >+/**
> >+ * Prepare special converted key to use with rte_softrss_be()
> >+ * @param orig
> >+ *   pointer to original RSS key
> >+ * @param targ
> >+ *   pointer to target RSS key
> >+ * @param len
> >+ *   RSS key length
> >+ */
> >+static inline void
> >+rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len) {
> >+      int i;
> >+
> >+      for (i = 0; i < (len >> 2); i++)
> >+              targ[i] = rte_be_to_cpu_32(orig[i]);
> >+}
> >+
> >+/**
> >+ * Prepare and load IPv6 addresses (src and dst)
> >+ * into target tuple
> >+ * @param orig
> >+ *   Pointer to ipv6 header of the original packet
> >+ * @param targ
> >+ *   Pointer to rte_ipv6_tuple structure
> >+ */
> >+static inline void
> >+rte_thash_load_v6_addrs(const struct ipv6_hdr *orig, union
> >+rte_thash_tuple *targ) {
> >+      __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
> >+      *(__m128i *)targ->v6.src_addr =
> >+                      _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
> >+      ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
> >+      *(__m128i *)targ->v6.dst_addr =
> >+                      _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
> }
> >+
> >+/**
> >+ * Generic implementation. Can be used with original rss_key
> >+ * @param input_tuple
> >+ *   Pointer to input tuple
> >+ * @param input_len
> >+ *   Length of input_tuple in 4-bytes chunks
> >+ * @param rss_key
> >+ *   Pointer to RSS hash key.
> >+ * @return
> >+ *   Calculated hash value.
> >+ */
> >+static inline uint32_t
> >+rte_softrss(uint32_t *input_tuple, uint32_t input_len,
> >+              const uint8_t *rss_key)
> >+{
> >+      uint32_t i, j, ret = 0;
> >+
> >+      for (j = 0; j < input_len; j++) {
> >+              for (i = 0; i < 32; i++) {
> >+                      if (input_tuple[j] & (1 << (31 - i))) {
> >+                              ret ^= rte_cpu_to_be_32(((const uint32_t
> *)rss_key)[j]) << i
> >|
> >+
> (uint32_t)((uint64_t)(rte_cpu_to_be_32(((const
> >uint32_t *)rss_key)[j + 1])) >>
> >+                                      (32 - i));
> >+                      }
> >+              }
> >+      }
> >+      return ret;
> >+}
> >+
> >+/**
> >+ * Optimized implementation.
> >+ * If you want the calculated hash value matches NIC RSS value
> >+ * you have to use special converted key with rte_convert_rss_key() fn.
> >+ * @param input_tuple
> >+ *   Pointer to input tuple
> >+ * @param input_len
> >+ *   Length of input_tuple in 4-bytes chunks
> >+ * @param *rss_key
> >+ *   Pointer to RSS hash key.
> >+ * @return
> >+ *   Calculated hash value.
> >+ */
> >+static inline uint32_t
> >+rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
> >+              const uint8_t *rss_key)
> >+{
> >+      uint32_t i, j, ret = 0;
> >+
> >+      for (j = 0; j < input_len; j++) {
> >+              for (i = 0; i < 32; i++) {
> >+                      if (input_tuple[j] & (1 << (31 - i))) {
> >+                              ret ^= ((const uint32_t *)rss_key)[j] << i
> |
> >+                                      (uint32_t)((uint64_t)(((const
> uint32_t *)rss_key)[j +
> >1]) >> (32 - i));
> >+                      }
> >+              }
> >+      }
> >+      return ret;
> >+}
> >+
> >+#ifdef __cplusplus
> >+}
> >+#endif
> >+
> >+#endif /* _RTE_THASH_H */
> >--
> >1.8.3.2
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
  2015-07-27 11:57             ` Vladimir Medvedkin
@ 2015-07-29  5:01               ` Qiu, Michael
  2015-07-29 14:00                 ` Vladimir Medvedkin
  0 siblings, 1 reply; 37+ messages in thread
From: Qiu, Michael @ 2015-07-29  5:01 UTC (permalink / raw)
  To: Vladimir Medvedkin; +Cc: dev

Hi, Vladimir

You need also to fix this issue in i686 platform:

RHEL65_32,2.6.32,4.4.7,14.0.0
SUSE11SP3_32,3.0.76-0,4.3.4,14.0.0


i686-native-linuxapp-gcc/include/rte_thash.h:63: error: integer constant is too large for 'long' type
i686-native-linuxapp-gcc/include/rte_thash.h:63: error: integer constant is too large for 'long' type


Thanks,
Michael
On 2015/7/27 4:58, Vladimir Medvedkin wrote:

Hi Tony,

Sorry for the late reply, I was on vacation.
I'll prepare patch soon.

Regards,
Vladimir

2015-07-22 10:55 GMT+03:00 Tony Lu <zlu@ezchip.com><mailto:zlu@ezchip.com>:



Hi, Vladimir

When compiling thash for no-X86 arches, it fails with the following errors.
I wonder if
it is possible to make the thash library arch-independent?

== Build app/test
  CC test_thash.o
In file included from /u/zlu.bjg/git/dpdk.org/app/test/test_thash.c:40:
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:56:22
:
error: rte_vect.h: No such file or directory
In file included from /u/zlu.bjg/git/dpdk.org/app/test/test_thash.c:40:
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:62:
error: expected '=', ',', ';', 'asm' or '__attribute__' before
'rte_thash_ipv6_bswap_mask'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:129:
error: requested alignment is not a constant
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h: In
function 'rte_thash_load_v6_addrs':
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
error: '__m128i' undeclared (first use in this function)
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
error: (Each undeclared identifier is reported only once
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
error: for each function it appears in.)
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
error: expected ';' before 'ipv6'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:161:
error: expected expression before ')' token
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
error: 'ipv6' undeclared (first use in this function)
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
warning: implicit declaration of function '_mm_loadu_si128'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
warning: nested extern declaration of '_mm_loadu_si128'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
error: expected ')' before '__m128i'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
warning: type defaults to 'int' in declaration of 'type name'
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
warning: cast from pointer to integer of different size
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:164:
error: expected expression before ')' token
/u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:158:
warning: unused parameter 'targ'
make[3]: *** [test_thash.o] Error 1
make[2]: *** [test] Error 2
make[1]: *** [app] Error 2
make: *** [all] Error 2

Thanks
-Zhigang Lu



-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Vladimir Medvedkin
Sent: Wednesday, July 01, 2015 7:40 AM
To: dev@dpdk.org<mailto:dev@dpdk.org>
Subject: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS

Software implementation of the Toeplitz hash function used by RSS.
Can be used either for packet distribution on single queue NIC or for


simulating


of RSS computation on specific NIC (for example after GRE header
decapsulating).

v6 changes
- Fix compilation error
- Rename some defines and function

v5 changes
- Fix errors reported by checkpatch.pl

v4 changes
- Fix copyright
- rename bswap_mask constant, add rte_ prefix
- change rte_ipv[46]_tuple struct
- change rte_thash_load_v6_addr prototype

v3 changes
- Rework API to be more generic
- Add sctp_tag into tuple

v2 changes
- Add ipv6 support
- Various style fixes

Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com><mailto:medvedkinv@gmail.com>
---
lib/librte_hash/Makefile    |   1 +
lib/librte_hash/rte_thash.h | 231
++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 232 insertions(+)
create mode 100644 lib/librte_hash/rte_thash.h

diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile index
3696cb1..981230b 100644
--- a/lib/librte_hash/Makefile
+++ b/lib/librte_hash/Makefile
@@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h

# this lib needs eal
diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h new


file


mode 100644 index 0000000..1808f47
--- /dev/null
+++ b/lib/librte_hash/rte_thash.h
@@ -0,0 +1,231 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com><mailto:medvedkinv@gmail.com>
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above


copyright


+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
+ */
+
+#ifndef _RTE_THASH_H
+#define _RTE_THASH_H
+
+/**
+ * @file
+ *
+ * toeplitz hash functions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Software implementation of the Toeplitz hash function used by RSS.
+ * Can be used either for packet distribution on single queue NIC
+ * or for simulating of RSS computation on specific NIC (for example
+ * after GRE header decapsulating)
+ */
+
+#include <stdint.h>
+#include <rte_byteorder.h>
+#include <rte_vect.h>
+#include <rte_ip.h>
+
+/* Byte swap mask used for converting IPv6 address
+ * 4-byte chunks to CPU byte order
+ */
+static const __m128i rte_thash_ipv6_bswap_mask = {
+              0x0405060700010203, 0x0C0D0E0F08090A0B};
+
+/**
+ * length in dwords of input tuple to
+ * calculate hash of ipv4 header only
+ */
+#define RTE_THASH_V4_L3_LEN   ((sizeof(struct rte_ipv4_tuple) -       \
+                      sizeof(((struct rte_ipv4_tuple *)0)->sctp_tag)) /


4)


+
+/**
+ * length in dwords of input tuple to
+ * calculate hash of ipv4 header +
+ * transport header
+ */
+#define RTE_THASH_V4_L4_LEN    ((sizeof(struct rte_ipv4_tuple)) / 4)
+
+/**
+ * length in dwords of input tuple to
+ * calculate hash of ipv6 header only
+ */
+#define RTE_THASH_V6_L3_LEN   ((sizeof(struct rte_ipv6_tuple) -       \
+                      sizeof(((struct rte_ipv6_tuple *)0)->sctp_tag)) /


4)


+
+/**
+ * length in dwords of input tuple to
+ * calculate hash of ipv6 header +
+ * transport header
+ */
+#define RTE_THASH_V6_L4_LEN   ((sizeof(struct rte_ipv6_tuple)) / 4)
+
+/**
+ * IPv4 tuple
+ * addreses and ports/sctp_tag have to be CPU byte order  */ struct
+rte_ipv4_tuple {
+      uint32_t        src_addr;
+      uint32_t        dst_addr;
+      union {
+              struct {
+                      uint16_t dport;
+                      uint16_t sport;
+              };
+              uint32_t        sctp_tag;
+      };
+};
+
+/**
+ * IPv6 tuple
+ * Addresses have to be filled by rte_thash_load_v6_addr()
+ * ports/sctp_tag have to be CPU byte order  */ struct rte_ipv6_tuple {
+      uint8_t         src_addr[16];
+      uint8_t         dst_addr[16];
+      union {
+              struct {
+                      uint16_t dport;
+                      uint16_t sport;
+              };
+              uint32_t        sctp_tag;
+      };
+};
+
+union rte_thash_tuple {
+      struct rte_ipv4_tuple   v4;
+      struct rte_ipv6_tuple   v6;
+} __attribute__((aligned(XMM_SIZE)));
+
+/**
+ * Prepare special converted key to use with rte_softrss_be()
+ * @param orig
+ *   pointer to original RSS key
+ * @param targ
+ *   pointer to target RSS key
+ * @param len
+ *   RSS key length
+ */
+static inline void
+rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len) {
+      int i;
+
+      for (i = 0; i < (len >> 2); i++)
+              targ[i] = rte_be_to_cpu_32(orig[i]);
+}
+
+/**
+ * Prepare and load IPv6 addresses (src and dst)
+ * into target tuple
+ * @param orig
+ *   Pointer to ipv6 header of the original packet
+ * @param targ
+ *   Pointer to rte_ipv6_tuple structure
+ */
+static inline void
+rte_thash_load_v6_addrs(const struct ipv6_hdr *orig, union
+rte_thash_tuple *targ) {
+      __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
+      *(__m128i *)targ->v6.src_addr =
+                      _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
+      ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
+      *(__m128i *)targ->v6.dst_addr =
+                      _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);


}


+
+/**
+ * Generic implementation. Can be used with original rss_key
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss(uint32_t *input_tuple, uint32_t input_len,
+              const uint8_t *rss_key)
+{
+      uint32_t i, j, ret = 0;
+
+      for (j = 0; j < input_len; j++) {
+              for (i = 0; i < 32; i++) {
+                      if (input_tuple[j] & (1 << (31 - i))) {
+                              ret ^= rte_cpu_to_be_32(((const uint32_t


*)rss_key)[j]) << i


|
+


(uint32_t)((uint64_t)(rte_cpu_to_be_32(((const


uint32_t *)rss_key)[j + 1])) >>
+                                      (32 - i));
+                      }
+              }
+      }
+      return ret;
+}
+
+/**
+ * Optimized implementation.
+ * If you want the calculated hash value matches NIC RSS value
+ * you have to use special converted key with rte_convert_rss_key() fn.
+ * @param input_tuple
+ *   Pointer to input tuple
+ * @param input_len
+ *   Length of input_tuple in 4-bytes chunks
+ * @param *rss_key
+ *   Pointer to RSS hash key.
+ * @return
+ *   Calculated hash value.
+ */
+static inline uint32_t
+rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
+              const uint8_t *rss_key)
+{
+      uint32_t i, j, ret = 0;
+
+      for (j = 0; j < input_len; j++) {
+              for (i = 0; i < 32; i++) {
+                      if (input_tuple[j] & (1 << (31 - i))) {
+                              ret ^= ((const uint32_t *)rss_key)[j] << i


|


+                                      (uint32_t)((uint64_t)(((const


uint32_t *)rss_key)[j +


1]) >> (32 - i));
+                      }
+              }
+      }
+      return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_THASH_H */
--
1.8.3.2

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
  2015-07-29  5:01               ` Qiu, Michael
@ 2015-07-29 14:00                 ` Vladimir Medvedkin
  0 siblings, 0 replies; 37+ messages in thread
From: Vladimir Medvedkin @ 2015-07-29 14:00 UTC (permalink / raw)
  To: Qiu, Michael; +Cc: dev

Hi Michael,

Thanks for comment, it will be fixed in next patch.

Regards,
Vladimir

2015-07-29 8:01 GMT+03:00 Qiu, Michael <michael.qiu@intel.com>:

>  Hi, Vladimir
>
> You need also to fix this issue in i686 platform:
>
> RHEL65_32,2.6.32,4.4.7,14.0.0
> SUSE11SP3_32,3.0.76-0,4.3.4,14.0.0
>
>
> i686-native-linuxapp-gcc/include/rte_thash.h:63: error: integer constant
> is too large for 'long' type
> i686-native-linuxapp-gcc/include/rte_thash.h:63: error: integer constant
> is too large for 'long' type
>
>
> Thanks,
> Michael
>
> On 2015/7/27 4:58, Vladimir Medvedkin wrote:
>
> Hi Tony,
>
> Sorry for the late reply, I was on vacation.
> I'll prepare patch soon.
>
> Regards,
> Vladimir
>
> 2015-07-22 10:55 GMT+03:00 Tony Lu <zlu@ezchip.com> <zlu@ezchip.com>:
>
>
>  Hi, Vladimir
>
> When compiling thash for no-X86 arches, it fails with the following errors.
> I wonder if
> it is possible to make the thash library arch-independent?
>
> == Build app/test
>   CC test_thash.o
> In file included from /u/zlu.bjg/git/dpdk.org/app/test/test_thash.c:40:
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:56:22
> :
> error: rte_vect.h: No such file or directory
> In file included from /u/zlu.bjg/git/dpdk.org/app/test/test_thash.c:40:
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:62:
> error: expected '=', ',', ';', 'asm' or '__attribute__' before
> 'rte_thash_ipv6_bswap_mask'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:129:
> error: requested alignment is not a constant
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h: In
> function 'rte_thash_load_v6_addrs':
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
> error: '__m128i' undeclared (first use in this function)
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
> error: (Each undeclared identifier is reported only once
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
> error: for each function it appears in.)
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:160:
> error: expected ';' before 'ipv6'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:161:
> error: expected expression before ')' token
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> error: 'ipv6' undeclared (first use in this function)
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> warning: implicit declaration of function '_mm_loadu_si128'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> warning: nested extern declaration of '_mm_loadu_si128'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> error: expected ')' before '__m128i'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> warning: type defaults to 'int' in declaration of 'type name'
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:163:
> warning: cast from pointer to integer of different size
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:164:
> error: expected expression before ')' token
> /u/zlu.bjg/git/dpdk.org/tile-tilegx-linuxapp-gcc/include/rte_thash.h:158:
> warning: unused parameter 'targ'
> make[3]: *** [test_thash.o] Error 1
> make[2]: *** [test] Error 2
> make[1]: *** [app] Error 2
> make: *** [all] Error 2
>
> Thanks
> -Zhigang Lu
>
>
>  -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org <dev-bounces@dpdk.org>] On Behalf Of Vladimir Medvedkin
> Sent: Wednesday, July 01, 2015 7:40 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v6] Add toeplitz hash algorithm used by RSS
>
> Software implementation of the Toeplitz hash function used by RSS.
> Can be used either for packet distribution on single queue NIC or for
>
>  simulating
>
>  of RSS computation on specific NIC (for example after GRE header
> decapsulating).
>
> v6 changes
> - Fix compilation error
> - Rename some defines and function
>
> v5 changes
> - Fix errors reported by checkpatch.pl
>
> v4 changes
> - Fix copyright
> - rename bswap_mask constant, add rte_ prefix
> - change rte_ipv[46]_tuple struct
> - change rte_thash_load_v6_addr prototype
>
> v3 changes
> - Rework API to be more generic
> - Add sctp_tag into tuple
>
> v2 changes
> - Add ipv6 support
> - Various style fixes
>
> Signed-off-by: Vladimir Medvedkin <medvedkinv@gmail.com> <medvedkinv@gmail.com>
> ---
> lib/librte_hash/Makefile    |   1 +
> lib/librte_hash/rte_thash.h | 231
> ++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 232 insertions(+)
> create mode 100644 lib/librte_hash/rte_thash.h
>
> diff --git a/lib/librte_hash/Makefile b/lib/librte_hash/Makefile index
> 3696cb1..981230b 100644
> --- a/lib/librte_hash/Makefile
> +++ b/lib/librte_hash/Makefile
> @@ -49,6 +49,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += rte_fbk_hash.c
> SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include := rte_hash.h
> SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_hash_crc.h
> SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_jhash.h
> +SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_thash.h
> SYMLINK-$(CONFIG_RTE_LIBRTE_HASH)-include += rte_fbk_hash.h
>
> # this lib needs eal
> diff --git a/lib/librte_hash/rte_thash.h b/lib/librte_hash/rte_thash.h new
>
>  file
>
>  mode 100644 index 0000000..1808f47
> --- /dev/null
> +++ b/lib/librte_hash/rte_thash.h
> @@ -0,0 +1,231 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2015 Vladimir Medvedkin <medvedkinv@gmail.com> <medvedkinv@gmail.com>
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above
>
>  copyright
>
>  + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> + */
> +
> +#ifndef _RTE_THASH_H
> +#define _RTE_THASH_H
> +
> +/**
> + * @file
> + *
> + * toeplitz hash functions.
> + */
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Software implementation of the Toeplitz hash function used by RSS.
> + * Can be used either for packet distribution on single queue NIC
> + * or for simulating of RSS computation on specific NIC (for example
> + * after GRE header decapsulating)
> + */
> +
> +#include <stdint.h>
> +#include <rte_byteorder.h>
> +#include <rte_vect.h>
> +#include <rte_ip.h>
> +
> +/* Byte swap mask used for converting IPv6 address
> + * 4-byte chunks to CPU byte order
> + */
> +static const __m128i rte_thash_ipv6_bswap_mask = {
> +              0x0405060700010203, 0x0C0D0E0F08090A0B};
> +
> +/**
> + * length in dwords of input tuple to
> + * calculate hash of ipv4 header only
> + */
> +#define RTE_THASH_V4_L3_LEN   ((sizeof(struct rte_ipv4_tuple) -       \
> +                      sizeof(((struct rte_ipv4_tuple *)0)->sctp_tag)) /
>
>  4)
>
>  +
> +/**
> + * length in dwords of input tuple to
> + * calculate hash of ipv4 header +
> + * transport header
> + */
> +#define RTE_THASH_V4_L4_LEN    ((sizeof(struct rte_ipv4_tuple)) / 4)
> +
> +/**
> + * length in dwords of input tuple to
> + * calculate hash of ipv6 header only
> + */
> +#define RTE_THASH_V6_L3_LEN   ((sizeof(struct rte_ipv6_tuple) -       \
> +                      sizeof(((struct rte_ipv6_tuple *)0)->sctp_tag)) /
>
>  4)
>
>  +
> +/**
> + * length in dwords of input tuple to
> + * calculate hash of ipv6 header +
> + * transport header
> + */
> +#define RTE_THASH_V6_L4_LEN   ((sizeof(struct rte_ipv6_tuple)) / 4)
> +
> +/**
> + * IPv4 tuple
> + * addreses and ports/sctp_tag have to be CPU byte order  */ struct
> +rte_ipv4_tuple {
> +      uint32_t        src_addr;
> +      uint32_t        dst_addr;
> +      union {
> +              struct {
> +                      uint16_t dport;
> +                      uint16_t sport;
> +              };
> +              uint32_t        sctp_tag;
> +      };
> +};
> +
> +/**
> + * IPv6 tuple
> + * Addresses have to be filled by rte_thash_load_v6_addr()
> + * ports/sctp_tag have to be CPU byte order  */ struct rte_ipv6_tuple {
> +      uint8_t         src_addr[16];
> +      uint8_t         dst_addr[16];
> +      union {
> +              struct {
> +                      uint16_t dport;
> +                      uint16_t sport;
> +              };
> +              uint32_t        sctp_tag;
> +      };
> +};
> +
> +union rte_thash_tuple {
> +      struct rte_ipv4_tuple   v4;
> +      struct rte_ipv6_tuple   v6;
> +} __attribute__((aligned(XMM_SIZE)));
> +
> +/**
> + * Prepare special converted key to use with rte_softrss_be()
> + * @param orig
> + *   pointer to original RSS key
> + * @param targ
> + *   pointer to target RSS key
> + * @param len
> + *   RSS key length
> + */
> +static inline void
> +rte_convert_rss_key(const uint32_t *orig, uint32_t *targ, int len) {
> +      int i;
> +
> +      for (i = 0; i < (len >> 2); i++)
> +              targ[i] = rte_be_to_cpu_32(orig[i]);
> +}
> +
> +/**
> + * Prepare and load IPv6 addresses (src and dst)
> + * into target tuple
> + * @param orig
> + *   Pointer to ipv6 header of the original packet
> + * @param targ
> + *   Pointer to rte_ipv6_tuple structure
> + */
> +static inline void
> +rte_thash_load_v6_addrs(const struct ipv6_hdr *orig, union
> +rte_thash_tuple *targ) {
> +      __m128i ipv6 = _mm_loadu_si128((const __m128i *)orig->src_addr);
> +      *(__m128i *)targ->v6.src_addr =
> +                      _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
> +      ipv6 = _mm_loadu_si128((const __m128i *)orig->dst_addr);
> +      *(__m128i *)targ->v6.dst_addr =
> +                      _mm_shuffle_epi8(ipv6, rte_thash_ipv6_bswap_mask);
>
>  }
>
>  +
> +/**
> + * Generic implementation. Can be used with original rss_key
> + * @param input_tuple
> + *   Pointer to input tuple
> + * @param input_len
> + *   Length of input_tuple in 4-bytes chunks
> + * @param rss_key
> + *   Pointer to RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +static inline uint32_t
> +rte_softrss(uint32_t *input_tuple, uint32_t input_len,
> +              const uint8_t *rss_key)
> +{
> +      uint32_t i, j, ret = 0;
> +
> +      for (j = 0; j < input_len; j++) {
> +              for (i = 0; i < 32; i++) {
> +                      if (input_tuple[j] & (1 << (31 - i))) {
> +                              ret ^= rte_cpu_to_be_32(((const uint32_t
>
>  *)rss_key)[j]) << i
>
>  |
> +
>
>  (uint32_t)((uint64_t)(rte_cpu_to_be_32(((const
>
>  uint32_t *)rss_key)[j + 1])) >>
> +                                      (32 - i));
> +                      }
> +              }
> +      }
> +      return ret;
> +}
> +
> +/**
> + * Optimized implementation.
> + * If you want the calculated hash value matches NIC RSS value
> + * you have to use special converted key with rte_convert_rss_key() fn.
> + * @param input_tuple
> + *   Pointer to input tuple
> + * @param input_len
> + *   Length of input_tuple in 4-bytes chunks
> + * @param *rss_key
> + *   Pointer to RSS hash key.
> + * @return
> + *   Calculated hash value.
> + */
> +static inline uint32_t
> +rte_softrss_be(uint32_t *input_tuple, uint32_t input_len,
> +              const uint8_t *rss_key)
> +{
> +      uint32_t i, j, ret = 0;
> +
> +      for (j = 0; j < input_len; j++) {
> +              for (i = 0; i < 32; i++) {
> +                      if (input_tuple[j] & (1 << (31 - i))) {
> +                              ret ^= ((const uint32_t *)rss_key)[j] << i
>
>  |
>
>  +                                      (uint32_t)((uint64_t)(((const
>
>  uint32_t *)rss_key)[j +
>
>  1]) >> (32 - i));
> +                      }
> +              }
> +      }
> +      return ret;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_THASH_H */
> --
> 1.8.3.2
>
>
>

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2015-07-29 14:00 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-08 19:06 [dpdk-dev] [PATCH] Add toeplitz hash algorithm Vladimir Medvedkin
2015-04-08 22:24 ` Stephen Hemminger
2015-04-09 12:50   ` Vladimir Medvedkin
2015-04-09  6:37 ` Gleb Natapov
2015-04-09 12:57   ` Vladimir Medvedkin
2015-05-05 13:20 ` [dpdk-dev] [PATCH v2] Add toeplitz hash algorithm used by RSS Vladimir Medvedkin
2015-05-05 16:03   ` Chilikin, Andrey
2015-05-07 10:28     ` Vladimir Medvedkin
2015-05-07 11:38       ` Chilikin, Andrey
2015-05-08 14:58         ` Vladimir Medvedkin
2015-05-08 14:58   ` Vladimir Medvedkin
2015-06-03 14:07     ` Thomas Monjalon
2015-06-16  9:07       ` Thomas Monjalon
2015-06-16 10:36         ` Bruce Richardson
2015-06-16 12:29     ` Bruce Richardson
2015-06-16 19:26       ` Vladimir Medvedkin
2015-06-19 14:55     ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
2015-06-19 15:59       ` Richardson, Bruce
2015-06-19 16:14         ` Vladimir Medvedkin
2015-06-29 12:18           ` Bruce Richardson
2015-06-19 16:33         ` Mcnamara, John
2015-06-19 17:31       ` [dpdk-dev] [PATCH v5] " Vladimir Medvedkin
2015-06-29 12:40         ` Bruce Richardson
2015-06-30 12:14           ` Vladimir Medvedkin
2015-06-30 12:48             ` Bruce Richardson
2015-06-30 23:40         ` [dpdk-dev] [PATCH v6] " Vladimir Medvedkin
2015-07-01 15:29           ` Bruce Richardson
2015-07-01 21:23             ` Thomas Monjalon
2015-07-22  7:55           ` Tony Lu
2015-07-27 11:57             ` Vladimir Medvedkin
2015-07-29  5:01               ` Qiu, Michael
2015-07-29 14:00                 ` Vladimir Medvedkin
2015-06-19 17:32       ` [dpdk-dev] [PATCH v3] Add unit test for thash library Vladimir Medvedkin
2015-06-29 12:42         ` Bruce Richardson
2015-06-30 23:41         ` [dpdk-dev] [PATCH v4] " Vladimir Medvedkin
2015-07-01 15:30           ` Bruce Richardson
2015-07-01 21:28             ` Thomas Monjalon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).