Add big endian support for s390x architecture. Signed-off-by: Vivian Kong <vivk...@ca.ibm.com> --- lib/librte_lpm/Makefile | 2 + lib/librte_lpm/meson.build | 2 +- lib/librte_lpm/rte_lpm.h | 2 + lib/librte_lpm/rte_lpm6.c | 26 ++++++- lib/librte_lpm/rte_lpm_s390x.h | 130 +++++++++++++++++++++++++++++++++ 5 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 lib/librte_lpm/rte_lpm_s390x.h
diff --git a/lib/librte_lpm/Makefile b/lib/librte_lpm/Makefile index a7946a1c5..16b868304 100644 --- a/lib/librte_lpm/Makefile +++ b/lib/librte_lpm/Makefile @@ -26,6 +26,8 @@ else ifeq ($(CONFIG_RTE_ARCH_X86),y) SYMLINK-$(CONFIG_RTE_LIBRTE_LPM)-include += rte_lpm_sse.h else ifeq ($(CONFIG_RTE_ARCH_PPC_64),y) SYMLINK-$(CONFIG_RTE_LIBRTE_LPM)-include += rte_lpm_altivec.h +else ifeq ($(CONFIG_RTE_ARCH_S390X),y) +SYMLINK-$(CONFIG_RTE_LIBRTE_LPM)-include += rte_lpm_s390x.h endif include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_lpm/meson.build b/lib/librte_lpm/meson.build index a5176d8ae..68317ed52 100644 --- a/lib/librte_lpm/meson.build +++ b/lib/librte_lpm/meson.build @@ -6,5 +6,5 @@ sources = files('rte_lpm.c', 'rte_lpm6.c') headers = files('rte_lpm.h', 'rte_lpm6.h') # since header files have different names, we can install all vector headers # without worrying about which architecture we actually need -headers += files('rte_lpm_altivec.h', 'rte_lpm_neon.h', 'rte_lpm_sse.h') +headers += files('rte_lpm_s390x.h', 'rte_lpm_altivec.h', 'rte_lpm_neon.h', 'rte_lpm_sse.h') deps += ['hash'] diff --git a/lib/librte_lpm/rte_lpm.h b/lib/librte_lpm/rte_lpm.h index 21550444d..aa8a43968 100644 --- a/lib/librte_lpm/rte_lpm.h +++ b/lib/librte_lpm/rte_lpm.h @@ -459,6 +459,8 @@ rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4], #include "rte_lpm_neon.h" #elif defined(RTE_ARCH_PPC_64) #include "rte_lpm_altivec.h" +#elif defined(RTE_ARCH_S390X) +#include "rte_lpm_s390x.h" #else #include "rte_lpm_sse.h" #endif diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c index a91803113..7aead4035 100644 --- a/lib/librte_lpm/rte_lpm6.c +++ b/lib/librte_lpm/rte_lpm6.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2010-2014 Intel Corporation */ + #include <string.h> #include <stdint.h> #include <errno.h> @@ -24,6 +25,7 @@ #include <rte_hash.h> #include <assert.h> #include <rte_jhash.h> +#include <rte_byteorder.h> #include "rte_lpm6.h" @@ -58,17 +60,33 @@ static struct rte_tailq_elem rte_lpm6_tailq = { }; EAL_REGISTER_TAILQ(rte_lpm6_tailq) +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + /** Tbl entry structure. It is the same for both tbl24 and tbl8 */ struct rte_lpm6_tbl_entry { - uint32_t next_hop: 21; /**< Next hop / next table to be checked. */ - uint32_t depth :8; /**< Rule depth. */ + uint32_t next_hop :21; /**< Next hop / next table to be checked. */ + uint32_t depth :8; /**< Rule depth. */ + + /* Flags. */ + uint32_t valid :1; /**< Validation flag. */ + uint32_t valid_group :1; /**< Group validation flag. */ + uint32_t ext_entry :1; /**< External entry. */ +}; + +#else +struct rte_lpm6_tbl_entry { /* Flags. */ - uint32_t valid :1; /**< Validation flag. */ + uint32_t ext_entry :1; /**< External entry. */ uint32_t valid_group :1; /**< Group validation flag. */ - uint32_t ext_entry :1; /**< External entry. */ + uint32_t valid :1; /**< Validation flag. */ + + uint32_t depth :8; /**< Rule depth. */ + uint32_t next_hop :21; /**< Next hop / next table to be checked. */ }; +#endif + /** Rules tbl entry structure. */ struct rte_lpm6_rule { uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE]; /**< Rule IP address. */ diff --git a/lib/librte_lpm/rte_lpm_s390x.h b/lib/librte_lpm/rte_lpm_s390x.h new file mode 100644 index 000000000..eb1fdd450 --- /dev/null +++ b/lib/librte_lpm/rte_lpm_s390x.h @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * (c) Copyright IBM Corp. 2016, 2018 + */ + +#ifndef _RTE_LPM_S390X_H_ +#define _RTE_LPM_S390X_H_ + +#include <rte_branch_prediction.h> +#include <rte_byteorder.h> +#include <rte_common.h> +#include <rte_vect.h> + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void +rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4], + uint32_t defv) +{ + typedef int vector_signed_int + __attribute__((vector_size(4*sizeof(int)))); + vector_signed_int i24; + rte_xmm_t i8; + uint32_t tbl[4]; + uint64_t idx, pt, pt2; + const uint32_t *ptbl; + + const uint32_t mask = UINT8_MAX; + const vector_signed_int mask8 = (xmm_t){mask, mask, mask, mask}; + + /* + * RTE_LPM_VALID_EXT_ENTRY_BITMASK for 2 LPM entries + * as one 64-bit value (0x0300000003000000). + */ + const uint64_t mask_xv = + ((uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK | + (uint64_t)RTE_LPM_VALID_EXT_ENTRY_BITMASK << 32); + + /* + * RTE_LPM_LOOKUP_SUCCESS for 2 LPM entries + * as one 64-bit value (0x0100000001000000). + */ + const uint64_t mask_v = + ((uint64_t)RTE_LPM_LOOKUP_SUCCESS | + (uint64_t)RTE_LPM_LOOKUP_SUCCESS << 32); + + /* get 4 indexes for tbl24[]. */ + i24[0] = (uint32_t)ip[0] >> 8; + i24[1] = (uint32_t)ip[1] >> 8; + i24[2] = (uint32_t)ip[2] >> 8; + i24[3] = (uint32_t)ip[3] >> 8; + + /* extract values from tbl24[] */ + idx = (uint32_t)i24[0]; + idx = idx < (1<<24) ? idx : (1<<24)-1; + ptbl = (const uint32_t *)&lpm->tbl24[idx]; + tbl[0] = *ptbl; + + idx = (uint32_t) i24[1]; + idx = idx < (1<<24) ? idx : (1<<24)-1; + ptbl = (const uint32_t *)&lpm->tbl24[idx]; + tbl[1] = *ptbl; + + idx = (uint32_t) i24[2]; + idx = idx < (1<<24) ? idx : (1<<24)-1; + ptbl = (const uint32_t *)&lpm->tbl24[idx]; + tbl[2] = *ptbl; + + idx = (uint32_t) i24[3]; + idx = idx < (1<<24) ? idx : (1<<24)-1; + ptbl = (const uint32_t *)&lpm->tbl24[idx]; + tbl[3] = *ptbl; + + /* get 4 indexes for tbl8[]. */ + i8.x = vec_and(ip, mask8); + + pt = (uint64_t)tbl[0] | + (uint64_t)tbl[1] << 32; + pt2 = (uint64_t)tbl[2] | + (uint64_t)tbl[3] << 32; + + /* search successfully finished for all 4 IP addresses. */ + if (likely((pt & mask_xv) == mask_v) && + likely((pt2 & mask_xv) == mask_v)) { + *(uint64_t *)hop = pt & RTE_LPM_MASKX4_RES; + *(uint64_t *)(hop + 2) = pt2 & RTE_LPM_MASKX4_RES; + return; + } + + if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == + RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { + i8.u32[0] = i8.u32[0] + + (uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; + ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[0]]; + tbl[0] = *ptbl; + } + if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == + RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { + i8.u32[1] = i8.u32[1] + + (uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; + ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[1]]; + tbl[1] = *ptbl; + } + if (unlikely((pt2 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == + RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { + i8.u32[2] = i8.u32[2] + + (uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; + ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[2]]; + tbl[2] = *ptbl; + } + if (unlikely((pt2 >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) == + RTE_LPM_VALID_EXT_ENTRY_BITMASK)) { + i8.u32[3] = i8.u32[3] + + (uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES; + ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[3]]; + tbl[3] = *ptbl; + } + + hop[0] = (tbl[0] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[0] & 0x00FFFFFF : defv; + hop[1] = (tbl[1] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[1] & 0x00FFFFFF : defv; + hop[2] = (tbl[2] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[2] & 0x00FFFFFF : defv; + hop[3] = (tbl[3] & RTE_LPM_LOOKUP_SUCCESS) ? tbl[3] & 0x00FFFFFF : defv; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_LPM_S390X_H_ */ -- 2.17.1