Skip to contentSkip to conversation

integrate librte_ipsec SAD into ipsec-secgw

PATCH Superseded Vladimir Medvedkin 5 participants 60 messages Dec 11, 2019 – Feb 4, 2020 2 messages not in the archive Arm/Amlogic Meson SoC support

lore
Share & tools
lore
#0 lore raw

cover integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's.

Vladimir Medvedkin (4):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  13 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          | 236 +++++++++++++++++++------------------
 examples/ipsec-secgw/sad.c         |  90 ++++++++++++++
 examples/ipsec-secgw/sad.h         |  74 ++++++++++++
 examples/ipsec-secgw/sp4.c         |  24 ++--
 examples/ipsec-secgw/sp6.c         |  24 ++--
 lib/librte_ipsec/ipsec_sad.c       |  20 ++--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 11 files changed, 344 insertions(+), 146 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
Signature · 1 line
2.7.4
#1 lore raw

PATCH 1/4 ipsec: move ipsec sad name length into .h

Move IPSEC_SAD_NAMESIZE into public header
and rename it to RTE_IPSEC_SAD_NAMESIZE

---
 lib/librte_ipsec/ipsec_sad.c     | 20 ++++++++++----------
 lib/librte_ipsec/rte_ipsec_sad.h |  2 ++
 2 files changed, 12 insertions(+), 10 deletions(-)
lib/librte_ipsec/ipsec_sad.c +10 -10
index db2c44c..2c994ed 100644
@@ -20,7 +20,6 @@
  * indicate presence of entries with the same SPI in DIP and DIP+SIP tables.
  */
 
-#define IPSEC_SAD_NAMESIZE	64
 #define SAD_PREFIX		"SAD_"
 /* "SAD_<name>" */
 #define SAD_FORMAT		SAD_PREFIX "%s"
