199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #include <rte_eal_memconfig.h> 699a2dd95SBruce Richardson #include <rte_string_fns.h> 799a2dd95SBruce Richardson #include <rte_acl.h> 899a2dd95SBruce Richardson #include <rte_tailq.h> 999a2dd95SBruce Richardson 1099a2dd95SBruce Richardson #include "acl.h" 11*73d85848SStephen Hemminger #include "acl_log.h" 12*73d85848SStephen Hemminger 13*73d85848SStephen Hemminger RTE_LOG_REGISTER_DEFAULT(acl_logtype, INFO); 1499a2dd95SBruce Richardson 1599a2dd95SBruce Richardson TAILQ_HEAD(rte_acl_list, rte_tailq_entry); 1699a2dd95SBruce Richardson 1799a2dd95SBruce Richardson static struct rte_tailq_elem rte_acl_tailq = { 1899a2dd95SBruce Richardson .name = "RTE_ACL", 1999a2dd95SBruce Richardson }; 2099a2dd95SBruce Richardson EAL_REGISTER_TAILQ(rte_acl_tailq) 2199a2dd95SBruce Richardson 2299a2dd95SBruce Richardson #ifndef CC_AVX512_SUPPORT 2399a2dd95SBruce Richardson /* 2499a2dd95SBruce Richardson * If the compiler doesn't support AVX512 instructions, 2599a2dd95SBruce Richardson * then the dummy one would be used instead for AVX512 classify method. 2699a2dd95SBruce Richardson */ 2799a2dd95SBruce Richardson int 2899a2dd95SBruce Richardson rte_acl_classify_avx512x16(__rte_unused const struct rte_acl_ctx *ctx, 2999a2dd95SBruce Richardson __rte_unused const uint8_t **data, 3099a2dd95SBruce Richardson __rte_unused uint32_t *results, 3199a2dd95SBruce Richardson __rte_unused uint32_t num, 3299a2dd95SBruce Richardson __rte_unused uint32_t categories) 3399a2dd95SBruce Richardson { 3499a2dd95SBruce Richardson return -ENOTSUP; 3599a2dd95SBruce Richardson } 3699a2dd95SBruce Richardson 3799a2dd95SBruce Richardson int 3899a2dd95SBruce Richardson rte_acl_classify_avx512x32(__rte_unused const struct rte_acl_ctx *ctx, 3999a2dd95SBruce Richardson __rte_unused const uint8_t **data, 4099a2dd95SBruce Richardson __rte_unused uint32_t *results, 4199a2dd95SBruce Richardson __rte_unused uint32_t num, 4299a2dd95SBruce Richardson __rte_unused uint32_t categories) 4399a2dd95SBruce Richardson { 4499a2dd95SBruce Richardson return -ENOTSUP; 4599a2dd95SBruce Richardson } 4699a2dd95SBruce Richardson #endif 4799a2dd95SBruce Richardson 48b0986c39SBruce Richardson #ifndef RTE_ARCH_X86 4999a2dd95SBruce Richardson /* 50b0986c39SBruce Richardson * If ISA doesn't have AVX2 or SSE, provide dummy fallbacks 5199a2dd95SBruce Richardson */ 5299a2dd95SBruce Richardson int 5399a2dd95SBruce Richardson rte_acl_classify_avx2(__rte_unused const struct rte_acl_ctx *ctx, 5499a2dd95SBruce Richardson __rte_unused const uint8_t **data, 5599a2dd95SBruce Richardson __rte_unused uint32_t *results, 5699a2dd95SBruce Richardson __rte_unused uint32_t num, 5799a2dd95SBruce Richardson __rte_unused uint32_t categories) 5899a2dd95SBruce Richardson { 5999a2dd95SBruce Richardson return -ENOTSUP; 6099a2dd95SBruce Richardson } 6199a2dd95SBruce Richardson int 6299a2dd95SBruce Richardson rte_acl_classify_sse(__rte_unused const struct rte_acl_ctx *ctx, 6399a2dd95SBruce Richardson __rte_unused const uint8_t **data, 6499a2dd95SBruce Richardson __rte_unused uint32_t *results, 6599a2dd95SBruce Richardson __rte_unused uint32_t num, 6699a2dd95SBruce Richardson __rte_unused uint32_t categories) 6799a2dd95SBruce Richardson { 6899a2dd95SBruce Richardson return -ENOTSUP; 6999a2dd95SBruce Richardson } 7099a2dd95SBruce Richardson #endif 7199a2dd95SBruce Richardson 7299a2dd95SBruce Richardson #ifndef RTE_ARCH_ARM 7399a2dd95SBruce Richardson int 7499a2dd95SBruce Richardson rte_acl_classify_neon(__rte_unused const struct rte_acl_ctx *ctx, 7599a2dd95SBruce Richardson __rte_unused const uint8_t **data, 7699a2dd95SBruce Richardson __rte_unused uint32_t *results, 7799a2dd95SBruce Richardson __rte_unused uint32_t num, 7899a2dd95SBruce Richardson __rte_unused uint32_t categories) 7999a2dd95SBruce Richardson { 8099a2dd95SBruce Richardson return -ENOTSUP; 8199a2dd95SBruce Richardson } 8299a2dd95SBruce Richardson #endif 8399a2dd95SBruce Richardson 8499a2dd95SBruce Richardson #ifndef RTE_ARCH_PPC_64 8599a2dd95SBruce Richardson int 8699a2dd95SBruce Richardson rte_acl_classify_altivec(__rte_unused const struct rte_acl_ctx *ctx, 8799a2dd95SBruce Richardson __rte_unused const uint8_t **data, 8899a2dd95SBruce Richardson __rte_unused uint32_t *results, 8999a2dd95SBruce Richardson __rte_unused uint32_t num, 9099a2dd95SBruce Richardson __rte_unused uint32_t categories) 9199a2dd95SBruce Richardson { 9299a2dd95SBruce Richardson return -ENOTSUP; 9399a2dd95SBruce Richardson } 9499a2dd95SBruce Richardson #endif 9599a2dd95SBruce Richardson 9699a2dd95SBruce Richardson static const rte_acl_classify_t classify_fns[] = { 9799a2dd95SBruce Richardson [RTE_ACL_CLASSIFY_DEFAULT] = rte_acl_classify_scalar, 9899a2dd95SBruce Richardson [RTE_ACL_CLASSIFY_SCALAR] = rte_acl_classify_scalar, 9999a2dd95SBruce Richardson [RTE_ACL_CLASSIFY_SSE] = rte_acl_classify_sse, 10099a2dd95SBruce Richardson [RTE_ACL_CLASSIFY_AVX2] = rte_acl_classify_avx2, 10199a2dd95SBruce Richardson [RTE_ACL_CLASSIFY_NEON] = rte_acl_classify_neon, 10299a2dd95SBruce Richardson [RTE_ACL_CLASSIFY_ALTIVEC] = rte_acl_classify_altivec, 10399a2dd95SBruce Richardson [RTE_ACL_CLASSIFY_AVX512X16] = rte_acl_classify_avx512x16, 10499a2dd95SBruce Richardson [RTE_ACL_CLASSIFY_AVX512X32] = rte_acl_classify_avx512x32, 10599a2dd95SBruce Richardson }; 10699a2dd95SBruce Richardson 10799a2dd95SBruce Richardson /* 10899a2dd95SBruce Richardson * Helper function for acl_check_alg. 10999a2dd95SBruce Richardson * Check support for ARM specific classify methods. 11099a2dd95SBruce Richardson */ 11199a2dd95SBruce Richardson static int 11299a2dd95SBruce Richardson acl_check_alg_arm(enum rte_acl_classify_alg alg) 11399a2dd95SBruce Richardson { 11499a2dd95SBruce Richardson if (alg == RTE_ACL_CLASSIFY_NEON) { 11599a2dd95SBruce Richardson #if defined(RTE_ARCH_ARM64) 11699a2dd95SBruce Richardson if (rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) 11799a2dd95SBruce Richardson return 0; 11899a2dd95SBruce Richardson #elif defined(RTE_ARCH_ARM) 11999a2dd95SBruce Richardson if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON) && 12099a2dd95SBruce Richardson rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) 12199a2dd95SBruce Richardson return 0; 12299a2dd95SBruce Richardson #endif 12399a2dd95SBruce Richardson return -ENOTSUP; 12499a2dd95SBruce Richardson } 12599a2dd95SBruce Richardson 12699a2dd95SBruce Richardson return -EINVAL; 12799a2dd95SBruce Richardson } 12899a2dd95SBruce Richardson 12999a2dd95SBruce Richardson /* 13099a2dd95SBruce Richardson * Helper function for acl_check_alg. 13199a2dd95SBruce Richardson * Check support for PPC specific classify methods. 13299a2dd95SBruce Richardson */ 13399a2dd95SBruce Richardson static int 13499a2dd95SBruce Richardson acl_check_alg_ppc(enum rte_acl_classify_alg alg) 13599a2dd95SBruce Richardson { 13699a2dd95SBruce Richardson if (alg == RTE_ACL_CLASSIFY_ALTIVEC) { 13799a2dd95SBruce Richardson #if defined(RTE_ARCH_PPC_64) 13899a2dd95SBruce Richardson if (rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) 13999a2dd95SBruce Richardson return 0; 14099a2dd95SBruce Richardson #endif 14199a2dd95SBruce Richardson return -ENOTSUP; 14299a2dd95SBruce Richardson } 14399a2dd95SBruce Richardson 14499a2dd95SBruce Richardson return -EINVAL; 14599a2dd95SBruce Richardson } 14699a2dd95SBruce Richardson 14799a2dd95SBruce Richardson #ifdef CC_AVX512_SUPPORT 14899a2dd95SBruce Richardson static int 14999a2dd95SBruce Richardson acl_check_avx512_cpu_flags(void) 15099a2dd95SBruce Richardson { 15199a2dd95SBruce Richardson return (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) && 15299a2dd95SBruce Richardson rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512VL) && 15399a2dd95SBruce Richardson rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512CD) && 15499a2dd95SBruce Richardson rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512BW)); 15599a2dd95SBruce Richardson } 15699a2dd95SBruce Richardson #endif 15799a2dd95SBruce Richardson 15899a2dd95SBruce Richardson /* 15999a2dd95SBruce Richardson * Helper function for acl_check_alg. 16099a2dd95SBruce Richardson * Check support for x86 specific classify methods. 16199a2dd95SBruce Richardson */ 16299a2dd95SBruce Richardson static int 16399a2dd95SBruce Richardson acl_check_alg_x86(enum rte_acl_classify_alg alg) 16499a2dd95SBruce Richardson { 16599a2dd95SBruce Richardson if (alg == RTE_ACL_CLASSIFY_AVX512X32) { 16699a2dd95SBruce Richardson #ifdef CC_AVX512_SUPPORT 16799a2dd95SBruce Richardson if (acl_check_avx512_cpu_flags() != 0 && 16899a2dd95SBruce Richardson rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_512) 16999a2dd95SBruce Richardson return 0; 17099a2dd95SBruce Richardson #endif 17199a2dd95SBruce Richardson return -ENOTSUP; 17299a2dd95SBruce Richardson } 17399a2dd95SBruce Richardson 17499a2dd95SBruce Richardson if (alg == RTE_ACL_CLASSIFY_AVX512X16) { 17599a2dd95SBruce Richardson #ifdef CC_AVX512_SUPPORT 17699a2dd95SBruce Richardson if (acl_check_avx512_cpu_flags() != 0 && 17799a2dd95SBruce Richardson rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_256) 17899a2dd95SBruce Richardson return 0; 17999a2dd95SBruce Richardson #endif 18099a2dd95SBruce Richardson return -ENOTSUP; 18199a2dd95SBruce Richardson } 18299a2dd95SBruce Richardson 18399a2dd95SBruce Richardson if (alg == RTE_ACL_CLASSIFY_AVX2) { 184b0986c39SBruce Richardson #ifdef RTE_ARCH_X86 18599a2dd95SBruce Richardson if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2) && 18699a2dd95SBruce Richardson rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_256) 18799a2dd95SBruce Richardson return 0; 18899a2dd95SBruce Richardson #endif 18999a2dd95SBruce Richardson return -ENOTSUP; 19099a2dd95SBruce Richardson } 19199a2dd95SBruce Richardson 19299a2dd95SBruce Richardson if (alg == RTE_ACL_CLASSIFY_SSE) { 19399a2dd95SBruce Richardson #ifdef RTE_ARCH_X86 19499a2dd95SBruce Richardson if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1) && 19599a2dd95SBruce Richardson rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) 19699a2dd95SBruce Richardson return 0; 19799a2dd95SBruce Richardson #endif 19899a2dd95SBruce Richardson return -ENOTSUP; 19999a2dd95SBruce Richardson } 20099a2dd95SBruce Richardson 20199a2dd95SBruce Richardson return -EINVAL; 20299a2dd95SBruce Richardson } 20399a2dd95SBruce Richardson 20499a2dd95SBruce Richardson /* 20599a2dd95SBruce Richardson * Check if input alg is supported by given platform/binary. 20699a2dd95SBruce Richardson * Note that both conditions should be met: 20799a2dd95SBruce Richardson * - at build time compiler supports ISA used by given methods 20899a2dd95SBruce Richardson * - at run time target cpu supports necessary ISA. 20999a2dd95SBruce Richardson */ 21099a2dd95SBruce Richardson static int 21199a2dd95SBruce Richardson acl_check_alg(enum rte_acl_classify_alg alg) 21299a2dd95SBruce Richardson { 21399a2dd95SBruce Richardson switch (alg) { 21499a2dd95SBruce Richardson case RTE_ACL_CLASSIFY_NEON: 21599a2dd95SBruce Richardson return acl_check_alg_arm(alg); 21699a2dd95SBruce Richardson case RTE_ACL_CLASSIFY_ALTIVEC: 21799a2dd95SBruce Richardson return acl_check_alg_ppc(alg); 21899a2dd95SBruce Richardson case RTE_ACL_CLASSIFY_AVX512X32: 21999a2dd95SBruce Richardson case RTE_ACL_CLASSIFY_AVX512X16: 22099a2dd95SBruce Richardson case RTE_ACL_CLASSIFY_AVX2: 22199a2dd95SBruce Richardson case RTE_ACL_CLASSIFY_SSE: 22299a2dd95SBruce Richardson return acl_check_alg_x86(alg); 22399a2dd95SBruce Richardson /* scalar method is supported on all platforms */ 22499a2dd95SBruce Richardson case RTE_ACL_CLASSIFY_SCALAR: 22599a2dd95SBruce Richardson return 0; 22699a2dd95SBruce Richardson default: 22799a2dd95SBruce Richardson return -EINVAL; 22899a2dd95SBruce Richardson } 22999a2dd95SBruce Richardson } 23099a2dd95SBruce Richardson 23199a2dd95SBruce Richardson /* 23299a2dd95SBruce Richardson * Get preferred alg for given platform. 23399a2dd95SBruce Richardson */ 23499a2dd95SBruce Richardson static enum rte_acl_classify_alg 23599a2dd95SBruce Richardson acl_get_best_alg(void) 23699a2dd95SBruce Richardson { 23799a2dd95SBruce Richardson /* 23899a2dd95SBruce Richardson * array of supported methods for each platform. 23999a2dd95SBruce Richardson * Note that order is important - from most to less preferable. 24099a2dd95SBruce Richardson */ 24199a2dd95SBruce Richardson static const enum rte_acl_classify_alg alg[] = { 24299a2dd95SBruce Richardson #if defined(RTE_ARCH_ARM) 24399a2dd95SBruce Richardson RTE_ACL_CLASSIFY_NEON, 24499a2dd95SBruce Richardson #elif defined(RTE_ARCH_PPC_64) 24599a2dd95SBruce Richardson RTE_ACL_CLASSIFY_ALTIVEC, 24699a2dd95SBruce Richardson #elif defined(RTE_ARCH_X86) 24799a2dd95SBruce Richardson RTE_ACL_CLASSIFY_AVX512X32, 24899a2dd95SBruce Richardson RTE_ACL_CLASSIFY_AVX512X16, 24999a2dd95SBruce Richardson RTE_ACL_CLASSIFY_AVX2, 25099a2dd95SBruce Richardson RTE_ACL_CLASSIFY_SSE, 25199a2dd95SBruce Richardson #endif 25299a2dd95SBruce Richardson RTE_ACL_CLASSIFY_SCALAR, 25399a2dd95SBruce Richardson }; 25499a2dd95SBruce Richardson 25599a2dd95SBruce Richardson uint32_t i; 25699a2dd95SBruce Richardson 25799a2dd95SBruce Richardson /* find best possible alg */ 25899a2dd95SBruce Richardson for (i = 0; i != RTE_DIM(alg) && acl_check_alg(alg[i]) != 0; i++) 25999a2dd95SBruce Richardson ; 26099a2dd95SBruce Richardson 26199a2dd95SBruce Richardson /* we always have to find something suitable */ 26299a2dd95SBruce Richardson RTE_VERIFY(i != RTE_DIM(alg)); 26399a2dd95SBruce Richardson return alg[i]; 26499a2dd95SBruce Richardson } 26599a2dd95SBruce Richardson 26699a2dd95SBruce Richardson extern int 26799a2dd95SBruce Richardson rte_acl_set_ctx_classify(struct rte_acl_ctx *ctx, enum rte_acl_classify_alg alg) 26899a2dd95SBruce Richardson { 26999a2dd95SBruce Richardson int32_t rc; 27099a2dd95SBruce Richardson 27199a2dd95SBruce Richardson /* formal parameters check */ 27299a2dd95SBruce Richardson if (ctx == NULL || (uint32_t)alg >= RTE_DIM(classify_fns)) 27399a2dd95SBruce Richardson return -EINVAL; 27499a2dd95SBruce Richardson 27599a2dd95SBruce Richardson /* user asked us to select the *best* one */ 27699a2dd95SBruce Richardson if (alg == RTE_ACL_CLASSIFY_DEFAULT) 27799a2dd95SBruce Richardson alg = acl_get_best_alg(); 27899a2dd95SBruce Richardson 27999a2dd95SBruce Richardson /* check that given alg is supported */ 28099a2dd95SBruce Richardson rc = acl_check_alg(alg); 28199a2dd95SBruce Richardson if (rc != 0) 28299a2dd95SBruce Richardson return rc; 28399a2dd95SBruce Richardson 28499a2dd95SBruce Richardson ctx->alg = alg; 28599a2dd95SBruce Richardson return 0; 28699a2dd95SBruce Richardson } 28799a2dd95SBruce Richardson 28899a2dd95SBruce Richardson int 28999a2dd95SBruce Richardson rte_acl_classify_alg(const struct rte_acl_ctx *ctx, const uint8_t **data, 29099a2dd95SBruce Richardson uint32_t *results, uint32_t num, uint32_t categories, 29199a2dd95SBruce Richardson enum rte_acl_classify_alg alg) 29299a2dd95SBruce Richardson { 29399a2dd95SBruce Richardson if (categories != 1 && 29499a2dd95SBruce Richardson ((RTE_ACL_RESULTS_MULTIPLIER - 1) & categories) != 0) 29599a2dd95SBruce Richardson return -EINVAL; 29699a2dd95SBruce Richardson 29799a2dd95SBruce Richardson return classify_fns[alg](ctx, data, results, num, categories); 29899a2dd95SBruce Richardson } 29999a2dd95SBruce Richardson 30099a2dd95SBruce Richardson int 30199a2dd95SBruce Richardson rte_acl_classify(const struct rte_acl_ctx *ctx, const uint8_t **data, 30299a2dd95SBruce Richardson uint32_t *results, uint32_t num, uint32_t categories) 30399a2dd95SBruce Richardson { 30499a2dd95SBruce Richardson return rte_acl_classify_alg(ctx, data, results, num, categories, 30599a2dd95SBruce Richardson ctx->alg); 30699a2dd95SBruce Richardson } 30799a2dd95SBruce Richardson 30899a2dd95SBruce Richardson struct rte_acl_ctx * 30999a2dd95SBruce Richardson rte_acl_find_existing(const char *name) 31099a2dd95SBruce Richardson { 31199a2dd95SBruce Richardson struct rte_acl_ctx *ctx = NULL; 31299a2dd95SBruce Richardson struct rte_acl_list *acl_list; 31399a2dd95SBruce Richardson struct rte_tailq_entry *te; 31499a2dd95SBruce Richardson 31599a2dd95SBruce Richardson acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); 31699a2dd95SBruce Richardson 31799a2dd95SBruce Richardson rte_mcfg_tailq_read_lock(); 31899a2dd95SBruce Richardson TAILQ_FOREACH(te, acl_list, next) { 31999a2dd95SBruce Richardson ctx = (struct rte_acl_ctx *) te->data; 32099a2dd95SBruce Richardson if (strncmp(name, ctx->name, sizeof(ctx->name)) == 0) 32199a2dd95SBruce Richardson break; 32299a2dd95SBruce Richardson } 32399a2dd95SBruce Richardson rte_mcfg_tailq_read_unlock(); 32499a2dd95SBruce Richardson 32599a2dd95SBruce Richardson if (te == NULL) { 32699a2dd95SBruce Richardson rte_errno = ENOENT; 32799a2dd95SBruce Richardson return NULL; 32899a2dd95SBruce Richardson } 32999a2dd95SBruce Richardson return ctx; 33099a2dd95SBruce Richardson } 33199a2dd95SBruce Richardson 33299a2dd95SBruce Richardson void 33399a2dd95SBruce Richardson rte_acl_free(struct rte_acl_ctx *ctx) 33499a2dd95SBruce Richardson { 33599a2dd95SBruce Richardson struct rte_acl_list *acl_list; 33699a2dd95SBruce Richardson struct rte_tailq_entry *te; 33799a2dd95SBruce Richardson 33899a2dd95SBruce Richardson if (ctx == NULL) 33999a2dd95SBruce Richardson return; 34099a2dd95SBruce Richardson 34199a2dd95SBruce Richardson acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); 34299a2dd95SBruce Richardson 34399a2dd95SBruce Richardson rte_mcfg_tailq_write_lock(); 34499a2dd95SBruce Richardson 34599a2dd95SBruce Richardson /* find our tailq entry */ 34699a2dd95SBruce Richardson TAILQ_FOREACH(te, acl_list, next) { 34799a2dd95SBruce Richardson if (te->data == (void *) ctx) 34899a2dd95SBruce Richardson break; 34999a2dd95SBruce Richardson } 35099a2dd95SBruce Richardson if (te == NULL) { 35199a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 35299a2dd95SBruce Richardson return; 35399a2dd95SBruce Richardson } 35499a2dd95SBruce Richardson 35599a2dd95SBruce Richardson TAILQ_REMOVE(acl_list, te, next); 35699a2dd95SBruce Richardson 35799a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 35899a2dd95SBruce Richardson 35999a2dd95SBruce Richardson rte_free(ctx->mem); 36099a2dd95SBruce Richardson rte_free(ctx); 36199a2dd95SBruce Richardson rte_free(te); 36299a2dd95SBruce Richardson } 36399a2dd95SBruce Richardson 36499a2dd95SBruce Richardson struct rte_acl_ctx * 36599a2dd95SBruce Richardson rte_acl_create(const struct rte_acl_param *param) 36699a2dd95SBruce Richardson { 36799a2dd95SBruce Richardson size_t sz; 36899a2dd95SBruce Richardson struct rte_acl_ctx *ctx; 36999a2dd95SBruce Richardson struct rte_acl_list *acl_list; 37099a2dd95SBruce Richardson struct rte_tailq_entry *te; 37199a2dd95SBruce Richardson char name[sizeof(ctx->name)]; 37299a2dd95SBruce Richardson 37399a2dd95SBruce Richardson acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); 37499a2dd95SBruce Richardson 37599a2dd95SBruce Richardson /* check that input parameters are valid. */ 37699a2dd95SBruce Richardson if (param == NULL || param->name == NULL) { 37799a2dd95SBruce Richardson rte_errno = EINVAL; 37899a2dd95SBruce Richardson return NULL; 37999a2dd95SBruce Richardson } 38099a2dd95SBruce Richardson 38199a2dd95SBruce Richardson snprintf(name, sizeof(name), "ACL_%s", param->name); 38299a2dd95SBruce Richardson 38399a2dd95SBruce Richardson /* calculate amount of memory required for pattern set. */ 38499a2dd95SBruce Richardson sz = sizeof(*ctx) + param->max_rule_num * param->rule_size; 38599a2dd95SBruce Richardson 38699a2dd95SBruce Richardson /* get EAL TAILQ lock. */ 38799a2dd95SBruce Richardson rte_mcfg_tailq_write_lock(); 38899a2dd95SBruce Richardson 38999a2dd95SBruce Richardson /* if we already have one with that name */ 39099a2dd95SBruce Richardson TAILQ_FOREACH(te, acl_list, next) { 39199a2dd95SBruce Richardson ctx = (struct rte_acl_ctx *) te->data; 39299a2dd95SBruce Richardson if (strncmp(param->name, ctx->name, sizeof(ctx->name)) == 0) 39399a2dd95SBruce Richardson break; 39499a2dd95SBruce Richardson } 39599a2dd95SBruce Richardson 39699a2dd95SBruce Richardson /* if ACL with such name doesn't exist, then create a new one. */ 39799a2dd95SBruce Richardson if (te == NULL) { 39899a2dd95SBruce Richardson ctx = NULL; 39999a2dd95SBruce Richardson te = rte_zmalloc("ACL_TAILQ_ENTRY", sizeof(*te), 0); 40099a2dd95SBruce Richardson 40199a2dd95SBruce Richardson if (te == NULL) { 40299a2dd95SBruce Richardson RTE_LOG(ERR, ACL, "Cannot allocate tailq entry!\n"); 40399a2dd95SBruce Richardson goto exit; 40499a2dd95SBruce Richardson } 40599a2dd95SBruce Richardson 40699a2dd95SBruce Richardson ctx = rte_zmalloc_socket(name, sz, RTE_CACHE_LINE_SIZE, param->socket_id); 40799a2dd95SBruce Richardson 40899a2dd95SBruce Richardson if (ctx == NULL) { 40999a2dd95SBruce Richardson RTE_LOG(ERR, ACL, 41099a2dd95SBruce Richardson "allocation of %zu bytes on socket %d for %s failed\n", 41199a2dd95SBruce Richardson sz, param->socket_id, name); 41299a2dd95SBruce Richardson rte_free(te); 41399a2dd95SBruce Richardson goto exit; 41499a2dd95SBruce Richardson } 41599a2dd95SBruce Richardson /* init new allocated context. */ 41699a2dd95SBruce Richardson ctx->rules = ctx + 1; 41799a2dd95SBruce Richardson ctx->max_rules = param->max_rule_num; 41899a2dd95SBruce Richardson ctx->rule_sz = param->rule_size; 41999a2dd95SBruce Richardson ctx->socket_id = param->socket_id; 42099a2dd95SBruce Richardson ctx->alg = acl_get_best_alg(); 42199a2dd95SBruce Richardson strlcpy(ctx->name, param->name, sizeof(ctx->name)); 42299a2dd95SBruce Richardson 42399a2dd95SBruce Richardson te->data = (void *) ctx; 42499a2dd95SBruce Richardson 42599a2dd95SBruce Richardson TAILQ_INSERT_TAIL(acl_list, te, next); 42699a2dd95SBruce Richardson } 42799a2dd95SBruce Richardson 42899a2dd95SBruce Richardson exit: 42999a2dd95SBruce Richardson rte_mcfg_tailq_write_unlock(); 43099a2dd95SBruce Richardson return ctx; 43199a2dd95SBruce Richardson } 43299a2dd95SBruce Richardson 43399a2dd95SBruce Richardson static int 43499a2dd95SBruce Richardson acl_add_rules(struct rte_acl_ctx *ctx, const void *rules, uint32_t num) 43599a2dd95SBruce Richardson { 43699a2dd95SBruce Richardson uint8_t *pos; 43799a2dd95SBruce Richardson 43899a2dd95SBruce Richardson if (num + ctx->num_rules > ctx->max_rules) 43999a2dd95SBruce Richardson return -ENOMEM; 44099a2dd95SBruce Richardson 44199a2dd95SBruce Richardson pos = ctx->rules; 44299a2dd95SBruce Richardson pos += ctx->rule_sz * ctx->num_rules; 44399a2dd95SBruce Richardson memcpy(pos, rules, num * ctx->rule_sz); 44499a2dd95SBruce Richardson ctx->num_rules += num; 44599a2dd95SBruce Richardson 44699a2dd95SBruce Richardson return 0; 44799a2dd95SBruce Richardson } 44899a2dd95SBruce Richardson 44999a2dd95SBruce Richardson static int 45099a2dd95SBruce Richardson acl_check_rule(const struct rte_acl_rule_data *rd) 45199a2dd95SBruce Richardson { 45299a2dd95SBruce Richardson if ((RTE_LEN2MASK(RTE_ACL_MAX_CATEGORIES, typeof(rd->category_mask)) & 45399a2dd95SBruce Richardson rd->category_mask) == 0 || 45499a2dd95SBruce Richardson rd->priority > RTE_ACL_MAX_PRIORITY || 45599a2dd95SBruce Richardson rd->priority < RTE_ACL_MIN_PRIORITY) 45699a2dd95SBruce Richardson return -EINVAL; 45799a2dd95SBruce Richardson return 0; 45899a2dd95SBruce Richardson } 45999a2dd95SBruce Richardson 46099a2dd95SBruce Richardson int 46199a2dd95SBruce Richardson rte_acl_add_rules(struct rte_acl_ctx *ctx, const struct rte_acl_rule *rules, 46299a2dd95SBruce Richardson uint32_t num) 46399a2dd95SBruce Richardson { 46499a2dd95SBruce Richardson const struct rte_acl_rule *rv; 46599a2dd95SBruce Richardson uint32_t i; 46699a2dd95SBruce Richardson int32_t rc; 46799a2dd95SBruce Richardson 46899a2dd95SBruce Richardson if (ctx == NULL || rules == NULL || 0 == ctx->rule_sz) 46999a2dd95SBruce Richardson return -EINVAL; 47099a2dd95SBruce Richardson 47199a2dd95SBruce Richardson for (i = 0; i != num; i++) { 47299a2dd95SBruce Richardson rv = (const struct rte_acl_rule *) 47399a2dd95SBruce Richardson ((uintptr_t)rules + i * ctx->rule_sz); 47499a2dd95SBruce Richardson rc = acl_check_rule(&rv->data); 47599a2dd95SBruce Richardson if (rc != 0) { 47699a2dd95SBruce Richardson RTE_LOG(ERR, ACL, "%s(%s): rule #%u is invalid\n", 47799a2dd95SBruce Richardson __func__, ctx->name, i + 1); 47899a2dd95SBruce Richardson return rc; 47999a2dd95SBruce Richardson } 48099a2dd95SBruce Richardson } 48199a2dd95SBruce Richardson 48299a2dd95SBruce Richardson return acl_add_rules(ctx, rules, num); 48399a2dd95SBruce Richardson } 48499a2dd95SBruce Richardson 48599a2dd95SBruce Richardson /* 48699a2dd95SBruce Richardson * Reset all rules. 48799a2dd95SBruce Richardson * Note that RT structures are not affected. 48899a2dd95SBruce Richardson */ 48999a2dd95SBruce Richardson void 49099a2dd95SBruce Richardson rte_acl_reset_rules(struct rte_acl_ctx *ctx) 49199a2dd95SBruce Richardson { 49299a2dd95SBruce Richardson if (ctx != NULL) 49399a2dd95SBruce Richardson ctx->num_rules = 0; 49499a2dd95SBruce Richardson } 49599a2dd95SBruce Richardson 49699a2dd95SBruce Richardson /* 49799a2dd95SBruce Richardson * Reset all rules and destroys RT structures. 49899a2dd95SBruce Richardson */ 49999a2dd95SBruce Richardson void 50099a2dd95SBruce Richardson rte_acl_reset(struct rte_acl_ctx *ctx) 50199a2dd95SBruce Richardson { 50299a2dd95SBruce Richardson if (ctx != NULL) { 50399a2dd95SBruce Richardson rte_acl_reset_rules(ctx); 50499a2dd95SBruce Richardson rte_acl_build(ctx, &ctx->config); 50599a2dd95SBruce Richardson } 50699a2dd95SBruce Richardson } 50799a2dd95SBruce Richardson 50899a2dd95SBruce Richardson /* 50999a2dd95SBruce Richardson * Dump ACL context to the stdout. 51099a2dd95SBruce Richardson */ 51199a2dd95SBruce Richardson void 51299a2dd95SBruce Richardson rte_acl_dump(const struct rte_acl_ctx *ctx) 51399a2dd95SBruce Richardson { 51499a2dd95SBruce Richardson if (!ctx) 51599a2dd95SBruce Richardson return; 51699a2dd95SBruce Richardson printf("acl context <%s>@%p\n", ctx->name, ctx); 51799a2dd95SBruce Richardson printf(" socket_id=%"PRId32"\n", ctx->socket_id); 51899a2dd95SBruce Richardson printf(" alg=%"PRId32"\n", ctx->alg); 51999a2dd95SBruce Richardson printf(" first_load_sz=%"PRIu32"\n", ctx->first_load_sz); 52099a2dd95SBruce Richardson printf(" max_rules=%"PRIu32"\n", ctx->max_rules); 52199a2dd95SBruce Richardson printf(" rule_size=%"PRIu32"\n", ctx->rule_sz); 52299a2dd95SBruce Richardson printf(" num_rules=%"PRIu32"\n", ctx->num_rules); 52399a2dd95SBruce Richardson printf(" num_categories=%"PRIu32"\n", ctx->num_categories); 52499a2dd95SBruce Richardson printf(" num_tries=%"PRIu32"\n", ctx->num_tries); 52599a2dd95SBruce Richardson } 52699a2dd95SBruce Richardson 52799a2dd95SBruce Richardson /* 52899a2dd95SBruce Richardson * Dump all ACL contexts to the stdout. 52999a2dd95SBruce Richardson */ 53099a2dd95SBruce Richardson void 53199a2dd95SBruce Richardson rte_acl_list_dump(void) 53299a2dd95SBruce Richardson { 53399a2dd95SBruce Richardson struct rte_acl_ctx *ctx; 53499a2dd95SBruce Richardson struct rte_acl_list *acl_list; 53599a2dd95SBruce Richardson struct rte_tailq_entry *te; 53699a2dd95SBruce Richardson 53799a2dd95SBruce Richardson acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); 53899a2dd95SBruce Richardson 53999a2dd95SBruce Richardson rte_mcfg_tailq_read_lock(); 54099a2dd95SBruce Richardson TAILQ_FOREACH(te, acl_list, next) { 54199a2dd95SBruce Richardson ctx = (struct rte_acl_ctx *) te->data; 54299a2dd95SBruce Richardson rte_acl_dump(ctx); 54399a2dd95SBruce Richardson } 54499a2dd95SBruce Richardson rte_mcfg_tailq_read_unlock(); 54599a2dd95SBruce Richardson } 546