X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fipsec-secgw%2Fsp4.c;h=beddd7bc1dd2d45b5974d4264258e1a2371c156e;hb=573ef95dc7c9e4991da41fa1fc3d45c5c4076deb;hp=38c72a9271eb9ff42beac427a65197870dea8e36;hpb=0d547ed0371780b41f46d300be5bc3812101be51;p=dpdk.git diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c index 38c72a9271..beddd7bc1d 100644 --- a/examples/ipsec-secgw/sp4.c +++ b/examples/ipsec-secgw/sp4.c @@ -1,34 +1,5 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2016 Intel Corporation */ /* @@ -44,7 +15,19 @@ #include "ipsec.h" #include "parser.h" -#define MAX_ACL_RULE_NUM 1024 +#define INIT_ACL_RULE_NUM 128 + +#define IPV4_DST_FROM_SP(acr) \ + (rte_cpu_to_be_32((acr).field[DST_FIELD_IPV4].value.u32)) + +#define IPV4_SRC_FROM_SP(acr) \ + (rte_cpu_to_be_32((acr).field[SRC_FIELD_IPV4].value.u32)) + +#define IPV4_DST_MASK_FROM_SP(acr) \ + ((acr).field[DST_FIELD_IPV4].mask_range.u32) + +#define IPV4_SRC_MASK_FROM_SP(acr) \ + ((acr).field[SRC_FIELD_IPV4].mask_range.u32) /* * Rule and trace formats definitions. @@ -73,7 +56,7 @@ enum { RTE_ACL_IPV4_NUM }; -struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = { +static struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = { { .type = RTE_ACL_FIELD_TYPE_BITMASK, .size = sizeof(uint8_t), @@ -114,11 +97,39 @@ struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = { RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs)); -struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM]; -uint32_t nb_acl4_rules_out; +static struct acl4_rules *acl4_rules_out; +static uint32_t nb_acl4_rules_out; +static uint32_t sp_out_sz; + +static struct acl4_rules *acl4_rules_in; +static uint32_t nb_acl4_rules_in; +static uint32_t sp_in_sz; + +static int +extend_sp_arr(struct acl4_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz) +{ + if (*sp_tbl == NULL) { + *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl4_rules)); + if (*sp_tbl == NULL) + return -1; + *cur_sz = INIT_ACL_RULE_NUM; + return 0; + } + + if (cur_cnt >= *cur_sz) { + *sp_tbl = realloc(*sp_tbl, + *cur_sz * sizeof(struct acl4_rules) * 2); + if (*sp_tbl == NULL) + return -1; + /* clean reallocated extra space */ + memset(&(*sp_tbl)[*cur_sz], 0, + *cur_sz * sizeof(struct acl4_rules)); + *cur_sz *= 2; + } + + return 0; +} -struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM]; -uint32_t nb_acl4_rules_in; void parse_sp4_tokens(char **tokens, uint32_t n_tokens, @@ -128,6 +139,7 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens, uint32_t *ri = NULL; /* rule index */ uint32_t ti = 0; /* token index */ + uint32_t tv; uint32_t esp_p = 0; uint32_t protect_p = 0; @@ -143,9 +155,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens, if (strcmp(tokens[1], "in") == 0) { ri = &nb_acl4_rules_in; - APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, - "too many sp rules, abort insertion\n"); - if (status->status < 0) + if (extend_sp_arr(&acl4_rules_in, nb_acl4_rules_in, + &sp_in_sz) < 0) return; rule_ipv4 = &acl4_rules_in[*ri]; @@ -153,9 +164,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens, } else if (strcmp(tokens[1], "out") == 0) { ri = &nb_acl4_rules_out; - APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, - "too many sp rules, abort insertion\n"); - if (status->status < 0) + if (extend_sp_arr(&acl4_rules_out, nb_acl4_rules_out, + &sp_out_sz) < 0) return; rule_ipv4 = &acl4_rules_out[*ri]; @@ -198,8 +208,12 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens, if (status->status < 0) return; - rule_ipv4->data.userdata = - PROTECT(atoi(tokens[ti])); + tv = atoi(tokens[ti]); + APP_CHECK(tv != DISCARD && tv != BYPASS, status, + "invalid SPI: %s", tokens[ti]); + if (status->status < 0) + return; + rule_ipv4->data.userdata = tv; protect_p = 1; continue; @@ -463,7 +477,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules, struct rte_acl_config acl_build_param; struct rte_acl_ctx *ctx; - printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM); + printf("Creating SP context with %u rules\n", rules_nb); memset(&acl_param, 0, sizeof(acl_param)); @@ -476,7 +490,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules, acl_param.name = s; acl_param.socket_id = socketid; acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip4_defs)); - acl_param.max_rule_num = MAX_ACL_RULE_NUM; + acl_param.max_rule_num = rules_nb; ctx = rte_acl_create(&acl_param); if (ctx == NULL) @@ -501,6 +515,42 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules, return ctx; } +/* + * check that for each rule it's SPI has a correspondent entry in SAD + */ +static int +check_spi_value(struct sa_ctx *sa_ctx, int inbound) +{ + uint32_t i, num, spi; + int32_t spi_idx; + struct acl4_rules *acr; + + if (inbound != 0) { + acr = acl4_rules_in; + num = nb_acl4_rules_in; + } else { + acr = acl4_rules_out; + num = nb_acl4_rules_out; + } + + for (i = 0; i != num; i++) { + spi = acr[i].data.userdata; + if (spi != DISCARD && spi != BYPASS) { + spi_idx = sa_spi_present(sa_ctx, spi, inbound); + if (spi_idx < 0) { + RTE_LOG(ERR, IPSEC, + "SPI %u is not present in SAD\n", + spi); + return -ENOENT; + } + /* Update userdata with spi index */ + acr[i].data.userdata = spi_idx + 1; + } + } + + return 0; +} + void sp4_init(struct socket_ctx *ctx, int32_t socket_id) { @@ -517,6 +567,14 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id) rte_exit(EXIT_FAILURE, "Outbound SP DB for socket %u already " "initialized\n", socket_id); + if (check_spi_value(ctx->sa_in, 1) < 0) + rte_exit(EXIT_FAILURE, + "Inbound IPv4 SP DB has unmatched in SAD SPIs\n"); + + if (check_spi_value(ctx->sa_out, 0) < 0) + rte_exit(EXIT_FAILURE, + "Outbound IPv4 SP DB has unmatched in SAD SPIs\n"); + if (nb_acl4_rules_in > 0) { name = "sp_ip4_in"; ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name, @@ -533,3 +591,58 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id) RTE_LOG(WARNING, IPSEC, "No IPv4 SP Outbound rule " "specified\n"); } + +static int +sp_cmp(const void *p, const void *q) +{ + uint32_t spi1 = ((const struct acl4_rules *)p)->data.userdata; + uint32_t spi2 = ((const struct acl4_rules *)q)->data.userdata; + + return (int)(spi1 - spi2); +} + + +/* + * Search though SP rules for given SPI. + */ +int +sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2], + uint32_t mask[2]) +{ + uint32_t num; + struct acl4_rules *rule; + const struct acl4_rules *acr; + struct acl4_rules tmpl; + + if (inbound != 0) { + acr = acl4_rules_in; + num = nb_acl4_rules_in; + } else { + acr = acl4_rules_out; + num = nb_acl4_rules_out; + } + + tmpl.data.userdata = spi; + + rule = bsearch(&tmpl, acr, num, sizeof(struct acl4_rules), sp_cmp); + if (rule != NULL) { + if (NULL != ip_addr && NULL != mask) { + ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(*rule); + ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(*rule); + mask[0] = IPV4_SRC_MASK_FROM_SP(*rule); + mask[1] = IPV4_DST_MASK_FROM_SP(*rule); + } + return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl4_rules); + } + + return -ENOENT; +} + +void +sp4_sort_arr(void) +{ + qsort(acl4_rules_in, nb_acl4_rules_in, sizeof(struct acl4_rules), + sp_cmp); + qsort(acl4_rules_out, nb_acl4_rules_out, sizeof(struct acl4_rules), + sp_cmp); +}