From b0806375ae0d11194e8787e885c3f46ea7c54a4e Mon Sep 17 00:00:00 2001 From: Vladimir Medvedkin Date: Fri, 31 Jan 2020 17:39:42 +0000 Subject: [PATCH] examples/ipsec-secgw: get rid of maximum SP limitation Get rid of maximum SP limitation. Keep parsed SP's into the sorted by SPI value array. Use binary search in the sorted SP array to find appropriate SP for a given SPI. Signed-off-by: Vladimir Medvedkin Acked-by: Konstantin Ananyev Acked-by: Akhil Goyal Acked-by: Anoob Joseph --- examples/ipsec-secgw/parser.c | 2 + examples/ipsec-secgw/parser.h | 6 +++ examples/ipsec-secgw/sp4.c | 90 +++++++++++++++++++++++++++-------- examples/ipsec-secgw/sp6.c | 88 ++++++++++++++++++++++++++-------- 4 files changed, 144 insertions(+), 42 deletions(-) diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c index 67df1705c6..65eb7e9e2f 100644 --- a/examples/ipsec-secgw/parser.c +++ b/examples/ipsec-secgw/parser.c @@ -643,6 +643,8 @@ parse_cfg_file(const char *cfg_filename) fclose(f); sa_sort_arr(); + sp4_sort_arr(); + sp6_sort_arr(); return 0; diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h index 1f8bd3e9d4..6e764fe926 100644 --- a/examples/ipsec-secgw/parser.h +++ b/examples/ipsec-secgw/parser.h @@ -66,10 +66,16 @@ parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask); int parse_range(const char *token, uint16_t *low, uint16_t *high); +void +sp4_sort_arr(void); + void parse_sp4_tokens(char **tokens, uint32_t n_tokens, struct parse_status *status); +void +sp6_sort_arr(void); + void parse_sp6_tokens(char **tokens, uint32_t n_tokens, struct parse_status *status); diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c index 1dcec5267b..beddd7bc1d 100644 --- a/examples/ipsec-secgw/sp4.c +++ b/examples/ipsec-secgw/sp4.c @@ -15,7 +15,7 @@ #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)) @@ -97,11 +97,39 @@ static struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = { RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs)); -static struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM]; +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[MAX_ACL_RULE_NUM]; +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; +} + void parse_sp4_tokens(char **tokens, uint32_t n_tokens, @@ -127,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]; @@ -137,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]; @@ -451,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)); @@ -464,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) @@ -566,6 +592,16 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id) "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. */ @@ -573,8 +609,10 @@ int sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2], uint32_t mask[2]) { - uint32_t i, num; + uint32_t num; + struct acl4_rules *rule; const struct acl4_rules *acr; + struct acl4_rules tmpl; if (inbound != 0) { acr = acl4_rules_in; @@ -584,17 +622,27 @@ sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2], num = nb_acl4_rules_out; } - for (i = 0; i != num; i++) { - if (acr[i].data.userdata == spi) { - if (NULL != ip_addr && NULL != mask) { - ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(acr[i]); - ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(acr[i]); - mask[0] = IPV4_SRC_MASK_FROM_SP(acr[i]); - mask[1] = IPV4_DST_MASK_FROM_SP(acr[i]); - } - return i; + 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); +} diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c index b489e1581a..328e085288 100644 --- a/examples/ipsec-secgw/sp6.c +++ b/examples/ipsec-secgw/sp6.c @@ -15,7 +15,7 @@ #include "ipsec.h" #include "parser.h" -#define MAX_ACL_RULE_NUM 1024 +#define INIT_ACL_RULE_NUM 128 #define IPV6_FROM_SP(acr, fidx_low, fidx_high) \ (((uint64_t)(acr).field[(fidx_high)].value.u32 << 32) | \ @@ -146,11 +146,38 @@ static struct rte_acl_field_def ip6_defs[IP6_NUM] = { RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs)); -static struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM]; +static struct acl6_rules *acl6_rules_out; static uint32_t nb_acl6_rules_out; +static uint32_t sp_out_sz; -static struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM]; +static struct acl6_rules *acl6_rules_in; static uint32_t nb_acl6_rules_in; +static uint32_t sp_in_sz; + +static int +extend_sp_arr(struct acl6_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz) +{ + if (*sp_tbl == NULL) { + *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl6_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 acl6_rules) * 2); + if (*sp_tbl == NULL) + return -1; + /* clean reallocated extra space */ + memset(&(*sp_tbl)[*cur_sz], 0, + *cur_sz * sizeof(struct acl6_rules)); + *cur_sz *= 2; + } + + return 0; +} void parse_sp6_tokens(char **tokens, uint32_t n_tokens, @@ -176,9 +203,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens, if (strcmp(tokens[1], "in") == 0) { ri = &nb_acl6_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(&acl6_rules_in, nb_acl6_rules_in, + &sp_in_sz) < 0) return; rule_ipv6 = &acl6_rules_in[*ri]; @@ -186,9 +212,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens, } else if (strcmp(tokens[1], "out") == 0) { ri = &nb_acl6_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(&acl6_rules_out, nb_acl6_rules_out, + &sp_out_sz) < 0) return; rule_ipv6 = &acl6_rules_out[*ri]; @@ -583,7 +608,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_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)); @@ -596,7 +621,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules, acl_param.name = s; acl_param.socket_id = socketid; acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_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) @@ -698,6 +723,15 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id) "specified\n"); } +static int +sp_cmp(const void *p, const void *q) +{ + uint32_t spi1 = ((const struct acl6_rules *)p)->data.userdata; + uint32_t spi2 = ((const struct acl6_rules *)q)->data.userdata; + + return (int)(spi1 - spi2); +} + /* * Search though SP rules for given SPI. */ @@ -705,8 +739,10 @@ int sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2], uint32_t mask[2]) { - uint32_t i, num; + uint32_t num; + struct acl6_rules *rule; const struct acl6_rules *acr; + struct acl6_rules tmpl; if (inbound != 0) { acr = acl6_rules_in; @@ -716,17 +752,27 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2], num = nb_acl6_rules_out; } - for (i = 0; i != num; i++) { - if (acr[i].data.userdata == spi) { - if (NULL != ip_addr && NULL != mask) { - IPV6_SRC_FROM_SP(ip_addr[0], acr[i]); - IPV6_DST_FROM_SP(ip_addr[1], acr[i]); - IPV6_SRC_MASK_FROM_SP(mask[0], acr[i]); - IPV6_DST_MASK_FROM_SP(mask[1], acr[i]); - } - return i; + tmpl.data.userdata = spi; + + rule = bsearch(&tmpl, acr, num, sizeof(struct acl6_rules), sp_cmp); + if (rule != NULL) { + if (NULL != ip_addr && NULL != mask) { + IPV6_SRC_FROM_SP(ip_addr[0], *rule); + IPV6_DST_FROM_SP(ip_addr[1], *rule); + IPV6_SRC_MASK_FROM_SP(mask[0], *rule); + IPV6_DST_MASK_FROM_SP(mask[1], *rule); } + return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl6_rules); } return -ENOENT; } + +void +sp6_sort_arr(void) +{ + qsort(acl6_rules_in, nb_acl6_rules_in, sizeof(struct acl6_rules), + sp_cmp); + qsort(acl6_rules_out, nb_acl6_rules_out, sizeof(struct acl6_rules), + sp_cmp); +}