xref: /dpdk/lib/acl/rte_acl.c (revision ae67895b507bb6af22263c79ba0d5c374b396485)
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"
1173d85848SStephen Hemminger #include "acl_log.h"
1273d85848SStephen Hemminger 
1373d85848SStephen 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 };
EAL_REGISTER_TAILQ(rte_acl_tailq)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
rte_acl_classify_avx512x32(__rte_unused const struct rte_acl_ctx * ctx,__rte_unused const uint8_t ** data,__rte_unused uint32_t * results,__rte_unused uint32_t num,__rte_unused uint32_t categories)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
rte_acl_classify_avx2(__rte_unused const struct rte_acl_ctx * ctx,__rte_unused const uint8_t ** data,__rte_unused uint32_t * results,__rte_unused uint32_t num,__rte_unused uint32_t categories)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
rte_acl_classify_sse(__rte_unused const struct rte_acl_ctx * ctx,__rte_unused const uint8_t ** data,__rte_unused uint32_t * results,__rte_unused uint32_t num,__rte_unused uint32_t categories)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
rte_acl_classify_neon(__rte_unused const struct rte_acl_ctx * ctx,__rte_unused const uint8_t ** data,__rte_unused uint32_t * results,__rte_unused uint32_t num,__rte_unused uint32_t categories)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
rte_acl_classify_altivec(__rte_unused const struct rte_acl_ctx * ctx,__rte_unused const uint8_t ** data,__rte_unused uint32_t * results,__rte_unused uint32_t num,__rte_unused uint32_t categories)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
acl_check_alg_arm(enum rte_acl_classify_alg alg)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
acl_check_alg_ppc(enum rte_acl_classify_alg alg)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
acl_check_avx512_cpu_flags(void)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
acl_check_alg_x86(enum rte_acl_classify_alg alg)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
acl_check_alg(enum rte_acl_classify_alg alg)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
acl_get_best_alg(void)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
rte_acl_set_ctx_classify(struct rte_acl_ctx * ctx,enum rte_acl_classify_alg alg)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
rte_acl_classify_alg(const struct rte_acl_ctx * ctx,const uint8_t ** data,uint32_t * results,uint32_t num,uint32_t categories,enum rte_acl_classify_alg alg)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
rte_acl_classify(const struct rte_acl_ctx * ctx,const uint8_t ** data,uint32_t * results,uint32_t num,uint32_t categories)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 *
rte_acl_find_existing(const char * name)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
rte_acl_free(struct rte_acl_ctx * ctx)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 *
rte_acl_create(const struct rte_acl_param * param)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) {
402*ae67895bSDavid Marchand 			ACL_LOG(ERR, "Cannot allocate tailq entry!");
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) {
409*ae67895bSDavid Marchand 			ACL_LOG(ERR,
410*ae67895bSDavid Marchand 				"allocation of %zu bytes on socket %d for %s failed",
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
acl_add_rules(struct rte_acl_ctx * ctx,const void * rules,uint32_t num)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
acl_check_rule(const struct rte_acl_rule_data * rd)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
rte_acl_add_rules(struct rte_acl_ctx * ctx,const struct rte_acl_rule * rules,uint32_t num)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) {
476*ae67895bSDavid Marchand 			ACL_LOG(ERR, "%s(%s): rule #%u is invalid",
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
rte_acl_reset_rules(struct rte_acl_ctx * ctx)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
rte_acl_reset(struct rte_acl_ctx * ctx)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
rte_acl_dump(const struct rte_acl_ctx * ctx)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
rte_acl_list_dump(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