From patchwork Sun May 15 20:03:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konstantin Ananyev X-Patchwork-Id: 111155 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 44AD8A00C2; Sun, 15 May 2022 22:03:34 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E320E40A7A; Sun, 15 May 2022 22:03:33 +0200 (CEST) Received: from forward500p.mail.yandex.net (forward500p.mail.yandex.net [77.88.28.110]) by mails.dpdk.org (Postfix) with ESMTP id 3A99840A79; Sun, 15 May 2022 22:03:32 +0200 (CEST) Received: from sas1-46a35d8d365a.qloud-c.yandex.net (sas1-46a35d8d365a.qloud-c.yandex.net [IPv6:2a02:6b8:c08:1aa0:0:640:46a3:5d8d]) by forward500p.mail.yandex.net (Yandex) with ESMTP id 98B26F01A39; Sun, 15 May 2022 23:03:31 +0300 (MSK) Received: from sas2-ffeb92823cb1.qloud-c.yandex.net (sas2-ffeb92823cb1.qloud-c.yandex.net [2a02:6b8:c08:6803:0:640:ffeb:9282]) by sas1-46a35d8d365a.qloud-c.yandex.net (mxback/Yandex) with ESMTP id j0M9vfLx8C-3Vh0uSHE; Sun, 15 May 2022 23:03:31 +0300 X-Yandex-Fwd: 2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1652645011; bh=zpb5D4jUHR2BLFwaAlaQNnwjr216hWnj8MfePcPYeek=; h=In-Reply-To:References:Date:Subject:Cc:To:From:Message-Id; b=s1SwHejbXITBdUqh27T5iQAUm57wIn8Kjh/SCEKTp/3fmnJb96TjQHNOb153xxokD Z09xafybqxL8B4qKtVcAYVW3KeUGe/ONwtRW087BVjPyf/SQjLVmxIrbtrgqObyVIw 7hkpbuEZRH1kRjgpIe0ITqMTgekTI+WpH+nTYPs4= Authentication-Results: sas1-46a35d8d365a.qloud-c.yandex.net; dkim=pass header.i=@yandex.ru Received: by sas2-ffeb92823cb1.qloud-c.yandex.net (smtp/Yandex) with ESMTPSA id 46XcTS98Er-3UMCV3IB; Sun, 15 May 2022 23:03:30 +0300 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (Client certificate not present) From: Konstantin Ananyev To: dev@dpdk.org Cc: ido@cgstowernetworks.com, stable@dpdk.org Subject: [PATCH v2 1/2] acl: fix rules with 8 bytes field size are broken Date: Sun, 15 May 2022 21:03:18 +0100 Message-Id: <20220515200319.81002-2-konstantin.v.ananyev@yandex.ru> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220515200319.81002-1-konstantin.v.ananyev@yandex.ru> References: <20220426174454.311999-1-konstantin.v.ananyev@yandex.ru> <20220515200319.81002-1-konstantin.v.ananyev@yandex.ru> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org In theory ACL library allows fields with 8B long. Though in practice they usually not used, not tested, and as was revealed by Ido, this functionality is not working properly. There are few places inside ACL build code-path that need to be addressed. Bugzilla ID: 673 Fixes: dc276b5780c2 ("acl: new library") Cc: stable@dpdk.org Reported-by: Ido Goshen Signed-off-by: Konstantin Ananyev Tested-by: Ido Goshen --- lib/acl/acl_bld.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/acl/acl_bld.c b/lib/acl/acl_bld.c index 7ea30f4186..2816632803 100644 --- a/lib/acl/acl_bld.c +++ b/lib/acl/acl_bld.c @@ -12,6 +12,9 @@ /* number of pointers per alloc */ #define ACL_PTR_ALLOC 32 +/* account for situation when all fields are 8B long */ +#define ACL_MAX_INDEXES (2 * RTE_ACL_MAX_FIELDS) + /* macros for dividing rule sets heuristics */ #define NODE_MAX 0x4000 #define NODE_MIN 0x800 @@ -80,7 +83,7 @@ struct acl_build_context { struct tb_mem_pool pool; struct rte_acl_trie tries[RTE_ACL_MAX_TRIES]; struct rte_acl_bld_trie bld_tries[RTE_ACL_MAX_TRIES]; - uint32_t data_indexes[RTE_ACL_MAX_TRIES][RTE_ACL_MAX_FIELDS]; + uint32_t data_indexes[RTE_ACL_MAX_TRIES][ACL_MAX_INDEXES]; /* memory free lists for nodes and blocks used for node ptrs */ struct acl_mem_block blocks[MEM_BLOCK_NUM]; @@ -988,7 +991,7 @@ build_trie(struct acl_build_context *context, struct rte_acl_build_rule *head, */ uint64_t mask; mask = RTE_ACL_MASKLEN_TO_BITMASK( - fld->mask_range.u32, + fld->mask_range.u64, rule->config->defs[n].size); /* gen a mini-trie for this field */ @@ -1301,6 +1304,9 @@ acl_build_index(const struct rte_acl_config *config, uint32_t *data_index) if (last_header != config->defs[n].input_index) { last_header = config->defs[n].input_index; data_index[m++] = config->defs[n].offset; + if (config->defs[n].size > sizeof(uint32_t)) + data_index[m++] = config->defs[n].offset + + sizeof(uint32_t); } } @@ -1487,7 +1493,7 @@ acl_set_data_indexes(struct rte_acl_ctx *ctx) memcpy(ctx->data_indexes + ofs, ctx->trie[i].data_index, n * sizeof(ctx->data_indexes[0])); ctx->trie[i].data_index = ctx->data_indexes + ofs; - ofs += RTE_ACL_MAX_FIELDS; + ofs += ACL_MAX_INDEXES; } } @@ -1643,7 +1649,7 @@ rte_acl_build(struct rte_acl_ctx *ctx, const struct rte_acl_config *cfg) /* allocate and fill run-time structures. */ rc = rte_acl_gen(ctx, bcx.tries, bcx.bld_tries, bcx.num_tries, bcx.cfg.num_categories, - RTE_ACL_MAX_FIELDS * RTE_DIM(bcx.tries) * + ACL_MAX_INDEXES * RTE_DIM(bcx.tries) * sizeof(ctx->data_indexes[0]), max_size); if (rc == 0) { /* set data indexes. */ From patchwork Sun May 15 20:03:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konstantin Ananyev X-Patchwork-Id: 111156 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6B7D8A00C2; Sun, 15 May 2022 22:03:40 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id CC80740A82; Sun, 15 May 2022 22:03:38 +0200 (CEST) Received: from forward501o.mail.yandex.net (forward501o.mail.yandex.net [37.140.190.203]) by mails.dpdk.org (Postfix) with ESMTP id D937D40A7F for ; Sun, 15 May 2022 22:03:37 +0200 (CEST) Received: from sas1-f3a441df9f84.qloud-c.yandex.net (sas1-f3a441df9f84.qloud-c.yandex.net [IPv6:2a02:6b8:c14:2726:0:640:f3a4:41df]) by forward501o.mail.yandex.net (Yandex) with ESMTP id 6D5E345C4491; Sun, 15 May 2022 23:03:37 +0300 (MSK) Received: from sas2-ffeb92823cb1.qloud-c.yandex.net (sas2-ffeb92823cb1.qloud-c.yandex.net [2a02:6b8:c08:6803:0:640:ffeb:9282]) by sas1-f3a441df9f84.qloud-c.yandex.net (mxback/Yandex) with ESMTP id aNGWnRbzim-3bfSu3NX; Sun, 15 May 2022 23:03:37 +0300 X-Yandex-Fwd: 2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1652645017; bh=pCILRqN+Gb+Dn5AhHmmpYJJHrL1DbIl0y9JwBV6c9tc=; h=In-Reply-To:References:Date:Subject:Cc:To:From:Message-Id; b=scs/jVNtxcYmZONaUkqkPOwxs9vV+SdHpdccNt7wtedKbxULKz32tXwUR7ZxpyVik b0O5HsOEjIwcaRYGsaZH0J4qiE1Q3WWrSLRLGskprvmOvBmmiuK2vevyIoi03Zb0Vg uiUR3OEwWBXi67NmU661jBOXO9Ox+qh9CK1wRAYo= Authentication-Results: sas1-f3a441df9f84.qloud-c.yandex.net; dkim=pass header.i=@yandex.ru Received: by sas2-ffeb92823cb1.qloud-c.yandex.net (smtp/Yandex) with ESMTPSA id 46XcTS98Er-3aMCK3Tu; Sun, 15 May 2022 23:03:36 +0300 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (Client certificate not present) From: Konstantin Ananyev To: dev@dpdk.org Cc: ido@cgstowernetworks.com Subject: [PATCH v2 2/2] app/acl: support different formats for IPv6 address Date: Sun, 15 May 2022 21:03:19 +0100 Message-Id: <20220515200319.81002-3-konstantin.v.ananyev@yandex.ru> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220515200319.81002-1-konstantin.v.ananyev@yandex.ru> References: <20220426174454.311999-1-konstantin.v.ananyev@yandex.ru> <20220515200319.81002-1-konstantin.v.ananyev@yandex.ru> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Within ACL rule IPv6 address can be represented in different ways: either as 4x4B fields, or as 2x8B fields. Till now, only first format was supported. Extend test-acl to support both formats, mainly for testing and demonstrating purposes. To control desired behavior '--ipv6' command-line option is extend to accept an optional argument: To be more precise: '--ipv6' - use 4x4B fields format (default behavior) '--ipv6=4B' - use 4x4B fields format (default behavior) '--ipv6=8B' - use 2x8B fields format Also replaced home brewed IPv4/IPv6 address parsing with inet_pton() calls. Signed-off-by: Konstantin Ananyev --- app/test-acl/main.c | 355 ++++++++++++++++++++++++++++++--------- app/test-acl/test-acl.sh | 4 +- 2 files changed, 279 insertions(+), 80 deletions(-) diff --git a/app/test-acl/main.c b/app/test-acl/main.c index 06e3847ab9..41ce83db08 100644 --- a/app/test-acl/main.c +++ b/app/test-acl/main.c @@ -57,6 +57,12 @@ enum { DUMP_MAX }; +enum { + IPV6_FRMT_NONE, + IPV6_FRMT_U32, + IPV6_FRMT_U64, +}; + struct acl_alg { const char *name; enum rte_acl_classify_alg alg; @@ -123,7 +129,7 @@ static struct { .name = "default", .alg = RTE_ACL_CLASSIFY_DEFAULT, }, - .ipv6 = 0 + .ipv6 = IPV6_FRMT_NONE, }; static struct rte_acl_param prm = { @@ -210,6 +216,7 @@ struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { #define IPV6_ADDR_LEN 16 #define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t)) #define IPV6_ADDR_U32 (IPV6_ADDR_LEN / sizeof(uint32_t)) +#define IPV6_ADDR_U64 (IPV6_ADDR_LEN / sizeof(uint64_t)) struct ipv6_5tuple { uint8_t proto; @@ -219,6 +226,7 @@ struct ipv6_5tuple { uint16_t port_dst; }; +/* treat IPV6 address as uint32_t[4] (default mode) */ enum { PROTO_FIELD_IPV6, SRC1_FIELD_IPV6, @@ -234,6 +242,27 @@ enum { NUM_FIELDS_IPV6 }; +/* treat IPV6 address as uint64_t[2] (default mode) */ +enum { + PROTO_FIELD_IPV6_U64, + SRC1_FIELD_IPV6_U64, + SRC2_FIELD_IPV6_U64, + DST1_FIELD_IPV6_U64, + DST2_FIELD_IPV6_U64, + SRCP_FIELD_IPV6_U64, + DSTP_FIELD_IPV6_U64, + NUM_FIELDS_IPV6_U64 +}; + +enum { + PROTO_INDEX_IPV6_U64 = PROTO_FIELD_IPV6_U64, + SRC1_INDEX_IPV6_U64 = SRC1_FIELD_IPV6_U64, + SRC2_INDEX_IPV6_U64 = SRC2_FIELD_IPV6_U64 + 1, + DST1_INDEX_IPV6_U64 = DST1_FIELD_IPV6_U64 + 2, + DST2_INDEX_IPV6_U64 = DST2_FIELD_IPV6_U64 + 3, + PRT_INDEX_IPV6_U64 = SRCP_FIELD_IPV6 + 4, +}; + struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, @@ -314,6 +343,57 @@ struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = { }, }; +struct rte_acl_field_def ipv6_u64_defs[NUM_FIELDS_IPV6_U64] = { + { + .type = RTE_ACL_FIELD_TYPE_BITMASK, + .size = sizeof(uint8_t), + .field_index = PROTO_FIELD_IPV6_U64, + .input_index = PROTO_FIELD_IPV6_U64, + .offset = offsetof(struct ipv6_5tuple, proto), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint64_t), + .field_index = SRC1_FIELD_IPV6_U64, + .input_index = SRC1_INDEX_IPV6_U64, + .offset = offsetof(struct ipv6_5tuple, ip_src[0]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint64_t), + .field_index = SRC2_FIELD_IPV6_U64, + .input_index = SRC2_INDEX_IPV6_U64, + .offset = offsetof(struct ipv6_5tuple, ip_src[2]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint64_t), + .field_index = DST1_FIELD_IPV6_U64, + .input_index = DST1_INDEX_IPV6_U64, + .offset = offsetof(struct ipv6_5tuple, ip_dst[0]), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint64_t), + .field_index = DST2_FIELD_IPV6_U64, + .input_index = DST2_INDEX_IPV6_U64, + .offset = offsetof(struct ipv6_5tuple, ip_dst[2]), + }, + { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = SRCP_FIELD_IPV6_U64, + .input_index = PRT_INDEX_IPV6_U64, + .offset = offsetof(struct ipv6_5tuple, port_src), + }, + { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = DSTP_FIELD_IPV6_U64, + .input_index = PRT_INDEX_IPV6_U64, + .offset = offsetof(struct ipv6_5tuple, port_dst), + }, +}; enum { CB_FLD_SRC_ADDR, @@ -385,49 +465,11 @@ parse_cb_ipv4_trace(char *str, struct ipv4_5tuple *v) return 0; } -/* - * Parse IPv6 address, expects the following format: - * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X is a hexadecimal digit). - */ -static int -parse_ipv6_addr(const char *in, const char **end, uint32_t v[IPV6_ADDR_U32], - char dlm) -{ - uint32_t addr[IPV6_ADDR_U16]; - - GET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':'); - GET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':'); - GET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':'); - GET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':'); - GET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':'); - GET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':'); - GET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':'); - GET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm); - - *end = in; - - v[0] = (addr[0] << 16) + addr[1]; - v[1] = (addr[2] << 16) + addr[3]; - v[2] = (addr[4] << 16) + addr[5]; - v[3] = (addr[6] << 16) + addr[7]; - - return 0; -} - static int parse_cb_ipv6_addr_trace(const char *in, uint32_t v[IPV6_ADDR_U32]) { - int32_t rc; - const char *end; - - rc = parse_ipv6_addr(in, &end, v, 0); - if (rc != 0) - return rc; - - v[0] = rte_cpu_to_be_32(v[0]); - v[1] = rte_cpu_to_be_32(v[1]); - v[2] = rte_cpu_to_be_32(v[2]); - v[3] = rte_cpu_to_be_32(v[3]); + if (inet_pton(AF_INET6, in, v) != 1) + return -EINVAL; return 0; } @@ -548,20 +590,33 @@ tracef_init(void) } static int -parse_ipv6_net(const char *in, struct rte_acl_field field[4]) +parse_ipv6_u32_net(char *in, struct rte_acl_field field[IPV6_ADDR_U32]) { - int32_t rc; - const char *mp; - uint32_t i, m, v[4]; + char *sa, *sm, *sv; + uint32_t i, m, v[IPV6_ADDR_U32]; + + const char *dlm = "/"; const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT; /* get address. */ - rc = parse_ipv6_addr(in, &mp, v, '/'); - if (rc != 0) - return rc; + sv = NULL; + sa = strtok_r(in, dlm, &sv); + if (sa == NULL) + return -EINVAL; + sm = strtok_r(NULL, dlm, &sv); + if (sm == NULL) + return -EINVAL; + + if (inet_pton(AF_INET6, sa, v) != 1) + return -EINVAL; + + v[0] = rte_be_to_cpu_32(v[0]); + v[1] = rte_be_to_cpu_32(v[1]); + v[2] = rte_be_to_cpu_32(v[2]); + v[3] = rte_be_to_cpu_32(v[3]); /* get mask. */ - GET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0); + GET_CB_FIELD(sm, m, 0, CHAR_BIT * sizeof(v), 0); /* put all together. */ for (i = 0; i != RTE_DIM(v); i++) { @@ -569,7 +624,7 @@ parse_ipv6_net(const char *in, struct rte_acl_field field[4]) field[i].mask_range.u32 = nbu32; else field[i].mask_range.u32 = m > (i * nbu32) ? - m - (i * 32) : 0; + m - (i * nbu32) : 0; field[i].value.u32 = v[i]; } @@ -577,14 +632,88 @@ parse_ipv6_net(const char *in, struct rte_acl_field field[4]) return 0; } +static int +parse_ipv6_u64_net(char *in, struct rte_acl_field field[IPV6_ADDR_U64]) +{ + char *sa, *sm, *sv; + uint32_t i, m; + uint64_t v[IPV6_ADDR_U64]; + + const char *dlm = "/"; + const uint32_t nbu64 = sizeof(uint64_t) * CHAR_BIT; + + /* get address. */ + sv = NULL; + sa = strtok_r(in, dlm, &sv); + if (sa == NULL) + return -EINVAL; + sm = strtok_r(NULL, dlm, &sv); + if (sm == NULL) + return -EINVAL; + + if (inet_pton(AF_INET6, sa, v) != 1) + return -EINVAL; + + v[0] = rte_be_to_cpu_64(v[0]); + v[1] = rte_be_to_cpu_64(v[1]); + + /* get mask. */ + GET_CB_FIELD(sm, m, 0, CHAR_BIT * sizeof(v), 0); + + /* put all together. */ + for (i = 0; i != RTE_DIM(v); i++) { + if (m >= (i + 1) * nbu64) + field[i].mask_range.u32 = nbu64; + else + field[i].mask_range.u32 = m > (i * nbu64) ? + m - (i * nbu64) : 0; + + field[i].value.u64 = v[i]; + } + + return 0; +} static int -parse_cb_ipv6_rule(char *str, struct acl_rule *v) +parse_cb_ipv6_rule(char *str, struct acl_rule *v, int frmt) { int i, rc; + uint32_t fidx; + const uint32_t *field_map; char *s, *sp, *in[CB_FLD_NUM]; + int (*parse_ipv6_net)(char *s, struct rte_acl_field f[]); + static const char *dlm = " \t\n"; + static const uint32_t field_map_u32[CB_FLD_NUM] = { + [CB_FLD_SRC_ADDR] = SRC1_FIELD_IPV6, + [CB_FLD_DST_ADDR] = DST1_FIELD_IPV6, + [CB_FLD_SRC_PORT_LOW] = SRCP_FIELD_IPV6, + [CB_FLD_SRC_PORT_HIGH] = SRCP_FIELD_IPV6, + [CB_FLD_DST_PORT_LOW] = DSTP_FIELD_IPV6, + [CB_FLD_DST_PORT_HIGH] = DSTP_FIELD_IPV6, + [CB_FLD_PROTO] = PROTO_FIELD_IPV6, + }; + + static const uint32_t field_map_u64[CB_FLD_NUM] = { + [CB_FLD_SRC_ADDR] = SRC1_FIELD_IPV6_U64, + [CB_FLD_DST_ADDR] = DST1_FIELD_IPV6_U64, + [CB_FLD_SRC_PORT_LOW] = SRCP_FIELD_IPV6_U64, + [CB_FLD_SRC_PORT_HIGH] = SRCP_FIELD_IPV6_U64, + [CB_FLD_DST_PORT_LOW] = DSTP_FIELD_IPV6_U64, + [CB_FLD_DST_PORT_HIGH] = DSTP_FIELD_IPV6_U64, + [CB_FLD_PROTO] = PROTO_FIELD_IPV6_U64, + }; + + if (frmt == IPV6_FRMT_U32) { + field_map = field_map_u32; + parse_ipv6_net = parse_ipv6_u32_net; + } else if (frmt == IPV6_FRMT_U64) { + field_map = field_map_u64; + parse_ipv6_net = parse_ipv6_u64_net; + } else + return -ENOTSUP; + /* * Skip leading '@' */ @@ -600,28 +729,30 @@ parse_cb_ipv6_rule(char *str, struct acl_rule *v) s = NULL; } - rc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6); + fidx = CB_FLD_SRC_ADDR; + rc = parse_ipv6_net(in[fidx], v->field + field_map[fidx]); if (rc != 0) { RTE_LOG(ERR, TESTACL, - "failed to read source address/mask: %s\n", - in[CB_FLD_SRC_ADDR]); + "failed to read source address/mask: %s\n", in[fidx]); return rc; } - rc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6); + fidx = CB_FLD_DST_ADDR; + rc = parse_ipv6_net(in[fidx], v->field + field_map[fidx]); if (rc != 0) { RTE_LOG(ERR, TESTACL, "failed to read destination address/mask: %s\n", - in[CB_FLD_DST_ADDR]); + in[fidx]); return rc; } /* source port. */ - GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], - v->field[SRCP_FIELD_IPV6].value.u16, + fidx = CB_FLD_SRC_PORT_LOW; + GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].value.u16, 0, UINT16_MAX, 0); - GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], - v->field[SRCP_FIELD_IPV6].mask_range.u16, + + fidx = CB_FLD_SRC_PORT_HIGH; + GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, @@ -629,37 +760,61 @@ parse_cb_ipv6_rule(char *str, struct acl_rule *v) return -EINVAL; /* destination port. */ - GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], - v->field[DSTP_FIELD_IPV6].value.u16, + fidx = CB_FLD_DST_PORT_LOW; + GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].value.u16, 0, UINT16_MAX, 0); - GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], - v->field[DSTP_FIELD_IPV6].mask_range.u16, + + fidx = CB_FLD_DST_PORT_HIGH; + GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].mask_range.u16, 0, UINT16_MAX, 0); if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, sizeof(cb_port_delim)) != 0) return -EINVAL; - GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8, + fidx = CB_FLD_PROTO; + GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].value.u8, 0, UINT8_MAX, '/'); - GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8, + GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].mask_range.u8, 0, UINT8_MAX, 0); return 0; } static int -parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len) +parse_cb_ipv6_u32_rule(char *str, struct acl_rule *v) { - uint8_t a, b, c, d, m; + return parse_cb_ipv6_rule(str, v, IPV6_FRMT_U32); +} - GET_CB_FIELD(in, a, 0, UINT8_MAX, '.'); - GET_CB_FIELD(in, b, 0, UINT8_MAX, '.'); - GET_CB_FIELD(in, c, 0, UINT8_MAX, '.'); - GET_CB_FIELD(in, d, 0, UINT8_MAX, '/'); - GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0); +static int +parse_cb_ipv6_u64_rule(char *str, struct acl_rule *v) +{ + return parse_cb_ipv6_rule(str, v, IPV6_FRMT_U64); +} + +static int +parse_ipv4_net(char *in, uint32_t *addr, uint32_t *mask_len) +{ + char *sa, *sm, *sv; + uint32_t m, v; - addr[0] = RTE_IPV4(a, b, c, d); + const char *dlm = "/"; + + sv = NULL; + sa = strtok_r(in, dlm, &sv); + if (sa == NULL) + return -EINVAL; + sm = strtok_r(NULL, dlm, &sv); + if (sm == NULL) + return -EINVAL; + + if (inet_pton(AF_INET, sa, &v) != 1) + return -EINVAL; + + addr[0] = rte_be_to_cpu_32(v); + + GET_CB_FIELD(sm, m, 0, sizeof(uint32_t) * CHAR_BIT, 0); mask_len[0] = m; return 0; @@ -757,8 +912,14 @@ add_cb_rules(FILE *f, struct rte_acl_ctx *ctx) struct acl_rule v; parse_5tuple parser; + static const parse_5tuple parser_func[] = { + [IPV6_FRMT_NONE] = parse_cb_ipv4_rule, + [IPV6_FRMT_U32] = parse_cb_ipv6_u32_rule, + [IPV6_FRMT_U64] = parse_cb_ipv6_u64_rule, + }; + memset(&v, 0, sizeof(v)); - parser = (config.ipv6 != 0) ? parse_cb_ipv6_rule : parse_cb_ipv4_rule; + parser = parser_func[config.ipv6]; k = 0; for (i = 1; fgets(line, sizeof(line), f) != NULL; i++) { @@ -804,9 +965,12 @@ acx_init(void) memset(&cfg, 0, sizeof(cfg)); /* setup ACL build config. */ - if (config.ipv6) { + if (config.ipv6 == IPV6_FRMT_U32) { cfg.num_fields = RTE_DIM(ipv6_defs); memcpy(&cfg.defs, ipv6_defs, sizeof(ipv6_defs)); + } else if (config.ipv6 == IPV6_FRMT_U64) { + cfg.num_fields = RTE_DIM(ipv6_u64_defs); + memcpy(&cfg.defs, ipv6_u64_defs, sizeof(ipv6_u64_defs)); } else { cfg.num_fields = RTE_DIM(ipv4_defs); memcpy(&cfg.defs, ipv4_defs, sizeof(ipv4_defs)); @@ -958,6 +1122,37 @@ get_alg_opt(const char *opt, const char *name) opt, name); } +static void +get_ipv6_opt(const char *opt, const char *name) +{ + uint32_t i; + + static const struct { + const char *name; + uint32_t val; + } ipv6_opt[] = { + { + .name = "4B", + .val = IPV6_FRMT_U32, + }, + { + .name = "8B", + .val = IPV6_FRMT_U64, + }, + }; + + for (i = 0; i != RTE_DIM(ipv6_opt); i++) { + if (strcmp(opt, ipv6_opt[i].name) == 0) { + config.ipv6 = ipv6_opt[i].val; + return; + } + } + + rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n", + opt, name); +} + + static void print_usage(const char *prgname) { @@ -999,7 +1194,7 @@ print_usage(const char *prgname) "[--" OPT_ITER_NUM "=]\n" "[--" OPT_VERBOSE "=]\n" "[--" OPT_SEARCH_ALG "=%s]\n" - "[--" OPT_IPV6 "=]\n", + "[--" OPT_IPV6 "(=4B | 8B) ]\n", prgname, RTE_ACL_RESULTS_MULTIPLIER, (uint32_t)RTE_ACL_MAX_CATEGORIES, buf); @@ -1050,7 +1245,7 @@ get_input_opts(int argc, char **argv) {OPT_ITER_NUM, 1, 0, 0}, {OPT_VERBOSE, 1, 0, 0}, {OPT_SEARCH_ALG, 1, 0, 0}, - {OPT_IPV6, 0, 0, 0}, + {OPT_IPV6, 2, 0, 0}, {NULL, 0, 0, 0} }; @@ -1099,7 +1294,9 @@ get_input_opts(int argc, char **argv) OPT_SEARCH_ALG) == 0) { get_alg_opt(optarg, lgopts[opt_idx].name); } else if (strcmp(lgopts[opt_idx].name, OPT_IPV6) == 0) { - config.ipv6 = 1; + config.ipv6 = IPV6_FRMT_U32; + if (optarg != NULL) + get_ipv6_opt(optarg, lgopts[opt_idx].name); } } config.trace_sz = config.ipv6 ? sizeof(struct ipv6_5tuple) : diff --git a/app/test-acl/test-acl.sh b/app/test-acl/test-acl.sh index c7bdc24113..30814f3fe2 100644 --- a/app/test-acl/test-acl.sh +++ b/app/test-acl/test-acl.sh @@ -86,7 +86,9 @@ for i in ${V4F}; do done for i in ${V6F}; do - XPRM='--ipv6' + XPRM='--ipv6=4B' + run_test $i + XPRM='--ipv6=8B' run_test $i unset XPRM done