DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h
@ 2019-12-11 16:13 Vladimir Medvedkin
  2019-12-11 16:13 ` [dpdk-dev] [PATCH 2/4] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Vladimir Medvedkin @ 2019-12-11 16:13 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, akhil.goyal

Move IPSEC_SAD_NAMESIZE into public header
and rename it to RTE_IPSEC_SAD_NAMESIZE

Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 lib/librte_ipsec/ipsec_sad.c     | 20 ++++++++++----------
 lib/librte_ipsec/rte_ipsec_sad.h |  2 ++
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/lib/librte_ipsec/ipsec_sad.c b/lib/librte_ipsec/ipsec_sad.c
index db2c44c..2c994ed 100644
--- a/lib/librte_ipsec/ipsec_sad.c
+++ b/lib/librte_ipsec/ipsec_sad.c
@@ -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();
diff --git a/lib/librte_ipsec/rte_ipsec_sad.h b/lib/librte_ipsec/rte_ipsec_sad.h
index 8386f73..dcc8224 100644
--- a/lib/librte_ipsec/rte_ipsec_sad.h
+++ b/lib/librte_ipsec/rte_ipsec_sad.h
@@ -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 */
-- 
2.7.4


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH 2/4] examples/ipsec-secgw: implement inbound SAD
  2019-12-11 16:13 [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
@ 2019-12-11 16:13 ` Vladimir Medvedkin
  2019-12-11 16:13 ` [dpdk-dev] [PATCH 3/4] examples/ipsec-secgw: integrate " Vladimir Medvedkin
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Vladimir Medvedkin @ 2019-12-11 16:13 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, akhil.goyal

Add initial support for librte_ipsec SAD library

Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 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

diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8e07521..132286c 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
diff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c
new file mode 100644
index 0000000..bcac462
--- /dev/null
+++ b/examples/ipsec-secgw/sad.c
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <rte_errno.h>
+
+#include "ipsec.h"
+#include "sad.h"
+
+int
+ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
+{
+	int ret;
+	union rte_ipsec_sad_key key = { {0} };
+
+	/* spi field is common for ipv4 and ipv6 key types */
+	key.v4.spi = rte_cpu_to_be_32(sa->spi);
+	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
+	case IP4_TUNNEL:
+		key.v4.dip = rte_cpu_to_be_32(sa->dst.ip.ip4);
+		key.v4.sip = rte_cpu_to_be_32(sa->src.ip.ip4);
+		ret = rte_ipsec_sad_add(sad->sad_v4, &key,
+				RTE_IPSEC_SAD_SPI_DIP_SIP, sa);
+		if (ret != 0)
+			return ret;
+		break;
+	case IP6_TUNNEL:
+		memcpy(key.v6.dip, sa->dst.ip.ip6.ip6,
+				sizeof(key.v6.dip));
+		memcpy(key.v6.sip, sa->src.ip.ip6.ip6,
+				sizeof(key.v6.sip));
+		ret = rte_ipsec_sad_add(sad->sad_v6, &key,
+				RTE_IPSEC_SAD_SPI_DIP_SIP, sa);
+		if (ret != 0)
+			return ret;
+		break;
+	case TRANSPORT:
+		if (sp4_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
+			ret = rte_ipsec_sad_add(sad->sad_v4, &key,
+				RTE_IPSEC_SAD_SPI_ONLY, sa);
+			if (ret != 0)
+				return ret;
+		}
+
+		if (sp6_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
+			ret = rte_ipsec_sad_add(sad->sad_v6, &key,
+				RTE_IPSEC_SAD_SPI_ONLY, sa);
+			if (ret != 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+int
+ipsec_sad_create(const char *name, struct ipsec_sad *sad,
+	int socket_id, struct ipsec_sa_cnt *sa_cnt)
+{
+	int ret;
+	struct rte_ipsec_sad_conf sad_conf;
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
+
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v4", name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
+		return -ENAMETOOLONG;
+
+	sad_conf.socket_id = socket_id;
+	sad_conf.flags = 0;
+	/* Make SAD have extra 25% of required number of entries */
+	sad_conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = sa_cnt->nb_trn * 5 / 4;
+	sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
+	sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = sa_cnt->nb_v4_tun * 5 / 4;
+
+	sad->sad_v4 = rte_ipsec_sad_create(sad_name, &sad_conf);
+	if (sad->sad_v4 == NULL)
+		return -rte_errno;
+
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v6", name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
+		return -ENAMETOOLONG;
+	sad_conf.flags = RTE_IPSEC_SAD_FLAG_IPV6;
+	sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = sa_cnt->nb_v6_tun * 5 / 4;
+
+	sad->sad_v6 = rte_ipsec_sad_create(name, &sad_conf);
+	if (sad->sad_v6 == NULL)
+		return -rte_errno;
+
+	return 0;
+}
diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h
new file mode 100644
index 0000000..e754d57
--- /dev/null
+++ b/examples/ipsec-secgw/sad.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef __SAD_H__
+#define __SAD_H__
+
+#include <rte_ipsec_sad.h>
+
+struct ipsec_sad {
+	struct rte_ipsec_sad *sad_v4;
+	struct rte_ipsec_sad *sad_v6;
+};
+
+int ipsec_sad_create(const char *name, struct ipsec_sad *sad,
+	int socket_id, struct ipsec_sa_cnt *sa_cnt);
+
+int ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa);
+
+static inline void
+sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
+	void *sa[], uint16_t nb_pkts)
+{
+	uint32_t i;
+	uint32_t nb_v4 = 0, nb_v6 = 0;
+	struct rte_esp_hdr *esp;
+	struct rte_ipv4_hdr *ipv4;
+	struct rte_ipv6_hdr *ipv6;
+	struct rte_ipsec_sadv4_key	v4[nb_pkts];
+	struct rte_ipsec_sadv6_key	v6[nb_pkts];
+	int v4_idxes[nb_pkts];
+	int v6_idxes[nb_pkts];
+	const union rte_ipsec_sad_key	*keys_v4[nb_pkts];
+	const union rte_ipsec_sad_key	*keys_v6[nb_pkts];
+	void *v4_res[nb_pkts];
+	void *v6_res[nb_pkts];
+
+	for (i = 0; i < nb_pkts; i++) {
+		ipv4 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv4_hdr *);
+		esp = rte_pktmbuf_mtod_offset(pkts[i], struct rte_esp_hdr *,
+				pkts[i]->l3_len);
+		if ((ipv4->version_ihl >> 4) == IPVERSION) {
+			v4[nb_v4].spi = esp->spi;
+			v4[nb_v4].dip = ipv4->dst_addr;
+			v4[nb_v4].sip = ipv4->src_addr;
+			keys_v4[nb_v4] = (const union rte_ipsec_sad_key *)
+						&v4[nb_v4];
+			v4_idxes[nb_v4++] = i;
+		} else {
+			ipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *);
+			v6[nb_v6].spi = esp->spi;
+			memcpy(v6[nb_v6].dip, ipv6->dst_addr,
+					sizeof(ipv6->dst_addr));
+			memcpy(v6[nb_v6].sip, ipv6->src_addr,
+					sizeof(ipv6->src_addr));
+			keys_v6[nb_v6] = (const union rte_ipsec_sad_key *)
+						&v6[nb_v6];
+			v6_idxes[nb_v6++] = i;
+		}
+	}
+
+	if (nb_v4 != 0)
+		rte_ipsec_sad_lookup(sad->sad_v4, keys_v4, v4_res, nb_v4);
+	if (nb_v6 != 0)
+		rte_ipsec_sad_lookup(sad->sad_v6, keys_v6, v6_res, nb_v6);
+
+	for (i = 0; i < nb_v4; i++)
+		sa[v4_idxes[i]] = v4_res[i];
+
+	for (i = 0; i < nb_v6; i++)
+		sa[v6_idxes[i]] = v6_res[i];
+}
+
+#endif /* __SAD_H__ */
-- 
2.7.4


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH 3/4] examples/ipsec-secgw: integrate inbound SAD
  2019-12-11 16:13 [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
  2019-12-11 16:13 ` [dpdk-dev] [PATCH 2/4] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
