X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_acl%2Frte_acl.c;h=b6ddeebcaf5ec0b853ab18c1532499d7942031f3;hb=a2348166ea186506d45b61d5073d16ad974e79bb;hp=129a41f9b92b735874021043b505a2193faaf86c;hpb=dc276b5780c29a86c537774b6f7b91379ee0690d;p=dpdk.git diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c index 129a41f9b9..b6ddeebcaf 100644 --- a/lib/librte_acl/rte_acl.c +++ b/lib/librte_acl/rte_acl.c @@ -36,43 +36,151 @@ #define BIT_SIZEOF(x) (sizeof(x) * CHAR_BIT) -TAILQ_HEAD(rte_acl_list, rte_acl_ctx); +TAILQ_HEAD(rte_acl_list, rte_tailq_entry); + +static struct rte_tailq_elem rte_acl_tailq = { + .name = "RTE_ACL", +}; +EAL_REGISTER_TAILQ(rte_acl_tailq) + +/* + * If the compiler doesn't support AVX2 instructions, + * then the dummy one would be used instead for AVX2 classify method. + */ +int __attribute__ ((weak)) +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) +{ + return -ENOTSUP; +} + +static const rte_acl_classify_t classify_fns[] = { + [RTE_ACL_CLASSIFY_DEFAULT] = rte_acl_classify_scalar, + [RTE_ACL_CLASSIFY_SCALAR] = rte_acl_classify_scalar, + [RTE_ACL_CLASSIFY_SSE] = rte_acl_classify_sse, + [RTE_ACL_CLASSIFY_AVX2] = rte_acl_classify_avx2, +}; + +/* by default, use always available scalar code path. */ +static enum rte_acl_classify_alg rte_acl_default_classify = + RTE_ACL_CLASSIFY_SCALAR; + +static void +rte_acl_set_default_classify(enum rte_acl_classify_alg alg) +{ + rte_acl_default_classify = alg; +} + +extern int +rte_acl_set_ctx_classify(struct rte_acl_ctx *ctx, enum rte_acl_classify_alg alg) +{ + if (ctx == NULL || (uint32_t)alg >= RTE_DIM(classify_fns)) + return -EINVAL; + + ctx->alg = alg; + return 0; +} + +/* + * Select highest available classify method as default one. + * Note that CLASSIFY_AVX2 should be set as a default only + * if both conditions are met: + * at build time compiler supports AVX2 and target cpu supports AVX2. + */ +static void __attribute__((constructor)) +rte_acl_init(void) +{ + enum rte_acl_classify_alg alg = RTE_ACL_CLASSIFY_DEFAULT; + +#ifdef CC_AVX2_SUPPORT + if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2)) + alg = RTE_ACL_CLASSIFY_AVX2; + else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1)) +#else + if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_1)) +#endif + alg = RTE_ACL_CLASSIFY_SSE; + + rte_acl_set_default_classify(alg); +} + +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) +{ + if (categories != 1 && + ((RTE_ACL_RESULTS_MULTIPLIER - 1) & categories) != 0) + return -EINVAL; + + return classify_fns[alg](ctx, data, results, num, categories); +} + +int +rte_acl_classify(const struct rte_acl_ctx *ctx, const uint8_t **data, + uint32_t *results, uint32_t num, uint32_t categories) +{ + return rte_acl_classify_alg(ctx, data, results, num, categories, + ctx->alg); +} struct rte_acl_ctx * rte_acl_find_existing(const char *name) { - struct rte_acl_ctx *ctx; + struct rte_acl_ctx *ctx = NULL; struct rte_acl_list *acl_list; + struct rte_tailq_entry *te; - /* check that we have an initialised tail queue */ - acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list); - if (acl_list == NULL) { - rte_errno = E_RTE_NO_TAILQ; - return NULL; - } + acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); - TAILQ_FOREACH(ctx, acl_list, next) { + TAILQ_FOREACH(te, acl_list, next) { + ctx = (struct rte_acl_ctx *) te->data; if (strncmp(name, ctx->name, sizeof(ctx->name)) == 0) break; } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); - if (ctx == NULL) + if (te == NULL) { rte_errno = ENOENT; + return NULL; + } return ctx; } void rte_acl_free(struct rte_acl_ctx *ctx) { + struct rte_acl_list *acl_list; + struct rte_tailq_entry *te; + if (ctx == NULL) return; - RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_ACL, rte_acl_list, ctx); + acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); + + rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); + + /* find our tailq entry */ + TAILQ_FOREACH(te, acl_list, next) { + if (te->data == (void *) ctx) + break; + } + if (te == NULL) { + rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); + return; + } + + TAILQ_REMOVE(acl_list, te, next); + + rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); rte_free(ctx->mem); rte_free(ctx); + rte_free(te); } struct rte_acl_ctx * @@ -81,14 +189,10 @@ rte_acl_create(const struct rte_acl_param *param) size_t sz; struct rte_acl_ctx *ctx; struct rte_acl_list *acl_list; + struct rte_tailq_entry *te; char name[sizeof(ctx->name)]; - /* check that we have an initialised tail queue */ - acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list); - if (acl_list == NULL) { - rte_errno = E_RTE_NO_TAILQ; - return NULL; - } + acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); /* check that input parameters are valid. */ if (param == NULL || param->name == NULL) { @@ -96,7 +200,7 @@ rte_acl_create(const struct rte_acl_param *param) return NULL; } - rte_snprintf(name, sizeof(name), "ACL_%s", param->name); + snprintf(name, sizeof(name), "ACL_%s", param->name); /* calculate amount of memory required for pattern set. */ sz = sizeof(*ctx) + param->max_rule_num * param->rule_size; @@ -105,30 +209,45 @@ rte_acl_create(const struct rte_acl_param *param) rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK); /* if we already have one with that name */ - TAILQ_FOREACH(ctx, acl_list, next) { + TAILQ_FOREACH(te, acl_list, next) { + ctx = (struct rte_acl_ctx *) te->data; if (strncmp(param->name, ctx->name, sizeof(ctx->name)) == 0) break; } /* if ACL with such name doesn't exist, then create a new one. */ - if (ctx == NULL && (ctx = rte_zmalloc_socket(name, sz, CACHE_LINE_SIZE, - param->socket_id)) != NULL) { + if (te == NULL) { + ctx = NULL; + te = rte_zmalloc("ACL_TAILQ_ENTRY", sizeof(*te), 0); + + if (te == NULL) { + RTE_LOG(ERR, ACL, "Cannot allocate tailq entry!\n"); + goto exit; + } + + ctx = rte_zmalloc_socket(name, sz, RTE_CACHE_LINE_SIZE, param->socket_id); + if (ctx == NULL) { + RTE_LOG(ERR, ACL, + "allocation of %zu bytes on socket %d for %s failed\n", + sz, param->socket_id, name); + rte_free(te); + goto exit; + } /* init new allocated context. */ ctx->rules = ctx + 1; ctx->max_rules = param->max_rule_num; ctx->rule_sz = param->rule_size; ctx->socket_id = param->socket_id; - rte_snprintf(ctx->name, sizeof(ctx->name), "%s", param->name); + ctx->alg = rte_acl_default_classify; + snprintf(ctx->name, sizeof(ctx->name), "%s", param->name); - TAILQ_INSERT_TAIL(acl_list, ctx, next); + te->data = (void *) ctx; - } else if (ctx == NULL) { - RTE_LOG(ERR, ACL, - "allocation of %zu bytes on socket %d for %s failed\n", - sz, param->socket_id, name); + TAILQ_INSERT_TAIL(acl_list, te, next); } +exit: rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); return ctx; } @@ -217,6 +336,8 @@ rte_acl_dump(const struct rte_acl_ctx *ctx) if (!ctx) return; printf("acl context <%s>@%p\n", ctx->name, ctx); + printf(" socket_id=%"PRId32"\n", ctx->socket_id); + printf(" alg=%"PRId32"\n", ctx->alg); printf(" max_rules=%"PRIu32"\n", ctx->max_rules); printf(" rule_size=%"PRIu32"\n", ctx->rule_sz); printf(" num_rules=%"PRIu32"\n", ctx->num_rules); @@ -232,16 +353,13 @@ rte_acl_list_dump(void) { struct rte_acl_ctx *ctx; struct rte_acl_list *acl_list; + struct rte_tailq_entry *te; - /* check that we have an initialised tail queue */ - acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list); - if (acl_list == NULL) { - rte_errno = E_RTE_NO_TAILQ; - return; - } + acl_list = RTE_TAILQ_CAST(rte_acl_tailq.head, rte_acl_list); rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK); - TAILQ_FOREACH(ctx, acl_list, next) { + TAILQ_FOREACH(te, acl_list, next) { + ctx = (struct rte_acl_ctx *) te->data; rte_acl_dump(ctx); } rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK); @@ -410,6 +528,7 @@ rte_acl_ipv4vlan_build(struct rte_acl_ctx *ctx, if (ctx == NULL || layout == NULL) return -EINVAL; + memset(&cfg, 0, sizeof(cfg)); acl_ipv4vlan_config(&cfg, layout, num_categories); return rte_acl_build(ctx, &cfg); }