Right now ACL library determines best possible (default) classify method on a given platform with specilal constructor function rte_acl_init(). This patch makes the following changes: - Move selection of default classify method into a separate private function and call it for each ACL context creation (rte_acl_create()). - Remove library constructor function - Make rte_acl_set_ctx_classify() to check that requested algorithm is supported on given platform.
The purpose of these changes to improve and simplify algorithm selection process and prepare ACL library to be integrated with: add max SIMD bitwidth to EAL (https://patches.dpdk.org/project/dpdk/list/?series=11831) patch-set Signed-off-by: Konstantin Ananyev <konstantin.anan...@intel.com> --- lib/librte_acl/rte_acl.c | 166 ++++++++++++++++++++++++++++++--------- lib/librte_acl/rte_acl.h | 1 + 2 files changed, 132 insertions(+), 35 deletions(-) diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c index 715b02359..fbcf45fdc 100644 --- a/lib/librte_acl/rte_acl.c +++ b/lib/librte_acl/rte_acl.c @@ -79,57 +79,153 @@ static const rte_acl_classify_t classify_fns[] = { [RTE_ACL_CLASSIFY_ALTIVEC] = rte_acl_classify_altivec, }; -/* by default, use always available scalar code path. */ -static enum rte_acl_classify_alg rte_acl_default_classify = - RTE_ACL_CLASSIFY_SCALAR; +/* + * Helper function for acl_check_alg. + * Check support for ARM specific classify methods. + */ +static int +acl_check_alg_arm(enum rte_acl_classify_alg alg) +{ + if (alg == RTE_ACL_CLASSIFY_NEON) { +#if defined(RTE_ARCH_ARM64) + return 0; +#elif defined(RTE_ARCH_ARM) + if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) + return 0; + return -ENOTSUP; +#else + return -ENOTSUP; +#endif + } + + return -EINVAL; +} -static void -rte_acl_set_default_classify(enum rte_acl_classify_alg alg) +/* + * Helper function for acl_check_alg. + * Check support for PPC specific classify methods. + */ +static int +acl_check_alg_ppc(enum rte_acl_classify_alg alg) { - rte_acl_default_classify = alg; + if (alg == RTE_ACL_CLASSIFY_ALTIVEC) { +#if defined(RTE_ARCH_PPC_64) + return 0; +#else + return -ENOTSUP; +#endif + } + + return -EINVAL; } -extern int -rte_acl_set_ctx_classify(struct rte_acl_ctx *ctx, enum rte_acl_classify_alg alg) +/* + * Helper function for acl_check_alg. + * Check support for x86 specific classify methods. + */ +static int +acl_check_alg_x86(enum rte_acl_classify_alg alg) { - if (ctx == NULL || (uint32_t)alg >= RTE_DIM(classify_fns)) - return -EINVAL; + if (alg == RTE_ACL_CLASSIFY_AVX2) { +#ifdef CC_AVX2_SUPPORT + if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2)) + return 0; +#endif + return -ENOTSUP; + } - ctx->alg = alg; - return 0; + if (alg == RTE_ACL_CLASSIFY_SSE) { +#ifdef RTE_ARCH_X86 + if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1)) + return 0; +#endif + return -ENOTSUP; + } + + return -EINVAL; } /* - * Select highest available classify method as default one. - * Note that CLASSIFY_AVX2 should be set as a default only - * if both conditions are met: - * at build time compiler supports AVX2 and target cpu supports AVX2. + * Check if input alg is supported by given platform/binary. + * Note that both conditions should be met: + * - at build time compiler supports ISA used by given methos + * at run time target cpu supports necessary ISA. */ -RTE_INIT(rte_acl_init) +static int +acl_check_alg(enum rte_acl_classify_alg alg) { - enum rte_acl_classify_alg alg = RTE_ACL_CLASSIFY_DEFAULT; + switch (alg) { + case RTE_ACL_CLASSIFY_NEON: + return acl_check_alg_arm(alg); + case RTE_ACL_CLASSIFY_ALTIVEC: + return acl_check_alg_ppc(alg); + case RTE_ACL_CLASSIFY_AVX2: + case RTE_ACL_CLASSIFY_SSE: + return acl_check_alg_x86(alg); + /* scalar method is supported on all platforms */ + case RTE_ACL_CLASSIFY_SCALAR: + return 0; + default: + return -EINVAL; + } +} -#if defined(RTE_ARCH_ARM64) - alg = RTE_ACL_CLASSIFY_NEON; -#elif defined(RTE_ARCH_ARM) - if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) - alg = RTE_ACL_CLASSIFY_NEON; +/* + * Get preferred alg for given platform. + */ +static enum rte_acl_classify_alg +acl_get_best_alg(void) +{ + /* + * array of supported methods for each platform. + * Note that order is important - from most to less preferable. + */ + static const enum rte_acl_classify_alg alg[] = { +#if defined(RTE_ARCH_ARM) + RTE_ACL_CLASSIFY_NEON, #elif defined(RTE_ARCH_PPC_64) - alg = RTE_ACL_CLASSIFY_ALTIVEC; -#else -#ifdef CC_AVX2_SUPPORT - if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2)) - alg = RTE_ACL_CLASSIFY_AVX2; - else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1)) -#else - if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1)) + RTE_ACL_CLASSIFY_ALTIVEC, +#elif defined(RTE_ARCH_X86) + RTE_ACL_CLASSIFY_AVX2, + RTE_ACL_CLASSIFY_SSE, #endif - alg = RTE_ACL_CLASSIFY_SSE; + RTE_ACL_CLASSIFY_SCALAR, + }; -#endif - rte_acl_set_default_classify(alg); + uint32_t i; + + /* find best possible alg */ + for (i = 0; i != RTE_DIM(alg) && acl_check_alg(alg[i]) != 0; i++) + ; + + /* we always have to find something suitable */ + RTE_VERIFY(i != RTE_DIM(alg)); + return alg[i]; +} + +extern int +rte_acl_set_ctx_classify(struct rte_acl_ctx *ctx, enum rte_acl_classify_alg alg) +{ + int32_t rc; + + /* formal parameters check */ + if (ctx == NULL || (uint32_t)alg >= RTE_DIM(classify_fns)) + return -EINVAL; + + /* user asked us to select the *best* one */ + if (alg == RTE_ACL_CLASSIFY_DEFAULT) + alg = acl_get_best_alg(); + + /* check that given alg is supported */ + rc = acl_check_alg(alg); + if (rc != 0) + return rc; + + ctx->alg = alg; + return 0; } + int rte_acl_classify_alg(const struct rte_acl_ctx *ctx, const uint8_t **data, uint32_t *results, uint32_t num, uint32_t categories, @@ -262,7 +358,7 @@ rte_acl_create(const struct rte_acl_param *param) ctx->max_rules = param->max_rule_num; ctx->rule_sz = param->rule_size; ctx->socket_id = param->socket_id; - ctx->alg = rte_acl_default_classify; + ctx->alg = acl_get_best_alg(); strlcpy(ctx->name, param->name, sizeof(ctx->name)); te->data = (void *) ctx; diff --git a/lib/librte_acl/rte_acl.h b/lib/librte_acl/rte_acl.h index b814423a6..3999f15de 100644 --- a/lib/librte_acl/rte_acl.h +++ b/lib/librte_acl/rte_acl.h @@ -329,6 +329,7 @@ rte_acl_classify_alg(const struct rte_acl_ctx *ctx, * existing algorithm, and that it could be run on the given CPU. * @return * - -EINVAL if the parameters are invalid. + * - -ENOTSUP requested algorithm is not supported by given platform. * - Zero if operation completed successfully. */ extern int -- 2.17.1