@ 2019-12-11 16:13 ` Vladimir Medvedkin
  2019-12-11 16:13 ` [dpdk-dev] [PATCH 4/4] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
  2019-12-11 16:43 ` [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Medvedkin, Vladimir
  3 siblings, 0 replies; 6+ messages in thread
From: Vladimir Medvedkin @ 2019-12-11 16:13 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, akhil.goyal

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

Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 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(-)

diff --git a/examples/ipsec-secgw/Makefile b/examples/ipsec-secgw/Makefile
index 851123b..8734b15 100644
--- a/examples/ipsec-secgw/Makefile
+++ b/examples/ipsec-secgw/Makefile
@@ -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
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 3b5aaf6..3e5f82e 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -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)
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 132286c..f731bf8 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
diff --git a/examples/ipsec-secgw/meson.build b/examples/ipsec-secgw/meson.build
index 9ece345..6bd5b78 100644
--- a/examples/ipsec-secgw/meson.build
+++ b/examples/ipsec-secgw/meson.build
@@ -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'
 )
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 7f046e3..8cc7b17 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -24,6 +24,7 @@
 #include "ipsec.h"
 #include "esp.h"
 #include "parser.h"
+#include "sad.h"
 
 #define IPDEFTTL 64
 
@@ -134,9 +135,11 @@ const struct supported_aead_algo aead_algos[] = {
 
 static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
 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 uint32_t nb_sa_in;
+static struct ipsec_sa_cnt sa_in_cnt;
 
 static const struct supported_cipher_algo *
 find_match_cipher_algo(const char *cipher_keyword)
@@ -229,6 +232,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	struct rte_ipsec_session *ips;
 	uint32_t ti; /*token index*/
 	uint32_t *ri /*rule index*/;
+	struct ipsec_sa_cnt *sa_cnt;
 	uint32_t cipher_algo_p = 0;
 	uint32_t auth_algo_p = 0;
 	uint32_t aead_algo_p = 0;
@@ -241,6 +245,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 
 	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");
@@ -251,6 +256,7 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 		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");
@@ -280,13 +286,16 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			if (status->status < 0)
 				return;
 
-			if (strcmp(tokens[ti], "ipv4-tunnel") == 0)
+			if (strcmp(tokens[ti], "ipv4-tunnel") == 0) {
+				sa_cnt->nb_v4_tun++;
 				rule->flags = IP4_TUNNEL;
-			else if (strcmp(tokens[ti], "ipv6-tunnel") == 0)
+			} else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
+				sa_cnt->nb_v6_tun++;
 				rule->flags = IP6_TUNNEL;
-			else if (strcmp(tokens[ti], "transport") == 0)
+			} else if (strcmp(tokens[ti], "transport") == 0) {
+				sa_cnt->nb_trn++;
 				rule->flags = TRANSPORT;
-			else {
+			} else {
 				APP_CHECK(0, status, "unrecognized "
 					"input \"%s\"", tokens[ti]);
 				return;
@@ -772,19 +781,21 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
 	printf("\n");
 }
 
+struct ipsec_xf {
+	struct rte_crypto_sym_xform a;
+	struct rte_crypto_sym_xform b;
+};
+
 struct sa_ctx {
 	void *satbl; /* pointer to array of rte_ipsec_sa objects*/
-	struct ipsec_sa sa[IPSEC_SA_MAX_ENTRIES];
-	union {
-		struct {
-			struct rte_crypto_sym_xform a;
-			struct rte_crypto_sym_xform b;
-		};
-	} xf[IPSEC_SA_MAX_ENTRIES];
+	struct ipsec_sad sad;
+	struct ipsec_xf *xf;
+	uint32_t nb_sa;
+	struct ipsec_sa sa[];
 };
 
 static struct sa_ctx *
-sa_create(const char *name, int32_t socket_id)
+sa_create(const char *name, int32_t socket_id, uint32_t nb_sa)
 {
 	char s[PATH_MAX];
 	struct sa_ctx *sa_ctx;
@@ -793,20 +804,31 @@ sa_create(const char *name, int32_t socket_id)
 
 	snprintf(s, sizeof(s), "%s_%u", name, socket_id);
 
-	/* Create SA array table */
+	/* Create SA context */
 	printf("Creating SA context with %u maximum entries on socket %d\n",
-			IPSEC_SA_MAX_ENTRIES, socket_id);
+			nb_sa, socket_id);
 
-	mz_size = sizeof(struct sa_ctx);
+	mz_size = sizeof(struct ipsec_xf) * nb_sa;
 	mz = rte_memzone_reserve(s, mz_size, socket_id,
 			RTE_MEMZONE_1GB | RTE_MEMZONE_SIZE_HINT_ONLY);
 	if (mz == NULL) {
-		printf("Failed to allocate SA DB memory\n");
+		printf("Failed to allocate SA XFORM memory\n");
 		rte_errno = ENOMEM;
 		return NULL;
 	}
 
-	sa_ctx = (struct sa_ctx *)mz->addr;
+	sa_ctx = rte_malloc(NULL, sizeof(struct sa_ctx) +
+		sizeof(struct ipsec_sa) * nb_sa, RTE_CACHE_LINE_SIZE);
+
+	if (sa_ctx == NULL) {
+		printf("Failed to allocate SA CTX memory\n");
+		rte_errno = ENOMEM;
+		rte_memzone_free(mz);
+		return NULL;
+	}
+
+	sa_ctx->xf = (struct ipsec_xf *)mz->addr;
+	sa_ctx->nb_sa = nb_sa;
 
 	return sa_ctx;
 }
@@ -949,7 +971,7 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 	aad_length = (app_sa_prm.enable_esn != 0) ? sizeof(uint32_t) : 0;
 
 	for (i = 0; i < nb_entries; i++) {
-		idx = SPI2IDX(entries[i].spi);
+		idx = i;
 		sa = &sa_ctx->sa[idx];
 		if (sa->spi != 0) {
 			printf("Index %u already in use by SPI %u\n",
@@ -957,6 +979,13 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			return -EINVAL;
 		}
 		*sa = entries[i];
+
+		if (inbound) {
+			rc = ipsec_sad_add(&sa_ctx->sad, sa);
+			if (rc != 0)
+				return rc;
+		}
+
 		sa->seq = 0;
 		ips = ipsec_get_primary_session(sa);
 
@@ -1237,8 +1266,7 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
  * one per session.
  */
 static int
-ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
-	uint32_t nb_ent, int32_t socket)
+ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket)
 {
 	int32_t rc, sz;
 	uint32_t i, idx;
@@ -1248,7 +1276,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
 	struct rte_ipsec_sa_prm prm;
 
 	/* determine SA size */
-	idx = SPI2IDX(ent[0].spi);
+	idx = 0;
 	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL);
 	sz = rte_ipsec_sa_size(&prm);
 	if (sz < 0) {
@@ -1271,7 +1299,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
 	rc = 0;
 	for (i = 0; i != nb_ent && rc == 0; i++) {
 
-		idx = SPI2IDX(ent[i].spi);
+		idx = i;
 
 		sa = (struct rte_ipsec_sa *)((uintptr_t)ctx->satbl + sz * i);
 		lsa = ctx->sa + idx;
@@ -1286,18 +1314,16 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
  * Walk through all SA rules to find an SA with given SPI
  */
 int
-sa_spi_present(uint32_t spi, int inbound)
+sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
 {
 	uint32_t i, num;
 	const struct ipsec_sa *sar;
 
-	if (inbound != 0) {
-		sar = sa_in;
+	sar = sa_ctx->sa;
+	if (inbound != 0)
 		num = nb_sa_in;
-	} else {
-		sar = sa_out;
+	else
 		num = nb_sa_out;
-	}
 
 	for (i = 0; i != num; i++) {
 		if (sar[i].spi == spi)
@@ -1326,16 +1352,21 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 
 	if (nb_sa_in > 0) {
 		name = "sa_in";
-		ctx->sa_in = sa_create(name, socket_id);
+		ctx->sa_in = sa_create(name, socket_id, nb_sa_in);
 		if (ctx->sa_in == NULL)
 			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
 				"context %s in socket %d\n", rte_errno,
 				name, socket_id);
 
+		rc = ipsec_sad_create(name, &ctx->sa_in->sad, socket_id,
+				&sa_in_cnt);
+		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);
 
 		if (app_sa_prm.enable != 0) {
-			rc = ipsec_satbl_init(ctx->sa_in, sa_in, nb_sa_in,
+			rc = ipsec_satbl_init(ctx->sa_in, nb_sa_in,
 				socket_id);
 			if (rc != 0)
 				rte_exit(EXIT_FAILURE,
@@ -1346,7 +1377,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 
 	if (nb_sa_out > 0) {
 		name = "sa_out";
-		ctx->sa_out = sa_create(name, socket_id);
+		ctx->sa_out = sa_create(name, socket_id, nb_sa_out);
 		if (ctx->sa_out == NULL)
 			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
 				"context %s in socket %d\n", rte_errno,
@@ -1355,7 +1386,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 		sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out, ctx);
 
 		if (app_sa_prm.enable != 0) {
-			rc = ipsec_satbl_init(ctx->sa_out, sa_out, nb_sa_out,
+			rc = ipsec_satbl_init(ctx->sa_out, nb_sa_out,
 				socket_id);
 			if (rc != 0)
 				rte_exit(EXIT_FAILURE,
@@ -1381,28 +1412,13 @@ inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx)
 	return 0;
 }
 
-static inline void
-single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,
-		void **sa_ret)
+void
+inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
+		void *sa[], uint16_t nb_pkts)
 {
-	struct rte_esp_hdr *esp;
-	struct ip *ip;
-	uint32_t *src4_addr;
-	uint8_t *src6_addr;
-	struct ipsec_sa *sa;
-	void *result_sa;
+	uint32_t i;
 
-	*sa_ret = NULL;
-
-	ip = rte_pktmbuf_mtod(pkt, struct ip *);
-	esp = rte_pktmbuf_mtod_offset(pkt, struct rte_esp_hdr *, pkt->l3_len);
-
-	if (esp->spi == INVALID_SPI)
-		return;
-
-	result_sa = sa = &sadb[SPI2IDX(rte_be_to_cpu_32(esp->spi))];
-	if (rte_be_to_cpu_32(esp->spi) != sa->spi)
-		return;
+	sad_lookup(&sa_ctx->sad, pkts, sa, nb_pkts);
 
 	/*
 	 * Mark need for inline offload fallback on the LSB of SA pointer.
@@ -1413,40 +1429,14 @@ single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,
 	 * pointer to prevent from unintentional use. Use ipsec_mask_saptr
 	 * to get valid struct pointer.
 	 */
-	if (MBUF_NO_SEC_OFFLOAD(pkt) && sa->fallback_sessions > 0) {
-		uintptr_t intsa = (uintptr_t)sa;
-		intsa |= IPSEC_SA_OFFLOAD_FALLBACK_FLAG;
-		result_sa = (void *)intsa;
+	for (i = 0; i < nb_pkts; i++) {
+		if (MBUF_NO_SEC_OFFLOAD(pkts[i]) && (sa[i] != NULL) &&
+			((struct ipsec_sa *)sa[i])->fallback_sessions > 0) {
+			uintptr_t intsa = (uintptr_t)sa[i];
+			intsa |= IPSEC_SA_OFFLOAD_FALLBACK_FLAG;
+			sa[i] = (void *)intsa;
+		}
 	}
-
-	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_ret = result_sa;
-		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_ret = result_sa;
-		break;
-	case TRANSPORT:
-		*sa_ret = result_sa;
-	}
-}
-
-void
-inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
-		void *sa[], uint16_t nb_pkts)
-{
-	uint32_t i;
-
-	for (i = 0; i < nb_pkts; i++)
-		single_inbound_lookup(sa_ctx->sa, pkts[i], &sa[i]);
 }
 
 void
diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c
index 3871c6c..1dcec52 100644
--- a/examples/ipsec-secgw/sp4.c
+++ b/examples/ipsec-secgw/sp4.c
@@ -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");
 
diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c
index d8be6b1..b489e15 100644
--- a/examples/ipsec-secgw/sp6.c
+++ b/examples/ipsec-secgw/sp6.c
@@ -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");
 
-- 
2.7.4


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH 4/4] examples/ipsec-secgw: get rid of maximum sa limitation
  2019-12-11 16:13 [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
  2019-12-11 16:13 ` [dpdk-dev] [PATCH 2/4] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
  2019-12-11 16:13 ` [dpdk-dev] [PATCH 3/4] examples/ipsec-secgw: integrate " Vladimir Medvedkin
@ 2019-12-11 16:13 ` Vladimir Medvedkin
  2019-12-11 16:43 ` [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Medvedkin, Vladimir
  3 siblings, 0 replies; 6+ messages in thread
From: Vladimir Medvedkin @ 2019-12-11 16:13 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, akhil.goyal

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

Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 examples/ipsec-secgw/sa.c | 78 +++++++++++++++++++++++++++++------------------
 1 file changed, 48 insertions(+), 30 deletions(-)

diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 8cc7b17..32919fe 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -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 ==
-- 
2.7.4


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h
  2019-12-11 16:13 [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
                   ` (2 preceding siblings ...)
  2019-12-11 16:13 ` [dpdk-dev] [PATCH 4/4] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
@ 2019-12-11 16:43 ` Medvedkin, Vladimir
  3 siblings, 0 replies; 6+ messages in thread