@@ -34,7 +33,7 @@ struct hash_cnt {
 };
 
 struct rte_ipsec_sad {
-	char name[IPSEC_SAD_NAMESIZE];
+	char name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_hash	*hash[RTE_IPSEC_SAD_KEY_TYPE_MASK];
 	/* Array to track number of more specific rules
 	 * (spi_dip or spi_dip_sip). Used only in add/delete
@@ -231,7 +230,7 @@ struct rte_ipsec_sad *
 rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 {
 	char hash_name[RTE_HASH_NAMESIZE];
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	struct rte_ipsec_sad *sad, *tmp_sad = NULL;
@@ -249,8 +248,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 		return NULL;
 	}
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -326,7 +325,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 	/* guarantee there's no existing */
 	TAILQ_FOREACH(te, sad_list, next) {
 		tmp_sad = (struct rte_ipsec_sad *)te->data;
-		if (strncmp(sad_name, tmp_sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, tmp_sad->name,
+				RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	if (te != NULL) {
@@ -354,14 +354,14 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 struct rte_ipsec_sad *
 rte_ipsec_sad_find_existing(const char *name)
 {
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_ipsec_sad *sad = NULL;
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	int ret;
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -372,7 +372,7 @@ rte_ipsec_sad_find_existing(const char *name)
 	rte_mcfg_tailq_read_lock();
 	TAILQ_FOREACH(te, sad_list, next) {
 		sad = (struct rte_ipsec_sad *) te->data;
-		if (strncmp(sad_name, sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, sad->name, RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	rte_mcfg_tailq_read_unlock();
lib/librte_ipsec/rte_ipsec_sad.h +2 -0
index 8386f73..dcc8224 100644
@@ -47,6 +47,8 @@ union rte_ipsec_sad_key {
 	struct rte_ipsec_sadv6_key	v6;
 };
 
+/** Max number of characters in SAD name. */
+#define RTE_IPSEC_SAD_NAMESIZE		64
 /** Flag to create SAD with ipv6 dip and sip addresses */
 #define RTE_IPSEC_SAD_FLAG_IPV6			0x1
 /** Flag to support reader writer concurrency */
Signature · 1 line
2.7.4
#2 lore raw

PATCH 2/4 examples/ipsec-secgw: implement inbound SAD

In reply to Vladimir Medvedkin

Add initial support for librte_ipsec SAD library

---
 examples/ipsec-secgw/ipsec.h | 11 ++++++
 examples/ipsec-secgw/sad.c   | 90 ++++++++++++++++++++++++++++++++++++++++++++
 examples/ipsec-secgw/sad.h   | 74 ++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
examples/ipsec-secgw/ipsec.h +11 -0
index 8e07521..132286c 100644
@@ -53,6 +53,17 @@ struct ipsec_xform;
 struct rte_mbuf;
 
 struct ipsec_sa;
+/*
+ * Keeps number of configured SA's of each type:
+ * transport
+ * v4 tunnel
+ * v6 tunnel
+ */
+struct ipsec_sa_cnt {
+	uint32_t	nb_trn;
+	uint32_t	nb_v4_tun;
+	uint32_t	nb_v6_tun;
+};
 
 typedef int32_t (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa,
 		struct rte_crypto_op *cop);
examples/ipsec-secgw/sad.c new file +90 -0

90 lines not on this page · raw message

examples/ipsec-secgw/sad.h new file +74 -0

74 lines not on this page · raw message

Signature · 1 line
2.7.4
#3 lore raw

PATCH 3/4 examples/ipsec-secgw: integrate inbound SAD

In reply to Vladimir Medvedkin

Integrate ipsec SAD support into secgw app:

1. Use SAD library for inbound SA lookup
2. Changes in struct sa_ctx:
- sa array allocates dynamically depending on number of configured sa
- All SA's are kept one by one without using SPI2IDX
3. SP's userdata now contain index of SA in sa_ctx instead of SPI
4. Get rid of SPI2IDX macro

---
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |   2 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          | 160 +++++++++++++++++--------------------
 examples/ipsec-secgw/sp4.c         |  24 +++---
 examples/ipsec-secgw/sp6.c         |  24 +++---
 7 files changed, 110 insertions(+), 107 deletions(-)
examples/ipsec-secgw/Makefile +1 -0
index 851123b..8734b15 100644
@@ -12,6 +12,7 @@ SRCS-y += esp.c
 SRCS-y += sp4.c
 SRCS-y += sp6.c
 SRCS-y += sa.c
+SRCS-y += sad.c
 SRCS-y += rt.c
 SRCS-y += ipsec_process.c
 SRCS-y += ipsec-secgw.c
examples/ipsec-secgw/ipsec-secgw.c +2 -2
index 3b5aaf6..3e5f82e 100644
@@ -601,7 +601,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 			continue;
 		}
 
-		sa_idx = SPI2IDX(res);
+		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
 			rte_pktmbuf_free(m);
 			continue;
@@ -688,7 +688,7 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	j = 0;
 	for (i = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
-		sa_idx = SPI2IDX(ip->res[i]);
+		sa_idx = ip->res[i] - 1;
 		if (ip->res[i] == DISCARD)
 			rte_pktmbuf_free(m);
 		else if (ip->res[i] == BYPASS)
examples/ipsec-secgw/ipsec.h +1 -1
index 132286c..f731bf8 100644
@@ -363,7 +363,7 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
  * or -ENOENT otherwise.
  */
 int
-sa_spi_present(uint32_t spi, int inbound);
+sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound);
 
 void
 sa_init(struct socket_ctx *ctx, int32_t socket_id);
examples/ipsec-secgw/meson.build +1 -1
index 9ece345..6bd5b78 100644
@@ -10,5 +10,5 @@ deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec']
 allow_experimental_apis = true
 sources = files(
 	'esp.c', 'ipsec.c', 'ipsec_process.c', 'ipsec-secgw.c',
-	'parser.c', 'rt.c', 'sa.c', 'sp4.c', 'sp6.c'
+	'parser.c', 'rt.c', 'sa.c', 'sad.c', 'sp4.c', 'sp6.c'
 )
examples/ipsec-secgw/sa.c +75 -85

311 lines not on this page · raw message

examples/ipsec-secgw/sp4.c +15 -9
index 3871c6c..1dcec52 100644
@@ -493,10 +493,11 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl4_rules *acr;
+	int32_t spi_idx;
+	struct acl4_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl4_rules_in;
@@ -508,11 +509,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -535,11 +541,11 @@ 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(1) < 0)
+	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(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv4 SP DB has unmatched in SAD SPIs\n");
 
examples/ipsec-secgw/sp6.c +15 -9
index d8be6b1..b489e15 100644
@@ -625,10 +625,11 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl6_rules *acr;
+	int32_t spi_idx;
+	struct acl6_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl6_rules_in;
@@ -640,11 +641,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -667,11 +673,11 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
 		rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
 				"already initialized\n", socket_id);
 
-	if (check_spi_value(1) < 0)
+	if (check_spi_value(ctx->sa_in, 1) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Inbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
-	if (check_spi_value(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
Signature · 1 line
2.7.4
#4 lore raw

PATCH 4/4 examples/ipsec-secgw: get rid of maximum sa limitation

In reply to Vladimir Medvedkin

Parse config file and save SA's into linked list
instead of flat array with predefined size.

---
 examples/ipsec-secgw/sa.c | 78 +++++++++++++++++++++++++++++------------------
 1 file changed, 48 insertions(+), 30 deletions(-)
examples/ipsec-secgw/sa.c +48 -30
index 8cc7b17..32919fe 100644
@@ -20,6 +20,7 @@
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
+#include <sys/queue.h>
 
 #include "ipsec.h"
 #include "esp.h"
@@ -133,11 +134,17 @@ const struct supported_aead_algo aead_algos[] = {
 	}
 };
 
-static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
+struct ipsec_sa_mgmt {
+	STAILQ_ENTRY(ipsec_sa_mgmt) next;
+	struct ipsec_sa         sa;
+};
+STAILQ_HEAD(sa_head, ipsec_sa_mgmt);
+
+static struct sa_head sa_out_head = STAILQ_HEAD_INITIALIZER(sa_out_head);
 static uint32_t nb_sa_out;
 static struct ipsec_sa_cnt sa_out_cnt;
 
-static struct ipsec_sa sa_in[IPSEC_SA_MAX_ENTRIES];
+static struct sa_head sa_in_head = STAILQ_HEAD_INITIALIZER(sa_in_head);
 static uint32_t nb_sa_in;
 static struct ipsec_sa_cnt sa_in_cnt;
 
@@ -228,6 +235,8 @@ void
 parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status)
 {
+	struct ipsec_sa_mgmt *sa_mgmt;
+	struct sa_head *head;
 	struct ipsec_sa *rule = NULL;
 	struct rte_ipsec_session *ips;
 	uint32_t ti; /*token index*/
@@ -243,27 +252,21 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t portid_p = 0;
 	uint32_t fallback_p = 0;
 
+	sa_mgmt = calloc(1, sizeof(struct ipsec_sa_mgmt));
+	if (sa_mgmt == NULL)
+		return;
+
+	rule = &sa_mgmt->sa;
+
 	if (strcmp(tokens[0], "in") == 0) {
 		ri = &nb_sa_in;
 		sa_cnt = &sa_in_cnt;
-
-		APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,
-			"too many sa rules, abort insertion\n");
-		if (status->status < 0)
-			return;
-
-		rule = &sa_in[*ri];
+		head = &sa_in_head;
 		rule->direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
 	} else {
 		ri = &nb_sa_out;
 		sa_cnt = &sa_out_cnt;
-
-		APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,
-			"too many sa rules, abort insertion\n");
-		if (status->status < 0)
-			return;
-
-		rule = &sa_out[*ri];
+		head = &sa_out_head;
 		rule->direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
 	}
 
@@ -687,6 +690,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 		rule->portid = -1;
 	}
 
+	STAILQ_INSERT_TAIL(head, sa_mgmt, next);
 	*ri = *ri + 1;
 }
 
@@ -956,12 +960,13 @@ sa_add_address_inline_crypto(struct ipsec_sa *sa)
 }
 
 static int
-sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
+sa_add_rules(struct sa_ctx *sa_ctx, struct sa_head *entries,
 		uint32_t nb_entries, uint32_t inbound,
 		struct socket_ctx *skt_ctx)
 {
+	struct ipsec_sa_mgmt *sa_mgmt;
 	struct ipsec_sa *sa;
-	uint32_t i, idx;
+	uint32_t idx;
 	uint16_t iv_length, aad_length;
 	int inline_status;
 	int32_t rc;
@@ -970,15 +975,18 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 	/* for ESN upper 32 bits of SQN also need to be part of AAD */
 	aad_length = (app_sa_prm.enable_esn != 0) ? sizeof(uint32_t) : 0;
 
-	for (i = 0; i < nb_entries; i++) {
-		idx = i;
+	sa_mgmt = STAILQ_FIRST(entries);
+	for (idx = 0; idx < nb_entries; idx++) {
+		if (sa_mgmt == NULL)
+			rte_exit(EXIT_FAILURE, "SA mgmt queue is broken\n");
+
 		sa = &sa_ctx->sa[idx];
 		if (sa->spi != 0) {
 			printf("Index %u already in use by SPI %u\n",
 					idx, sa->spi);
 			return -EINVAL;
 		}
-		*sa = entries[i];
+		*sa = sa_mgmt->sa;
 
 		if (inbound) {
 			rc = ipsec_sad_add(&sa_ctx->sad, sa);
@@ -1114,20 +1122,29 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 
 			print_one_sa_rule(sa, inbound);
 		}
+		sa_mgmt = STAILQ_NEXT(sa_mgmt, next);
 	}
 
+	for (sa_mgmt = STAILQ_FIRST(entries); sa_mgmt != NULL;
+			sa_mgmt = STAILQ_FIRST(entries)) {
+		STAILQ_REMOVE_HEAD(entries, next);
+		free(sa_mgmt);
+	}
+
+	STAILQ_INIT(entries);
+
 	return 0;
 }
 
 static inline int
-sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
+sa_out_add_rules(struct sa_ctx *sa_ctx, struct sa_head *entries,
 		uint32_t nb_entries, struct socket_ctx *skt_ctx)
 {
 	return sa_add_rules(sa_ctx, entries, nb_entries, 0, skt_ctx);
 }
 
 static inline int
-sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
+sa_in_add_rules(struct sa_ctx *sa_ctx, struct sa_head *entries,
 		uint32_t nb_entries, struct socket_ctx *skt_ctx)
 {
 	return sa_add_rules(sa_ctx, entries, nb_entries, 1, skt_ctx);
@@ -1363,7 +1380,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 		if (rc != 0)
 			rte_exit(EXIT_FAILURE, "failed to init SAD\n");
 
-		sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in, ctx);
+		sa_in_add_rules(ctx->sa_in, &sa_in_head, nb_sa_in, ctx);
 
 		if (app_sa_prm.enable != 0) {
 			rc = ipsec_satbl_init(ctx->sa_in, nb_sa_in,
@@ -1383,7 +1400,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 				"context %s in socket %d\n", rte_errno,
 				name, socket_id);
 
-		sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out, ctx);
+		sa_out_add_rules(ctx->sa_out, &sa_out_head, nb_sa_out, ctx);
 
 		if (app_sa_prm.enable != 0) {
 			rc = ipsec_satbl_init(ctx->sa_out, nb_sa_out,
@@ -1451,21 +1468,22 @@ outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
 
 /*
  * Select HW offloads to be used.
+ * Called before sa_init, so working with mgmt queue
  */
 int
 sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
 		uint64_t *tx_offloads)
 {
+	struct ipsec_sa_mgmt *sa_mgmt;
 	struct ipsec_sa *rule;
-	uint32_t idx_sa;
 	enum rte_security_session_action_type rule_type;
 
 	*rx_offloads = 0;
 	*tx_offloads = 0;
 
 	/* Check for inbound rules that use offloads and use this port */
-	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
-		rule = &sa_in[idx_sa];
+	STAILQ_FOREACH(sa_mgmt, &sa_in_head, next) {
+		rule = &sa_mgmt->sa;
 		rule_type = ipsec_get_action_type(rule);
 		if ((rule_type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
 				rule_type ==
@@ -1475,8 +1493,8 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
 	}
 
 	/* Check for outbound rules that use offloads and use this port */
-	for (idx_sa = 0; idx_sa < nb_sa_out; idx_sa++) {
-		rule = &sa_out[idx_sa];
+	STAILQ_FOREACH(sa_mgmt, &sa_out_head, next) {
+		rule = &sa_mgmt->sa;
 		rule_type = ipsec_get_action_type(rule);
 		if ((rule_type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
 				rule_type ==
Signature · 1 line
2.7.4
#5 lore raw

v2 cover integrate librte_ipsec SAD into ipsec-secgw

In reply to Vladimir Medvedkin

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  13 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          | 236 +++++++++++++++++++------------------
 examples/ipsec-secgw/sad.c         |  90 ++++++++++++++
 examples/ipsec-secgw/sad.h         |  74 ++++++++++++
 examples/ipsec-secgw/sp4.c         | 141 ++++++++++++----------
 examples/ipsec-secgw/sp6.c         | 138 ++++++++++++----------
 lib/librte_ipsec/ipsec_sad.c       |  20 ++--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 11 files changed, 474 insertions(+), 247 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
Signature · 1 line
2.7.4
#6 lore raw

PATCH v2 1/5 ipsec: move ipsec sad name length into .h

Move IPSEC_SAD_NAMESIZE into public header
and rename it to RTE_IPSEC_SAD_NAMESIZE

---
 lib/librte_ipsec/ipsec_sad.c     | 20 ++++++++++----------
 lib/librte_ipsec/rte_ipsec_sad.h |  2 ++
 2 files changed, 12 insertions(+), 10 deletions(-)
lib/librte_ipsec/ipsec_sad.c +10 -10
index db2c44c..2c994ed 100644
@@ -20,7 +20,6 @@
  * indicate presence of entries with the same SPI in DIP and DIP+SIP tables.
  */
 
-#define IPSEC_SAD_NAMESIZE	64
 #define SAD_PREFIX		"SAD_"
 /* "SAD_<name>" */
 #define SAD_FORMAT		SAD_PREFIX "%s"
@@ -34,7 +33,7 @@ struct hash_cnt {
 };
 
 struct rte_ipsec_sad {
-	char name[IPSEC_SAD_NAMESIZE];
+	char name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_hash	*hash[RTE_IPSEC_SAD_KEY_TYPE_MASK];
 	/* Array to track number of more specific rules
 	 * (spi_dip or spi_dip_sip). Used only in add/delete
@@ -231,7 +230,7 @@ struct rte_ipsec_sad *
 rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 {
 	char hash_name[RTE_HASH_NAMESIZE];
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	struct rte_ipsec_sad *sad, *tmp_sad = NULL;
@@ -249,8 +248,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 		return NULL;
 	}
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -326,7 +325,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 	/* guarantee there's no existing */
 	TAILQ_FOREACH(te, sad_list, next) {
 		tmp_sad = (struct rte_ipsec_sad *)te->data;
-		if (strncmp(sad_name, tmp_sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, tmp_sad->name,
+				RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	if (te != NULL) {
@@ -354,14 +354,14 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 struct rte_ipsec_sad *
 rte_ipsec_sad_find_existing(const char *name)
 {
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_ipsec_sad *sad = NULL;
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	int ret;
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -372,7 +372,7 @@ rte_ipsec_sad_find_existing(const char *name)
 	rte_mcfg_tailq_read_lock();
 	TAILQ_FOREACH(te, sad_list, next) {
 		sad = (struct rte_ipsec_sad *) te->data;
-		if (strncmp(sad_name, sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, sad->name, RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	rte_mcfg_tailq_read_unlock();
lib/librte_ipsec/rte_ipsec_sad.h +2 -0
index 8386f73..dcc8224 100644
@@ -47,6 +47,8 @@ union rte_ipsec_sad_key {
 	struct rte_ipsec_sadv6_key	v6;
 };
 
+/** Max number of characters in SAD name. */
+#define RTE_IPSEC_SAD_NAMESIZE		64
 /** Flag to create SAD with ipv6 dip and sip addresses */
 #define RTE_IPSEC_SAD_FLAG_IPV6			0x1
 /** Flag to support reader writer concurrency */
Signature · 1 line
2.7.4
#7 lore raw

PATCH v2 2/5 examples/ipsec-secgw: implement inbound SAD

In reply to Vladimir Medvedkin

Add initial support for librte_ipsec SAD library

---
 examples/ipsec-secgw/ipsec.h | 11 ++++++
 examples/ipsec-secgw/sad.c   | 90 ++++++++++++++++++++++++++++++++++++++++++++
 examples/ipsec-secgw/sad.h   | 74 ++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
examples/ipsec-secgw/ipsec.h +11 -0
index 8e07521..132286c 100644
@@ -53,6 +53,17 @@ struct ipsec_xform;
 struct rte_mbuf;
 
 struct ipsec_sa;
+/*
+ * Keeps number of configured SA's of each type:
+ * transport
+ * v4 tunnel
+ * v6 tunnel
+ */
+struct ipsec_sa_cnt {
+	uint32_t	nb_trn;
+	uint32_t	nb_v4_tun;
+	uint32_t	nb_v6_tun;
+};
 
 typedef int32_t (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa,
 		struct rte_crypto_op *cop);
examples/ipsec-secgw/sad.c new file +90 -0

90 lines not on this page · raw message

examples/ipsec-secgw/sad.h new file +74 -0

74 lines not on this page · raw message

Signature · 1 line
2.7.4
#8 lore raw

PATCH v2 3/5 examples/ipsec-secgw: integrate inbound SAD

In reply to Vladimir Medvedkin

Integrate ipsec SAD support into secgw app:

1. Use SAD library for inbound SA lookup
2. Changes in struct sa_ctx:
- sa array allocates dynamically depending on number of configured sa
- All SA's are kept one by one without using SPI2IDX
3. SP's userdata now contain index of SA in sa_ctx instead of SPI
4. Get rid of SPI2IDX macro

---
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |   2 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          | 160 +++++++++++++++++--------------------
 examples/ipsec-secgw/sp4.c         |  24 +++---
 examples/ipsec-secgw/sp6.c         |  24 +++---
 7 files changed, 110 insertions(+), 107 deletions(-)
examples/ipsec-secgw/Makefile +1 -0
index 851123b..8734b15 100644
@@ -12,6 +12,7 @@ SRCS-y += esp.c
 SRCS-y += sp4.c
 SRCS-y += sp6.c
 SRCS-y += sa.c
+SRCS-y += sad.c
 SRCS-y += rt.c
 SRCS-y += ipsec_process.c
 SRCS-y += ipsec-secgw.c
examples/ipsec-secgw/ipsec-secgw.c +2 -2
index 3b5aaf6..3e5f82e 100644
@@ -601,7 +601,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 			continue;
 		}
 
-		sa_idx = SPI2IDX(res);
+		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
 			rte_pktmbuf_free(m);
 			continue;
@@ -688,7 +688,7 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	j = 0;
 	for (i = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
-		sa_idx = SPI2IDX(ip->res[i]);
+		sa_idx = ip->res[i] - 1;
 		if (ip->res[i] == DISCARD)
 			rte_pktmbuf_free(m);
 		else if (ip->res[i] == BYPASS)
examples/ipsec-secgw/ipsec.h +1 -1
index 132286c..f731bf8 100644
@@ -363,7 +363,7 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
  * or -ENOENT otherwise.
  */
 int
-sa_spi_present(uint32_t spi, int inbound);
+sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound);
 
 void
 sa_init(struct socket_ctx *ctx, int32_t socket_id);
examples/ipsec-secgw/meson.build +1 -1
index 9ece345..6bd5b78 100644
@@ -10,5 +10,5 @@ deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec']
 allow_experimental_apis = true
 sources = files(
 	'esp.c', 'ipsec.c', 'ipsec_process.c', 'ipsec-secgw.c',
-	'parser.c', 'rt.c', 'sa.c', 'sp4.c', 'sp6.c'
+	'parser.c', 'rt.c', 'sa.c', 'sad.c', 'sp4.c', 'sp6.c'
 )
examples/ipsec-secgw/sa.c +75 -85

311 lines not on this page · raw message

examples/ipsec-secgw/sp4.c +15 -9
index 3871c6c..1dcec52 100644
@@ -493,10 +493,11 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl4_rules *acr;
+	int32_t spi_idx;
+	struct acl4_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl4_rules_in;
@@ -508,11 +509,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -535,11 +541,11 @@ 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(1) < 0)
+	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(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv4 SP DB has unmatched in SAD SPIs\n");
 
examples/ipsec-secgw/sp6.c +15 -9
index d8be6b1..b489e15 100644
@@ -625,10 +625,11 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl6_rules *acr;
+	int32_t spi_idx;
+	struct acl6_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl6_rules_in;
@@ -640,11 +641,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -667,11 +673,11 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
 		rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
 				"already initialized\n", socket_id);
 
-	if (check_spi_value(1) < 0)
+	if (check_spi_value(ctx->sa_in, 1) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Inbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
-	if (check_spi_value(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
Signature · 1 line
2.7.4
#9 lore raw

PATCH v2 4/5 examples/ipsec-secgw: get rid of maximum sa limitation

In reply to Vladimir Medvedkin

Parse config file and save SA's into linked list
instead of flat array with predefined size.

---
 examples/ipsec-secgw/sa.c | 78 +++++++++++++++++++++++++++++------------------
 1 file changed, 48 insertions(+), 30 deletions(-)
examples/ipsec-secgw/sa.c +48 -30
index 8cc7b17..32919fe 100644
@@ -20,6 +20,7 @@
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
+#include <sys/queue.h>
 
 #include "ipsec.h"
 #include "esp.h"
@@ -133,11 +134,17 @@ const struct supported_aead_algo aead_algos[] = {
 	}
 };
 
-static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
+struct ipsec_sa_mgmt {
+	STAILQ_ENTRY(ipsec_sa_mgmt) next;
+	struct ipsec_sa         sa;
+};
+STAILQ_HEAD(sa_head, ipsec_sa_mgmt);
+
+static struct sa_head sa_out_head = STAILQ_HEAD_INITIALIZER(sa_out_head);
 static uint32_t nb_sa_out;
 static struct ipsec_sa_cnt sa_out_cnt;
 
-static struct ipsec_sa sa_in[IPSEC_SA_MAX_ENTRIES];
+static struct sa_head sa_in_head = STAILQ_HEAD_INITIALIZER(sa_in_head);
 static uint32_t nb_sa_in;
 static struct ipsec_sa_cnt sa_in_cnt;
 
@@ -228,6 +235,8 @@ void
 parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status)
 {
+	struct ipsec_sa_mgmt *sa_mgmt;
+	struct sa_head *head;
 	struct ipsec_sa *rule = NULL;
 	struct rte_ipsec_session *ips;
 	uint32_t ti; /*token index*/
@@ -243,27 +252,21 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t portid_p = 0;
 	uint32_t fallback_p = 0;
 
+	sa_mgmt = calloc(1, sizeof(struct ipsec_sa_mgmt));
+	if (sa_mgmt == NULL)
+		return;
+
+	rule = &sa_mgmt->sa;
+
 	if (strcmp(tokens[0], "in") == 0) {
 		ri = &nb_sa_in;
 		sa_cnt = &sa_in_cnt;
-
-		APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,
-			"too many sa rules, abort insertion\n");
-		if (status->status < 0)
-			return;
-
-		rule = &sa_in[*ri];
+		head = &sa_in_head;
 		rule->direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
 	} else {
 		ri = &nb_sa_out;
 		sa_cnt = &sa_out_cnt;
-
-		APP_CHECK(*ri <= IPSEC_SA_MAX_ENTRIES - 1, status,
-			"too many sa rules, abort insertion\n");
-		if (status->status < 0)
-			return;
-
-		rule = &sa_out[*ri];
+		head = &sa_out_head;
 		rule->direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
 	}
 
@@ -687,6 +690,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 		rule->portid = -1;
 	}
 
+	STAILQ_INSERT_TAIL(head, sa_mgmt, next);
 	*ri = *ri + 1;
 }
 
@@ -956,12 +960,13 @@ sa_add_address_inline_crypto(struct ipsec_sa *sa)
 }
 
 static int
-sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
+sa_add_rules(struct sa_ctx *sa_ctx, struct sa_head *entries,
 		uint32_t nb_entries, uint32_t inbound,
 		struct socket_ctx *skt_ctx)
 {
+	struct ipsec_sa_mgmt *sa_mgmt;
 	struct ipsec_sa *sa;
-	uint32_t i, idx;
+	uint32_t idx;
 	uint16_t iv_length, aad_length;
 	int inline_status;
 	int32_t rc;
@@ -970,15 +975,18 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 	/* for ESN upper 32 bits of SQN also need to be part of AAD */
 	aad_length = (app_sa_prm.enable_esn != 0) ? sizeof(uint32_t) : 0;
 
-	for (i = 0; i < nb_entries; i++) {
-		idx = i;
+	sa_mgmt = STAILQ_FIRST(entries);
+	for (idx = 0; idx < nb_entries; idx++) {
+		if (sa_mgmt == NULL)
+			rte_exit(EXIT_FAILURE, "SA mgmt queue is broken\n");
+
 		sa = &sa_ctx->sa[idx];
 		if (sa->spi != 0) {
 			printf("Index %u already in use by SPI %u\n",
 					idx, sa->spi);
 			return -EINVAL;
 		}
-		*sa = entries[i];
+		*sa = sa_mgmt->sa;
 
 		if (inbound) {
 			rc = ipsec_sad_add(&sa_ctx->sad, sa);
@@ -1114,20 +1122,29 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 
 			print_one_sa_rule(sa, inbound);
 		}
+		sa_mgmt = STAILQ_NEXT(sa_mgmt, next);
 	}
 
+	for (sa_mgmt = STAILQ_FIRST(entries); sa_mgmt != NULL;
+			sa_mgmt = STAILQ_FIRST(entries)) {
+		STAILQ_REMOVE_HEAD(entries, next);
+		free(sa_mgmt);
+	}
+
+	STAILQ_INIT(entries);
+
 	return 0;
 }
 
 static inline int
-sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
+sa_out_add_rules(struct sa_ctx *sa_ctx, struct sa_head *entries,
 		uint32_t nb_entries, struct socket_ctx *skt_ctx)
 {
 	return sa_add_rules(sa_ctx, entries, nb_entries, 0, skt_ctx);
 }
 
 static inline int
-sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
+sa_in_add_rules(struct sa_ctx *sa_ctx, struct sa_head *entries,
 		uint32_t nb_entries, struct socket_ctx *skt_ctx)
 {
 	return sa_add_rules(sa_ctx, entries, nb_entries, 1, skt_ctx);
@@ -1363,7 +1380,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 		if (rc != 0)
 			rte_exit(EXIT_FAILURE, "failed to init SAD\n");
 
-		sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in, ctx);
+		sa_in_add_rules(ctx->sa_in, &sa_in_head, nb_sa_in, ctx);
 
 		if (app_sa_prm.enable != 0) {
 			rc = ipsec_satbl_init(ctx->sa_in, nb_sa_in,
@@ -1383,7 +1400,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 				"context %s in socket %d\n", rte_errno,
 				name, socket_id);
 
-		sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out, ctx);
+		sa_out_add_rules(ctx->sa_out, &sa_out_head, nb_sa_out, ctx);
 
 		if (app_sa_prm.enable != 0) {
 			rc = ipsec_satbl_init(ctx->sa_out, nb_sa_out,
@@ -1451,21 +1468,22 @@ outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
 
 /*
  * Select HW offloads to be used.
+ * Called before sa_init, so working with mgmt queue
  */
 int
 sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
 		uint64_t *tx_offloads)
 {
+	struct ipsec_sa_mgmt *sa_mgmt;
 	struct ipsec_sa *rule;
-	uint32_t idx_sa;
 	enum rte_security_session_action_type rule_type;
 
 	*rx_offloads = 0;
 	*tx_offloads = 0;
 
 	/* Check for inbound rules that use offloads and use this port */
-	for (idx_sa = 0; idx_sa < nb_sa_in; idx_sa++) {
-		rule = &sa_in[idx_sa];
+	STAILQ_FOREACH(sa_mgmt, &sa_in_head, next) {
+		rule = &sa_mgmt->sa;
 		rule_type = ipsec_get_action_type(rule);
 		if ((rule_type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
 				rule_type ==
@@ -1475,8 +1493,8 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
 	}
 
 	/* Check for outbound rules that use offloads and use this port */
-	for (idx_sa = 0; idx_sa < nb_sa_out; idx_sa++) {
-		rule = &sa_out[idx_sa];
+	STAILQ_FOREACH(sa_mgmt, &sa_out_head, next) {
+		rule = &sa_mgmt->sa;
 		rule_type = ipsec_get_action_type(rule);
 		if ((rule_type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
 				rule_type ==
Signature · 1 line
2.7.4
#10 lore raw

PATCH v2 5/5 examples/ipsec-secgw: get rid of maximum sp limitation

In reply to Vladimir Medvedkin

Parse config file and save SP rules into linked list instead of flat array with predefined size.

---
 examples/ipsec-secgw/sp4.c | 121 ++++++++++++++++++++++++++-------------------
 examples/ipsec-secgw/sp6.c | 118 +++++++++++++++++++++++--------------------
 2 files changed, 134 insertions(+), 105 deletions(-)
examples/ipsec-secgw/sp4.c +69 -52
index 1dcec52..f0938c5 100644
@@ -8,6 +8,7 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
+#include <sys/queue.h>
 
 #include <rte_acl.h>
 #include <rte_ip.h>
@@ -15,8 +16,6 @@
 #include "ipsec.h"
 #include "parser.h"
 
-#define MAX_ACL_RULE_NUM	1024
-
 #define IPV4_DST_FROM_SP(acr) \
 		(rte_cpu_to_be_32((acr).field[DST_FIELD_IPV4].value.u32))
 
@@ -97,16 +96,24 @@ 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];
+struct ipsec_sp_mgmt {
+	STAILQ_ENTRY(ipsec_sp_mgmt)	next;
+	struct acl4_rules		sp;
+};
+STAILQ_HEAD(sp_head, ipsec_sp_mgmt);
+
+static struct sp_head sp_out_head = STAILQ_HEAD_INITIALIZER(sp_out_head);
 static uint32_t nb_acl4_rules_out;
 
-static struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM];
+static struct sp_head sp_in_head = STAILQ_HEAD_INITIALIZER(sp_in_head);
 static uint32_t nb_acl4_rules_in;
 
 void
 parse_sp4_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status)
 {
+	struct ipsec_sp_mgmt *sp_mgmt;
+	struct sp_head *head;
 	struct acl4_rules *rule_ipv4 = NULL;
 
 	uint32_t *ri = NULL; /* rule index */
@@ -124,25 +131,18 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t sport_p = 0;
 	uint32_t dport_p = 0;
 
+	sp_mgmt = calloc(1, sizeof(struct ipsec_sp_mgmt));
+	if (sp_mgmt == NULL)
+		return;
+
+	rule_ipv4 = &sp_mgmt->sp;
+
 	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)
-			return;
-
-		rule_ipv4 = &acl4_rules_in[*ri];
-
+		head = &sp_in_head;
 	} 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)
-			return;
-
-		rule_ipv4 = &acl4_rules_out[*ri];
+		head = &sp_out_head;
 	} else {
 		APP_CHECK(0, status, "unrecognized input \"%s\", expect"
 			" \"in\" or \"out\"\n", tokens[ti]);
@@ -400,6 +400,7 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
 	if (status->status < 0)
 		return;
 
+	STAILQ_INSERT_TAIL(head, sp_mgmt, next);
 	*ri = *ri + 1;
 }
 
@@ -443,18 +444,34 @@ dump_ip4_rules(const struct acl4_rules *rule, int32_t num, int32_t extra)
 }
 
 static struct rte_acl_ctx *
-acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
+acl4_init(const char *name, int32_t socketid, struct sp_head *rules_list,
 		uint32_t rules_nb)
 {
 	char s[PATH_MAX];
 	struct rte_acl_param acl_param;
 	struct rte_acl_config acl_build_param;
 	struct rte_acl_ctx *ctx;
+	struct acl4_rules *rules; /* Temporary array containing rules */
+	struct ipsec_sp_mgmt *sp_mgmt;
+	uint32_t i;
 
-	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));
 
+	/* Create flat array of rules which is needed for acl context */
+	rules = calloc(rules_nb, sizeof(struct acl4_rules));
+	if (rules == NULL)
+		rte_exit(EXIT_FAILURE, "Can't allocate rules array\n");
+
+	sp_mgmt = STAILQ_FIRST(rules_list);
+	for (i = 0; i < rules_nb; i++) {
+		if (sp_mgmt == NULL)
+			rte_exit(EXIT_FAILURE, "SP list is broken\n");
+		rules[i] = sp_mgmt->sp;
+		sp_mgmt = STAILQ_NEXT(sp_mgmt, next);
+	}
+
 	/* Create ACL contexts */
 	snprintf(s, sizeof(s), "%s_%d", name, socketid);
 
@@ -464,7 +481,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)
@@ -486,6 +503,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
 
 	rte_acl_dump(ctx);
 
+	free(rules);
 	return ctx;
 }
 
@@ -495,20 +513,19 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
 static int
 check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
-	uint32_t i, num, spi;
+	uint32_t spi;
 	int32_t spi_idx;
-	struct acl4_rules *acr;
+	struct ipsec_sp_mgmt	*sp_mgmt;
+	struct sp_head		*head;
 
-	if (inbound != 0) {
-		acr = acl4_rules_in;
-		num = nb_acl4_rules_in;
-	} else {
-		acr = acl4_rules_out;
-		num = nb_acl4_rules_out;
-	}
+	if (inbound != 0)
+		head = &sp_in_head;
+	else
+		head = &sp_out_head;
 
-	for (i = 0; i != num; i++) {
-		spi = acr[i].data.userdata;
+
+	STAILQ_FOREACH(sp_mgmt, head, next) {
+		spi = sp_mgmt->sp.data.userdata;
 		if (spi != DISCARD && spi != BYPASS) {
 			spi_idx = sa_spi_present(sa_ctx, spi, inbound);
 			if (spi_idx < 0) {
@@ -518,7 +535,7 @@ check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 				return -ENOENT;
 			}
 			/* Update userdata with spi index */
-			acr[i].data.userdata = spi_idx + 1;
+			sp_mgmt->sp.data.userdata = spi_idx + 1;
 		}
 	}
 
@@ -548,11 +565,10 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id)
 	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,
-			socket_id, acl4_rules_in, nb_acl4_rules_in);
+			socket_id, &sp_in_head, nb_acl4_rules_in);
 	} else
 		RTE_LOG(WARNING, IPSEC, "No IPv4 SP Inbound rule "
 			"specified\n");
@@ -560,7 +576,7 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id)
 	if (nb_acl4_rules_out > 0) {
 		name = "sp_ip4_out";
 		ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name,
-			socket_id, acl4_rules_out, nb_acl4_rules_out);
+			socket_id, &sp_out_head, nb_acl4_rules_out);
 	} else
 		RTE_LOG(WARNING, IPSEC, "No IPv4 SP Outbound rule "
 			"specified\n");
@@ -573,27 +589,28 @@ int
 sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
 			uint32_t mask[2])
 {
-	uint32_t i, num;
-	const struct acl4_rules *acr;
+	uint32_t i = 0;
+	struct ipsec_sp_mgmt	*sp_mgmt;
+	struct sp_head		*head;
 
-	if (inbound != 0) {
-		acr = acl4_rules_in;
-		num = nb_acl4_rules_in;
-	} else {
-		acr = acl4_rules_out;
-		num = nb_acl4_rules_out;
-	}
+	if (inbound != 0)
+		head = &sp_in_head;
+	else
+		head = &sp_out_head;
 
-	for (i = 0; i != num; i++) {
-		if (acr[i].data.userdata == spi) {
+	STAILQ_FOREACH(sp_mgmt, head, next) {
+		if (sp_mgmt->sp.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]);
+				ip_addr[0].ip.ip4 =
+					IPV4_SRC_FROM_SP(sp_mgmt->sp);
+				ip_addr[1].ip.ip4 =
+					IPV4_DST_FROM_SP(sp_mgmt->sp);
+				mask[0] = IPV4_SRC_MASK_FROM_SP(sp_mgmt->sp);
+				mask[1] = IPV4_DST_MASK_FROM_SP(sp_mgmt->sp);
 			}
 			return i;
 		}
+		i++;
 	}
 
 	return -ENOENT;
examples/ipsec-secgw/sp6.c +65 -53

230 lines not on this page · raw message

Signature · 1 line
2.7.4
#11 lore raw

v3 cover integrate librte_ipsec SAD into ipsec-secgw

In reply to Vladimir Medvedkin

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  15 ++-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 234 +++++++++++++++++++++----------------
 examples/ipsec-secgw/sad.c         |  94 +++++++++++++++
 examples/ipsec-secgw/sad.h         |  74 ++++++++++++
 examples/ipsec-secgw/sp4.c         | 114 +++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 ++--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 507 insertions(+), 178 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
Signature · 1 line
2.7.4
#12 lore raw

PATCH v3 1/5 ipsec: move ipsec sad name length into .h

Move IPSEC_SAD_NAMESIZE into public header
and rename it to RTE_IPSEC_SAD_NAMESIZE

---
 lib/librte_ipsec/ipsec_sad.c     | 20 ++++++++++----------
 lib/librte_ipsec/rte_ipsec_sad.h |  2 ++
 2 files changed, 12 insertions(+), 10 deletions(-)
lib/librte_ipsec/ipsec_sad.c +10 -10
index db2c44c..2c994ed 100644
@@ -20,7 +20,6 @@
  * indicate presence of entries with the same SPI in DIP and DIP+SIP tables.
  */
 
-#define IPSEC_SAD_NAMESIZE	64
 #define SAD_PREFIX		"SAD_"
 /* "SAD_<name>" */
 #define SAD_FORMAT		SAD_PREFIX "%s"
@@ -34,7 +33,7 @@ struct hash_cnt {
 };
 
 struct rte_ipsec_sad {
-	char name[IPSEC_SAD_NAMESIZE];
+	char name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_hash	*hash[RTE_IPSEC_SAD_KEY_TYPE_MASK];
 	/* Array to track number of more specific rules
 	 * (spi_dip or spi_dip_sip). Used only in add/delete
@@ -231,7 +230,7 @@ struct rte_ipsec_sad *
 rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 {
 	char hash_name[RTE_HASH_NAMESIZE];
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	struct rte_ipsec_sad *sad, *tmp_sad = NULL;
@@ -249,8 +248,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 		return NULL;
 	}
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -326,7 +325,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 	/* guarantee there's no existing */
 	TAILQ_FOREACH(te, sad_list, next) {
 		tmp_sad = (struct rte_ipsec_sad *)te->data;
-		if (strncmp(sad_name, tmp_sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, tmp_sad->name,
+				RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	if (te != NULL) {
@@ -354,14 +354,14 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 struct rte_ipsec_sad *
 rte_ipsec_sad_find_existing(const char *name)
 {
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_ipsec_sad *sad = NULL;
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	int ret;
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -372,7 +372,7 @@ rte_ipsec_sad_find_existing(const char *name)
 	rte_mcfg_tailq_read_lock();
 	TAILQ_FOREACH(te, sad_list, next) {
 		sad = (struct rte_ipsec_sad *) te->data;
-		if (strncmp(sad_name, sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, sad->name, RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	rte_mcfg_tailq_read_unlock();
lib/librte_ipsec/rte_ipsec_sad.h +2 -0
index 8386f73..dcc8224 100644
@@ -47,6 +47,8 @@ union rte_ipsec_sad_key {
 	struct rte_ipsec_sadv6_key	v6;
 };
 
+/** Max number of characters in SAD name. */
+#define RTE_IPSEC_SAD_NAMESIZE		64
 /** Flag to create SAD with ipv6 dip and sip addresses */
 #define RTE_IPSEC_SAD_FLAG_IPV6			0x1
 /** Flag to support reader writer concurrency */
Signature · 1 line
2.7.4
#13 lore raw

PATCH v3 2/5 examples/ipsec-secgw: implement inbound SAD

In reply to Vladimir Medvedkin

Add initial support for librte_ipsec SAD library

---
 examples/ipsec-secgw/ipsec.h | 11 ++++++
 examples/ipsec-secgw/sad.c   | 94 ++++++++++++++++++++++++++++++++++++++++++++
 examples/ipsec-secgw/sad.h   | 74 ++++++++++++++++++++++++++++++++++
 3 files changed, 179 insertions(+)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
examples/ipsec-secgw/ipsec.h +11 -0
index 8e07521..132286c 100644
@@ -53,6 +53,17 @@ struct ipsec_xform;
 struct rte_mbuf;
 
 struct ipsec_sa;
+/*
+ * Keeps number of configured SA's of each type:
+ * transport
+ * v4 tunnel
+ * v6 tunnel
+ */
+struct ipsec_sa_cnt {
+	uint32_t	nb_trn;
+	uint32_t	nb_v4_tun;
+	uint32_t	nb_v6_tun;
+};
 
 typedef int32_t (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa,
 		struct rte_crypto_op *cop);
examples/ipsec-secgw/sad.c new file +94 -0

94 lines not on this page · raw message

examples/ipsec-secgw/sad.h new file +74 -0

74 lines not on this page · raw message

Signature · 1 line
2.7.4
#14 lore raw

PATCH v3 3/5 examples/ipsec-secgw: integrate inbound SAD

In reply to Vladimir Medvedkin

Integrate ipsec SAD support into secgw app:

1. Use SAD library for inbound SA lookup
2. Changes in struct sa_ctx:
- sa array allocates dynamically depending on number of configured sa
- All SA's are kept one by one without using SPI2IDX
3. SP's userdata now contain index of SA in sa_ctx instead of SPI
4. Get rid of SPI2IDX macro

---
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |   3 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          | 160 +++++++++++++++++--------------------
 examples/ipsec-secgw/sp4.c         |  24 +++---
 examples/ipsec-secgw/sp6.c         |  24 +++---
 7 files changed, 110 insertions(+), 108 deletions(-)
examples/ipsec-secgw/Makefile +1 -0
index 851123b..8734b15 100644
@@ -12,6 +12,7 @@ SRCS-y += esp.c
 SRCS-y += sp4.c
 SRCS-y += sp6.c
 SRCS-y += sa.c
+SRCS-y += sad.c
 SRCS-y += rt.c
 SRCS-y += ipsec_process.c
 SRCS-y += ipsec-secgw.c
examples/ipsec-secgw/ipsec-secgw.c +2 -2
index 3b5aaf6..3e5f82e 100644
@@ -601,7 +601,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 			continue;
 		}
 
-		sa_idx = SPI2IDX(res);
+		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
 			rte_pktmbuf_free(m);
 			continue;
@@ -688,7 +688,7 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	j = 0;
 	for (i = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
-		sa_idx = SPI2IDX(ip->res[i]);
+		sa_idx = ip->res[i] - 1;
 		if (ip->res[i] == DISCARD)
 			rte_pktmbuf_free(m);
 		else if (ip->res[i] == BYPASS)
examples/ipsec-secgw/ipsec.h +1 -2
index 132286c..8ca6c2a 100644
@@ -38,7 +38,6 @@
 #define DEFAULT_MAX_CATEGORIES	1
 
 #define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
-#define SPI2IDX(spi) (spi & (IPSEC_SA_MAX_ENTRIES - 1))
 #define INVALID_SPI (0)
 
 #define DISCARD	INVALID_SPI
@@ -363,7 +362,7 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
  * or -ENOENT otherwise.
  */
 int
-sa_spi_present(uint32_t spi, int inbound);
+sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound);
 
 void
 sa_init(struct socket_ctx *ctx, int32_t socket_id);
examples/ipsec-secgw/meson.build +1 -1
index 9ece345..6bd5b78 100644
@@ -10,5 +10,5 @@ deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec']
 allow_experimental_apis = true
 sources = files(
 	'esp.c', 'ipsec.c', 'ipsec_process.c', 'ipsec-secgw.c',
-	'parser.c', 'rt.c', 'sa.c', 'sp4.c', 'sp6.c'
+	'parser.c', 'rt.c', 'sa.c', 'sad.c', 'sp4.c', 'sp6.c'
 )
examples/ipsec-secgw/sa.c +75 -85

311 lines not on this page · raw message

examples/ipsec-secgw/sp4.c +15 -9
index 3871c6c..1dcec52 100644
@@ -493,10 +493,11 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl4_rules *acr;
+	int32_t spi_idx;
+	struct acl4_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl4_rules_in;
@@ -508,11 +509,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -535,11 +541,11 @@ 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(1) < 0)
+	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(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv4 SP DB has unmatched in SAD SPIs\n");
 
examples/ipsec-secgw/sp6.c +15 -9
index d8be6b1..b489e15 100644
@@ -625,10 +625,11 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl6_rules *acr;
+	int32_t spi_idx;
+	struct acl6_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl6_rules_in;
@@ -640,11 +641,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -667,11 +673,11 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
 		rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
 				"already initialized\n", socket_id);
 
-	if (check_spi_value(1) < 0)
+	if (check_spi_value(ctx->sa_in, 1) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Inbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
-	if (check_spi_value(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
Signature · 1 line
2.7.4
#15 lore raw

PATCH v3 4/5 examples/ipsec-secgw: get rid of maximum sa limitation

In reply to Vladimir Medvedkin

Get rid of maximum SA limitation.
Keep parsed SA's into the sorted by SPI value array. Use binary search in the sorted SA array to find appropriate SA for a given SPI.

---
 examples/ipsec-secgw/ipsec.h  |  1 -
 examples/ipsec-secgw/parser.c |  2 ++
 examples/ipsec-secgw/parser.h |  3 ++
 examples/ipsec-secgw/sa.c     | 74 +++++++++++++++++++++++++++++++++----------
 4 files changed, 62 insertions(+), 18 deletions(-)
examples/ipsec-secgw/ipsec.h +0 -1
index 8ca6c2a..0475a54 100644
@@ -37,7 +37,6 @@
 
 #define DEFAULT_MAX_CATEGORIES	1
 
-#define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
 #define INVALID_SPI (0)
 
 #define DISCARD	INVALID_SPI
examples/ipsec-secgw/parser.c +2 -0
index fc8c238..67df170 100644
@@ -642,6 +642,8 @@ parse_cfg_file(const char *cfg_filename)
 	cmdline_stdin_exit(cl);
 	fclose(f);
 
+	sa_sort_arr();
+
 	return 0;
 
 error_exit:
examples/ipsec-secgw/parser.h +3 -0
index 6b8a100..1f8bd3e 100644
@@ -75,6 +75,9 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status);
 
 void
+sa_sort_arr(void);
+
+void
 parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status);
 
examples/ipsec-secgw/sa.c +57 -17

123 lines not on this page · raw message

Signature · 1 line
2.7.4
#16 lore raw

PATCH v3 5/5 examples/ipsec-secgw: get rid of maximum sp limitation

In reply to Vladimir Medvedkin

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.

---
 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(-)
examples/ipsec-secgw/parser.c +2 -0
index 67df170..65eb7e9 100644
@@ -643,6 +643,8 @@ parse_cfg_file(const char *cfg_filename)
 	fclose(f);
 
 	sa_sort_arr();
+	sp4_sort_arr();
+	sp6_sort_arr();
 
 	return 0;
 
examples/ipsec-secgw/parser.h +6 -0
index 1f8bd3e..6e764fe 100644
@@ -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);
 
examples/ipsec-secgw/sp4.c +69 -21

150 lines not on this page · raw message

examples/ipsec-secgw/sp6.c +67 -21

148 lines not on this page · raw message

Signature · 1 line
2.7.4
#17 lore raw

v4 cover integrate librte_ipsec SAD into ipsec-secgw

In reply to Vladimir Medvedkin

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++--------------
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
Signature · 1 line
2.7.4
#18 lore raw

PATCH v4 1/5 ipsec: move ipsec sad name length into .h

Move IPSEC_SAD_NAMESIZE into public header
and rename it to RTE_IPSEC_SAD_NAMESIZE

---
 lib/librte_ipsec/ipsec_sad.c     | 20 ++++++++++----------
 lib/librte_ipsec/rte_ipsec_sad.h |  2 ++
 2 files changed, 12 insertions(+), 10 deletions(-)
lib/librte_ipsec/ipsec_sad.c +10 -10
index db2c44c..2c994ed 100644
@@ -20,7 +20,6 @@
  * indicate presence of entries with the same SPI in DIP and DIP+SIP tables.
  */
 
-#define IPSEC_SAD_NAMESIZE	64
 #define SAD_PREFIX		"SAD_"
 /* "SAD_<name>" */
 #define SAD_FORMAT		SAD_PREFIX "%s"
@@ -34,7 +33,7 @@ struct hash_cnt {
 };
 
 struct rte_ipsec_sad {
-	char name[IPSEC_SAD_NAMESIZE];
+	char name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_hash	*hash[RTE_IPSEC_SAD_KEY_TYPE_MASK];
 	/* Array to track number of more specific rules
 	 * (spi_dip or spi_dip_sip). Used only in add/delete
@@ -231,7 +230,7 @@ struct rte_ipsec_sad *
 rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 {
 	char hash_name[RTE_HASH_NAMESIZE];
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	struct rte_ipsec_sad *sad, *tmp_sad = NULL;
@@ -249,8 +248,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 		return NULL;
 	}
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -326,7 +325,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 	/* guarantee there's no existing */
 	TAILQ_FOREACH(te, sad_list, next) {
 		tmp_sad = (struct rte_ipsec_sad *)te->data;
-		if (strncmp(sad_name, tmp_sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, tmp_sad->name,
+				RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	if (te != NULL) {
@@ -354,14 +354,14 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 struct rte_ipsec_sad *
 rte_ipsec_sad_find_existing(const char *name)
 {
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_ipsec_sad *sad = NULL;
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	int ret;
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -372,7 +372,7 @@ rte_ipsec_sad_find_existing(const char *name)
 	rte_mcfg_tailq_read_lock();
 	TAILQ_FOREACH(te, sad_list, next) {
 		sad = (struct rte_ipsec_sad *) te->data;
-		if (strncmp(sad_name, sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, sad->name, RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	rte_mcfg_tailq_read_unlock();
lib/librte_ipsec/rte_ipsec_sad.h +2 -0
index 8386f73..dcc8224 100644
@@ -47,6 +47,8 @@ union rte_ipsec_sad_key {
 	struct rte_ipsec_sadv6_key	v6;
 };
 
+/** Max number of characters in SAD name. */
+#define RTE_IPSEC_SAD_NAMESIZE		64
 /** Flag to create SAD with ipv6 dip and sip addresses */
 #define RTE_IPSEC_SAD_FLAG_IPV6			0x1
 /** Flag to support reader writer concurrency */
Signature · 1 line
2.7.4
Acked-by on v4 1/5
#19 lore raw

Re: [dpdk-dev] [PATCH v4 1/5] ipsec: move ipsec sad name length into .h

Quoted 9 lines

-----Original Message-----
From: Medvedkin, Vladimir <[email protected]>
Sent: Tuesday, January 14, 2020 2:27 PM
To: [email protected]
Cc: Ananyev, Konstantin <[email protected]>; [email protected]
Subject: [PATCH v4 1/5] ipsec: move ipsec sad name length into .h

Quoted 5 lines

Move IPSEC_SAD_NAMESIZE into public header
and rename it to RTE_IPSEC_SAD_NAMESIZE

---

Quoted 2 lines

--
2.7.4

#20 lore raw

PATCH v4 2/5 examples/ipsec-secgw: implement inbound SAD

In reply to Vladimir Medvedkin

Add initial support for librte_ipsec SAD library

---
 examples/ipsec-secgw/ipsec.h |  7 ++++
 examples/ipsec-secgw/sad.c   | 90 ++++++++++++++++++++++++++++++++++++++++++++
 examples/ipsec-secgw/sad.h   | 74 ++++++++++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
examples/ipsec-secgw/ipsec.h +7 -0
index 8e07521..9ddb5d9 100644
@@ -53,6 +53,13 @@ struct ipsec_xform;
 struct rte_mbuf;
 
 struct ipsec_sa;
+/*
+ * Keeps number of configured SA's for each address family:
+ */
+struct ipsec_sa_cnt {
+	uint32_t	nb_v4;
+	uint32_t	nb_v6;
+};
 
 typedef int32_t (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa,
 		struct rte_crypto_op *cop);
examples/ipsec-secgw/sad.c new file +90 -0

90 lines not on this page · raw message

examples/ipsec-secgw/sad.h new file +74 -0

74 lines not on this page · raw message

Signature · 1 line
2.7.4
#22 lore raw

PATCH v4 3/5 examples/ipsec-secgw: integrate inbound SAD

In reply to Vladimir Medvedkin

Integrate ipsec SAD support into secgw app:

1. Use SAD library for inbound SA lookup
2. Changes in struct sa_ctx:
- sa array allocates dynamically depending on number of configured sa
- All SA's are kept one by one without using SPI2IDX
3. SP's userdata now contain index of SA in sa_ctx instead of SPI
4. Get rid of SPI2IDX macro

---
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |   3 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          | 182 +++++++++++++++++++++----------------
 examples/ipsec-secgw/sp4.c         |  24 +++--
 examples/ipsec-secgw/sp6.c         |  24 +++--
 7 files changed, 139 insertions(+), 101 deletions(-)
examples/ipsec-secgw/Makefile +1 -0
index 851123b..8734b15 100644
@@ -12,6 +12,7 @@ SRCS-y += esp.c
 SRCS-y += sp4.c
 SRCS-y += sp6.c
 SRCS-y += sa.c
+SRCS-y += sad.c
 SRCS-y += rt.c
 SRCS-y += ipsec_process.c
 SRCS-y += ipsec-secgw.c
examples/ipsec-secgw/ipsec-secgw.c +2 -2
index 3b5aaf6..3e5f82e 100644
@@ -601,7 +601,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 			continue;
 		}
 
-		sa_idx = SPI2IDX(res);
+		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
 			rte_pktmbuf_free(m);
 			continue;
@@ -688,7 +688,7 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	j = 0;
 	for (i = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
-		sa_idx = SPI2IDX(ip->res[i]);
+		sa_idx = ip->res[i] - 1;
 		if (ip->res[i] == DISCARD)
 			rte_pktmbuf_free(m);
 		else if (ip->res[i] == BYPASS)
examples/ipsec-secgw/ipsec.h +1 -2
index 9ddb5d9..5988d59 100644
@@ -38,7 +38,6 @@
 #define DEFAULT_MAX_CATEGORIES	1
 
 #define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
-#define SPI2IDX(spi) (spi & (IPSEC_SA_MAX_ENTRIES - 1))
 #define INVALID_SPI (0)
 
 #define DISCARD	INVALID_SPI
@@ -359,7 +358,7 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
  * or -ENOENT otherwise.
  */
 int
-sa_spi_present(uint32_t spi, int inbound);
+sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound);
 
 void
 sa_init(struct socket_ctx *ctx, int32_t socket_id);
examples/ipsec-secgw/meson.build +1 -1
index 9ece345..6bd5b78 100644
@@ -10,5 +10,5 @@ deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec']
 allow_experimental_apis = true
 sources = files(
 	'esp.c', 'ipsec.c', 'ipsec_process.c', 'ipsec-secgw.c',
-	'parser.c', 'rt.c', 'sa.c', 'sp4.c', 'sp6.c'
+	'parser.c', 'rt.c', 'sa.c', 'sad.c', 'sp4.c', 'sp6.c'
 )
examples/ipsec-secgw/sa.c +104 -78

343 lines not on this page · raw message

examples/ipsec-secgw/sp4.c +15 -9
index 3871c6c..1dcec52 100644
@@ -493,10 +493,11 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl4_rules *acr;
+	int32_t spi_idx;
+	struct acl4_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl4_rules_in;
@@ -508,11 +509,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -535,11 +541,11 @@ 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(1) < 0)
+	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(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv4 SP DB has unmatched in SAD SPIs\n");
 
examples/ipsec-secgw/sp6.c +15 -9
index d8be6b1..b489e15 100644
@@ -625,10 +625,11 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl6_rules *acr;
+	int32_t spi_idx;
+	struct acl6_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl6_rules_in;
@@ -640,11 +641,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -667,11 +673,11 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
 		rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
 				"already initialized\n", socket_id);
 
-	if (check_spi_value(1) < 0)
+	if (check_spi_value(ctx->sa_in, 1) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Inbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
-	if (check_spi_value(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
Signature · 1 line
2.7.4
Acked-by on v4 3/5
#23 lore raw

Re: [dpdk-dev] [PATCH v4 3/5] examples/ipsec-secgw: integrate inbound SAD

Quoted 18 lines

-----Original Message-----
From: Medvedkin, Vladimir <[email protected]>
Sent: Tuesday, January 14, 2020 2:27 PM
To: [email protected]
Cc: Ananyev, Konstantin <[email protected]>; [email protected]
Subject: [PATCH v4 3/5] examples/ipsec-secgw: integrate inbound SAD

Integrate ipsec SAD support into secgw app:

1. Use SAD library for inbound SA lookup
2. Changes in struct sa_ctx:
- sa array allocates dynamically depending on number of configured sa
- All SA's are kept one by one without using SPI2IDX
3. SP's userdata now contain index of SA in sa_ctx instead of SPI
4. Get rid of SPI2IDX macro

Quoted 2 lines

---

Quoted 1 line

2.7.4

#24 lore raw

PATCH v4 4/5 examples/ipsec-secgw: get rid of maximum sa limitation

In reply to Vladimir Medvedkin

Get rid of maximum SA limitation.
Keep parsed SA's into the sorted by SPI value array. Use binary search in the sorted SA array to find appropriate SA for a given SPI.

---
 examples/ipsec-secgw/ipsec.h  |  1 -
 examples/ipsec-secgw/parser.c |  2 ++
 examples/ipsec-secgw/parser.h |  3 ++
 examples/ipsec-secgw/sa.c     | 74 +++++++++++++++++++++++++++++++++----------
 4 files changed, 62 insertions(+), 18 deletions(-)
examples/ipsec-secgw/ipsec.h +0 -1
index 5988d59..3c77232 100644
@@ -37,7 +37,6 @@
 
 #define DEFAULT_MAX_CATEGORIES	1
 
-#define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
 #define INVALID_SPI (0)
 
 #define DISCARD	INVALID_SPI
examples/ipsec-secgw/parser.c +2 -0
index fc8c238..67df170 100644
@@ -642,6 +642,8 @@ parse_cfg_file(const char *cfg_filename)
 	cmdline_stdin_exit(cl);
 	fclose(f);
 
+	sa_sort_arr();
+
 	return 0;
 
 error_exit:
examples/ipsec-secgw/parser.h +3 -0
index 6b8a100..1f8bd3e 100644
@@ -75,6 +75,9 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status);
 
 void
+sa_sort_arr(void);
+
+void
 parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status);
 
examples/ipsec-secgw/sa.c +57 -17

123 lines not on this page · raw message

Signature · 1 line
2.7.4
Acked-by on v4 4/5
#25 lore raw

Re: [dpdk-dev] [PATCH v4 4/5] examples/ipsec-secgw: get rid of maximum sa limitation

Quoted 9 lines

-----Original Message-----
From: Medvedkin, Vladimir <[email protected]>
Sent: Tuesday, January 14, 2020 2:27 PM
To: [email protected]
Cc: Ananyev, Konstantin <[email protected]>; [email protected]
Subject: [PATCH v4 4/5] examples/ipsec-secgw: get rid of maximum sa limitation

Quoted 7 lines

Get rid of maximum SA limitation.
Keep parsed SA's into the sorted by SPI value array. Use binary search in the sorted SA array to find appropriate SA for a given SPI.

---

Quoted 1 line

2.7.4

#26 lore raw

PATCH v4 5/5 examples/ipsec-secgw: get rid of maximum sp limitation

In reply to Vladimir Medvedkin

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.

---
 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(-)
examples/ipsec-secgw/parser.c +2 -0
index 67df170..65eb7e9 100644
@@ -643,6 +643,8 @@ parse_cfg_file(const char *cfg_filename)
 	fclose(f);
 
 	sa_sort_arr();
+	sp4_sort_arr();
+	sp6_sort_arr();
 
 	return 0;
 
examples/ipsec-secgw/parser.h +6 -0
index 1f8bd3e..6e764fe 100644
@@ -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);
 
examples/ipsec-secgw/sp4.c +69 -21

150 lines not on this page · raw message

examples/ipsec-secgw/sp6.c +67 -21

148 lines not on this page · raw message

Signature · 1 line
2.7.4
#28 lore raw
In reply to Vladimir Medvedkin

Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with both legacy mode and the ipsec lib mode. This would need some debugging. Didn't you see any drop on intel?

Regards,
Akhil

Quoted 47 lines

-----Original Message-----
From: Vladimir Medvedkin <[email protected]>
Sent: Tuesday, January 14, 2020 7:57 PM
To: [email protected]
Cc: [email protected]; Akhil Goyal <[email protected]>
Subject: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++--------------
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

--
2.7.4

#29 lore raw

Hi Vladimir,

The lookup logic for SAD has been brought more closer to real use case, but it looks very high on CPU and should be optimized. We cannot have 10-15% drop because of this change in SA lookup for small packet(82B) sizes where CPU is bottleneck. For large packet sizes it will not impact.

Quoted 52 lines

Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with both legacy mode and the ipsec lib mode. This would need some debugging. Didn't you see any drop on intel?

Regards,
Akhil

Quoted 22 lines

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

Quoted 7 lines
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++-------------

-

Quoted 12 lines
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

--
2.7.4

#30 lore raw
In reply to Akhil Goyal

Hi Akhil,

Indeed with our tests we also seeing ~15% perf drop for small packets (~90B) and ~3-4% drop for 1KB packets. While I am looking on a ways to minimize the drop, I think it would be hard, if possible at all to eliminate it completely. Reason for that: current SAD implementation is completely synthetic (using plain array structure indexed by SPI value). That provides a very low overhead, but doesn't provide expected functionality and can't be used in proper implementation. To measure plain IPsec performance without SAD user can still use '--signle-sa' option.

Quoted 55 lines · Akhil Goyal

Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with both legacy mode and the ipsec lib mode. This would need some debugging. Didn't you see any drop on intel?

Regards,
Akhil

Quoted 47 lines

-----Original Message-----
From: Vladimir Medvedkin <[email protected]>
Sent: Tuesday, January 14, 2020 7:57 PM
To: [email protected]
Cc: [email protected]; Akhil Goyal <[email protected]>
Subject: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

  examples/ipsec-secgw/Makefile      |   1 +
  examples/ipsec-secgw/ipsec-secgw.c |   4 +-
  examples/ipsec-secgw/ipsec.h       |  11 +-
  examples/ipsec-secgw/meson.build   |   2 +-
  examples/ipsec-secgw/parser.c      |   4 +
  examples/ipsec-secgw/parser.h      |   9 ++
  examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++--------------
  examples/ipsec-secgw/sad.c         |  90 +++++++++++++
  examples/ipsec-secgw/sad.h         |  74 +++++++++++
  examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
  examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
  lib/librte_ipsec/ipsec_sad.c       |  20 +--
  lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
  13 files changed, 528 insertions(+), 171 deletions(-)

create mode 100644 examples/ipsec-secgw/sad.c
create mode 100644 examples/ipsec-secgw/sad.h

--
2.7.4

Signature · 2 lines
Regards,
Vladimir
#31 lore raw

Hi Vladimir,
The SA lookup logic and management is purely requirement based for the application. The application may only cater to <128 SAs which can be handled based on the current logic. –single-sa option cannot handle this. Sample applications in DPDK are there to showcase the best a hardware can deliver. IMO, we cannot allow this logic on NXP hardwares. We give performance numbers based on IPSec app to customers and we cannot allow 15% degradation. Other vendors(Marvell, ARM, AMD) please comment?
Regards,
Akhil
From: Medvedkin, Vladimir <[email protected]>
Sent: Friday, January 17, 2020 10:35 PM
To: Akhil Goyal <[email protected]>; [email protected]
Cc: [email protected]
Subject: Re: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

Hi Akhil,
Indeed with our tests we also seeing ~15% perf drop for small packets (~90B) and ~3-4% drop for 1KB packets. While I am looking on a ways to minimize the drop, I think it would be hard, if possible at all to eliminate it completely. Reason for that: current SAD implementation is completely synthetic (using plain array structure indexed by SPI value). That provides a very low overhead, but doesn't provide expected functionality and can't be used in proper implementation. To measure plain IPsec performance without SAD user can still use '--signle-sa' option.
On 15/01/2020 15:45, Akhil Goyal wrote:

Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with both legacy mode and the ipsec lib mode. This would need some debugging.

Didn't you see any drop on intel?

Regards,

Akhil

-----Original Message-----

From: Vladimir Medvedkin <[email protected]><mailto:[email protected]>

Sent: Tuesday, January 14, 2020 7:57 PM

To: [email protected]<mailto:[email protected]>

Subject: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library.

The goal is to make ipsec-secgw RFC compliant regarding inbound SAD.

Also patch series removes hardcoded limitation for maximum number of SA's

and SP's.

v4:

- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:

- parse SA and SP into sorted array instead of linked list

v2:

- get rid of maximum sp limitation

Vladimir Medvedkin (5):

ipsec: move ipsec sad name length into .h

examples/ipsec-secgw: implement inbound SAD

examples/ipsec-secgw: integrate inbound SAD

examples/ipsec-secgw: get rid of maximum sa limitation

examples/ipsec-secgw: get rid of maximum sp limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++--------------
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

--

2.7.4

--

Regards,

Vladimir
-->

#32 lore raw

Hi Vladimir, Akhil,

Marvell is also observing 10-15% drop with the SAD change. I agree with Akhil's opinion and we are not in favor of making this change.

Thanks,
Anoob

From: Akhil Goyal <[email protected]>
Sent: Monday, January 20, 2020 12:14 PM
To: Medvedkin, Vladimir <[email protected]>; [email protected]
Cc: [email protected]; Anoob Joseph <[email protected]>; Thomas Monjalon <[email protected]>; Ravi Kumar <[email protected]>; Ruifeng Wang <[email protected]>
Subject: [EXT] RE: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

External Email
________________________________________
Hi Vladimir,
The SA lookup logic and management is purely requirement based for the application. The application may only cater to <128 SAs which can be handled based on the current logic. –single-sa option cannot handle this. Sample applications in DPDK are there to showcase the best a hardware can deliver. IMO, we cannot allow this logic on NXP hardwares. We give performance numbers based on IPSec app to customers and we cannot allow 15% degradation. Other vendors(Marvell, ARM, AMD) please comment?
Regards,
Akhil
From: Medvedkin, Vladimir <mailto:[email protected]>
Sent: Friday, January 17, 2020 10:35 PM
To: Akhil Goyal <mailto:[email protected]>; mailto:[email protected]
Cc: mailto:[email protected]
Subject: Re: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

Hi Akhil,
Indeed with our tests we also seeing ~15% perf drop for small packets (~90B) and ~3-4% drop for 1KB packets. While I am looking on a ways to minimize the drop, I think it would be hard, if possible at all to eliminate it completely. Reason for that: current SAD implementation is completely synthetic (using plain array structure indexed by SPI value). That provides a very low overhead, but doesn't provide expected functionality and can't be used in proper implementation. To measure plain IPsec performance without SAD user can still use '--signle-sa' option.
On 15/01/2020 15:45, Akhil Goyal wrote:
Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with both legacy mode and the ipsec lib mode. This would need some debugging. Didn't you see any drop on intel?

Regards,
Akhil

-----Original Message-----
From: Vladimir Medvedkin mailto:[email protected]
Sent: Tuesday, January 14, 2020 7:57 PM
To: mailto:[email protected]
Cc: mailto:[email protected]; Akhil Goyal mailto:[email protected]
Subject: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
  ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++--------------
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

--
2.7.4

Signature · 3 lines
Regards,
Vladimir
-->

A message that is not in the archive (sent off-list or not yet received): SN6PR11MB25581C7C8F969AA18EE8C1949A320@SN6PR11MB2558.namprd11.prod.outlook.com

A message that is not in the archive (sent off-list or not yet received): SN6PR11MB25588E3DD326CFC90DD1E3989A320@SN6PR11MB2558.namprd11.prod.outlook.com

#35 lore raw

v4 cover integrate librte_ipsec SAD into ipsec-secgw

Hi Akhil,

Quoted 4 lines

Hi Vladimir,
The SA lookup logic and management is purely requirement based for the application. The application may only cater to <128 SAs which can
be handled based on the current logic.

Not always, current implementation can handle < 128 SA, whose SPI%128 never match (let say it cant't handle SPI=1 and SPI=129). Yes, what we have right now has nearly zero overhead,
and might be ok for some really simple show-cases.
But for majority of production IPsec implementations,
I believe that definitely wouldn't be enough.

Quoted 2 lines

–single-sa option cannot handle this.
Sample applications in DPDK are there to showcase the best a hardware can deliver.

My thought was - that's the reason we have single-sa option - demonstrate best possible HW perf without minimal SW intervention. For something more serious than that, we use generic SAD implementation.

Quoted 2 lines

IMO, we cannot allow this logic on NXP hardwares. We
give performance numbers based on IPSec app to customers and we cannot allow 15% degradation.

As Vladimir said, we are looking how to improve current SAD numbers
and minimize the drop.
But with same equals - plain array will always be faster than hash table,
so not sure we will be able to match existing performance.
So two questions:
1. What exact case you use for perf testing
(total number of SAs, packets per burst belong to the same/different SAs)?
Might be there is a way to speedup it.
Again if 10-15% is not an affordable drop, which one is: zero or ...?
2. I think there are 2 different directions for ipsec-secgw:
From one-side there is a desire to use it as a show-case for best-possible HW IPsec performance
(which is understandable).
From other side - attempt to make it as close as real-world generic ipsec processing app as possible (support for ESN, replay window, fragmented packets, generic proper SAD, etc). Obviously these goals contradict and it makes really hard for the same app to fulfill both. Any thoughts how to deal with that?
One obvious would be to split the app, anything else?

Konstantin

Quoted 77 lines

Other vendors(Marvell, ARM, AMD) please comment?
Regards,
Akhil
From: Medvedkin, Vladimir <mailto:[email protected]>
Sent: Friday, January 17, 2020 10:35 PM
To: Akhil Goyal <mailto:[email protected]>; mailto:[email protected]
Cc: mailto:[email protected]
Subject: Re: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

Hi Akhil,
Indeed with our tests we also seeing ~15% perf drop for small packets (~90B) and ~3-4% drop for 1KB packets. While I am looking on a ways to minimize the drop, I think it would be hard, if possible at all to eliminate it completely.
Reason for that: current SAD implementation is completely synthetic (using plain array structure indexed by SPI value). That provides a very low overhead, but doesn't provide expected functionality and can't be used in proper implementation.
To measure plain IPsec performance without SAD user can still use '--signle-sa' option.
On 15/01/2020 15:45, Akhil Goyal wrote:
Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with both legacy mode and the ipsec lib mode. This would need some debugging.
Didn't you see any drop on intel?

Regards,
Akhil

-----Original Message-----
From: Vladimir Medvedkin mailto:[email protected]
Sent: Tuesday, January 14, 2020 7:57 PM
To: mailto:[email protected]
Cc: mailto:[email protected]; Akhil Goyal mailto:[email protected]
Subject: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
  ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++--------------
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

--
2.7.4

--
Regards,
Vladimir
-->

#36 lore raw

Hi Konstantin,

Quoted 28 lines

Hi Akhil,

Quoted 2 lines

Hi Vladimir,
The SA lookup logic and management is purely requirement based for the

application.

Quoted 2 lines

The application may only cater to <128 SAs which can be handled based on the current logic.

Not always, current implementation can handle < 128 SA, whose SPI%128 never match (let say it cant't handle SPI=1 and SPI=129). Yes, what we have right now has nearly zero overhead,
and might be ok for some really simple show-cases.
But for majority of production IPsec implementations,
I believe that definitely wouldn't be enough.

Quoted 2 lines

–single-sa option cannot handle this.
Sample applications in DPDK are there to showcase the best a hardware can

deliver.

My thought was - that's the reason we have single-sa option - demonstrate best possible HW perf without minimal SW intervention. For something more serious than that, we use generic SAD implementation.

Quoted 2 lines

IMO, we cannot allow this logic on NXP hardwares. We
give performance numbers based on IPSec app to customers and we cannot

allow 15% degradation.

Quoted 9 lines

As Vladimir said, we are looking how to improve current SAD numbers and minimize the drop.
But with same equals - plain array will always be faster than hash table, so not sure we will be able to match existing performance.
So two questions:
1. What exact case you use for perf testing
(total number of SAs, packets per burst belong to the same/different SAs)? Might be there is a way to speedup it.
Again if 10-15% is not an affordable drop, which one is: zero or ...?

We should add features judiciously, we cannot drop the performance of a benchmarking Application in lieu of adding functionality. We should only add features which are not Impacting the performance significantly.
Every vendor may have different cases. We cannot tune for everybody. However, I see drop in 64 outbound 64 inbound SAs all with different SPI and IPs. Packets per burst = 32 all with different SAs.

Quoted 4 lines

2. I think there are 2 different directions for ipsec-secgw:
From one-side there is a desire to use it as a show-case for best-possible HW
IPsec performance
(which is understandable).

Quoted 8 lines

From other side - attempt to make it as close as real-world generic ipsec
processing app as possible
(support for ESN, replay window, fragmented packets, generic proper SAD,
etc).
Obviously these goals contradict and it makes really hard for the same app to
fulfill both.
Any thoughts how to deal with that?
One obvious would be to split the app, anything else?

We can have a fallback mechanism back to original functionality for whatever feature which has some perf drop.
Splitting an app can be thought of but that would be similar to a full fledged IPSec stack like VPP-IPSec.

Quoted 88 lines

Konstantin

Quoted 11 lines

Other vendors(Marvell, ARM, AMD) please comment?
Regards,
Akhil
From: Medvedkin, Vladimir <mailto:[email protected]>
Sent: Friday, January 17, 2020 10:35 PM
To: Akhil Goyal <mailto:[email protected]>; mailto:[email protected]
Cc: mailto:[email protected]
Subject: Re: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

Hi Akhil,
Indeed with our tests we also seeing ~15% perf drop for small packets (~90B)

and ~3-4% drop for 1KB packets. While I am looking on a ways

Quoted 1 line

to minimize the drop, I think it would be hard, if possible at all to eliminate it

completely.

Quoted 1 line

Reason for that: current SAD implementation is completely synthetic (using

plain array structure indexed by SPI value). That provides a very

Quoted 1 line

low overhead, but doesn't provide expected functionality and can't be used in

proper implementation.

Quoted 1 line

To measure plain IPsec performance without SAD user can still use '--signle-sa'

option.

Quoted 4 lines · Akhil Goyal

Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with both

legacy mode and the ipsec lib mode. This would need some

Quoted 11 lines

debugging.
Didn't you see any drop on intel?

Regards,
Akhil

-----Original Message-----
From: Vladimir Medvedkin mailto:[email protected]
Sent: Tuesday, January 14, 2020 7:57 PM
To: mailto:[email protected]
Cc: mailto:[email protected]; Akhil Goyal

mailto:[email protected]

Quoted 23 lines

Subject: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
  ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

Quoted 7 lines
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++-------------

-

Quoted 17 lines
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

--
2.7.4

--
Regards,
Vladimir
-->

#37 lore raw

Hi All,

Quoted 40 lines

Hi Konstantin,

Quoted 28 lines

Hi Akhil,

Quoted 2 lines

Hi Vladimir,
The SA lookup logic and management is purely requirement based for the

application.

Quoted 2 lines

The application may only cater to <128 SAs which can be handled based on the current logic.

Not always, current implementation can handle < 128 SA, whose SPI%128 never match (let say it cant't handle SPI=1 and SPI=129). Yes, what we have right now has nearly zero overhead,
and might be ok for some really simple show-cases.
But for majority of production IPsec implementations,
I believe that definitely wouldn't be enough.

Quoted 2 lines

–single-sa option cannot handle this.
Sample applications in DPDK are there to showcase the best a hardware can

deliver.

My thought was - that's the reason we have single-sa option - demonstrate best possible HW perf without minimal SW intervention. For something more serious than that, we use generic SAD implementation.

Quoted 2 lines

IMO, we cannot allow this logic on NXP hardwares. We
give performance numbers based on IPSec app to customers and we cannot

allow 15% degradation.

Quoted 9 lines

As Vladimir said, we are looking how to improve current SAD numbers and minimize the drop.
But with same equals - plain array will always be faster than hash table, so not sure we will be able to match existing performance.
So two questions:
1. What exact case you use for perf testing
(total number of SAs, packets per burst belong to the same/different SAs)? Might be there is a way to speedup it.
Again if 10-15% is not an affordable drop, which one is: zero or ...?

Quoted 9 lines

We should add features judiciously, we cannot drop the performance of a benchmarking
Application in lieu of adding functionality. We should only add features which are not
Impacting the performance significantly.
Every vendor may have different cases. We cannot tune for everybody. However, I see drop in 64 outbound 64 inbound SAs all with different SPI and IPs. Packets per burst = 32 all with different SAs.

We can have two modes of lookup similar to l3fwd - EM and LPM.
LPM is O(1) while EM is more realistic. Similar logic can be added here as well. With L3fwd also we showcase performance for best case(lpm) and the worst case(em) What Say?

As discussed in the DPDK-status meeting today, this patchset need to be discussed in Techboard meeting. Please include this topic in the upcoming meeting on 29th Jan.

-Akhil

Quoted 111 lines
Quoted 4 lines

2. I think there are 2 different directions for ipsec-secgw:
From one-side there is a desire to use it as a show-case for best-possible HW
IPsec performance
(which is understandable).

Quoted 8 lines

From other side - attempt to make it as close as real-world generic ipsec
processing app as possible
(support for ESN, replay window, fragmented packets, generic proper SAD,
etc).
Obviously these goals contradict and it makes really hard for the same app to
fulfill both.
Any thoughts how to deal with that?
One obvious would be to split the app, anything else?

We can have a fallback mechanism back to original functionality for whatever feature
which has some perf drop.
Splitting an app can be thought of but that would be similar to a full fledged IPSec stack
like VPP-IPSec.

Quoted 12 lines

Konstantin

Quoted 9 lines

Other vendors(Marvell, ARM, AMD) please comment?
Regards,
Akhil
From: Medvedkin, Vladimir <mailto:[email protected]>
Sent: Friday, January 17, 2020 10:35 PM
To: Akhil Goyal <mailto:[email protected]>; mailto:[email protected]
Cc: mailto:[email protected]
Subject: Re: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

Quoted 8 lines
Quoted 2 lines

Hi Akhil,
Indeed with our tests we also seeing ~15% perf drop for small packets (~90B)

and ~3-4% drop for 1KB packets. While I am looking on a ways

Quoted 1 line

to minimize the drop, I think it would be hard, if possible at all to eliminate it

completely.

Quoted 1 line

Reason for that: current SAD implementation is completely synthetic (using

plain array structure indexed by SPI value). That provides a very

Quoted 1 line

low overhead, but doesn't provide expected functionality and can't be used

in

Quoted 2 lines

proper implementation.

Quoted 1 line

To measure plain IPsec performance without SAD user can still use '--signle-

sa'

Quoted 12 lines

option.

Quoted 4 lines · Akhil Goyal

Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with both

legacy mode and the ipsec lib mode. This would need some

Quoted 6 lines

debugging.
Didn't you see any drop on intel?

Regards,
Akhil

Quoted 36 lines
Quoted 5 lines

-----Original Message-----
From: Vladimir Medvedkin mailto:[email protected]
Sent: Tuesday, January 14, 2020 7:57 PM
To: mailto:[email protected]
Cc: mailto:[email protected]; Akhil Goyal

mailto:[email protected]

Quoted 30 lines

Subject: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
  ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++-----------

--

Quoted 18 lines

-

Quoted 17 lines
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

--
2.7.4

--
Regards,
Vladimir
-->

#38 lore raw

Hi Akhil,

Quoted 45 lines
Quoted 35 lines
Quoted 25 lines
Quoted 2 lines

Hi Vladimir,
The SA lookup logic and management is purely requirement based for the

application.

Quoted 2 lines

The application may only cater to <128 SAs which can be handled based on the current logic.

Not always, current implementation can handle < 128 SA, whose SPI%128 never match (let say it cant't handle SPI=1 and SPI=129). Yes, what we have right now has nearly zero overhead,
and might be ok for some really simple show-cases.
But for majority of production IPsec implementations,
I believe that definitely wouldn't be enough.

Quoted 2 lines

–single-sa option cannot handle this.
Sample applications in DPDK are there to showcase the best a hardware can

deliver.

My thought was - that's the reason we have single-sa option - demonstrate best possible HW perf without minimal SW intervention. For something more serious than that, we use generic SAD implementation.

Quoted 2 lines

IMO, we cannot allow this logic on NXP hardwares. We
give performance numbers based on IPSec app to customers and we cannot

allow 15% degradation.

Quoted 9 lines

As Vladimir said, we are looking how to improve current SAD numbers and minimize the drop.
But with same equals - plain array will always be faster than hash table, so not sure we will be able to match existing performance.
So two questions:
1. What exact case you use for perf testing
(total number of SAs, packets per burst belong to the same/different SAs)? Might be there is a way to speedup it.
Again if 10-15% is not an affordable drop, which one is: zero or ...?

Quoted 9 lines

We should add features judiciously, we cannot drop the performance of a benchmarking
Application in lieu of adding functionality. We should only add features which are not
Impacting the performance significantly.
Every vendor may have different cases. We cannot tune for everybody. However, I see drop in 64 outbound 64 inbound SAs all with different SPI and IPs. Packets per burst = 32 all with different SAs.

Quoted 4 lines

We can have two modes of lookup similar to l3fwd - EM and LPM.
LPM is O(1) while EM is more realistic. Similar logic can be added here as well. With L3fwd also we showcase performance for best case(lpm) and the worst case(em) What Say?

We discussed it off-line with Vladimir and came up with similar idea:
Have a proper/generic SAD implementation and add limited size plain-array on top of it as 1xway associative cache.
So for the case when all active SAs fit into the cache and no SPI collisions, we should have same performance as now (with plain array).
From other side, we'll still have generic/scalable/rfc compliant implementation. Sort of best sides from two words.
Plans are to submit v4 with such approach in next few days.

Quoted 3 lines

As discussed in the DPDK-status meeting today, this patchset need to be discussed in Techboard meeting. Please include this topic in the upcoming meeting on 29th Jan.

As I said above, I think we found a way to deal with it without any perf drop for existing cases.
Though sure, if you feel some extra discussion is needed, let's request to put it into agenda.

Konstantin

Quoted 114 lines

-Akhil

Quoted 111 lines
Quoted 4 lines

2. I think there are 2 different directions for ipsec-secgw:
From one-side there is a desire to use it as a show-case for best-possible HW
IPsec performance
(which is understandable).

Quoted 8 lines

From other side - attempt to make it as close as real-world generic ipsec
processing app as possible
(support for ESN, replay window, fragmented packets, generic proper SAD,
etc).
Obviously these goals contradict and it makes really hard for the same app to
fulfill both.
Any thoughts how to deal with that?
One obvious would be to split the app, anything else?

We can have a fallback mechanism back to original functionality for whatever feature
which has some perf drop.
Splitting an app can be thought of but that would be similar to a full fledged IPSec stack
like VPP-IPSec.

Quoted 12 lines

Konstantin

Quoted 9 lines

Other vendors(Marvell, ARM, AMD) please comment?
Regards,
Akhil
From: Medvedkin, Vladimir <mailto:[email protected]>
Sent: Friday, January 17, 2020 10:35 PM
To: Akhil Goyal <mailto:[email protected]>; mailto:[email protected]
Cc: mailto:[email protected]
Subject: Re: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

Quoted 8 lines
Quoted 2 lines

Hi Akhil,
Indeed with our tests we also seeing ~15% perf drop for small packets (~90B)

and ~3-4% drop for 1KB packets. While I am looking on a ways

Quoted 1 line

to minimize the drop, I think it would be hard, if possible at all to eliminate it

completely.

Quoted 1 line

Reason for that: current SAD implementation is completely synthetic (using

plain array structure indexed by SPI value). That provides a very

Quoted 1 line

low overhead, but doesn't provide expected functionality and can't be used

in

Quoted 2 lines

proper implementation.

Quoted 1 line

To measure plain IPsec performance without SAD user can still use '--signle-

sa'

Quoted 12 lines

option.

Quoted 4 lines · Akhil Goyal

Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with both

legacy mode and the ipsec lib mode. This would need some

Quoted 6 lines

debugging.
Didn't you see any drop on intel?

Regards,
Akhil

Quoted 36 lines
Quoted 5 lines

-----Original Message-----
From: Vladimir Medvedkin mailto:[email protected]
Sent: Tuesday, January 14, 2020 7:57 PM
To: mailto:[email protected]
Cc: mailto:[email protected]; Akhil Goyal

mailto:[email protected]

Quoted 30 lines

Subject: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
  ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++-----------

--

Quoted 18 lines

-

Quoted 17 lines
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

--
2.7.4

--
Regards,
Vladimir
-->

#39 lore raw

Hi Konstantin,

Quoted 57 lines

Hi Akhil,

Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 2 lines

Hi Vladimir,
The SA lookup logic and management is purely requirement based for the

application.

Quoted 2 lines

The application may only cater to <128 SAs which can be handled based on the current logic.

Not always, current implementation can handle < 128 SA, whose SPI%128 never match (let say it cant't handle SPI=1 and SPI=129). Yes, what we have right now has nearly zero overhead,
and might be ok for some really simple show-cases.
But for majority of production IPsec implementations,
I believe that definitely wouldn't be enough.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

–single-sa option cannot handle this.
Sample applications in DPDK are there to showcase the best a hardware

can

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

deliver.

My thought was - that's the reason we have single-sa option - demonstrate best possible HW perf without minimal SW intervention. For something more serious than that, we use generic SAD implementation.

Quoted 2 lines

IMO, we cannot allow this logic on NXP hardwares. We give performance numbers based on IPSec app to customers and we

cannot

Quoted 12 lines
Quoted 12 lines
Quoted 11 lines

allow 15% degradation.

As Vladimir said, we are looking how to improve current SAD numbers and minimize the drop.
But with same equals - plain array will always be faster than hash table, so not sure we will be able to match existing performance.
So two questions:
1. What exact case you use for perf testing
(total number of SAs, packets per burst belong to the same/different SAs)? Might be there is a way to speedup it.
Again if 10-15% is not an affordable drop, which one is: zero or ...?

Quoted 7 lines
Quoted 7 lines

We should add features judiciously, we cannot drop the performance of a benchmarking
Application in lieu of adding functionality. We should only add features which are not
Impacting the performance significantly.
Every vendor may have different cases. We cannot tune for everybody. However, I see drop in 64 outbound 64 inbound SAs all with different SPI and

IPs.

Quoted 6 lines
Quoted 2 lines

Packets per burst = 32 all with different SAs.

We can have two modes of lookup similar to l3fwd - EM and LPM.
LPM is O(1) while EM is more realistic. Similar logic can be added here as well. With L3fwd also we showcase performance for best case(lpm) and the worst

case(em)

Quoted 1 line

What Say?

Quoted 8 lines

We discussed it off-line with Vladimir and came up with similar idea:
Have a proper/generic SAD implementation and add limited size plain-array on top of it as 1xway associative cache.
So for the case when all active SAs fit into the cache and no SPI collisions, we should have same performance as now (with plain array).
From other side, we'll still have generic/scalable/rfc compliant implementation. Sort of best sides from two words.
Plans are to submit v4 with such approach in next few days.

OK lets check the v4 before moving the discussion to techboard. @Thomas: Do you have more thoughts on this? Should we get it added in the agenda Or wait for the v4?

Quoted 140 lines
Quoted 3 lines

As discussed in the DPDK-status meeting today, this patchset need to be

discussed in

Quoted 1 line

Techboard meeting. Please include this topic in the upcoming meeting on 29th

Jan.

As I said above, I think we found a way to deal with it without any perf drop for existing cases.
Though sure, if you feel some extra discussion is needed, let's request to put it into agenda.

Konstantin

Quoted 5 lines

-Akhil

Quoted 2 lines
Quoted 2 lines

2. I think there are 2 different directions for ipsec-secgw:
From one-side there is a desire to use it as a show-case for best-possible

HW

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

IPsec performance
(which is understandable).
From other side - attempt to make it as close as real-world generic ipsec
processing app as possible
(support for ESN, replay window, fragmented packets, generic proper

SAD,

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

etc).
Obviously these goals contradict and it makes really hard for the same

app to

Quoted 5 lines
Quoted 5 lines
Quoted 3 lines

fulfill both.
Any thoughts how to deal with that?
One obvious would be to split the app, anything else?

We can have a fallback mechanism back to original functionality for

whatever

Quoted 18 lines
Quoted 18 lines

feature
which has some perf drop.
Splitting an app can be thought of but that would be similar to a full fledged IPSec stack
like VPP-IPSec.

Quoted 12 lines

Konstantin

Quoted 9 lines

Other vendors(Marvell, ARM, AMD) please comment?
Regards,
Akhil
From: Medvedkin, Vladimir <mailto:[email protected]>
Sent: Friday, January 17, 2020 10:35 PM
To: Akhil Goyal <mailto:[email protected]>; mailto:[email protected]
Cc: mailto:[email protected]
Subject: Re: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Hi Akhil,
Indeed with our tests we also seeing ~15% perf drop for small packets

(~90B)

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

and ~3-4% drop for 1KB packets. While I am looking on a ways

Quoted 1 line

to minimize the drop, I think it would be hard, if possible at all to

eliminate it

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

completely.

Quoted 1 line

Reason for that: current SAD implementation is completely synthetic

(using

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

plain array structure indexed by SPI value). That provides a very

Quoted 1 line

low overhead, but doesn't provide expected functionality and can't be

used

Quoted 3 lines
Quoted 3 lines

in

Quoted 2 lines

proper implementation.

Quoted 1 line

To measure plain IPsec performance without SAD user can still use '--

signle-

Quoted 6 lines
Quoted 6 lines

sa'

Quoted 5 lines

option.

Quoted 4 lines · Akhil Goyal

Hi Vladimir,

There is more than 10% drop with this patchset on NXP hardware with

both

Quoted 12 lines
Quoted 12 lines
Quoted 12 lines

legacy mode and the ipsec lib mode. This would need some

Quoted 11 lines

debugging.
Didn't you see any drop on intel?

Regards,
Akhil

-----Original Message-----
From: Vladimir Medvedkin mailto:[email protected]
Sent: Tuesday, January 14, 2020 7:57 PM
To: mailto:[email protected]
Cc: mailto:[email protected]; Akhil Goyal

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

mailto:[email protected]

Quoted 5 lines

Subject: [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of

SA's

Quoted 18 lines
Quoted 18 lines
Quoted 18 lines
Quoted 18 lines

and SP's.

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (5):
  ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |  11 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 256 +++++++++++++++++++++++------

-----

Quoted 19 lines
Quoted 19 lines

--

Quoted 18 lines

-

Quoted 17 lines
 examples/ipsec-secgw/sad.c         |  90 +++++++++++++
 examples/ipsec-secgw/sad.h         |  74 +++++++++++
 examples/ipsec-secgw/sp4.c         | 114 ++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 +++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 528 insertions(+), 171 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

--
2.7.4

--
Regards,
Vladimir
-->

#40 lore raw

23/01/2020 13:56, Akhil Goyal:

Quoted 67 lines

Hi Konstantin,

Quoted 57 lines

Hi Akhil,

Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 2 lines

Hi Vladimir,
The SA lookup logic and management is purely requirement based for the

application.

Quoted 2 lines

The application may only cater to <128 SAs which can be handled based on the current logic.

Not always, current implementation can handle < 128 SA, whose SPI%128 never match (let say it cant't handle SPI=1 and SPI=129). Yes, what we have right now has nearly zero overhead,
and might be ok for some really simple show-cases.
But for majority of production IPsec implementations,
I believe that definitely wouldn't be enough.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

–single-sa option cannot handle this.
Sample applications in DPDK are there to showcase the best a hardware

can

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

deliver.

My thought was - that's the reason we have single-sa option - demonstrate best possible HW perf without minimal SW intervention. For something more serious than that, we use generic SAD implementation.

Quoted 2 lines

IMO, we cannot allow this logic on NXP hardwares. We give performance numbers based on IPSec app to customers and we

cannot

Quoted 12 lines
Quoted 12 lines
Quoted 11 lines

allow 15% degradation.

As Vladimir said, we are looking how to improve current SAD numbers and minimize the drop.
But with same equals - plain array will always be faster than hash table, so not sure we will be able to match existing performance.
So two questions:
1. What exact case you use for perf testing
(total number of SAs, packets per burst belong to the same/different SAs)? Might be there is a way to speedup it.
Again if 10-15% is not an affordable drop, which one is: zero or ...?

Quoted 7 lines
Quoted 7 lines

We should add features judiciously, we cannot drop the performance of a benchmarking
Application in lieu of adding functionality. We should only add features which are not
Impacting the performance significantly.
Every vendor may have different cases. We cannot tune for everybody. However, I see drop in 64 outbound 64 inbound SAs all with different SPI and

IPs.

Quoted 6 lines
Quoted 2 lines

Packets per burst = 32 all with different SAs.

We can have two modes of lookup similar to l3fwd - EM and LPM.
LPM is O(1) while EM is more realistic. Similar logic can be added here as well. With L3fwd also we showcase performance for best case(lpm) and the worst

case(em)

Quoted 1 line

What Say?

Quoted 8 lines

We discussed it off-line with Vladimir and came up with similar idea:
Have a proper/generic SAD implementation and add limited size plain-array on top of it as 1xway associative cache.
So for the case when all active SAs fit into the cache and no SPI collisions, we should have same performance as now (with plain array).
From other side, we'll still have generic/scalable/rfc compliant implementation. Sort of best sides from two words.
Plans are to submit v4 with such approach in next few days.

Quoted 3 lines

OK lets check the v4 before moving the discussion to techboard. @Thomas: Do you have more thoughts on this? Should we get it added in the agenda Or wait for the v4?

If v4 is good for both cases, it lowers the priority of the discussion.

But still, it would be interesting to state the objectives of the examples:
- show API usage?
- show feature performance?
- show best hardware performance?
- what else?

#41 lore raw
Quoted 67 lines
Quoted 63 lines
Quoted 54 lines
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 2 lines

The SA lookup logic and management is purely requirement based for the

application.

Quoted 2 lines

The application may only cater to <128 SAs which can be handled based on the current logic.

Not always, current implementation can handle < 128 SA, whose SPI%128 never match (let say it cant't handle SPI=1 and SPI=129). Yes, what we have right now has nearly zero overhead,
and might be ok for some really simple show-cases.
But for majority of production IPsec implementations,
I believe that definitely wouldn't be enough.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

–single-sa option cannot handle this.
Sample applications in DPDK are there to showcase the best a hardware

can

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

deliver.

My thought was - that's the reason we have single-sa option - demonstrate best possible HW perf without minimal SW intervention. For something more serious than that, we use generic SAD implementation.

Quoted 2 lines

IMO, we cannot allow this logic on NXP hardwares. We give performance numbers based on IPSec app to customers and we

cannot

Quoted 12 lines
Quoted 12 lines
Quoted 11 lines

allow 15% degradation.

As Vladimir said, we are looking how to improve current SAD numbers and minimize the drop.
But with same equals - plain array will always be faster than hash table, so not sure we will be able to match existing performance.
So two questions:
1. What exact case you use for perf testing
(total number of SAs, packets per burst belong to the same/different SAs)? Might be there is a way to speedup it.
Again if 10-15% is not an affordable drop, which one is: zero or ...?

Quoted 7 lines
Quoted 7 lines

We should add features judiciously, we cannot drop the performance of a benchmarking
Application in lieu of adding functionality. We should only add features which are not
Impacting the performance significantly.
Every vendor may have different cases. We cannot tune for everybody. However, I see drop in 64 outbound 64 inbound SAs all with different SPI and

IPs.

Quoted 6 lines
Quoted 2 lines

Packets per burst = 32 all with different SAs.

We can have two modes of lookup similar to l3fwd - EM and LPM.
LPM is O(1) while EM is more realistic. Similar logic can be added here as well. With L3fwd also we showcase performance for best case(lpm) and the worst

case(em)

Quoted 1 line

What Say?

Quoted 8 lines

We discussed it off-line with Vladimir and came up with similar idea:
Have a proper/generic SAD implementation and add limited size plain-array on top of it as 1xway associative cache.
So for the case when all active SAs fit into the cache and no SPI collisions, we should have same performance as now (with plain array).
From other side, we'll still have generic/scalable/rfc compliant implementation. Sort of best sides from two words.
Plans are to submit v4 with such approach in next few days.

Quoted 3 lines

OK lets check the v4 before moving the discussion to techboard. @Thomas: Do you have more thoughts on this? Should we get it added in the agenda Or wait for the v4?

Quoted 7 lines

If v4 is good for both cases, it lowers the priority of the discussion.

But still, it would be interesting to state the objectives of the examples:
- show API usage?
- show feature performance?
- show best hardware performance?
- what else?

Agree, that’s a good topic to discuss.

#42 lore raw

v5 cover integrate librte_ipsec SAD into ipsec-secgw

In reply to Vladimir Medvedkin

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.
According to our measurements, after this series of patches, ipsec-secgw performance drops by about 0-2%.

v5:
- introduce SAD cache to solve performance degradation
- ipsec_sad_add() returns an error if the key is present

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (6):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation examples/ipsec-secgw: add SAD cache

 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |  34 +++++-
 examples/ipsec-secgw/ipsec.h       |  12 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 238 +++++++++++++++++++++----------------
 examples/ipsec-secgw/sad.c         | 149 +++++++++++++++++++++++
 examples/ipsec-secgw/sad.h         | 168 ++++++++++++++++++++++++++
 examples/ipsec-secgw/sp4.c         | 114 +++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 ++++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 ++--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 686 insertions(+), 179 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
Signature · 1 line
2.7.4
#43 lore raw

PATCH v5 1/6 ipsec: move ipsec sad name length into .h

Move IPSEC_SAD_NAMESIZE into public header
and rename it to RTE_IPSEC_SAD_NAMESIZE

---
 lib/librte_ipsec/ipsec_sad.c     | 20 ++++++++++----------
 lib/librte_ipsec/rte_ipsec_sad.h |  2 ++
 2 files changed, 12 insertions(+), 10 deletions(-)
lib/librte_ipsec/ipsec_sad.c +10 -10
index db2c44c..2c994ed 100644
@@ -20,7 +20,6 @@
  * indicate presence of entries with the same SPI in DIP and DIP+SIP tables.
  */
 
-#define IPSEC_SAD_NAMESIZE	64
 #define SAD_PREFIX		"SAD_"
 /* "SAD_<name>" */
 #define SAD_FORMAT		SAD_PREFIX "%s"
@@ -34,7 +33,7 @@ struct hash_cnt {
 };
 
 struct rte_ipsec_sad {
-	char name[IPSEC_SAD_NAMESIZE];
+	char name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_hash	*hash[RTE_IPSEC_SAD_KEY_TYPE_MASK];
 	/* Array to track number of more specific rules
 	 * (spi_dip or spi_dip_sip). Used only in add/delete
@@ -231,7 +230,7 @@ struct rte_ipsec_sad *
 rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 {
 	char hash_name[RTE_HASH_NAMESIZE];
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	struct rte_ipsec_sad *sad, *tmp_sad = NULL;
@@ -249,8 +248,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 		return NULL;
 	}
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -326,7 +325,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 	/* guarantee there's no existing */
 	TAILQ_FOREACH(te, sad_list, next) {
 		tmp_sad = (struct rte_ipsec_sad *)te->data;
-		if (strncmp(sad_name, tmp_sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, tmp_sad->name,
+				RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	if (te != NULL) {
@@ -354,14 +354,14 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 struct rte_ipsec_sad *
 rte_ipsec_sad_find_existing(const char *name)
 {
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_ipsec_sad *sad = NULL;
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	int ret;
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -372,7 +372,7 @@ rte_ipsec_sad_find_existing(const char *name)
 	rte_mcfg_tailq_read_lock();
 	TAILQ_FOREACH(te, sad_list, next) {
 		sad = (struct rte_ipsec_sad *) te->data;
-		if (strncmp(sad_name, sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, sad->name, RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	rte_mcfg_tailq_read_unlock();
lib/librte_ipsec/rte_ipsec_sad.h +2 -0
index 8386f73..dcc8224 100644
@@ -47,6 +47,8 @@ union rte_ipsec_sad_key {
 	struct rte_ipsec_sadv6_key	v6;
 };
 
+/** Max number of characters in SAD name. */
+#define RTE_IPSEC_SAD_NAMESIZE		64
 /** Flag to create SAD with ipv6 dip and sip addresses */
 #define RTE_IPSEC_SAD_FLAG_IPV6			0x1
 /** Flag to support reader writer concurrency */
Signature · 1 line
2.7.4
#44 lore raw

PATCH v5 2/6 examples/ipsec-secgw: implement inbound SAD

In reply to Vladimir Medvedkin

Add initial support for librte_ipsec SAD library

---
 examples/ipsec-secgw/ipsec.h |   7 +++
 examples/ipsec-secgw/sad.c   | 109 +++++++++++++++++++++++++++++++++++++++++++
 examples/ipsec-secgw/sad.h   |  75 +++++++++++++++++++++++++++++
 3 files changed, 191 insertions(+)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
examples/ipsec-secgw/ipsec.h +7 -0
index 8e07521..9ddb5d9 100644
@@ -53,6 +53,13 @@ struct ipsec_xform;
 struct rte_mbuf;
 
 struct ipsec_sa;
+/*
+ * Keeps number of configured SA's for each address family:
+ */
+struct ipsec_sa_cnt {
+	uint32_t	nb_v4;
+	uint32_t	nb_v6;
+};
 
 typedef int32_t (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa,
 		struct rte_crypto_op *cop);
examples/ipsec-secgw/sad.c new file +109 -0

109 lines not on this page · raw message

examples/ipsec-secgw/sad.h new file +75 -0

75 lines not on this page · raw message

Signature · 1 line
2.7.4
#45 lore raw

PATCH v5 3/6 examples/ipsec-secgw: integrate inbound SAD

In reply to Vladimir Medvedkin

Integrate ipsec SAD support into secgw app:

1. Use SAD library for inbound SA lookup
2. Changes in struct sa_ctx:
- sa array allocates dynamically depending on number of configured sa
- All SA's are kept one by one without using SPI2IDX
3. SP's userdata now contain index of SA in sa_ctx instead of SPI
4. Get rid of SPI2IDX macro

---
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |   3 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          | 182 +++++++++++++++++++++----------------
 examples/ipsec-secgw/sp4.c         |  24 +++--
 examples/ipsec-secgw/sp6.c         |  24 +++--
 7 files changed, 139 insertions(+), 101 deletions(-)
examples/ipsec-secgw/Makefile +1 -0
index 851123b..8734b15 100644
@@ -12,6 +12,7 @@ SRCS-y += esp.c
 SRCS-y += sp4.c
 SRCS-y += sp6.c
 SRCS-y += sa.c
+SRCS-y += sad.c
 SRCS-y += rt.c
 SRCS-y += ipsec_process.c
 SRCS-y += ipsec-secgw.c
examples/ipsec-secgw/ipsec-secgw.c +2 -2
index 3b5aaf6..3e5f82e 100644
@@ -601,7 +601,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 			continue;
 		}
 
-		sa_idx = SPI2IDX(res);
+		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
 			rte_pktmbuf_free(m);
 			continue;
@@ -688,7 +688,7 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	j = 0;
 	for (i = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
-		sa_idx = SPI2IDX(ip->res[i]);
+		sa_idx = ip->res[i] - 1;
 		if (ip->res[i] == DISCARD)
 			rte_pktmbuf_free(m);
 		else if (ip->res[i] == BYPASS)
examples/ipsec-secgw/ipsec.h +1 -2
index 9ddb5d9..5988d59 100644
@@ -38,7 +38,6 @@
 #define DEFAULT_MAX_CATEGORIES	1
 
 #define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
-#define SPI2IDX(spi) (spi & (IPSEC_SA_MAX_ENTRIES - 1))
 #define INVALID_SPI (0)
 
 #define DISCARD	INVALID_SPI
@@ -359,7 +358,7 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
  * or -ENOENT otherwise.
  */
 int
-sa_spi_present(uint32_t spi, int inbound);
+sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound);
 
 void
 sa_init(struct socket_ctx *ctx, int32_t socket_id);
examples/ipsec-secgw/meson.build +1 -1
index 9ece345..6bd5b78 100644
@@ -10,5 +10,5 @@ deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec']
 allow_experimental_apis = true
 sources = files(
 	'esp.c', 'ipsec.c', 'ipsec_process.c', 'ipsec-secgw.c',
-	'parser.c', 'rt.c', 'sa.c', 'sp4.c', 'sp6.c'
+	'parser.c', 'rt.c', 'sa.c', 'sad.c', 'sp4.c', 'sp6.c'
 )
examples/ipsec-secgw/sa.c +104 -78

343 lines not on this page · raw message

examples/ipsec-secgw/sp4.c +15 -9
index 3871c6c..1dcec52 100644
@@ -493,10 +493,11 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl4_rules *acr;
+	int32_t spi_idx;
+	struct acl4_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl4_rules_in;
@@ -508,11 +509,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -535,11 +541,11 @@ 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(1) < 0)
+	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(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv4 SP DB has unmatched in SAD SPIs\n");
 
examples/ipsec-secgw/sp6.c +15 -9
index d8be6b1..b489e15 100644
@@ -625,10 +625,11 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl6_rules *acr;
+	int32_t spi_idx;
+	struct acl6_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl6_rules_in;
@@ -640,11 +641,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -667,11 +673,11 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
 		rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
 				"already initialized\n", socket_id);
 
-	if (check_spi_value(1) < 0)
+	if (check_spi_value(ctx->sa_in, 1) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Inbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
-	if (check_spi_value(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
Signature · 1 line
2.7.4
#46 lore raw

PATCH v5 4/6 examples/ipsec-secgw: get rid of maximum sa limitation

In reply to Vladimir Medvedkin

Get rid of maximum SA limitation.
Keep parsed SA's into the sorted by SPI value array. Use binary search in the sorted SA array to find appropriate SA for a given SPI.

---
 examples/ipsec-secgw/ipsec.h  |  1 -
 examples/ipsec-secgw/parser.c |  2 ++
 examples/ipsec-secgw/parser.h |  3 ++
 examples/ipsec-secgw/sa.c     | 74 +++++++++++++++++++++++++++++++++----------
 4 files changed, 62 insertions(+), 18 deletions(-)
examples/ipsec-secgw/ipsec.h +0 -1
index 5988d59..3c77232 100644
@@ -37,7 +37,6 @@
 
 #define DEFAULT_MAX_CATEGORIES	1
 
-#define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
 #define INVALID_SPI (0)
 
 #define DISCARD	INVALID_SPI
examples/ipsec-secgw/parser.c +2 -0
index fc8c238..67df170 100644
@@ -642,6 +642,8 @@ parse_cfg_file(const char *cfg_filename)
 	cmdline_stdin_exit(cl);
 	fclose(f);
 
+	sa_sort_arr();
+
 	return 0;
 
 error_exit:
examples/ipsec-secgw/parser.h +3 -0
index 6b8a100..1f8bd3e 100644
@@ -75,6 +75,9 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status);
 
 void
+sa_sort_arr(void);
+
+void
 parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status);
 
examples/ipsec-secgw/sa.c +57 -17

123 lines not on this page · raw message

Signature · 1 line
2.7.4
#47 lore raw

PATCH v5 5/6 examples/ipsec-secgw: get rid of maximum sp limitation

In reply to Vladimir Medvedkin

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.

---
 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(-)
examples/ipsec-secgw/parser.c +2 -0
index 67df170..65eb7e9 100644
@@ -643,6 +643,8 @@ parse_cfg_file(const char *cfg_filename)
 	fclose(f);
 
 	sa_sort_arr();
+	sp4_sort_arr();
+	sp6_sort_arr();
 
 	return 0;
 
examples/ipsec-secgw/parser.h +6 -0
index 1f8bd3e..6e764fe 100644
@@ -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);
 
examples/ipsec-secgw/sp4.c +69 -21

150 lines not on this page · raw message

examples/ipsec-secgw/sp6.c +67 -21

148 lines not on this page · raw message

Signature · 1 line
2.7.4
#48 lore raw

PATCH v5 6/6 examples/ipsec-secgw: add SAD cache

In reply to Vladimir Medvedkin

Introduce SAD cache.
Stores the most recent SA in a per lcore cache. Cache represents flat array containing SA's indexed by SPI.

---
 examples/ipsec-secgw/ipsec-secgw.c |  30 +++++++++-
 examples/ipsec-secgw/ipsec.h       |   1 +
 examples/ipsec-secgw/sa.c          |  32 +----------
 examples/ipsec-secgw/sad.c         |  40 ++++++++++++++
 examples/ipsec-secgw/sad.h         | 109 ++++++++++++++++++++++++++++++++++---
 5 files changed, 171 insertions(+), 41 deletions(-)
examples/ipsec-secgw/ipsec-secgw.c +27 -3
index 3e5f82e..32ecd26 100644
@@ -46,6 +46,7 @@
 
 #include "ipsec.h"
 #include "parser.h"
+#include "sad.h"
 
 #define RTE_LOGTYPE_IPSEC RTE_LOGTYPE_USER1
 
@@ -192,7 +193,10 @@ static uint32_t mtu_size = RTE_ETHER_MTU;
 static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
 
 /* application wide librte_ipsec/SA parameters */
-struct app_sa_prm app_sa_prm = {.enable = 0};
+struct app_sa_prm app_sa_prm = {
+			.enable = 0,
+			.cache_sz = SA_CACHE_SZ
+		};
 static const char *cfgfile;
 
 struct lcore_rx_queue {
@@ -1102,7 +1106,7 @@ main_loop(__attribute__((unused)) void *dummy)
 	uint16_t portid;
 	uint8_t queueid;
 	struct lcore_conf *qconf;
-	int32_t socket_id;
+	int32_t rc, socket_id;
 	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)
 			/ US_PER_S * BURST_TX_DRAIN_US;
 	struct lcore_rx_queue *rxql;
@@ -1132,6 +1136,14 @@ main_loop(__attribute__((unused)) void *dummy)
 	qconf->frag.pool_dir = socket_ctx[socket_id].mbuf_pool;
 	qconf->frag.pool_indir = socket_ctx[socket_id].mbuf_pool_indir;
 
+	rc = ipsec_sad_lcore_cache_init(app_sa_prm.cache_sz);
+	if (rc != 0) {
+		RTE_LOG(ERR, IPSEC,
+			"SAD cache init on lcore %u, failed with code: %d\n",
+			lcore_id, rc);
+		return rc;
+	}
+
 	if (qconf->nb_rx_queue == 0) {
 		RTE_LOG(DEBUG, IPSEC, "lcore %u has nothing to do\n",
 			lcore_id);
@@ -1271,6 +1283,7 @@ print_usage(const char *prgname)
 		" [-w REPLAY_WINDOW_SIZE]"
 		" [-e]"
 		" [-a]"
+		" [-c]"
 		" -f CONFIG_FILE"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
 		" [--single-sa SAIDX]"
@@ -1290,6 +1303,8 @@ print_usage(const char *prgname)
 		"     size for each SA\n"
 		"  -e enables ESN\n"
 		"  -a enables SA SQN atomic behaviour\n"
+		"  -c specifies inbound SAD cache size,\n"
+		"     zero value disables the cache (default value: 128)\n"
 		"  -f CONFIG_FILE: Configuration file\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --single-sa SAIDX: Use single SA index for outbound traffic,\n"
@@ -1442,7 +1457,7 @@ parse_args(int32_t argc, char **argv)
 
 	argvopt = argv;
 
-	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:",
+	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:",
 				lgopts, &option_index)) != EOF) {
 
 		switch (opt) {
@@ -1501,6 +1516,15 @@ parse_args(int32_t argc, char **argv)
 			app_sa_prm.enable = 1;
 			app_sa_prm.flags |= RTE_IPSEC_SAFLAG_SQN_ATOM;
 			break;
+		case 'c':
+			ret = parse_decimal(optarg);
+			if (ret < 0) {
+				printf("Invalid SA cache size: %s\n", optarg);
+				print_usage(prgname);
+				return -1;
+			}
+			app_sa_prm.cache_sz = ret;
+			break;
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
 			if (ret) {
examples/ipsec-secgw/ipsec.h +1 -0
index 3c77232..4f2fd61 100644
@@ -81,6 +81,7 @@ struct app_sa_prm {
 	uint32_t enable; /* use librte_ipsec API for ipsec pkt processing */
 	uint32_t window_size; /* replay window size */
 	uint32_t enable_esn;  /* enable/disable ESN support */
+	uint32_t cache_sz;	/* per lcore SA cache size */
 	uint64_t flags;       /* rte_ipsec_sa_prm.flags */
 };
 
examples/ipsec-secgw/sa.c +2 -30
index b3b83e3..099a11b 100644
@@ -839,7 +839,7 @@ sa_create(const char *name, int32_t socket_id, uint32_t nb_sa)
 		return NULL;
 	}
 
-	sa_ctx = rte_malloc(NULL, sizeof(struct sa_ctx) +
+	sa_ctx = rte_zmalloc(NULL, sizeof(struct sa_ctx) +
 		sizeof(struct ipsec_sa) * nb_sa, RTE_CACHE_LINE_SIZE);
 
 	if (sa_ctx == NULL) {
@@ -1451,9 +1451,6 @@ inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
 		void *sa_arr[], uint16_t nb_pkts)
 {
 	uint32_t i;
-	struct ip *ip;
-	uint32_t *src4_addr;
-	uint8_t *src6_addr;
 	void *result_sa;
 	struct ipsec_sa *sa;
 
@@ -1479,32 +1476,7 @@ inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
 			intsa |= IPSEC_SA_OFFLOAD_FALLBACK_FLAG;
 			result_sa = (void *)intsa;
 		}
-
-		ip = rte_pktmbuf_mtod(pkts[i], struct ip *);
-		switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
-		case IP4_TUNNEL:
-			src4_addr = RTE_PTR_ADD(ip,
-				offsetof(struct ip, ip_src));
-			if ((ip->ip_v == IPVERSION) &&
-					(sa->src.ip.ip4 == *src4_addr) &&
-					(sa->dst.ip.ip4 == *(src4_addr + 1)))
-				sa_arr[i] = result_sa;
-			else
-				sa_arr[i] = NULL;
-			break;
-		case IP6_TUNNEL:
-			src6_addr = RTE_PTR_ADD(ip,
-				offsetof(struct ip6_hdr, ip6_src));
-			if ((ip->ip_v == IP6_VERSION) &&
-				!memcmp(&sa->src.ip.ip6.ip6, src6_addr, 16) &&
-				!memcmp(&sa->dst.ip.ip6.ip6, src6_addr + 16, 16))
-				sa_arr[i] = result_sa;
-			else
-				sa_arr[i] = NULL;
-			break;
-		case TRANSPORT:
-			sa_arr[i] = result_sa;
-		}
+		sa_arr[i] = result_sa;
 	}
 }
 
examples/ipsec-secgw/sad.c +40 -0
index fd31101..5b2c0e6 100644
@@ -3,10 +3,17 @@
  */
 
 #include <rte_errno.h>
+#include <rte_malloc.h>
 
 #include "ipsec.h"
 #include "sad.h"
 
+RTE_DEFINE_PER_LCORE(struct ipsec_sad_cache, sad_cache) = {
+	.v4 = NULL,
+	.v6 = NULL,
+	.mask = 0,
+};
+
 int
 ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
 {
@@ -65,6 +72,39 @@ ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
 	return 0;
 }
 
+/*
+ * Init per lcore SAD cache.
+ * Must be called by every processing lcore.
+ */
+int
+ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent)
+{
+	uint32_t cache_elem;
+	size_t cache_mem_sz;
+	struct ipsec_sad_cache *cache;
+
+	cache = &RTE_PER_LCORE(sad_cache);
+
+	cache_elem = rte_align32pow2(nb_cache_ent);
+	cache_mem_sz = sizeof(struct ipsec_sa *) * cache_elem;
+
+	if (cache_mem_sz != 0) {
+		cache->v4 = rte_zmalloc_socket(NULL, cache_mem_sz,
+			RTE_CACHE_LINE_SIZE, rte_socket_id());
+		if (cache->v4 == NULL)
+			return -rte_errno;
+
+		cache->v6 = rte_zmalloc_socket(NULL, cache_mem_sz,
+			RTE_CACHE_LINE_SIZE, rte_socket_id());
+		if (cache->v6 == NULL)
+			return -rte_errno;
+
+		cache->mask = cache_elem - 1;
+	}
+
+	return 0;
+}
+
 int
 ipsec_sad_create(const char *name, struct ipsec_sad *sad,
 	int socket_id, struct ipsec_sa_cnt *sa_cnt)
examples/ipsec-secgw/sad.h +101 -8

146 lines not on this page · raw message

Signature · 1 line
2.7.4
Acked-by on the v5 series
#49 lore raw
In reply to Vladimir Medvedkin
Quoted 30 lines

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.
According to our measurements, after this series of patches, ipsec-secgw performance drops by about 0-2%.

v5:
- introduce SAD cache to solve performance degradation
- ipsec_sad_add() returns an error if the key is present

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (6):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation examples/ipsec-secgw: add SAD cache

Quoted 17 lines
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |  34 +++++-
 examples/ipsec-secgw/ipsec.h       |  12 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 238 +++++++++++++++++++++----------------
 examples/ipsec-secgw/sad.c         | 149 +++++++++++++++++++++++
 examples/ipsec-secgw/sad.h         | 168 ++++++++++++++++++++++++++
 examples/ipsec-secgw/sp4.c         | 114 +++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 ++++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 ++--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 686 insertions(+), 179 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h

Series

Hi Anoob,

Do you have any comments on this set. I do not see degradation on this patchset now.

Regards,
Akhil

Acked-by
#50 lore raw

Hi Akhil,

Quoted 48 lines
Quoted 29 lines

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.
According to our measurements, after this series of patches, ipsec-secgw performance drops by about 0-2%.

v5:
- introduce SAD cache to solve performance degradation
- ipsec_sad_add() returns an error if the key is present

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (6):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation examples/ipsec-secgw: add SAD cache

Quoted 7 lines
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |  34 +++++-
 examples/ipsec-secgw/ipsec.h       |  12 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 238 +++++++++++++++++++++-----------

-----

Quoted 10 lines
 examples/ipsec-secgw/sad.c         | 149 +++++++++++++++++++++++
 examples/ipsec-secgw/sad.h         | 168 ++++++++++++++++++++++++++
 examples/ipsec-secgw/sp4.c         | 114 +++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 ++++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 ++--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 686 insertions(+), 179 deletions(-)  create mode

100644 examples/ipsec-secgw/sad.c create mode 100644 examples/ipsec-secgw/sad.h

Quoted 7 lines

Series

Hi Anoob,

Do you have any comments on this set. I do not see degradation on this patchset now.

[Anoob] The perf degradation is negligible on our platform as well. I don't have any issue with the patch set.

Series

Applied
#51 lore raw
Quoted 56 lines

Hi Akhil,

Quoted 53 lines
Quoted 29 lines

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.
According to our measurements, after this series of patches, ipsec-secgw performance drops by about 0-2%.

v5:
- introduce SAD cache to solve performance degradation
- ipsec_sad_add() returns an error if the key is present

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (6):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation examples/ipsec-secgw: add SAD cache

Quoted 7 lines
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |  34 +++++-
 examples/ipsec-secgw/ipsec.h       |  12 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/parser.c      |   4 +
 examples/ipsec-secgw/parser.h      |   9 ++
 examples/ipsec-secgw/sa.c          | 238 +++++++++++++++++++++-----------

-----

Quoted 10 lines
 examples/ipsec-secgw/sad.c         | 149 +++++++++++++++++++++++
 examples/ipsec-secgw/sad.h         | 168 ++++++++++++++++++++++++++
 examples/ipsec-secgw/sp4.c         | 114 +++++++++++++-----
 examples/ipsec-secgw/sp6.c         | 112 ++++++++++++-----
 lib/librte_ipsec/ipsec_sad.c       |  20 ++--
 lib/librte_ipsec/rte_ipsec_sad.h   |   2 +
 13 files changed, 686 insertions(+), 179 deletions(-)  create mode

100644 examples/ipsec-secgw/sad.c create mode 100644 examples/ipsec-secgw/sad.h

Series

Hi Anoob,

Quoted 8 lines
Quoted 2 lines

Do you have any comments on this set. I do not see degradation on this patchset now.

[Anoob] The perf degradation is negligible on our platform as well. I don't have any issue with the patch set.

Series

Applied to dpdk-next-crypto

Thanks.

#52 lore raw

v6 cover integrate librte_ipsec SAD into ipsec-secgw

In reply to Vladimir Medvedkin

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.
According to our measurements, after this series of patches, ipsec-secgw performance drops by about 0-2%.

v6:
- add SA check for NULL pointer after rte_ipsec_sad_lookup()
- using mbuf ptype field to distinguish v4 and v6 packets
- add SAD cache size option into documentation

v5:
- introduce SAD cache to solve performance degradation
- ipsec_sad_add() returns an error if the key is present

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (8):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation examples/ipsec-secgw: add SAD cache examples/ipsec-secgw: set/use mbuf ptype
doc: update ipsec-secgw guide

 doc/guides/sample_app_ug/ipsec_secgw.rst |   6 +
 examples/ipsec-secgw/Makefile            |   1 +
 examples/ipsec-secgw/ipsec-secgw.c       |  36 ++++-
 examples/ipsec-secgw/ipsec.h             |  12 +-
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/parser.c            |   4 +
 examples/ipsec-secgw/parser.h            |   9 ++
 examples/ipsec-secgw/sa.c                | 238 ++++++++++++++++++-------------
 examples/ipsec-secgw/sad.c               | 149 +++++++++++++++++++
 examples/ipsec-secgw/sad.h               | 170 ++++++++++++++++++++++
 examples/ipsec-secgw/sp4.c               | 114 +++++++++++----
 examples/ipsec-secgw/sp6.c               | 112 +++++++++++----
 lib/librte_ipsec/ipsec_sad.c             |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h         |   2 +
 14 files changed, 696 insertions(+), 179 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
Signature · 1 line
2.7.4
#53 lore raw

PATCH v6 1/8 ipsec: move ipsec sad name length into .h

Move IPSEC_SAD_NAMESIZE into public header
and rename it to RTE_IPSEC_SAD_NAMESIZE

---
 lib/librte_ipsec/ipsec_sad.c     | 20 ++++++++++----------
 lib/librte_ipsec/rte_ipsec_sad.h |  2 ++
 2 files changed, 12 insertions(+), 10 deletions(-)
lib/librte_ipsec/ipsec_sad.c +10 -10
index db2c44c..2c994ed 100644
@@ -20,7 +20,6 @@
  * indicate presence of entries with the same SPI in DIP and DIP+SIP tables.
  */
 
-#define IPSEC_SAD_NAMESIZE	64
 #define SAD_PREFIX		"SAD_"
 /* "SAD_<name>" */
 #define SAD_FORMAT		SAD_PREFIX "%s"
@@ -34,7 +33,7 @@ struct hash_cnt {
 };
 
 struct rte_ipsec_sad {
-	char name[IPSEC_SAD_NAMESIZE];
+	char name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_hash	*hash[RTE_IPSEC_SAD_KEY_TYPE_MASK];
 	/* Array to track number of more specific rules
 	 * (spi_dip or spi_dip_sip). Used only in add/delete
@@ -231,7 +230,7 @@ struct rte_ipsec_sad *
 rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 {
 	char hash_name[RTE_HASH_NAMESIZE];
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	struct rte_ipsec_sad *sad, *tmp_sad = NULL;
@@ -249,8 +248,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 		return NULL;
 	}
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -326,7 +325,8 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 	/* guarantee there's no existing */
 	TAILQ_FOREACH(te, sad_list, next) {
 		tmp_sad = (struct rte_ipsec_sad *)te->data;
-		if (strncmp(sad_name, tmp_sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, tmp_sad->name,
+				RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	if (te != NULL) {
@@ -354,14 +354,14 @@ rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf)
 struct rte_ipsec_sad *
 rte_ipsec_sad_find_existing(const char *name)
 {
-	char sad_name[IPSEC_SAD_NAMESIZE];
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
 	struct rte_ipsec_sad *sad = NULL;
 	struct rte_tailq_entry *te;
 	struct rte_ipsec_sad_list *sad_list;
 	int ret;
 
-	ret = snprintf(sad_name, IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
-	if (ret < 0 || ret >= IPSEC_SAD_NAMESIZE) {
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, SAD_FORMAT, name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE) {
 		rte_errno = ENAMETOOLONG;
 		return NULL;
 	}
@@ -372,7 +372,7 @@ rte_ipsec_sad_find_existing(const char *name)
 	rte_mcfg_tailq_read_lock();
 	TAILQ_FOREACH(te, sad_list, next) {
 		sad = (struct rte_ipsec_sad *) te->data;
-		if (strncmp(sad_name, sad->name, IPSEC_SAD_NAMESIZE) == 0)
+		if (strncmp(sad_name, sad->name, RTE_IPSEC_SAD_NAMESIZE) == 0)
 			break;
 	}
 	rte_mcfg_tailq_read_unlock();
lib/librte_ipsec/rte_ipsec_sad.h +2 -0
index 8386f73..dcc8224 100644
@@ -47,6 +47,8 @@ union rte_ipsec_sad_key {
 	struct rte_ipsec_sadv6_key	v6;
 };
 
+/** Max number of characters in SAD name. */
+#define RTE_IPSEC_SAD_NAMESIZE		64
 /** Flag to create SAD with ipv6 dip and sip addresses */
 #define RTE_IPSEC_SAD_FLAG_IPV6			0x1
 /** Flag to support reader writer concurrency */
Signature · 1 line
2.7.4
#54 lore raw

PATCH v6 2/8 examples/ipsec-secgw: implement inbound SAD

In reply to Vladimir Medvedkin

Add initial support for librte_ipsec SAD library

---
 examples/ipsec-secgw/ipsec.h |   7 +++
 examples/ipsec-secgw/sad.c   | 109 +++++++++++++++++++++++++++++++++++++++++++
 examples/ipsec-secgw/sad.h   |  75 +++++++++++++++++++++++++++++
 3 files changed, 191 insertions(+)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
examples/ipsec-secgw/ipsec.h +7 -0
index 8e07521..9ddb5d9 100644
@@ -53,6 +53,13 @@ struct ipsec_xform;
 struct rte_mbuf;
 
 struct ipsec_sa;
+/*
+ * Keeps number of configured SA's for each address family:
+ */
+struct ipsec_sa_cnt {
+	uint32_t	nb_v4;
+	uint32_t	nb_v6;
+};
 
 typedef int32_t (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa,
 		struct rte_crypto_op *cop);
examples/ipsec-secgw/sad.c new file +109 -0

109 lines not on this page · raw message

examples/ipsec-secgw/sad.h new file +75 -0

75 lines not on this page · raw message

Signature · 1 line
2.7.4
#55 lore raw

PATCH v6 3/8 examples/ipsec-secgw: integrate inbound SAD

In reply to Vladimir Medvedkin

Integrate ipsec SAD support into secgw app:

1. Use SAD library for inbound SA lookup
2. Changes in struct sa_ctx:
- sa array allocates dynamically depending on number of configured sa
- All SA's are kept one by one without using SPI2IDX
3. SP's userdata now contain index of SA in sa_ctx instead of SPI
4. Get rid of SPI2IDX macro

---
 examples/ipsec-secgw/Makefile      |   1 +
 examples/ipsec-secgw/ipsec-secgw.c |   4 +-
 examples/ipsec-secgw/ipsec.h       |   3 +-
 examples/ipsec-secgw/meson.build   |   2 +-
 examples/ipsec-secgw/sa.c          | 182 +++++++++++++++++++++----------------
 examples/ipsec-secgw/sp4.c         |  24 +++--
 examples/ipsec-secgw/sp6.c         |  24 +++--
 7 files changed, 139 insertions(+), 101 deletions(-)
examples/ipsec-secgw/Makefile +1 -0
index 851123b..8734b15 100644
@@ -12,6 +12,7 @@ SRCS-y += esp.c
 SRCS-y += sp4.c
 SRCS-y += sp6.c
 SRCS-y += sa.c
+SRCS-y += sad.c
 SRCS-y += rt.c
 SRCS-y += ipsec_process.c
 SRCS-y += ipsec-secgw.c
examples/ipsec-secgw/ipsec-secgw.c +2 -2
index 3b5aaf6..3e5f82e 100644
@@ -601,7 +601,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 			continue;
 		}
 
-		sa_idx = SPI2IDX(res);
+		sa_idx = res - 1;
 		if (!inbound_sa_check(sa, m, sa_idx)) {
 			rte_pktmbuf_free(m);
 			continue;
@@ -688,7 +688,7 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip,
 	j = 0;
 	for (i = 0; i < ip->num; i++) {
 		m = ip->pkts[i];
-		sa_idx = SPI2IDX(ip->res[i]);
+		sa_idx = ip->res[i] - 1;
 		if (ip->res[i] == DISCARD)
 			rte_pktmbuf_free(m);
 		else if (ip->res[i] == BYPASS)
examples/ipsec-secgw/ipsec.h +1 -2
index 9ddb5d9..5988d59 100644
@@ -38,7 +38,6 @@
 #define DEFAULT_MAX_CATEGORIES	1
 
 #define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
-#define SPI2IDX(spi) (spi & (IPSEC_SA_MAX_ENTRIES - 1))
 #define INVALID_SPI (0)
 
 #define DISCARD	INVALID_SPI
@@ -359,7 +358,7 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
  * or -ENOENT otherwise.
  */
 int
-sa_spi_present(uint32_t spi, int inbound);
+sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound);
 
 void
 sa_init(struct socket_ctx *ctx, int32_t socket_id);
examples/ipsec-secgw/meson.build +1 -1
index 9ece345..6bd5b78 100644
@@ -10,5 +10,5 @@ deps += ['security', 'lpm', 'acl', 'hash', 'ip_frag', 'ipsec']
 allow_experimental_apis = true
 sources = files(
 	'esp.c', 'ipsec.c', 'ipsec_process.c', 'ipsec-secgw.c',
-	'parser.c', 'rt.c', 'sa.c', 'sp4.c', 'sp6.c'
+	'parser.c', 'rt.c', 'sa.c', 'sad.c', 'sp4.c', 'sp6.c'
 )
examples/ipsec-secgw/sa.c +104 -78

343 lines not on this page · raw message

examples/ipsec-secgw/sp4.c +15 -9
index 3871c6c..1dcec52 100644
@@ -493,10 +493,11 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl4_rules *acr;
+	int32_t spi_idx;
+	struct acl4_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl4_rules_in;
@@ -508,11 +509,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -535,11 +541,11 @@ 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(1) < 0)
+	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(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv4 SP DB has unmatched in SAD SPIs\n");
 
examples/ipsec-secgw/sp6.c +15 -9
index d8be6b1..b489e15 100644
@@ -625,10 +625,11 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
  * check that for each rule it's SPI has a correspondent entry in SAD
  */
 static int
-check_spi_value(int inbound)
+check_spi_value(struct sa_ctx *sa_ctx, int inbound)
 {
 	uint32_t i, num, spi;
-	const struct acl6_rules *acr;
+	int32_t spi_idx;
+	struct acl6_rules *acr;
 
 	if (inbound != 0) {
 		acr = acl6_rules_in;
@@ -640,11 +641,16 @@ check_spi_value(int inbound)
 
 	for (i = 0; i != num; i++) {
 		spi = acr[i].data.userdata;
-		if (spi != DISCARD && spi != BYPASS &&
-				sa_spi_present(spi, inbound) < 0) {
-			RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n",
-				spi);
-			return -ENOENT;
+		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;
 		}
 	}
 
@@ -667,11 +673,11 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
 		rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
 				"already initialized\n", socket_id);
 
-	if (check_spi_value(1) < 0)
+	if (check_spi_value(ctx->sa_in, 1) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Inbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
-	if (check_spi_value(0) < 0)
+	if (check_spi_value(ctx->sa_out, 0) < 0)
 		rte_exit(EXIT_FAILURE,
 			"Outbound IPv6 SP DB has unmatched in SAD SPIs\n");
 
Signature · 1 line
2.7.4
#56 lore raw

PATCH v6 4/8 examples/ipsec-secgw: get rid of maximum sa limitation

In reply to Vladimir Medvedkin

Get rid of maximum SA limitation.
Keep parsed SA's into the sorted by SPI value array. Use binary search in the sorted SA array to find appropriate SA for a given SPI.

---
 examples/ipsec-secgw/ipsec.h  |  1 -
 examples/ipsec-secgw/parser.c |  2 ++
 examples/ipsec-secgw/parser.h |  3 ++
 examples/ipsec-secgw/sa.c     | 74 +++++++++++++++++++++++++++++++++----------
 4 files changed, 62 insertions(+), 18 deletions(-)
examples/ipsec-secgw/ipsec.h +0 -1
index 5988d59..3c77232 100644
@@ -37,7 +37,6 @@
 
 #define DEFAULT_MAX_CATEGORIES	1
 
-#define IPSEC_SA_MAX_ENTRIES (128) /* must be power of 2, max 2 power 30 */
 #define INVALID_SPI (0)
 
 #define DISCARD	INVALID_SPI
examples/ipsec-secgw/parser.c +2 -0
index fc8c238..67df170 100644
@@ -642,6 +642,8 @@ parse_cfg_file(const char *cfg_filename)
 	cmdline_stdin_exit(cl);
 	fclose(f);
 
+	sa_sort_arr();
+
 	return 0;
 
 error_exit:
examples/ipsec-secgw/parser.h +3 -0
index 6b8a100..1f8bd3e 100644
@@ -75,6 +75,9 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status);
 
 void
+sa_sort_arr(void);
+
+void
 parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	struct parse_status *status);
 
examples/ipsec-secgw/sa.c +57 -17

123 lines not on this page · raw message

Signature · 1 line
2.7.4
#57 lore raw

PATCH v6 5/8 examples/ipsec-secgw: get rid of maximum sp limitation

In reply to Vladimir Medvedkin

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.

---
 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(-)
examples/ipsec-secgw/parser.c +2 -0
index 67df170..65eb7e9 100644
@@ -643,6 +643,8 @@ parse_cfg_file(const char *cfg_filename)
 	fclose(f);
 
 	sa_sort_arr();
+	sp4_sort_arr();
+	sp6_sort_arr();
 
 	return 0;
 
examples/ipsec-secgw/parser.h +6 -0
index 1f8bd3e..6e764fe 100644
@@ -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);
 
examples/ipsec-secgw/sp4.c +69 -21

150 lines not on this page · raw message

examples/ipsec-secgw/sp6.c +67 -21

148 lines not on this page · raw message

Signature · 1 line
2.7.4
#58 lore raw

PATCH v6 6/8 examples/ipsec-secgw: add SAD cache

In reply to Vladimir Medvedkin

Introduce SAD cache.
Stores the most recent SA in a per lcore cache. Cache represents flat array containing SA's indexed by SPI.

---
 examples/ipsec-secgw/ipsec-secgw.c |  30 +++++++++-
 examples/ipsec-secgw/ipsec.h       |   1 +
 examples/ipsec-secgw/sa.c          |  32 +----------
 examples/ipsec-secgw/sad.c         |  40 +++++++++++++
 examples/ipsec-secgw/sad.h         | 111 ++++++++++++++++++++++++++++++++++---
 5 files changed, 173 insertions(+), 41 deletions(-)
examples/ipsec-secgw/ipsec-secgw.c +27 -3
index 3e5f82e..32ecd26 100644
@@ -46,6 +46,7 @@
 
 #include "ipsec.h"
 #include "parser.h"
+#include "sad.h"
 
 #define RTE_LOGTYPE_IPSEC RTE_LOGTYPE_USER1
 
@@ -192,7 +193,10 @@ static uint32_t mtu_size = RTE_ETHER_MTU;
 static uint64_t frag_ttl_ns = MAX_FRAG_TTL_NS;
 
 /* application wide librte_ipsec/SA parameters */
-struct app_sa_prm app_sa_prm = {.enable = 0};
+struct app_sa_prm app_sa_prm = {
+			.enable = 0,
+			.cache_sz = SA_CACHE_SZ
+		};
 static const char *cfgfile;
 
 struct lcore_rx_queue {
@@ -1102,7 +1106,7 @@ main_loop(__attribute__((unused)) void *dummy)
 	uint16_t portid;
 	uint8_t queueid;
 	struct lcore_conf *qconf;
-	int32_t socket_id;
+	int32_t rc, socket_id;
 	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)
 			/ US_PER_S * BURST_TX_DRAIN_US;
 	struct lcore_rx_queue *rxql;
@@ -1132,6 +1136,14 @@ main_loop(__attribute__((unused)) void *dummy)
 	qconf->frag.pool_dir = socket_ctx[socket_id].mbuf_pool;
 	qconf->frag.pool_indir = socket_ctx[socket_id].mbuf_pool_indir;
 
+	rc = ipsec_sad_lcore_cache_init(app_sa_prm.cache_sz);
+	if (rc != 0) {
+		RTE_LOG(ERR, IPSEC,
+			"SAD cache init on lcore %u, failed with code: %d\n",
+			lcore_id, rc);
+		return rc;
+	}
+
 	if (qconf->nb_rx_queue == 0) {
 		RTE_LOG(DEBUG, IPSEC, "lcore %u has nothing to do\n",
 			lcore_id);
@@ -1271,6 +1283,7 @@ print_usage(const char *prgname)
 		" [-w REPLAY_WINDOW_SIZE]"
 		" [-e]"
 		" [-a]"
+		" [-c]"
 		" -f CONFIG_FILE"
 		" --config (port,queue,lcore)[,(port,queue,lcore)]"
 		" [--single-sa SAIDX]"
@@ -1290,6 +1303,8 @@ print_usage(const char *prgname)
 		"     size for each SA\n"
 		"  -e enables ESN\n"
 		"  -a enables SA SQN atomic behaviour\n"
+		"  -c specifies inbound SAD cache size,\n"
+		"     zero value disables the cache (default value: 128)\n"
 		"  -f CONFIG_FILE: Configuration file\n"
 		"  --config (port,queue,lcore): Rx queue configuration\n"
 		"  --single-sa SAIDX: Use single SA index for outbound traffic,\n"
@@ -1442,7 +1457,7 @@ parse_args(int32_t argc, char **argv)
 
 	argvopt = argv;
 
-	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:",
+	while ((opt = getopt_long(argc, argvopt, "aelp:Pu:f:j:w:c:",
 				lgopts, &option_index)) != EOF) {
 
 		switch (opt) {
@@ -1501,6 +1516,15 @@ parse_args(int32_t argc, char **argv)
 			app_sa_prm.enable = 1;
 			app_sa_prm.flags |= RTE_IPSEC_SAFLAG_SQN_ATOM;
 			break;
+		case 'c':
+			ret = parse_decimal(optarg);
+			if (ret < 0) {
+				printf("Invalid SA cache size: %s\n", optarg);
+				print_usage(prgname);
+				return -1;
+			}
+			app_sa_prm.cache_sz = ret;
+			break;
 		case CMD_LINE_OPT_CONFIG_NUM:
 			ret = parse_config(optarg);
 			if (ret) {
examples/ipsec-secgw/ipsec.h +1 -0
index 3c77232..4f2fd61 100644
@@ -81,6 +81,7 @@ struct app_sa_prm {
 	uint32_t enable; /* use librte_ipsec API for ipsec pkt processing */
 	uint32_t window_size; /* replay window size */
 	uint32_t enable_esn;  /* enable/disable ESN support */
+	uint32_t cache_sz;	/* per lcore SA cache size */
 	uint64_t flags;       /* rte_ipsec_sa_prm.flags */
 };
 
examples/ipsec-secgw/sa.c +2 -30
index b3b83e3..099a11b 100644
@@ -839,7 +839,7 @@ sa_create(const char *name, int32_t socket_id, uint32_t nb_sa)
 		return NULL;
 	}
 
-	sa_ctx = rte_malloc(NULL, sizeof(struct sa_ctx) +
+	sa_ctx = rte_zmalloc(NULL, sizeof(struct sa_ctx) +
 		sizeof(struct ipsec_sa) * nb_sa, RTE_CACHE_LINE_SIZE);
 
 	if (sa_ctx == NULL) {
@@ -1451,9 +1451,6 @@ inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
 		void *sa_arr[], uint16_t nb_pkts)
 {
 	uint32_t i;
-	struct ip *ip;
-	uint32_t *src4_addr;
-	uint8_t *src6_addr;
 	void *result_sa;
 	struct ipsec_sa *sa;
 
@@ -1479,32 +1476,7 @@ inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
 			intsa |= IPSEC_SA_OFFLOAD_FALLBACK_FLAG;
 			result_sa = (void *)intsa;
 		}
-
-		ip = rte_pktmbuf_mtod(pkts[i], struct ip *);
-		switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
-		case IP4_TUNNEL:
-			src4_addr = RTE_PTR_ADD(ip,
-				offsetof(struct ip, ip_src));
-			if ((ip->ip_v == IPVERSION) &&
-					(sa->src.ip.ip4 == *src4_addr) &&
-					(sa->dst.ip.ip4 == *(src4_addr + 1)))
-				sa_arr[i] = result_sa;
-			else
-				sa_arr[i] = NULL;
-			break;
-		case IP6_TUNNEL:
-			src6_addr = RTE_PTR_ADD(ip,
-				offsetof(struct ip6_hdr, ip6_src));
-			if ((ip->ip_v == IP6_VERSION) &&
-				!memcmp(&sa->src.ip.ip6.ip6, src6_addr, 16) &&
-				!memcmp(&sa->dst.ip.ip6.ip6, src6_addr + 16, 16))
-				sa_arr[i] = result_sa;
-			else
-				sa_arr[i] = NULL;
-			break;
-		case TRANSPORT:
-			sa_arr[i] = result_sa;
-		}
+		sa_arr[i] = result_sa;
 	}
 }
 
examples/ipsec-secgw/sad.c +40 -0
index fd31101..5b2c0e6 100644
@@ -3,10 +3,17 @@
  */
 
 #include <rte_errno.h>
+#include <rte_malloc.h>
 
 #include "ipsec.h"
 #include "sad.h"
 
+RTE_DEFINE_PER_LCORE(struct ipsec_sad_cache, sad_cache) = {
+	.v4 = NULL,
+	.v6 = NULL,
+	.mask = 0,
+};
+
 int
 ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
 {
@@ -65,6 +72,39 @@ ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
 	return 0;
 }
 
+/*
+ * Init per lcore SAD cache.
+ * Must be called by every processing lcore.
+ */
+int
+ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent)
+{
+	uint32_t cache_elem;
+	size_t cache_mem_sz;
+	struct ipsec_sad_cache *cache;
+
+	cache = &RTE_PER_LCORE(sad_cache);
+
+	cache_elem = rte_align32pow2(nb_cache_ent);
+	cache_mem_sz = sizeof(struct ipsec_sa *) * cache_elem;
+
+	if (cache_mem_sz != 0) {
+		cache->v4 = rte_zmalloc_socket(NULL, cache_mem_sz,
+			RTE_CACHE_LINE_SIZE, rte_socket_id());
+		if (cache->v4 == NULL)
+			return -rte_errno;
+
+		cache->v6 = rte_zmalloc_socket(NULL, cache_mem_sz,
+			RTE_CACHE_LINE_SIZE, rte_socket_id());
+		if (cache->v6 == NULL)
+			return -rte_errno;
+
+		cache->mask = cache_elem - 1;
+	}
+
+	return 0;
+}
+
 int
 ipsec_sad_create(const char *name, struct ipsec_sad *sad,
 	int socket_id, struct ipsec_sa_cnt *sa_cnt)
examples/ipsec-secgw/sad.h +103 -8

148 lines not on this page · raw message

Signature · 1 line
2.7.4
#59 lore raw

PATCH v6 7/8 examples/ipsec-secgw: set/use mbuf ptype

In reply to Vladimir Medvedkin

Set mbuf ptype in prepare_one_packet() after parsing ether_type. Use mbuf ptype after to recognize packet's address family.

---
 examples/ipsec-secgw/ipsec-secgw.c | 2 ++
 examples/ipsec-secgw/sad.h         | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)
examples/ipsec-secgw/ipsec-secgw.c +2 -0
index 32ecd26..4799bc9 100644
@@ -323,6 +323,7 @@ prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
 		}
 		pkt->l2_len = 0;
 		pkt->l3_len = sizeof(*iph4);
+		pkt->packet_type |= RTE_PTYPE_L3_IPV4;
 	} else if (eth->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
 		int next_proto;
 		size_t l3len, ext_len;
@@ -357,6 +358,7 @@ prepare_one_packet(struct rte_mbuf *pkt, struct ipsec_traffic *t)
 		}
 		pkt->l2_len = 0;
 		pkt->l3_len = l3len;
+		pkt->packet_type |= RTE_PTYPE_L3_IPV6;
 	} else {
 		/* Unknown/Unsupported type, drop the packet */
 		RTE_LOG(ERR, IPSEC, "Unsupported packet type 0x%x\n",
examples/ipsec-secgw/sad.h +1 -1
index 3f92db2..55712ba 100644
@@ -93,7 +93,7 @@ sad_lookup(struct ipsec_sad *sad, struct rte_mbuf *pkts[],
 		esp = rte_pktmbuf_mtod_offset(pkts[i], struct rte_esp_hdr *,
 				pkts[i]->l3_len);
 
-		is_ipv4 = ((ipv4->version_ihl >> 4) == IPVERSION);
+		is_ipv4 = pkts[i]->packet_type & RTE_PTYPE_L3_IPV4;
 		spi = rte_be_to_cpu_32(esp->spi);
 		cache_idx = SPI2IDX(spi, cache->mask);
 
Signature · 1 line
2.7.4
#60 lore raw

PATCH v6 8/8 doc: update ipsec-secgw guide

In reply to Vladimir Medvedkin

Add new SAD cache option in ipsec-secgw guide.

---
 doc/guides/sample_app_ug/ipsec_secgw.rst | 6 ++++++
 1 file changed, 6 insertions(+)
doc/guides/sample_app_ug/ipsec_secgw.rst +6 -0
index d6d8d44..5ec9b1e 100644
@@ -93,6 +93,7 @@ The application has a number of command line options::
    ./build/ipsec-secgw [EAL options] --
                         -p PORTMASK -P -u PORTMASK -j FRAMESIZE
                         -l -w REPLAY_WINOW_SIZE -e -a
+                        -c SAD_CACHE_SIZE
                         --config (port,queue,lcore)[,(port,queue,lcore]
                         --single-sa SAIDX
                         --rxoffload MASK
@@ -132,6 +133,11 @@ Where:
 *   ``-a``: enables Security Association sequence number atomic behavior
     (available only with librte_ipsec code path).
 
+*   ``-c``: specifies the SAD cache size. Stores the most recent SA in a per
+    lcore cache. Cache represents flat array containing SA's indexed by SPI.
+    Zero value disables cache.
+    Default value: 128.
+
 *   ``--config (port,queue,lcore)[,(port,queue,lcore)]``: determines which queues
     from which ports are mapped to which cores.
 
Signature · 1 line
2.7.4
Applied
#61 lore raw
In reply to Vladimir Medvedkin
Quoted 54 lines

This series integrates SA database (SAD) capabilities from ipsec library. The goal is to make ipsec-secgw RFC compliant regarding inbound SAD. Also patch series removes hardcoded limitation for maximum number of SA's and SP's.
According to our measurements, after this series of patches, ipsec-secgw performance drops by about 0-2%.

v6:
- add SA check for NULL pointer after rte_ipsec_sad_lookup()
- using mbuf ptype field to distinguish v4 and v6 packets
- add SAD cache size option into documentation

v5:
- introduce SAD cache to solve performance degradation
- ipsec_sad_add() returns an error if the key is present

v4:
- put tunnel SA's into SAD with SPI_ONLY type for performance reason

v3:
- parse SA and SP into sorted array instead of linked list

v2:
- get rid of maximum sp limitation

Vladimir Medvedkin (8):
ipsec: move ipsec sad name length into .h examples/ipsec-secgw: implement inbound SAD examples/ipsec-secgw: integrate inbound SAD examples/ipsec-secgw: get rid of maximum sa limitation examples/ipsec-secgw: get rid of maximum sp limitation examples/ipsec-secgw: add SAD cache examples/ipsec-secgw: set/use mbuf ptype
doc: update ipsec-secgw guide

 doc/guides/sample_app_ug/ipsec_secgw.rst |   6 +
 examples/ipsec-secgw/Makefile            |   1 +
 examples/ipsec-secgw/ipsec-secgw.c       |  36 ++++-
 examples/ipsec-secgw/ipsec.h             |  12 +-
 examples/ipsec-secgw/meson.build         |   2 +-
 examples/ipsec-secgw/parser.c            |   4 +
 examples/ipsec-secgw/parser.h            |   9 ++
 examples/ipsec-secgw/sa.c                | 238 ++++++++++++++++++-------------
 examples/ipsec-secgw/sad.c               | 149 +++++++++++++++++++
 examples/ipsec-secgw/sad.h               | 170 ++++++++++++++++++++++
 examples/ipsec-secgw/sp4.c               | 114 +++++++++++----
 examples/ipsec-secgw/sp6.c               | 112 +++++++++++----
 lib/librte_ipsec/ipsec_sad.c             |  20 +--
 lib/librte_ipsec/rte_ipsec_sad.h         |   2 +
 14 files changed, 696 insertions(+), 179 deletions(-)
 create mode 100644 examples/ipsec-secgw/sad.c
 create mode 100644 examples/ipsec-secgw/sad.h
Quoted 2 lines

--
2.7.4

Squashed the last patch with 6th patch

Applied to dpdk-next-crypto

Thanks.