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