From: Medvedkin, Vladimir @ 2019-12-11 16:43 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, akhil.goyal

Self NACK for series

Forgot cover letter, will resend again.

On 11/12/2019 16:13, Vladimir Medvedkin wrote:
> Move IPSEC_SAD_NAMESIZE into public header
> and rename it to RTE_IPSEC_SAD_NAMESIZE
>
> Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> ---
>   lib/librte_ipsec/ipsec_sad.c     | 20 ++++++++++----------
>   lib/librte_ipsec/rte_ipsec_sad.h |  2 ++
>   2 files changed, 12 insertions(+), 10 deletions(-)
>
> diff --git a/lib/librte_ipsec/ipsec_sad.c b/lib/librte_ipsec/ipsec_sad.c
> index db2c44c..2c994ed 100644
> --- a/lib/librte_ipsec/ipsec_sad.c
> +++ b/lib/librte_ipsec/ipsec_sad.c
> @@ -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();
> diff --git a/lib/librte_ipsec/rte_ipsec_sad.h b/lib/librte_ipsec/rte_ipsec_sad.h
> index 8386f73..dcc8224 100644
> --- a/lib/librte_ipsec/rte_ipsec_sad.h
> +++ b/lib/librte_ipsec/rte_ipsec_sad.h
> @@ -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 */

