1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
5 #include <rte_string_fns.h>
9 TAILQ_HEAD(rte_acl_list
, rte_tailq_entry
);
11 static struct rte_tailq_elem rte_acl_tailq
= {
14 EAL_REGISTER_TAILQ(rte_acl_tailq
)
17 * If the compiler doesn't support AVX2 instructions,
18 * then the dummy one would be used instead for AVX2 classify method.
21 rte_acl_classify_avx2(__rte_unused
const struct rte_acl_ctx
*ctx
,
22 __rte_unused
const uint8_t **data
,
23 __rte_unused
uint32_t *results
,
24 __rte_unused
uint32_t num
,
25 __rte_unused
uint32_t categories
)
31 rte_acl_classify_sse(__rte_unused
const struct rte_acl_ctx
*ctx
,
32 __rte_unused
const uint8_t **data
,
33 __rte_unused
uint32_t *results
,
34 __rte_unused
uint32_t num
,
35 __rte_unused
uint32_t categories
)
41 rte_acl_classify_neon(__rte_unused
const struct rte_acl_ctx
*ctx
,
42 __rte_unused
const uint8_t **data
,
43 __rte_unused
uint32_t *results
,
44 __rte_unused
uint32_t num
,
45 __rte_unused
uint32_t categories
)
51 rte_acl_classify_altivec(__rte_unused
const struct rte_acl_ctx
*ctx
,
52 __rte_unused
const uint8_t **data
,
53 __rte_unused
uint32_t *results
,
54 __rte_unused
uint32_t num
,
55 __rte_unused
uint32_t categories
)
60 static const rte_acl_classify_t classify_fns
[] = {
61 [RTE_ACL_CLASSIFY_DEFAULT
] = rte_acl_classify_scalar
,
62 [RTE_ACL_CLASSIFY_SCALAR
] = rte_acl_classify_scalar
,
63 [RTE_ACL_CLASSIFY_SSE
] = rte_acl_classify_sse
,
64 [RTE_ACL_CLASSIFY_AVX2
] = rte_acl_classify_avx2
,
65 [RTE_ACL_CLASSIFY_NEON
] = rte_acl_classify_neon
,
66 [RTE_ACL_CLASSIFY_ALTIVEC
] = rte_acl_classify_altivec
,
69 /* by default, use always available scalar code path. */
70 static enum rte_acl_classify_alg rte_acl_default_classify
=
71 RTE_ACL_CLASSIFY_SCALAR
;
74 rte_acl_set_default_classify(enum rte_acl_classify_alg alg
)
76 rte_acl_default_classify
= alg
;
80 rte_acl_set_ctx_classify(struct rte_acl_ctx
*ctx
, enum rte_acl_classify_alg alg
)
82 if (ctx
== NULL
|| (uint32_t)alg
>= RTE_DIM(classify_fns
))
90 * Select highest available classify method as default one.
91 * Note that CLASSIFY_AVX2 should be set as a default only
92 * if both conditions are met:
93 * at build time compiler supports AVX2 and target cpu supports AVX2.
95 RTE_INIT(rte_acl_init
)
97 enum rte_acl_classify_alg alg
= RTE_ACL_CLASSIFY_DEFAULT
;
99 #if defined(RTE_ARCH_ARM64)
100 alg
= RTE_ACL_CLASSIFY_NEON
;
101 #elif defined(RTE_ARCH_ARM)
102 if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON
))
103 alg
= RTE_ACL_CLASSIFY_NEON
;
104 #elif defined(RTE_ARCH_PPC_64)
105 alg
= RTE_ACL_CLASSIFY_ALTIVEC
;
107 #ifdef CC_AVX2_SUPPORT
108 if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2
))
109 alg
= RTE_ACL_CLASSIFY_AVX2
;
110 else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1
))
112 if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1
))
114 alg
= RTE_ACL_CLASSIFY_SSE
;
117 rte_acl_set_default_classify(alg
);
121 rte_acl_classify_alg(const struct rte_acl_ctx
*ctx
, const uint8_t **data
,
122 uint32_t *results
, uint32_t num
, uint32_t categories
,
123 enum rte_acl_classify_alg alg
)
125 if (categories
!= 1 &&
126 ((RTE_ACL_RESULTS_MULTIPLIER
- 1) & categories
) != 0)
129 return classify_fns
[alg
](ctx
, data
, results
, num
, categories
);
133 rte_acl_classify(const struct rte_acl_ctx
*ctx
, const uint8_t **data
,
134 uint32_t *results
, uint32_t num
, uint32_t categories
)
136 return rte_acl_classify_alg(ctx
, data
, results
, num
, categories
,
141 rte_acl_find_existing(const char *name
)
143 struct rte_acl_ctx
*ctx
= NULL
;
144 struct rte_acl_list
*acl_list
;
145 struct rte_tailq_entry
*te
;
147 acl_list
= RTE_TAILQ_CAST(rte_acl_tailq
.head
, rte_acl_list
);
149 rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK
);
150 TAILQ_FOREACH(te
, acl_list
, next
) {
151 ctx
= (struct rte_acl_ctx
*) te
->data
;
152 if (strncmp(name
, ctx
->name
, sizeof(ctx
->name
)) == 0)
155 rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK
);
165 rte_acl_free(struct rte_acl_ctx
*ctx
)
167 struct rte_acl_list
*acl_list
;
168 struct rte_tailq_entry
*te
;
173 acl_list
= RTE_TAILQ_CAST(rte_acl_tailq
.head
, rte_acl_list
);
175 rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK
);
177 /* find our tailq entry */
178 TAILQ_FOREACH(te
, acl_list
, next
) {
179 if (te
->data
== (void *) ctx
)
183 rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK
);
187 TAILQ_REMOVE(acl_list
, te
, next
);
189 rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK
);
197 rte_acl_create(const struct rte_acl_param
*param
)
200 struct rte_acl_ctx
*ctx
;
201 struct rte_acl_list
*acl_list
;
202 struct rte_tailq_entry
*te
;
203 char name
[sizeof(ctx
->name
)];
205 acl_list
= RTE_TAILQ_CAST(rte_acl_tailq
.head
, rte_acl_list
);
207 /* check that input parameters are valid. */
208 if (param
== NULL
|| param
->name
== NULL
) {
213 snprintf(name
, sizeof(name
), "ACL_%s", param
->name
);
215 /* calculate amount of memory required for pattern set. */
216 sz
= sizeof(*ctx
) + param
->max_rule_num
* param
->rule_size
;
218 /* get EAL TAILQ lock. */
219 rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK
);
221 /* if we already have one with that name */
222 TAILQ_FOREACH(te
, acl_list
, next
) {
223 ctx
= (struct rte_acl_ctx
*) te
->data
;
224 if (strncmp(param
->name
, ctx
->name
, sizeof(ctx
->name
)) == 0)
228 /* if ACL with such name doesn't exist, then create a new one. */
231 te
= rte_zmalloc("ACL_TAILQ_ENTRY", sizeof(*te
), 0);
234 RTE_LOG(ERR
, ACL
, "Cannot allocate tailq entry!\n");
238 ctx
= rte_zmalloc_socket(name
, sz
, RTE_CACHE_LINE_SIZE
, param
->socket_id
);
242 "allocation of %zu bytes on socket %d for %s failed\n",
243 sz
, param
->socket_id
, name
);
247 /* init new allocated context. */
248 ctx
->rules
= ctx
+ 1;
249 ctx
->max_rules
= param
->max_rule_num
;
250 ctx
->rule_sz
= param
->rule_size
;
251 ctx
->socket_id
= param
->socket_id
;
252 ctx
->alg
= rte_acl_default_classify
;
253 strlcpy(ctx
->name
, param
->name
, sizeof(ctx
->name
));
255 te
->data
= (void *) ctx
;
257 TAILQ_INSERT_TAIL(acl_list
, te
, next
);
261 rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK
);
266 acl_add_rules(struct rte_acl_ctx
*ctx
, const void *rules
, uint32_t num
)
270 if (num
+ ctx
->num_rules
> ctx
->max_rules
)
274 pos
+= ctx
->rule_sz
* ctx
->num_rules
;
275 memcpy(pos
, rules
, num
* ctx
->rule_sz
);
276 ctx
->num_rules
+= num
;
282 acl_check_rule(const struct rte_acl_rule_data
*rd
)
284 if ((RTE_LEN2MASK(RTE_ACL_MAX_CATEGORIES
, typeof(rd
->category_mask
)) &
285 rd
->category_mask
) == 0 ||
286 rd
->priority
> RTE_ACL_MAX_PRIORITY
||
287 rd
->priority
< RTE_ACL_MIN_PRIORITY
)
293 rte_acl_add_rules(struct rte_acl_ctx
*ctx
, const struct rte_acl_rule
*rules
,
296 const struct rte_acl_rule
*rv
;
300 if (ctx
== NULL
|| rules
== NULL
|| 0 == ctx
->rule_sz
)
303 for (i
= 0; i
!= num
; i
++) {
304 rv
= (const struct rte_acl_rule
*)
305 ((uintptr_t)rules
+ i
* ctx
->rule_sz
);
306 rc
= acl_check_rule(&rv
->data
);
308 RTE_LOG(ERR
, ACL
, "%s(%s): rule #%u is invalid\n",
309 __func__
, ctx
->name
, i
+ 1);
314 return acl_add_rules(ctx
, rules
, num
);
319 * Note that RT structures are not affected.
322 rte_acl_reset_rules(struct rte_acl_ctx
*ctx
)
329 * Reset all rules and destroys RT structures.
332 rte_acl_reset(struct rte_acl_ctx
*ctx
)
335 rte_acl_reset_rules(ctx
);
336 rte_acl_build(ctx
, &ctx
->config
);
341 * Dump ACL context to the stdout.
344 rte_acl_dump(const struct rte_acl_ctx
*ctx
)
348 printf("acl context <%s>@%p\n", ctx
->name
, ctx
);
349 printf(" socket_id=%"PRId32
"\n", ctx
->socket_id
);
350 printf(" alg=%"PRId32
"\n", ctx
->alg
);
351 printf(" max_rules=%"PRIu32
"\n", ctx
->max_rules
);
352 printf(" rule_size=%"PRIu32
"\n", ctx
->rule_sz
);
353 printf(" num_rules=%"PRIu32
"\n", ctx
->num_rules
);
354 printf(" num_categories=%"PRIu32
"\n", ctx
->num_categories
);
355 printf(" num_tries=%"PRIu32
"\n", ctx
->num_tries
);
359 * Dump all ACL contexts to the stdout.
362 rte_acl_list_dump(void)
364 struct rte_acl_ctx
*ctx
;
365 struct rte_acl_list
*acl_list
;
366 struct rte_tailq_entry
*te
;
368 acl_list
= RTE_TAILQ_CAST(rte_acl_tailq
.head
, rte_acl_list
);
370 rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK
);
371 TAILQ_FOREACH(te
, acl_list
, next
) {
372 ctx
= (struct rte_acl_ctx
*) te
->data
;
375 rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK
);