[dpdk-dev] [PATCH v3 5/5] examples/ipsec-secgw: get rid of maximum sp limitation

Vladimir Medvedkin vladimir.medvedkin at intel.com
Mon Jan 13 13:55:22 CET 2020


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 <vladimir.medvedkin at intel.com>
---
 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 67df170..65eb7e9 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 1f8bd3e..6e764fe 100644
--- a/examples/ipsec-secgw/parser.h
+++ b/examples/ipsec-secgw/parser.h
@@ -67,10 +67,16 @@ 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 1dcec52..beddd7b 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 b489e15..328e085 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);
+}
-- 
2.7.4



More information about the dev mailing list