-- 
Regards,
Vladimir


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [dpdk-dev] [PATCH 2/4] examples/ipsec-secgw: implement inbound SAD
  2019-12-11 16:45 [dpdk-dev] [PATCH 0/4] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
@ 2019-12-11 16:45 ` Vladimir Medvedkin
  0 siblings, 0 replies; 6+ messages in thread
From: Vladimir Medvedkin @ 2019-12-11 16:45 UTC (permalink / raw)
  To: dev; +Cc: konstantin.ananyev, akhil.goyal

Add initial support for librte_ipsec SAD library

Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
 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

diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8e07521..132286c 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
diff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c
new file mode 100644
index 0000000..bcac462
--- /dev/null
+++ b/examples/ipsec-secgw/sad.c
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <rte_errno.h>
+
+#include "ipsec.h"
+#include "sad.h"
+
+int
+ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
+{
+	int ret;
+	union rte_ipsec_sad_key key = { {0} };
+
+	/* spi field is common for ipv4 and ipv6 key types */
+	key.v4.spi = rte_cpu_to_be_32(sa->spi);
+	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
+	case IP4_TUNNEL:
+		key.v4.dip = rte_cpu_to_be_32(sa->dst.ip.ip4);
+		key.v4.sip = rte_cpu_to_be_32(sa->src.ip.ip4);
+		ret = rte_ipsec_sad_add(sad->sad_v4, &key,
+				RTE_IPSEC_SAD_SPI_DIP_SIP, sa);
+		if (ret != 0)
+			return ret;
+		break;
+	case IP6_TUNNEL:
+		memcpy(key.v6.dip, sa->dst.ip.ip6.ip6,
+				sizeof(key.v6.dip));
+		memcpy(key.v6.sip, sa->src.ip.ip6.ip6,
+				sizeof(key.v6.sip));
+		ret = rte_ipsec_sad_add(sad->sad_v6, &key,
+				RTE_IPSEC_SAD_SPI_DIP_SIP, sa);
+		if (ret != 0)
+			return ret;
+		break;
+	case TRANSPORT:
+		if (sp4_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
+			ret = rte_ipsec_sad_add(sad->sad_v4, &key,
+				RTE_IPSEC_SAD_SPI_ONLY, sa);
+			if (ret != 0)
+				return ret;
+		}
+
+		if (sp6_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
+			ret = rte_ipsec_sad_add(sad->sad_v6, &key,
+				RTE_IPSEC_SAD_SPI_ONLY, sa);
+			if (ret != 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+int
+ipsec_sad_create(const char *name, struct ipsec_sad *sad,
+	int socket_id, struct ipsec_sa_cnt *sa_cnt)
+{
+	int ret;
+	struct rte_ipsec_sad_conf sad_conf;
+	char sad_name[RTE_IPSEC_SAD_NAMESIZE];
+
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v4", name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
+		return -ENAMETOOLONG;
+
+	sad_conf.socket_id = socket_id;
+	sad_conf.flags = 0;
+	/* Make SAD have extra 25% of required number of entries */
+	sad_conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = sa_cnt->nb_trn * 5 / 4;
+	sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
+	sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = sa_cnt->nb_v4_tun * 5 / 4;
+
+	sad->sad_v4 = rte_ipsec_sad_create(sad_name, &sad_conf);
+	if (sad->sad_v4 == NULL)
+		return -rte_errno;
+
+	ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v6", name);
+	if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
+		return -ENAMETOOLONG;
+	sad_conf.flags = RTE_IPSEC_SAD_FLAG_IPV6;
+	sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = sa_cnt->nb_v6_tun * 5 / 4;
+
+	sad->sad_v6 = rte_ipsec_sad_create(name, &sad_conf);
+	if (sad->sad_v6 == NULL)
+		return -rte_errno;
+
+	return 0;
+}
diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h
new file mode 100644
index 0000000..e754d57
--- /dev/null
+++ b/examples/ipsec-secgw/sad.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef __SAD_H__
+#define __SAD_H__
+
+#include <rte_ipsec_sad.h>
+
+struct ipsec_sad {
+	struct rte_ipsec_sad *sad_v4;
+	struct rte_ipsec_sad *sad_v6;
+};
+
+int ipsec_sad_create(const char *name, struct ipsec_sad *sad,
+	int socket_id, struct ipsec_sa_cnt *sa_cnt);
+
+int ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa);
+
+static inline void
+sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
+	void *sa[], uint16_t nb_pkts)
+{
+	uint32_t i;
+	uint32_t nb_v4 = 0, nb_v6 = 0;
+	struct rte_esp_hdr *esp;
+	struct rte_ipv4_hdr *ipv4;
+	struct rte_ipv6_hdr *ipv6;
+	struct rte_ipsec_sadv4_key	v4[nb_pkts];
+	struct rte_ipsec_sadv6_key	v6[nb_pkts];
+	int v4_idxes[nb_pkts];
+	int v6_idxes[nb_pkts];
+	const union rte_ipsec_sad_key	*keys_v4[nb_pkts];
+	const union rte_ipsec_sad_key	*keys_v6[nb_pkts];
+	void *v4_res[nb_pkts];
+	void *v6_res[nb_pkts];
+
+	for (i = 0; i < nb_pkts; i++) {
+		ipv4 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv4_hdr *);
+		esp = rte_pktmbuf_mtod_offset(pkts[i], struct rte_esp_hdr *,
+				pkts[i]->l3_len);
+		if ((ipv4->version_ihl >> 4) == IPVERSION) {
+			v4[nb_v4].spi = esp->spi;
+			v4[nb_v4].dip = ipv4->dst_addr;
+			v4[nb_v4].sip = ipv4->src_addr;
+			keys_v4[nb_v4] = (const union rte_ipsec_sad_key *)
+						&v4[nb_v4];
+			v4_idxes[nb_v4++] = i;
+		} else {
+			ipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *);
+			v6[nb_v6].spi = esp->spi;
+			memcpy(v6[nb_v6].dip, ipv6->dst_addr,
+					sizeof(ipv6->dst_addr));
+			memcpy(v6[nb_v6].sip, ipv6->src_addr,
+					sizeof(ipv6->src_addr));
+			keys_v6[nb_v6] = (const union rte_ipsec_sad_key *)
+						&v6[nb_v6];
+			v6_idxes[nb_v6++] = i;
+		}
+	}
+
+	if (nb_v4 != 0)
+		rte_ipsec_sad_lookup(sad->sad_v4, keys_v4, v4_res, nb_v4);
+	if (nb_v6 != 0)
+		rte_ipsec_sad_lookup(sad->sad_v6, keys_v6, v6_res, nb_v6);
+
+	for (i = 0; i < nb_v4; i++)
+		sa[v4_idxes[i]] = v4_res[i];
+
+	for (i = 0; i < nb_v6; i++)
+		sa[v6_idxes[i]] = v6_res[i];
+}
+
+#endif /* __SAD_H__ */
-- 
2.7.4


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-12-11 16:45 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-11 16:13 [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
2019-12-11 16:13 ` [dpdk-dev] [PATCH 2/4] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
2019-12-11 16:13 ` [dpdk-dev] [PATCH 3/4] examples/ipsec-secgw: integrate " Vladimir Medvedkin
2019-12-11 16:13 ` [dpdk-dev] [PATCH 4/4] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
2019-12-11 16:43 ` [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Medvedkin, Vladimir
2019-12-11 16:45 [dpdk-dev] [PATCH 0/4] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
2019-12-11 16:45 ` [dpdk-dev] [PATCH 2/4] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).