* [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 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-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-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
* 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
* [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-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 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 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
* 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 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
* 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 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 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
* [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 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
* [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 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 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
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).