* [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h
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
2019-12-11 16:45 ` [dpdk-dev] [PATCH 2/4] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
` (8 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2019-12-11 16:45 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] 60+ 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 ` [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
@ 2019-12-11 16:45 ` Vladimir Medvedkin
2019-12-11 16:45 ` [dpdk-dev] [PATCH 3/4] examples/ipsec-secgw: integrate " Vladimir Medvedkin
` (7 subsequent siblings)
9 siblings, 0 replies; 60+ 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] 60+ messages in thread
* [dpdk-dev] [PATCH 3/4] examples/ipsec-secgw: integrate 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 ` [dpdk-dev] [PATCH 1/4] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
2019-12-11 16:45 ` [dpdk-dev] [PATCH 2/4] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
@ 2019-12-11 16:45 ` Vladimir Medvedkin
2019-12-11 16:45 ` [dpdk-dev] [PATCH 4/4] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
` (6 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2019-12-11 16:45 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] 60+ messages in thread
* [dpdk-dev] [PATCH 4/4] examples/ipsec-secgw: get rid of maximum sa limitation
2019-12-11 16:45 [dpdk-dev] [PATCH 0/4] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (2 preceding siblings ...)
2019-12-11 16:45 ` [dpdk-dev] [PATCH 3/4] examples/ipsec-secgw: integrate " Vladimir Medvedkin
@ 2019-12-11 16:45 ` Vladimir Medvedkin
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 0/5] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (5 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2019-12-11 16:45 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] 60+ messages in thread
* [dpdk-dev] [PATCH v2 0/5] integrate librte_ipsec SAD into ipsec-secgw
2019-12-11 16:45 [dpdk-dev] [PATCH 0/4] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (3 preceding siblings ...)
2019-12-11 16:45 ` [dpdk-dev] [PATCH 4/4] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
@ 2019-12-18 16:00 ` Vladimir Medvedkin
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
` (5 more replies)
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 1/5] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
` (4 subsequent siblings)
9 siblings, 6 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2019-12-18 16:00 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
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
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v3 0/5] integrate librte_ipsec SAD into ipsec-secgw
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 0/5] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
@ 2020-01-13 12:55 ` Vladimir Medvedkin
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
` (5 more replies)
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 1/5] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
` (4 subsequent siblings)
5 siblings, 6 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-13 12:55 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
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
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
@ 2020-01-14 14:27 ` Vladimir Medvedkin
2020-01-15 15:45 ` Akhil Goyal
` (7 more replies)
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 1/5] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
` (4 subsequent siblings)
5 siblings, 8 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-14 14:27 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
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
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
@ 2020-01-15 15:45 ` Akhil Goyal
2020-01-17 12:26 ` Akhil Goyal
2020-01-17 17:05 ` Medvedkin, Vladimir
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
` (6 subsequent siblings)
7 siblings, 2 replies; 60+ messages in thread
From: Akhil Goyal @ 2020-01-15 15:45 UTC (permalink / raw)
To: Vladimir Medvedkin, dev; +Cc: konstantin.ananyev
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 <vladimir.medvedkin@intel.com>
> Sent: Tuesday, January 14, 2020 7:57 PM
> To: dev@dpdk.org
> Cc: konstantin.ananyev@intel.com; Akhil Goyal <akhil.goyal@nxp.com>
> 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
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw
2020-01-15 15:45 ` Akhil Goyal
@ 2020-01-17 12:26 ` Akhil Goyal
2020-01-17 17:05 ` Medvedkin, Vladimir
1 sibling, 0 replies; 60+ messages in thread
From: Akhil Goyal @ 2020-01-17 12:26 UTC (permalink / raw)
To: Vladimir Medvedkin, dev; +Cc: konstantin.ananyev
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.
>
> 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
>
> >
> > 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
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw
2020-01-15 15:45 ` Akhil Goyal
2020-01-17 12:26 ` Akhil Goyal
@ 2020-01-17 17:05 ` Medvedkin, Vladimir
2020-01-20 6:44 ` Akhil Goyal
1 sibling, 1 reply; 60+ messages in thread
From: Medvedkin, Vladimir @ 2020-01-17 17:05 UTC (permalink / raw)
To: Akhil Goyal, dev; +Cc: konstantin.ananyev
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 <vladimir.medvedkin@intel.com>
>> Sent: Tuesday, January 14, 2020 7:57 PM
>> To: dev@dpdk.org
>> Cc: konstantin.ananyev@intel.com; Akhil Goyal <akhil.goyal@nxp.com>
>> 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
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw
2020-01-17 17:05 ` Medvedkin, Vladimir
@ 2020-01-20 6:44 ` Akhil Goyal
2020-01-20 12:44 ` Anoob Joseph
[not found] ` <SN6PR11MB25581C7C8F969AA18EE8C1949A320@SN6PR11MB2558.namprd11.prod.outlook.com>
0 siblings, 2 replies; 60+ messages in thread
From: Akhil Goyal @ 2020-01-20 6:44 UTC (permalink / raw)
To: Medvedkin, Vladimir, dev
Cc: konstantin.ananyev, Anoob Joseph, Thomas Monjalon, Ravi Kumar,
Ruifeng Wang
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 <vladimir.medvedkin@intel.com>
Sent: Friday, January 17, 2020 10:35 PM
To: Akhil Goyal <akhil.goyal@nxp.com>; dev@dpdk.org
Cc: konstantin.ananyev@intel.com
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 <vladimir.medvedkin@intel.com><mailto:vladimir.medvedkin@intel.com>
Sent: Tuesday, January 14, 2020 7:57 PM
To: dev@dpdk.org<mailto:dev@dpdk.org>
Cc: konstantin.ananyev@intel.com<mailto:konstantin.ananyev@intel.com>; Akhil Goyal <akhil.goyal@nxp.com><mailto:akhil.goyal@nxp.com>
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
-->
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v4 0/5] integrate librte_ipsec SAD into ipsec-secgw
2020-01-20 6:44 ` Akhil Goyal
@ 2020-01-20 12:44 ` Anoob Joseph
[not found] ` <SN6PR11MB25581C7C8F969AA18EE8C1949A320@SN6PR11MB2558.namprd11.prod.outlook.com>
1 sibling, 0 replies; 60+ messages in thread
From: Anoob Joseph @ 2020-01-20 12:44 UTC (permalink / raw)
To: Akhil Goyal, Medvedkin, Vladimir, dev
Cc: konstantin.ananyev, Thomas Monjalon, Ravi Kumar, Ruifeng Wang,
Jerin Jacob Kollanukkaran, Narayana Prasad Raju Athreya,
Lukas Bartosik
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 <akhil.goyal@nxp.com>
Sent: Monday, January 20, 2020 12:14 PM
To: Medvedkin, Vladimir <vladimir.medvedkin@intel.com>; dev@dpdk.org
Cc: konstantin.ananyev@intel.com; Anoob Joseph <anoobj@marvell.com>; Thomas Monjalon <thomas@monjalon.net>; Ravi Kumar <ravi1.kumar@amd.com>; Ruifeng Wang <ruifeng.wang@arm.com>
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:vladimir.medvedkin@intel.com>
Sent: Friday, January 17, 2020 10:35 PM
To: Akhil Goyal <mailto:akhil.goyal@nxp.com>; mailto:dev@dpdk.org
Cc: mailto:konstantin.ananyev@intel.com
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:vladimir.medvedkin@intel.com
Sent: Tuesday, January 14, 2020 7:57 PM
To: mailto:dev@dpdk.org
Cc: mailto:konstantin.ananyev@intel.com; Akhil Goyal mailto:akhil.goyal@nxp.com
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
-->
^ permalink raw reply [flat|nested] 60+ messages in thread
[parent not found: <SN6PR11MB25581C7C8F969AA18EE8C1949A320@SN6PR11MB2558.namprd11.prod.outlook.com>]
* [dpdk-dev] [PATCH v5 0/6] integrate librte_ipsec SAD into ipsec-secgw
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
2020-01-15 15:45 ` Akhil Goyal
@ 2020-01-29 14:06 ` Vladimir Medvedkin
2020-01-31 12:53 ` Akhil Goyal
` (9 more replies)
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 1/6] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
` (5 subsequent siblings)
7 siblings, 10 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-29 14:06 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
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
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v5 0/6] integrate librte_ipsec SAD into ipsec-secgw
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
@ 2020-01-31 12:53 ` Akhil Goyal
2020-02-04 4:11 ` Anoob Joseph
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 0/8] " Vladimir Medvedkin
` (8 subsequent siblings)
9 siblings, 1 reply; 60+ messages in thread
From: Akhil Goyal @ 2020-01-31 12:53 UTC (permalink / raw)
To: Anoob Joseph, Vladimir Medvedkin; +Cc: konstantin.ananyev, dev
>
> 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
>
Series
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
Hi Anoob,
Do you have any comments on this set. I do not see degradation on this patchset now.
Regards,
Akhil
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v5 0/6] integrate librte_ipsec SAD into ipsec-secgw
2020-01-31 12:53 ` Akhil Goyal
@ 2020-02-04 4:11 ` Anoob Joseph
2020-02-04 15:22 ` Akhil Goyal
0 siblings, 1 reply; 60+ messages in thread
From: Anoob Joseph @ 2020-02-04 4:11 UTC (permalink / raw)
To: Akhil Goyal, Vladimir Medvedkin; +Cc: konstantin.ananyev, dev
Hi Akhil,
> >
> > 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
> >
>
> Series
> Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
>
> 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
Acked-by: Anoob Joseph <anoobj@marvell.com>
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v5 0/6] integrate librte_ipsec SAD into ipsec-secgw
2020-02-04 4:11 ` Anoob Joseph
@ 2020-02-04 15:22 ` Akhil Goyal
0 siblings, 0 replies; 60+ messages in thread
From: Akhil Goyal @ 2020-02-04 15:22 UTC (permalink / raw)
To: Anoob Joseph, Vladimir Medvedkin; +Cc: konstantin.ananyev, dev
>
> Hi Akhil,
>
> > >
> > > 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
> > >
> >
> > Series
> > Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
> >
> > 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
> Acked-by: Anoob Joseph <anoobj@marvell.com>
Applied to dpdk-next-crypto
Thanks.
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v6 0/8] integrate librte_ipsec SAD into ipsec-secgw
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
2020-01-31 12:53 ` Akhil Goyal
@ 2020-01-31 17:39 ` Vladimir Medvedkin
2020-02-04 15:25 ` Akhil Goyal
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 1/8] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
` (7 subsequent siblings)
9 siblings, 1 reply; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-31 17:39 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
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
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v6 0/8] integrate librte_ipsec SAD into ipsec-secgw
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 0/8] " Vladimir Medvedkin
@ 2020-02-04 15:25 ` Akhil Goyal
0 siblings, 0 replies; 60+ messages in thread
From: Akhil Goyal @ 2020-02-04 15:25 UTC (permalink / raw)
To: Vladimir Medvedkin, dev; +Cc: konstantin.ananyev
> 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
>
> --
> 2.7.4
Squashed the last patch with 6th patch
Applied to dpdk-next-crypto
Thanks.
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v6 1/8] ipsec: move ipsec sad name length into .h
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
2020-01-31 12:53 ` Akhil Goyal
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 0/8] " Vladimir Medvedkin
@ 2020-01-31 17:39 ` Vladimir Medvedkin
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 2/8] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
` (6 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-31 17:39 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>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.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] 60+ messages in thread
* [dpdk-dev] [PATCH v6 2/8] examples/ipsec-secgw: implement inbound SAD
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
` (2 preceding siblings ...)
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 1/8] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
@ 2020-01-31 17:39 ` Vladimir Medvedkin
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 3/8] examples/ipsec-secgw: integrate " Vladimir Medvedkin
` (5 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-31 17:39 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>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
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
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8e07521..9ddb5d9 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
diff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c
new file mode 100644
index 0000000..fd31101
--- /dev/null
+++ b/examples/ipsec-secgw/sad.c
@@ -0,0 +1,109 @@
+/* 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;
+ void *tmp = NULL;
+ union rte_ipsec_sad_key key = { {0} };
+ const union rte_ipsec_sad_key *lookup_key[1];
+
+ /* spi field is common for ipv4 and ipv6 key types */
+ key.v4.spi = rte_cpu_to_be_32(sa->spi);
+ lookup_key[0] = &key;
+ switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
+ case IP4_TUNNEL:
+ rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
+ if (tmp != NULL)
+ return -EEXIST;
+
+ ret = rte_ipsec_sad_add(sad->sad_v4, &key,
+ RTE_IPSEC_SAD_SPI_ONLY, sa);
+ if (ret != 0)
+ return ret;
+ break;
+ case IP6_TUNNEL:
+ rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
+ if (tmp != NULL)
+ return -EEXIST;
+
+ ret = rte_ipsec_sad_add(sad->sad_v6, &key,
+ RTE_IPSEC_SAD_SPI_ONLY, sa);
+ if (ret != 0)
+ return ret;
+ break;
+ case TRANSPORT:
+ if (sp4_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
+ rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
+ if (tmp != NULL)
+ return -EEXIST;
+
+ 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) {
+ rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
+ if (tmp != NULL)
+ return -EEXIST;
+
+ 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];
+
+ if ((name == NULL) || (sad == NULL) || (sa_cnt == NULL))
+ return -EINVAL;
+
+ 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_v4 * 5 / 4;
+ sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
+ sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
+
+ if (sa_cnt->nb_v4 != 0) {
+ 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_ONLY] = sa_cnt->nb_v6 * 5 / 4;
+
+ if (sa_cnt->nb_v6 != 0) {
+ 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..29ed0f8
--- /dev/null
+++ b/examples/ipsec-secgw/sad.h
@@ -0,0 +1,75 @@
+/* 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];
+
+ /* split received packets by address family into two arrays */
+ 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] 60+ messages in thread
* [dpdk-dev] [PATCH v6 3/8] examples/ipsec-secgw: integrate inbound SAD
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
` (3 preceding siblings ...)
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 2/8] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
@ 2020-01-31 17:39 ` Vladimir Medvedkin
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 4/8] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
` (4 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-31 17:39 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>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
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(-)
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 9ddb5d9..5988d59 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
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..d10a6ec 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,17 @@ 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++;
rule->flags = IP4_TUNNEL;
- else if (strcmp(tokens[ti], "ipv6-tunnel") == 0)
+ } else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
+ sa_cnt->nb_v6++;
rule->flags = IP6_TUNNEL;
- else if (strcmp(tokens[ti], "transport") == 0)
+ } else if (strcmp(tokens[ti], "transport") == 0) {
+ sa_cnt->nb_v4++;
+ sa_cnt->nb_v6++;
rule->flags = TRANSPORT;
- else {
+ } else {
APP_CHECK(0, status, "unrecognized "
"input \"%s\"", tokens[ti]);
return;
@@ -772,19 +782,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 +805,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 +972,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 +980,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 +1267,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 +1277,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 +1300,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 +1315,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 +1353,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 +1378,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 +1387,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 +1413,18 @@ 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_arr[], uint16_t nb_pkts)
{
- struct rte_esp_hdr *esp;
+ uint32_t i;
struct ip *ip;
uint32_t *src4_addr;
uint8_t *src6_addr;
- struct ipsec_sa *sa;
void *result_sa;
+ struct ipsec_sa *sa;
- *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_arr, nb_pkts);
/*
* Mark need for inline offload fallback on the LSB of SA pointer.
@@ -1413,43 +1435,47 @@ 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 (sa_arr[i] == NULL)
+ continue;
- 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) &&
+ result_sa = sa = sa_arr[i];
+ if (MBUF_NO_SEC_OFFLOAD(pkts[i]) &&
+ sa->fallback_sessions > 0) {
+ uintptr_t intsa = (uintptr_t)sa;
+ 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_ret = result_sa;
- break;
- case TRANSPORT:
- *sa_ret = result_sa;
+ sa_arr[i] = result_sa;
+ else
+ sa_arr[i] = NULL;
+ break;
+ case TRANSPORT:
+ sa_arr[i] = 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
outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
void *sa[], uint16_t nb_pkts)
{
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] 60+ messages in thread
* [dpdk-dev] [PATCH v6 4/8] examples/ipsec-secgw: get rid of maximum sa limitation
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
` (4 preceding siblings ...)
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 3/8] examples/ipsec-secgw: integrate " Vladimir Medvedkin
@ 2020-01-31 17:39 ` Vladimir Medvedkin
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 5/8] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
` (3 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-31 17:39 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
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.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
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(-)
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 5988d59..3c77232 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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
diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
index fc8c238..67df170 100644
--- a/examples/ipsec-secgw/parser.c
+++ b/examples/ipsec-secgw/parser.c
@@ -642,6 +642,8 @@ parse_cfg_file(const char *cfg_filename)
cmdline_stdin_exit(cl);
fclose(f);
+ sa_sort_arr();
+
return 0;
error_exit:
diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
index 6b8a100..1f8bd3e 100644
--- a/examples/ipsec-secgw/parser.h
+++ b/examples/ipsec-secgw/parser.h
@@ -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);
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index d10a6ec..b3b83e3 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -133,11 +133,15 @@ const struct supported_aead_algo aead_algos[] = {
}
};
-static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
+#define SA_INIT_NB 128
+
+static struct ipsec_sa *sa_out;
+static uint32_t sa_out_sz;
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 ipsec_sa *sa_in;
+static uint32_t sa_in_sz;
static uint32_t nb_sa_in;
static struct ipsec_sa_cnt sa_in_cnt;
@@ -224,6 +228,31 @@ parse_key_string(const char *key_str, uint8_t *key)
return nb_bytes;
}
+static int
+extend_sa_arr(struct ipsec_sa **sa_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sa_tbl == NULL) {
+ *sa_tbl = calloc(SA_INIT_NB, sizeof(struct ipsec_sa));
+ if (*sa_tbl == NULL)
+ return -1;
+ *cur_sz = SA_INIT_NB;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sa_tbl = realloc(*sa_tbl,
+ *cur_sz * sizeof(struct ipsec_sa) * 2);
+ if (*sa_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sa_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct ipsec_sa));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
+
void
parse_sa_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status)
@@ -246,23 +275,15 @@ 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");
- if (status->status < 0)
+ if (extend_sa_arr(&sa_in, nb_sa_in, &sa_in_sz) < 0)
return;
-
rule = &sa_in[*ri];
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)
+ if (extend_sa_arr(&sa_out, nb_sa_out, &sa_out_sz) < 0)
return;
-
rule = &sa_out[*ri];
rule->direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
}
@@ -1311,13 +1332,24 @@ ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket)
return rc;
}
+static int
+sa_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct ipsec_sa *)p)->spi;
+ uint32_t spi2 = ((const struct ipsec_sa *)q)->spi;
+
+ return (int)(spi1 - spi2);
+}
+
/*
* Walk through all SA rules to find an SA with given SPI
*/
int
sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
{
- uint32_t i, num;
+ uint32_t num;
+ struct ipsec_sa *sa;
+ struct ipsec_sa tmpl;
const struct ipsec_sa *sar;
sar = sa_ctx->sa;
@@ -1326,10 +1358,11 @@ sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
else
num = nb_sa_out;
- for (i = 0; i != num; i++) {
- if (sar[i].spi == spi)
- return i;
- }
+ tmpl.spi = spi;
+
+ sa = bsearch(&tmpl, sar, num, sizeof(struct ipsec_sa), sa_cmp);
+ if (sa != NULL)
+ return RTE_PTR_DIFF(sa, sar) / sizeof(struct ipsec_sa);
return -ENOENT;
}
@@ -1522,3 +1555,10 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
}
return 0;
}
+
+void
+sa_sort_arr(void)
+{
+ qsort(sa_in, nb_sa_in, sizeof(struct ipsec_sa), sa_cmp);
+ qsort(sa_out, nb_sa_out, sizeof(struct ipsec_sa), sa_cmp);
+}
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v6 5/8] examples/ipsec-secgw: get rid of maximum sp limitation
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
` (5 preceding siblings ...)
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 4/8] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
@ 2020-01-31 17:39 ` Vladimir Medvedkin
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 6/8] examples/ipsec-secgw: add SAD cache Vladimir Medvedkin
` (2 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-31 17:39 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
Get rid of maximum SP limitation.
Keep parsed SP's into the sorted by SPI value array.
Use binary search in the sorted SP array to find appropriate SP
for a given SPI.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
examples/ipsec-secgw/parser.c | 2 +
examples/ipsec-secgw/parser.h | 6 +++
examples/ipsec-secgw/sp4.c | 90 +++++++++++++++++++++++++++++++++----------
examples/ipsec-secgw/sp6.c | 88 ++++++++++++++++++++++++++++++++----------
4 files changed, 144 insertions(+), 42 deletions(-)
diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
index 67df170..65eb7e9 100644
--- a/examples/ipsec-secgw/parser.c
+++ b/examples/ipsec-secgw/parser.c
@@ -643,6 +643,8 @@ parse_cfg_file(const char *cfg_filename)
fclose(f);
sa_sort_arr();
+ sp4_sort_arr();
+ sp6_sort_arr();
return 0;
diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
index 1f8bd3e..6e764fe 100644
--- a/examples/ipsec-secgw/parser.h
+++ b/examples/ipsec-secgw/parser.h
@@ -67,10 +67,16 @@ int
parse_range(const char *token, uint16_t *low, uint16_t *high);
void
+sp4_sort_arr(void);
+
+void
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status);
void
+sp6_sort_arr(void);
+
+void
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status);
diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c
index 1dcec52..beddd7b 100644
--- a/examples/ipsec-secgw/sp4.c
+++ b/examples/ipsec-secgw/sp4.c
@@ -15,7 +15,7 @@
#include "ipsec.h"
#include "parser.h"
-#define MAX_ACL_RULE_NUM 1024
+#define INIT_ACL_RULE_NUM 128
#define IPV4_DST_FROM_SP(acr) \
(rte_cpu_to_be_32((acr).field[DST_FIELD_IPV4].value.u32))
@@ -97,11 +97,39 @@ static struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = {
RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs));
-static struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM];
+static struct acl4_rules *acl4_rules_out;
static uint32_t nb_acl4_rules_out;
+static uint32_t sp_out_sz;
-static struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM];
+static struct acl4_rules *acl4_rules_in;
static uint32_t nb_acl4_rules_in;
+static uint32_t sp_in_sz;
+
+static int
+extend_sp_arr(struct acl4_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sp_tbl == NULL) {
+ *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl4_rules));
+ if (*sp_tbl == NULL)
+ return -1;
+ *cur_sz = INIT_ACL_RULE_NUM;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sp_tbl = realloc(*sp_tbl,
+ *cur_sz * sizeof(struct acl4_rules) * 2);
+ if (*sp_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sp_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct acl4_rules));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
+
void
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
@@ -127,9 +155,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
if (strcmp(tokens[1], "in") == 0) {
ri = &nb_acl4_rules_in;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
- "too many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl4_rules_in, nb_acl4_rules_in,
+ &sp_in_sz) < 0)
return;
rule_ipv4 = &acl4_rules_in[*ri];
@@ -137,9 +164,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
} else if (strcmp(tokens[1], "out") == 0) {
ri = &nb_acl4_rules_out;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
- "too many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl4_rules_out, nb_acl4_rules_out,
+ &sp_out_sz) < 0)
return;
rule_ipv4 = &acl4_rules_out[*ri];
@@ -451,7 +477,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
struct rte_acl_config acl_build_param;
struct rte_acl_ctx *ctx;
- printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
+ printf("Creating SP context with %u rules\n", rules_nb);
memset(&acl_param, 0, sizeof(acl_param));
@@ -464,7 +490,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
acl_param.name = s;
acl_param.socket_id = socketid;
acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip4_defs));
- acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+ acl_param.max_rule_num = rules_nb;
ctx = rte_acl_create(&acl_param);
if (ctx == NULL)
@@ -566,6 +592,16 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id)
"specified\n");
}
+static int
+sp_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct acl4_rules *)p)->data.userdata;
+ uint32_t spi2 = ((const struct acl4_rules *)q)->data.userdata;
+
+ return (int)(spi1 - spi2);
+}
+
+
/*
* Search though SP rules for given SPI.
*/
@@ -573,8 +609,10 @@ int
sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
uint32_t mask[2])
{
- uint32_t i, num;
+ uint32_t num;
+ struct acl4_rules *rule;
const struct acl4_rules *acr;
+ struct acl4_rules tmpl;
if (inbound != 0) {
acr = acl4_rules_in;
@@ -584,17 +622,27 @@ sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
num = nb_acl4_rules_out;
}
- for (i = 0; i != num; i++) {
- if (acr[i].data.userdata == spi) {
- if (NULL != ip_addr && NULL != mask) {
- ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(acr[i]);
- ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(acr[i]);
- mask[0] = IPV4_SRC_MASK_FROM_SP(acr[i]);
- mask[1] = IPV4_DST_MASK_FROM_SP(acr[i]);
- }
- return i;
+ tmpl.data.userdata = spi;
+
+ rule = bsearch(&tmpl, acr, num, sizeof(struct acl4_rules), sp_cmp);
+ if (rule != NULL) {
+ if (NULL != ip_addr && NULL != mask) {
+ ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(*rule);
+ ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(*rule);
+ mask[0] = IPV4_SRC_MASK_FROM_SP(*rule);
+ mask[1] = IPV4_DST_MASK_FROM_SP(*rule);
}
+ return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl4_rules);
}
return -ENOENT;
}
+
+void
+sp4_sort_arr(void)
+{
+ qsort(acl4_rules_in, nb_acl4_rules_in, sizeof(struct acl4_rules),
+ sp_cmp);
+ qsort(acl4_rules_out, nb_acl4_rules_out, sizeof(struct acl4_rules),
+ sp_cmp);
+}
diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c
index b489e15..328e085 100644
--- a/examples/ipsec-secgw/sp6.c
+++ b/examples/ipsec-secgw/sp6.c
@@ -15,7 +15,7 @@
#include "ipsec.h"
#include "parser.h"
-#define MAX_ACL_RULE_NUM 1024
+#define INIT_ACL_RULE_NUM 128
#define IPV6_FROM_SP(acr, fidx_low, fidx_high) \
(((uint64_t)(acr).field[(fidx_high)].value.u32 << 32) | \
@@ -146,11 +146,38 @@ static struct rte_acl_field_def ip6_defs[IP6_NUM] = {
RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
-static struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM];
+static struct acl6_rules *acl6_rules_out;
static uint32_t nb_acl6_rules_out;
+static uint32_t sp_out_sz;
-static struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM];
+static struct acl6_rules *acl6_rules_in;
static uint32_t nb_acl6_rules_in;
+static uint32_t sp_in_sz;
+
+static int
+extend_sp_arr(struct acl6_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sp_tbl == NULL) {
+ *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl6_rules));
+ if (*sp_tbl == NULL)
+ return -1;
+ *cur_sz = INIT_ACL_RULE_NUM;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sp_tbl = realloc(*sp_tbl,
+ *cur_sz * sizeof(struct acl6_rules) * 2);
+ if (*sp_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sp_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct acl6_rules));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
void
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
@@ -176,9 +203,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
if (strcmp(tokens[1], "in") == 0) {
ri = &nb_acl6_rules_in;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl6_rules_in, nb_acl6_rules_in,
+ &sp_in_sz) < 0)
return;
rule_ipv6 = &acl6_rules_in[*ri];
@@ -186,9 +212,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
} else if (strcmp(tokens[1], "out") == 0) {
ri = &nb_acl6_rules_out;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl6_rules_out, nb_acl6_rules_out,
+ &sp_out_sz) < 0)
return;
rule_ipv6 = &acl6_rules_out[*ri];
@@ -583,7 +608,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
struct rte_acl_config acl_build_param;
struct rte_acl_ctx *ctx;
- printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
+ printf("Creating SP context with %u rules\n", rules_nb);
memset(&acl_param, 0, sizeof(acl_param));
@@ -596,7 +621,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
acl_param.name = s;
acl_param.socket_id = socketid;
acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs));
- acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+ acl_param.max_rule_num = rules_nb;
ctx = rte_acl_create(&acl_param);
if (ctx == NULL)
@@ -698,6 +723,15 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
"specified\n");
}
+static int
+sp_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct acl6_rules *)p)->data.userdata;
+ uint32_t spi2 = ((const struct acl6_rules *)q)->data.userdata;
+
+ return (int)(spi1 - spi2);
+}
+
/*
* Search though SP rules for given SPI.
*/
@@ -705,8 +739,10 @@ int
sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
uint32_t mask[2])
{
- uint32_t i, num;
+ uint32_t num;
+ struct acl6_rules *rule;
const struct acl6_rules *acr;
+ struct acl6_rules tmpl;
if (inbound != 0) {
acr = acl6_rules_in;
@@ -716,17 +752,27 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
num = nb_acl6_rules_out;
}
- for (i = 0; i != num; i++) {
- if (acr[i].data.userdata == spi) {
- if (NULL != ip_addr && NULL != mask) {
- IPV6_SRC_FROM_SP(ip_addr[0], acr[i]);
- IPV6_DST_FROM_SP(ip_addr[1], acr[i]);
- IPV6_SRC_MASK_FROM_SP(mask[0], acr[i]);
- IPV6_DST_MASK_FROM_SP(mask[1], acr[i]);
- }
- return i;
+ tmpl.data.userdata = spi;
+
+ rule = bsearch(&tmpl, acr, num, sizeof(struct acl6_rules), sp_cmp);
+ if (rule != NULL) {
+ if (NULL != ip_addr && NULL != mask) {
+ IPV6_SRC_FROM_SP(ip_addr[0], *rule);
+ IPV6_DST_FROM_SP(ip_addr[1], *rule);
+ IPV6_SRC_MASK_FROM_SP(mask[0], *rule);
+ IPV6_DST_MASK_FROM_SP(mask[1], *rule);
}
+ return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl6_rules);
}
return -ENOENT;
}
+
+void
+sp6_sort_arr(void)
+{
+ qsort(acl6_rules_in, nb_acl6_rules_in, sizeof(struct acl6_rules),
+ sp_cmp);
+ qsort(acl6_rules_out, nb_acl6_rules_out, sizeof(struct acl6_rules),
+ sp_cmp);
+}
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v6 6/8] examples/ipsec-secgw: add SAD cache
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
` (6 preceding siblings ...)
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 5/8] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
@ 2020-01-31 17:39 ` Vladimir Medvedkin
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 7/8] examples/ipsec-secgw: set/use mbuf ptype Vladimir Medvedkin
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 8/8] doc: update ipsec-secgw guide Vladimir Medvedkin
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-31 17:39 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
Introduce SAD cache.
Stores the most recent SA in a per lcore cache.
Cache represents flat array containing SA's indexed by SPI.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
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(-)
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 3e5f82e..32ecd26 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -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) {
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 3c77232..4f2fd61 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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 */
};
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index b3b83e3..099a11b 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -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;
}
}
diff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c
index fd31101..5b2c0e6 100644
--- a/examples/ipsec-secgw/sad.c
+++ b/examples/ipsec-secgw/sad.c
@@ -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)
diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h
index 29ed0f8..3f92db2 100644
--- a/examples/ipsec-secgw/sad.h
+++ b/examples/ipsec-secgw/sad.h
@@ -7,6 +7,17 @@
#include <rte_ipsec_sad.h>
+#define SA_CACHE_SZ 128
+#define SPI2IDX(spi, mask) ((spi) & (mask))
+
+struct ipsec_sad_cache {
+ struct ipsec_sa **v4;
+ struct ipsec_sa **v6;
+ uint32_t mask;
+};
+
+RTE_DECLARE_PER_LCORE(struct ipsec_sad_cache, sad_cache);
+
struct ipsec_sad {
struct rte_ipsec_sad *sad_v4;
struct rte_ipsec_sad *sad_v6;
@@ -17,8 +28,42 @@ int ipsec_sad_create(const char *name, struct ipsec_sad *sad,
int ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa);
+int ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent);
+
+static inline int
+cmp_sa_key(struct ipsec_sa *sa, int is_v4, struct rte_ipv4_hdr *ipv4,
+ struct rte_ipv6_hdr *ipv6)
+{
+ int sa_type = WITHOUT_TRANSPORT_VERSION(sa->flags);
+ if ((sa_type == TRANSPORT) ||
+ /* IPv4 check */
+ (is_v4 && (sa_type == IP4_TUNNEL) &&
+ (sa->src.ip.ip4 == ipv4->src_addr) &&
+ (sa->dst.ip.ip4 == ipv4->dst_addr)) ||
+ /* IPv6 check */
+ (!is_v4 && (sa_type == IP6_TUNNEL) &&
+ (!memcmp(sa->src.ip.ip6.ip6, ipv6->src_addr, 16)) &&
+ (!memcmp(sa->dst.ip.ip6.ip6, ipv6->dst_addr, 16))))
+ return 1;
+
+ return 0;
+}
+
static inline void
-sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
+sa_cache_update(struct ipsec_sa **sa_cache, struct ipsec_sa *sa, uint32_t mask)
+{
+ uint32_t cache_idx;
+
+ /* SAD cache is disabled */
+ if (mask == 0)
+ return;
+
+ cache_idx = SPI2IDX(sa->spi, mask);
+ sa_cache[cache_idx] = sa;
+}
+
+static inline void
+sad_lookup(struct ipsec_sad *sad, struct rte_mbuf *pkts[],
void *sa[], uint16_t nb_pkts)
{
uint32_t i;
@@ -34,13 +79,39 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
const union rte_ipsec_sad_key *keys_v6[nb_pkts];
void *v4_res[nb_pkts];
void *v6_res[nb_pkts];
+ uint32_t spi, cache_idx;
+ struct ipsec_sad_cache *cache;
+ struct ipsec_sa *cached_sa;
+ int is_ipv4;
+
+ cache = &RTE_PER_LCORE(sad_cache);
/* split received packets by address family into two arrays */
for (i = 0; i < nb_pkts; i++) {
ipv4 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv4_hdr *);
+ ipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *);
esp = rte_pktmbuf_mtod_offset(pkts[i], struct rte_esp_hdr *,
pkts[i]->l3_len);
- if ((ipv4->version_ihl >> 4) == IPVERSION) {
+
+ is_ipv4 = ((ipv4->version_ihl >> 4) == IPVERSION);
+ spi = rte_be_to_cpu_32(esp->spi);
+ cache_idx = SPI2IDX(spi, cache->mask);
+
+ if (is_ipv4) {
+ cached_sa = (cache->mask != 0) ?
+ cache->v4[cache_idx] : NULL;
+ /* check SAD cache entry */
+ if ((cached_sa != NULL) && (cached_sa->spi == spi)) {
+ if (cmp_sa_key(cached_sa, 1, ipv4, ipv6)) {
+ /* cache hit */
+ sa[i] = cached_sa;
+ continue;
+ }
+ }
+ /*
+ * cache miss
+ * preparing sad key to proceed with sad lookup
+ */
v4[nb_v4].spi = esp->spi;
v4[nb_v4].dip = ipv4->dst_addr;
v4[nb_v4].sip = ipv4->src_addr;
@@ -48,7 +119,14 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
&v4[nb_v4];
v4_idxes[nb_v4++] = i;
} else {
- ipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *);
+ cached_sa = (cache->mask != 0) ?
+ cache->v6[cache_idx] : NULL;
+ if ((cached_sa != NULL) && (cached_sa->spi == spi)) {
+ if (cmp_sa_key(cached_sa, 0, ipv4, ipv6)) {
+ sa[i] = cached_sa;
+ continue;
+ }
+ }
v6[nb_v6].spi = esp->spi;
memcpy(v6[nb_v6].dip, ipv6->dst_addr,
sizeof(ipv6->dst_addr));
@@ -65,11 +143,28 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
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];
+ for (i = 0; i < nb_v4; i++) {
+ ipv4 = rte_pktmbuf_mtod(pkts[v4_idxes[i]],
+ struct rte_ipv4_hdr *);
+ if ((v4_res[i] != NULL) &&
+ (cmp_sa_key(v4_res[i], 1, ipv4, NULL))) {
+ sa[v4_idxes[i]] = v4_res[i];
+ sa_cache_update(cache->v4, (struct ipsec_sa *)v4_res[i],
+ cache->mask);
+ } else
+ sa[v4_idxes[i]] = NULL;
+ }
+ for (i = 0; i < nb_v6; i++) {
+ ipv6 = rte_pktmbuf_mtod(pkts[v6_idxes[i]],
+ struct rte_ipv6_hdr *);
+ if ((v6_res[i] != NULL) &&
+ (cmp_sa_key(v6_res[i], 0, NULL, ipv6))) {
+ sa[v6_idxes[i]] = v6_res[i];
+ sa_cache_update(cache->v6, (struct ipsec_sa *)v6_res[i],
+ cache->mask);
+ } else
+ sa[v6_idxes[i]] = NULL;
+ }
}
#endif /* __SAD_H__ */
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v6 7/8] examples/ipsec-secgw: set/use mbuf ptype
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
` (7 preceding siblings ...)
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 6/8] examples/ipsec-secgw: add SAD cache Vladimir Medvedkin
@ 2020-01-31 17:39 ` Vladimir Medvedkin
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 8/8] doc: update ipsec-secgw guide Vladimir Medvedkin
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-31 17:39 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
Set mbuf ptype in prepare_one_packet() after parsing ether_type.
Use mbuf ptype after to recognize packet's address family.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
examples/ipsec-secgw/ipsec-secgw.c | 2 ++
examples/ipsec-secgw/sad.h | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 32ecd26..4799bc9 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -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",
diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h
index 3f92db2..55712ba 100644
--- a/examples/ipsec-secgw/sad.h
+++ b/examples/ipsec-secgw/sad.h
@@ -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);
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v6 8/8] doc: update ipsec-secgw guide
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
` (8 preceding siblings ...)
2020-01-31 17:39 ` [dpdk-dev] [PATCH v6 7/8] examples/ipsec-secgw: set/use mbuf ptype Vladimir Medvedkin
@ 2020-01-31 17:39 ` Vladimir Medvedkin
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-31 17:39 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
Add new SAD cache option in ipsec-secgw guide.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
doc/guides/sample_app_ug/ipsec_secgw.rst | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst
index d6d8d44..5ec9b1e 100644
--- a/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -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.
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v5 1/6] ipsec: move ipsec sad name length into .h
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
2020-01-15 15:45 ` Akhil Goyal
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 0/6] " Vladimir Medvedkin
@ 2020-01-29 14:06 ` Vladimir Medvedkin
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 2/6] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
` (4 subsequent siblings)
7 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-29 14:06 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>
Acked-by: Konstantin Ananyev <konstantin.ananyev@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] 60+ messages in thread
* [dpdk-dev] [PATCH v5 2/6] examples/ipsec-secgw: implement inbound SAD
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
` (2 preceding siblings ...)
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 1/6] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
@ 2020-01-29 14:06 ` Vladimir Medvedkin
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 3/6] examples/ipsec-secgw: integrate " Vladimir Medvedkin
` (3 subsequent siblings)
7 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-29 14:06 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>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
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
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8e07521..9ddb5d9 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
diff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c
new file mode 100644
index 0000000..fd31101
--- /dev/null
+++ b/examples/ipsec-secgw/sad.c
@@ -0,0 +1,109 @@
+/* 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;
+ void *tmp = NULL;
+ union rte_ipsec_sad_key key = { {0} };
+ const union rte_ipsec_sad_key *lookup_key[1];
+
+ /* spi field is common for ipv4 and ipv6 key types */
+ key.v4.spi = rte_cpu_to_be_32(sa->spi);
+ lookup_key[0] = &key;
+ switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
+ case IP4_TUNNEL:
+ rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
+ if (tmp != NULL)
+ return -EEXIST;
+
+ ret = rte_ipsec_sad_add(sad->sad_v4, &key,
+ RTE_IPSEC_SAD_SPI_ONLY, sa);
+ if (ret != 0)
+ return ret;
+ break;
+ case IP6_TUNNEL:
+ rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
+ if (tmp != NULL)
+ return -EEXIST;
+
+ ret = rte_ipsec_sad_add(sad->sad_v6, &key,
+ RTE_IPSEC_SAD_SPI_ONLY, sa);
+ if (ret != 0)
+ return ret;
+ break;
+ case TRANSPORT:
+ if (sp4_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
+ rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
+ if (tmp != NULL)
+ return -EEXIST;
+
+ 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) {
+ rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
+ if (tmp != NULL)
+ return -EEXIST;
+
+ 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];
+
+ if ((name == NULL) || (sad == NULL) || (sa_cnt == NULL))
+ return -EINVAL;
+
+ 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_v4 * 5 / 4;
+ sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
+ sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
+
+ if (sa_cnt->nb_v4 != 0) {
+ 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_ONLY] = sa_cnt->nb_v6 * 5 / 4;
+
+ if (sa_cnt->nb_v6 != 0) {
+ 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..29ed0f8
--- /dev/null
+++ b/examples/ipsec-secgw/sad.h
@@ -0,0 +1,75 @@
+/* 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];
+
+ /* split received packets by address family into two arrays */
+ 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] 60+ messages in thread
* [dpdk-dev] [PATCH v5 3/6] examples/ipsec-secgw: integrate inbound SAD
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
` (3 preceding siblings ...)
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 2/6] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
@ 2020-01-29 14:06 ` Vladimir Medvedkin
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 4/6] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
` (2 subsequent siblings)
7 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-29 14:06 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>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
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(-)
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 9ddb5d9..5988d59 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
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..d10a6ec 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,17 @@ 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++;
rule->flags = IP4_TUNNEL;
- else if (strcmp(tokens[ti], "ipv6-tunnel") == 0)
+ } else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
+ sa_cnt->nb_v6++;
rule->flags = IP6_TUNNEL;
- else if (strcmp(tokens[ti], "transport") == 0)
+ } else if (strcmp(tokens[ti], "transport") == 0) {
+ sa_cnt->nb_v4++;
+ sa_cnt->nb_v6++;
rule->flags = TRANSPORT;
- else {
+ } else {
APP_CHECK(0, status, "unrecognized "
"input \"%s\"", tokens[ti]);
return;
@@ -772,19 +782,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 +805,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 +972,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 +980,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 +1267,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 +1277,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 +1300,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 +1315,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 +1353,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 +1378,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 +1387,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 +1413,18 @@ 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_arr[], uint16_t nb_pkts)
{
- struct rte_esp_hdr *esp;
+ uint32_t i;
struct ip *ip;
uint32_t *src4_addr;
uint8_t *src6_addr;
- struct ipsec_sa *sa;
void *result_sa;
+ struct ipsec_sa *sa;
- *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_arr, nb_pkts);
/*
* Mark need for inline offload fallback on the LSB of SA pointer.
@@ -1413,43 +1435,47 @@ 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 (sa_arr[i] == NULL)
+ continue;
- 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) &&
+ result_sa = sa = sa_arr[i];
+ if (MBUF_NO_SEC_OFFLOAD(pkts[i]) &&
+ sa->fallback_sessions > 0) {
+ uintptr_t intsa = (uintptr_t)sa;
+ 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_ret = result_sa;
- break;
- case TRANSPORT:
- *sa_ret = result_sa;
+ sa_arr[i] = result_sa;
+ else
+ sa_arr[i] = NULL;
+ break;
+ case TRANSPORT:
+ sa_arr[i] = 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
outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
void *sa[], uint16_t nb_pkts)
{
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] 60+ messages in thread
* [dpdk-dev] [PATCH v5 4/6] examples/ipsec-secgw: get rid of maximum sa limitation
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
` (4 preceding siblings ...)
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 3/6] examples/ipsec-secgw: integrate " Vladimir Medvedkin
@ 2020-01-29 14:06 ` Vladimir Medvedkin
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 5/6] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 6/6] examples/ipsec-secgw: add SAD cache Vladimir Medvedkin
7 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-29 14:06 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
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.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
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(-)
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 5988d59..3c77232 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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
diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
index fc8c238..67df170 100644
--- a/examples/ipsec-secgw/parser.c
+++ b/examples/ipsec-secgw/parser.c
@@ -642,6 +642,8 @@ parse_cfg_file(const char *cfg_filename)
cmdline_stdin_exit(cl);
fclose(f);
+ sa_sort_arr();
+
return 0;
error_exit:
diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
index 6b8a100..1f8bd3e 100644
--- a/examples/ipsec-secgw/parser.h
+++ b/examples/ipsec-secgw/parser.h
@@ -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);
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index d10a6ec..b3b83e3 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -133,11 +133,15 @@ const struct supported_aead_algo aead_algos[] = {
}
};
-static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
+#define SA_INIT_NB 128
+
+static struct ipsec_sa *sa_out;
+static uint32_t sa_out_sz;
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 ipsec_sa *sa_in;
+static uint32_t sa_in_sz;
static uint32_t nb_sa_in;
static struct ipsec_sa_cnt sa_in_cnt;
@@ -224,6 +228,31 @@ parse_key_string(const char *key_str, uint8_t *key)
return nb_bytes;
}
+static int
+extend_sa_arr(struct ipsec_sa **sa_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sa_tbl == NULL) {
+ *sa_tbl = calloc(SA_INIT_NB, sizeof(struct ipsec_sa));
+ if (*sa_tbl == NULL)
+ return -1;
+ *cur_sz = SA_INIT_NB;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sa_tbl = realloc(*sa_tbl,
+ *cur_sz * sizeof(struct ipsec_sa) * 2);
+ if (*sa_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sa_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct ipsec_sa));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
+
void
parse_sa_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status)
@@ -246,23 +275,15 @@ 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");
- if (status->status < 0)
+ if (extend_sa_arr(&sa_in, nb_sa_in, &sa_in_sz) < 0)
return;
-
rule = &sa_in[*ri];
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)
+ if (extend_sa_arr(&sa_out, nb_sa_out, &sa_out_sz) < 0)
return;
-
rule = &sa_out[*ri];
rule->direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
}
@@ -1311,13 +1332,24 @@ ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket)
return rc;
}
+static int
+sa_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct ipsec_sa *)p)->spi;
+ uint32_t spi2 = ((const struct ipsec_sa *)q)->spi;
+
+ return (int)(spi1 - spi2);
+}
+
/*
* Walk through all SA rules to find an SA with given SPI
*/
int
sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
{
- uint32_t i, num;
+ uint32_t num;
+ struct ipsec_sa *sa;
+ struct ipsec_sa tmpl;
const struct ipsec_sa *sar;
sar = sa_ctx->sa;
@@ -1326,10 +1358,11 @@ sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
else
num = nb_sa_out;
- for (i = 0; i != num; i++) {
- if (sar[i].spi == spi)
- return i;
- }
+ tmpl.spi = spi;
+
+ sa = bsearch(&tmpl, sar, num, sizeof(struct ipsec_sa), sa_cmp);
+ if (sa != NULL)
+ return RTE_PTR_DIFF(sa, sar) / sizeof(struct ipsec_sa);
return -ENOENT;
}
@@ -1522,3 +1555,10 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
}
return 0;
}
+
+void
+sa_sort_arr(void)
+{
+ qsort(sa_in, nb_sa_in, sizeof(struct ipsec_sa), sa_cmp);
+ qsort(sa_out, nb_sa_out, sizeof(struct ipsec_sa), sa_cmp);
+}
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v5 5/6] examples/ipsec-secgw: get rid of maximum sp limitation
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
` (5 preceding siblings ...)
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 4/6] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
@ 2020-01-29 14:06 ` Vladimir Medvedkin
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 6/6] examples/ipsec-secgw: add SAD cache Vladimir Medvedkin
7 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-29 14:06 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
Get rid of maximum SP limitation.
Keep parsed SP's into the sorted by SPI value array.
Use binary search in the sorted SP array to find appropriate SP
for a given SPI.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
examples/ipsec-secgw/parser.c | 2 +
examples/ipsec-secgw/parser.h | 6 +++
examples/ipsec-secgw/sp4.c | 90 +++++++++++++++++++++++++++++++++----------
examples/ipsec-secgw/sp6.c | 88 ++++++++++++++++++++++++++++++++----------
4 files changed, 144 insertions(+), 42 deletions(-)
diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
index 67df170..65eb7e9 100644
--- a/examples/ipsec-secgw/parser.c
+++ b/examples/ipsec-secgw/parser.c
@@ -643,6 +643,8 @@ parse_cfg_file(const char *cfg_filename)
fclose(f);
sa_sort_arr();
+ sp4_sort_arr();
+ sp6_sort_arr();
return 0;
diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
index 1f8bd3e..6e764fe 100644
--- a/examples/ipsec-secgw/parser.h
+++ b/examples/ipsec-secgw/parser.h
@@ -67,10 +67,16 @@ int
parse_range(const char *token, uint16_t *low, uint16_t *high);
void
+sp4_sort_arr(void);
+
+void
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status);
void
+sp6_sort_arr(void);
+
+void
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status);
diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c
index 1dcec52..beddd7b 100644
--- a/examples/ipsec-secgw/sp4.c
+++ b/examples/ipsec-secgw/sp4.c
@@ -15,7 +15,7 @@
#include "ipsec.h"
#include "parser.h"
-#define MAX_ACL_RULE_NUM 1024
+#define INIT_ACL_RULE_NUM 128
#define IPV4_DST_FROM_SP(acr) \
(rte_cpu_to_be_32((acr).field[DST_FIELD_IPV4].value.u32))
@@ -97,11 +97,39 @@ static struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = {
RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs));
-static struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM];
+static struct acl4_rules *acl4_rules_out;
static uint32_t nb_acl4_rules_out;
+static uint32_t sp_out_sz;
-static struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM];
+static struct acl4_rules *acl4_rules_in;
static uint32_t nb_acl4_rules_in;
+static uint32_t sp_in_sz;
+
+static int
+extend_sp_arr(struct acl4_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sp_tbl == NULL) {
+ *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl4_rules));
+ if (*sp_tbl == NULL)
+ return -1;
+ *cur_sz = INIT_ACL_RULE_NUM;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sp_tbl = realloc(*sp_tbl,
+ *cur_sz * sizeof(struct acl4_rules) * 2);
+ if (*sp_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sp_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct acl4_rules));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
+
void
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
@@ -127,9 +155,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
if (strcmp(tokens[1], "in") == 0) {
ri = &nb_acl4_rules_in;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
- "too many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl4_rules_in, nb_acl4_rules_in,
+ &sp_in_sz) < 0)
return;
rule_ipv4 = &acl4_rules_in[*ri];
@@ -137,9 +164,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
} else if (strcmp(tokens[1], "out") == 0) {
ri = &nb_acl4_rules_out;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
- "too many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl4_rules_out, nb_acl4_rules_out,
+ &sp_out_sz) < 0)
return;
rule_ipv4 = &acl4_rules_out[*ri];
@@ -451,7 +477,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
struct rte_acl_config acl_build_param;
struct rte_acl_ctx *ctx;
- printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
+ printf("Creating SP context with %u rules\n", rules_nb);
memset(&acl_param, 0, sizeof(acl_param));
@@ -464,7 +490,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
acl_param.name = s;
acl_param.socket_id = socketid;
acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip4_defs));
- acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+ acl_param.max_rule_num = rules_nb;
ctx = rte_acl_create(&acl_param);
if (ctx == NULL)
@@ -566,6 +592,16 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id)
"specified\n");
}
+static int
+sp_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct acl4_rules *)p)->data.userdata;
+ uint32_t spi2 = ((const struct acl4_rules *)q)->data.userdata;
+
+ return (int)(spi1 - spi2);
+}
+
+
/*
* Search though SP rules for given SPI.
*/
@@ -573,8 +609,10 @@ int
sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
uint32_t mask[2])
{
- uint32_t i, num;
+ uint32_t num;
+ struct acl4_rules *rule;
const struct acl4_rules *acr;
+ struct acl4_rules tmpl;
if (inbound != 0) {
acr = acl4_rules_in;
@@ -584,17 +622,27 @@ sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
num = nb_acl4_rules_out;
}
- for (i = 0; i != num; i++) {
- if (acr[i].data.userdata == spi) {
- if (NULL != ip_addr && NULL != mask) {
- ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(acr[i]);
- ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(acr[i]);
- mask[0] = IPV4_SRC_MASK_FROM_SP(acr[i]);
- mask[1] = IPV4_DST_MASK_FROM_SP(acr[i]);
- }
- return i;
+ tmpl.data.userdata = spi;
+
+ rule = bsearch(&tmpl, acr, num, sizeof(struct acl4_rules), sp_cmp);
+ if (rule != NULL) {
+ if (NULL != ip_addr && NULL != mask) {
+ ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(*rule);
+ ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(*rule);
+ mask[0] = IPV4_SRC_MASK_FROM_SP(*rule);
+ mask[1] = IPV4_DST_MASK_FROM_SP(*rule);
}
+ return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl4_rules);
}
return -ENOENT;
}
+
+void
+sp4_sort_arr(void)
+{
+ qsort(acl4_rules_in, nb_acl4_rules_in, sizeof(struct acl4_rules),
+ sp_cmp);
+ qsort(acl4_rules_out, nb_acl4_rules_out, sizeof(struct acl4_rules),
+ sp_cmp);
+}
diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c
index b489e15..328e085 100644
--- a/examples/ipsec-secgw/sp6.c
+++ b/examples/ipsec-secgw/sp6.c
@@ -15,7 +15,7 @@
#include "ipsec.h"
#include "parser.h"
-#define MAX_ACL_RULE_NUM 1024
+#define INIT_ACL_RULE_NUM 128
#define IPV6_FROM_SP(acr, fidx_low, fidx_high) \
(((uint64_t)(acr).field[(fidx_high)].value.u32 << 32) | \
@@ -146,11 +146,38 @@ static struct rte_acl_field_def ip6_defs[IP6_NUM] = {
RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
-static struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM];
+static struct acl6_rules *acl6_rules_out;
static uint32_t nb_acl6_rules_out;
+static uint32_t sp_out_sz;
-static struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM];
+static struct acl6_rules *acl6_rules_in;
static uint32_t nb_acl6_rules_in;
+static uint32_t sp_in_sz;
+
+static int
+extend_sp_arr(struct acl6_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sp_tbl == NULL) {
+ *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl6_rules));
+ if (*sp_tbl == NULL)
+ return -1;
+ *cur_sz = INIT_ACL_RULE_NUM;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sp_tbl = realloc(*sp_tbl,
+ *cur_sz * sizeof(struct acl6_rules) * 2);
+ if (*sp_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sp_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct acl6_rules));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
void
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
@@ -176,9 +203,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
if (strcmp(tokens[1], "in") == 0) {
ri = &nb_acl6_rules_in;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl6_rules_in, nb_acl6_rules_in,
+ &sp_in_sz) < 0)
return;
rule_ipv6 = &acl6_rules_in[*ri];
@@ -186,9 +212,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
} else if (strcmp(tokens[1], "out") == 0) {
ri = &nb_acl6_rules_out;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl6_rules_out, nb_acl6_rules_out,
+ &sp_out_sz) < 0)
return;
rule_ipv6 = &acl6_rules_out[*ri];
@@ -583,7 +608,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
struct rte_acl_config acl_build_param;
struct rte_acl_ctx *ctx;
- printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
+ printf("Creating SP context with %u rules\n", rules_nb);
memset(&acl_param, 0, sizeof(acl_param));
@@ -596,7 +621,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
acl_param.name = s;
acl_param.socket_id = socketid;
acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs));
- acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+ acl_param.max_rule_num = rules_nb;
ctx = rte_acl_create(&acl_param);
if (ctx == NULL)
@@ -698,6 +723,15 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
"specified\n");
}
+static int
+sp_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct acl6_rules *)p)->data.userdata;
+ uint32_t spi2 = ((const struct acl6_rules *)q)->data.userdata;
+
+ return (int)(spi1 - spi2);
+}
+
/*
* Search though SP rules for given SPI.
*/
@@ -705,8 +739,10 @@ int
sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
uint32_t mask[2])
{
- uint32_t i, num;
+ uint32_t num;
+ struct acl6_rules *rule;
const struct acl6_rules *acr;
+ struct acl6_rules tmpl;
if (inbound != 0) {
acr = acl6_rules_in;
@@ -716,17 +752,27 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
num = nb_acl6_rules_out;
}
- for (i = 0; i != num; i++) {
- if (acr[i].data.userdata == spi) {
- if (NULL != ip_addr && NULL != mask) {
- IPV6_SRC_FROM_SP(ip_addr[0], acr[i]);
- IPV6_DST_FROM_SP(ip_addr[1], acr[i]);
- IPV6_SRC_MASK_FROM_SP(mask[0], acr[i]);
- IPV6_DST_MASK_FROM_SP(mask[1], acr[i]);
- }
- return i;
+ tmpl.data.userdata = spi;
+
+ rule = bsearch(&tmpl, acr, num, sizeof(struct acl6_rules), sp_cmp);
+ if (rule != NULL) {
+ if (NULL != ip_addr && NULL != mask) {
+ IPV6_SRC_FROM_SP(ip_addr[0], *rule);
+ IPV6_DST_FROM_SP(ip_addr[1], *rule);
+ IPV6_SRC_MASK_FROM_SP(mask[0], *rule);
+ IPV6_DST_MASK_FROM_SP(mask[1], *rule);
}
+ return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl6_rules);
}
return -ENOENT;
}
+
+void
+sp6_sort_arr(void)
+{
+ qsort(acl6_rules_in, nb_acl6_rules_in, sizeof(struct acl6_rules),
+ sp_cmp);
+ qsort(acl6_rules_out, nb_acl6_rules_out, sizeof(struct acl6_rules),
+ sp_cmp);
+}
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v5 6/6] examples/ipsec-secgw: add SAD cache
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
` (6 preceding siblings ...)
2020-01-29 14:06 ` [dpdk-dev] [PATCH v5 5/6] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
@ 2020-01-29 14:06 ` Vladimir Medvedkin
7 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-29 14:06 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
Introduce SAD cache.
Stores the most recent SA in a per lcore cache.
Cache represents flat array containing SA's indexed by SPI.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
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(-)
diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 3e5f82e..32ecd26 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -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) {
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 3c77232..4f2fd61 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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 */
};
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index b3b83e3..099a11b 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -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;
}
}
diff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c
index fd31101..5b2c0e6 100644
--- a/examples/ipsec-secgw/sad.c
+++ b/examples/ipsec-secgw/sad.c
@@ -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)
diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h
index 29ed0f8..81a6ff2 100644
--- a/examples/ipsec-secgw/sad.h
+++ b/examples/ipsec-secgw/sad.h
@@ -7,6 +7,17 @@
#include <rte_ipsec_sad.h>
+#define SA_CACHE_SZ 128
+#define SPI2IDX(spi, mask) ((spi) & (mask))
+
+struct ipsec_sad_cache {
+ struct ipsec_sa **v4;
+ struct ipsec_sa **v6;
+ uint32_t mask;
+};
+
+RTE_DECLARE_PER_LCORE(struct ipsec_sad_cache, sad_cache);
+
struct ipsec_sad {
struct rte_ipsec_sad *sad_v4;
struct rte_ipsec_sad *sad_v6;
@@ -17,8 +28,42 @@ int ipsec_sad_create(const char *name, struct ipsec_sad *sad,
int ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa);
+int ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent);
+
+static inline int
+cmp_sa_key(struct ipsec_sa *sa, int is_v4, struct rte_ipv4_hdr *ipv4,
+ struct rte_ipv6_hdr *ipv6)
+{
+ int sa_type = WITHOUT_TRANSPORT_VERSION(sa->flags);
+ if ((sa_type == TRANSPORT) ||
+ /* IPv4 check */
+ (is_v4 && (sa_type == IP4_TUNNEL) &&
+ (sa->src.ip.ip4 == ipv4->src_addr) &&
+ (sa->dst.ip.ip4 == ipv4->dst_addr)) ||
+ /* IPv6 check */
+ (!is_v4 && (sa_type == IP6_TUNNEL) &&
+ (!memcmp(sa->src.ip.ip6.ip6, ipv6->src_addr, 16)) &&
+ (!memcmp(sa->dst.ip.ip6.ip6, ipv6->dst_addr, 16))))
+ return 1;
+
+ return 0;
+}
+
static inline void
-sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
+sa_cache_update(struct ipsec_sa **sa_cache, struct ipsec_sa *sa, uint32_t mask)
+{
+ uint32_t cache_idx;
+
+ /* SAD cache is disabled */
+ if (mask == 0)
+ return;
+
+ cache_idx = SPI2IDX(sa->spi, mask);
+ sa_cache[cache_idx] = sa;
+}
+
+static inline void
+sad_lookup(struct ipsec_sad *sad, struct rte_mbuf *pkts[],
void *sa[], uint16_t nb_pkts)
{
uint32_t i;
@@ -34,13 +79,39 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
const union rte_ipsec_sad_key *keys_v6[nb_pkts];
void *v4_res[nb_pkts];
void *v6_res[nb_pkts];
+ uint32_t spi, cache_idx;
+ struct ipsec_sad_cache *cache;
+ struct ipsec_sa *cached_sa;
+ int is_ipv4;
+
+ cache = &RTE_PER_LCORE(sad_cache);
/* split received packets by address family into two arrays */
for (i = 0; i < nb_pkts; i++) {
ipv4 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv4_hdr *);
+ ipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *);
esp = rte_pktmbuf_mtod_offset(pkts[i], struct rte_esp_hdr *,
pkts[i]->l3_len);
- if ((ipv4->version_ihl >> 4) == IPVERSION) {
+
+ is_ipv4 = ((ipv4->version_ihl >> 4) == IPVERSION);
+ spi = rte_be_to_cpu_32(esp->spi);
+ cache_idx = SPI2IDX(spi, cache->mask);
+
+ if (is_ipv4) {
+ cached_sa = (cache->mask != 0) ?
+ cache->v4[cache_idx] : NULL;
+ /* check SAD cache entry */
+ if ((cached_sa != NULL) && (cached_sa->spi == spi)) {
+ if (cmp_sa_key(cached_sa, 1, ipv4, ipv6)) {
+ /* cache hit */
+ sa[i] = cached_sa;
+ continue;
+ }
+ }
+ /*
+ * cache miss
+ * preparing sad key to proceed with sad lookup
+ */
v4[nb_v4].spi = esp->spi;
v4[nb_v4].dip = ipv4->dst_addr;
v4[nb_v4].sip = ipv4->src_addr;
@@ -48,7 +119,14 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
&v4[nb_v4];
v4_idxes[nb_v4++] = i;
} else {
- ipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *);
+ cached_sa = (cache->mask != 0) ?
+ cache->v6[cache_idx] : NULL;
+ if ((cached_sa != NULL) && (cached_sa->spi == spi)) {
+ if (cmp_sa_key(cached_sa, 0, ipv4, ipv6)) {
+ sa[i] = cached_sa;
+ continue;
+ }
+ }
v6[nb_v6].spi = esp->spi;
memcpy(v6[nb_v6].dip, ipv6->dst_addr,
sizeof(ipv6->dst_addr));
@@ -65,11 +143,26 @@ sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[],
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];
+ for (i = 0; i < nb_v4; i++) {
+ ipv4 = rte_pktmbuf_mtod(pkts[v4_idxes[i]],
+ struct rte_ipv4_hdr *);
+ if (cmp_sa_key(v4_res[i], 1, ipv4, NULL)) {
+ sa[v4_idxes[i]] = v4_res[i];
+ sa_cache_update(cache->v4, (struct ipsec_sa *)v4_res[i],
+ cache->mask);
+ } else
+ sa[v4_idxes[i]] = NULL;
+ }
+ for (i = 0; i < nb_v6; i++) {
+ ipv6 = rte_pktmbuf_mtod(pkts[v6_idxes[i]],
+ struct rte_ipv6_hdr *);
+ if (cmp_sa_key(v6_res[i], 0, NULL, ipv6)) {
+ sa[v6_idxes[i]] = v6_res[i];
+ sa_cache_update(cache->v6, (struct ipsec_sa *)v6_res[i],
+ cache->mask);
+ } else
+ sa[v6_idxes[i]] = NULL;
+ }
}
#endif /* __SAD_H__ */
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v4 1/5] ipsec: move ipsec sad name length into .h
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
@ 2020-01-14 14:27 ` Vladimir Medvedkin
2020-01-14 15:51 ` Ananyev, Konstantin
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 2/5] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
` (3 subsequent siblings)
5 siblings, 1 reply; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-14 14:27 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] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v4 1/5] ipsec: move ipsec sad name length into .h
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 1/5] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
@ 2020-01-14 15:51 ` Ananyev, Konstantin
0 siblings, 0 replies; 60+ messages in thread
From: Ananyev, Konstantin @ 2020-01-14 15:51 UTC (permalink / raw)
To: Medvedkin, Vladimir, dev; +Cc: akhil.goyal
> -----Original Message-----
> From: Medvedkin, Vladimir <vladimir.medvedkin@intel.com>
> Sent: Tuesday, January 14, 2020 2:27 PM
> To: dev@dpdk.org
> Cc: Ananyev, Konstantin <konstantin.ananyev@intel.com>; akhil.goyal@nxp.com
> Subject: [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
>
> Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> ---
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> --
> 2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v4 2/5] examples/ipsec-secgw: implement inbound SAD
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 " Vladimir Medvedkin
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 1/5] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
@ 2020-01-14 14:27 ` Vladimir Medvedkin
2020-01-14 15:53 ` Ananyev, Konstantin
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 3/5] examples/ipsec-secgw: integrate " Vladimir Medvedkin
` (2 subsequent siblings)
5 siblings, 1 reply; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-14 14:27 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 | 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
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8e07521..9ddb5d9 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
diff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c
new file mode 100644
index 0000000..a193172
--- /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:
+ ret = rte_ipsec_sad_add(sad->sad_v4, &key,
+ RTE_IPSEC_SAD_SPI_ONLY, sa);
+ if (ret != 0)
+ return ret;
+ break;
+ case IP6_TUNNEL:
+ ret = rte_ipsec_sad_add(sad->sad_v6, &key,
+ RTE_IPSEC_SAD_SPI_ONLY, 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];
+
+ if ((name == NULL) || (sad == NULL) || (sa_cnt == NULL))
+ return -EINVAL;
+
+ 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_v4 * 5 / 4;
+ sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
+ sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
+
+ if (sa_cnt->nb_v4 != 0) {
+ 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_ONLY] = sa_cnt->nb_v6 * 5 / 4;
+
+ if (sa_cnt->nb_v6 != 0) {
+ 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] 60+ messages in thread
* [dpdk-dev] [PATCH v4 3/5] examples/ipsec-secgw: integrate inbound SAD
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
` (2 preceding siblings ...)
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 2/5] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
@ 2020-01-14 14:27 ` Vladimir Medvedkin
2020-01-14 15:54 ` Ananyev, Konstantin
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 4/5] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 5/5] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
5 siblings, 1 reply; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-14 14:27 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 | 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(-)
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 9ddb5d9..5988d59 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
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..d10a6ec 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,17 @@ 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++;
rule->flags = IP4_TUNNEL;
- else if (strcmp(tokens[ti], "ipv6-tunnel") == 0)
+ } else if (strcmp(tokens[ti], "ipv6-tunnel") == 0) {
+ sa_cnt->nb_v6++;
rule->flags = IP6_TUNNEL;
- else if (strcmp(tokens[ti], "transport") == 0)
+ } else if (strcmp(tokens[ti], "transport") == 0) {
+ sa_cnt->nb_v4++;
+ sa_cnt->nb_v6++;
rule->flags = TRANSPORT;
- else {
+ } else {
APP_CHECK(0, status, "unrecognized "
"input \"%s\"", tokens[ti]);
return;
@@ -772,19 +782,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 +805,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 +972,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 +980,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 +1267,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 +1277,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 +1300,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 +1315,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 +1353,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 +1378,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 +1387,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 +1413,18 @@ 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_arr[], uint16_t nb_pkts)
{
- struct rte_esp_hdr *esp;
+ uint32_t i;
struct ip *ip;
uint32_t *src4_addr;
uint8_t *src6_addr;
- struct ipsec_sa *sa;
void *result_sa;
+ struct ipsec_sa *sa;
- *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_arr, nb_pkts);
/*
* Mark need for inline offload fallback on the LSB of SA pointer.
@@ -1413,43 +1435,47 @@ 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 (sa_arr[i] == NULL)
+ continue;
- 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) &&
+ result_sa = sa = sa_arr[i];
+ if (MBUF_NO_SEC_OFFLOAD(pkts[i]) &&
+ sa->fallback_sessions > 0) {
+ uintptr_t intsa = (uintptr_t)sa;
+ 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_ret = result_sa;
- break;
- case TRANSPORT:
- *sa_ret = result_sa;
+ sa_arr[i] = result_sa;
+ else
+ sa_arr[i] = NULL;
+ break;
+ case TRANSPORT:
+ sa_arr[i] = 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
outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
void *sa[], uint16_t nb_pkts)
{
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] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v4 3/5] examples/ipsec-secgw: integrate inbound SAD
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 3/5] examples/ipsec-secgw: integrate " Vladimir Medvedkin
@ 2020-01-14 15:54 ` Ananyev, Konstantin
0 siblings, 0 replies; 60+ messages in thread
From: Ananyev, Konstantin @ 2020-01-14 15:54 UTC (permalink / raw)
To: Medvedkin, Vladimir, dev; +Cc: akhil.goyal
> -----Original Message-----
> From: Medvedkin, Vladimir <vladimir.medvedkin@intel.com>
> Sent: Tuesday, January 14, 2020 2:27 PM
> To: dev@dpdk.org
> Cc: Ananyev, Konstantin <konstantin.ananyev@intel.com>; akhil.goyal@nxp.com
> 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
>
> Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> ---
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> 2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v4 4/5] examples/ipsec-secgw: get rid of maximum sa limitation
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
` (3 preceding siblings ...)
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 3/5] examples/ipsec-secgw: integrate " Vladimir Medvedkin
@ 2020-01-14 14:27 ` Vladimir Medvedkin
2020-01-14 15:56 ` Ananyev, Konstantin
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 5/5] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
5 siblings, 1 reply; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-14 14:27 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
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.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
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(-)
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 5988d59..3c77232 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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
diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
index fc8c238..67df170 100644
--- a/examples/ipsec-secgw/parser.c
+++ b/examples/ipsec-secgw/parser.c
@@ -642,6 +642,8 @@ parse_cfg_file(const char *cfg_filename)
cmdline_stdin_exit(cl);
fclose(f);
+ sa_sort_arr();
+
return 0;
error_exit:
diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
index 6b8a100..1f8bd3e 100644
--- a/examples/ipsec-secgw/parser.h
+++ b/examples/ipsec-secgw/parser.h
@@ -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);
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index d10a6ec..b3b83e3 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -133,11 +133,15 @@ const struct supported_aead_algo aead_algos[] = {
}
};
-static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
+#define SA_INIT_NB 128
+
+static struct ipsec_sa *sa_out;
+static uint32_t sa_out_sz;
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 ipsec_sa *sa_in;
+static uint32_t sa_in_sz;
static uint32_t nb_sa_in;
static struct ipsec_sa_cnt sa_in_cnt;
@@ -224,6 +228,31 @@ parse_key_string(const char *key_str, uint8_t *key)
return nb_bytes;
}
+static int
+extend_sa_arr(struct ipsec_sa **sa_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sa_tbl == NULL) {
+ *sa_tbl = calloc(SA_INIT_NB, sizeof(struct ipsec_sa));
+ if (*sa_tbl == NULL)
+ return -1;
+ *cur_sz = SA_INIT_NB;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sa_tbl = realloc(*sa_tbl,
+ *cur_sz * sizeof(struct ipsec_sa) * 2);
+ if (*sa_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sa_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct ipsec_sa));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
+
void
parse_sa_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status)
@@ -246,23 +275,15 @@ 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");
- if (status->status < 0)
+ if (extend_sa_arr(&sa_in, nb_sa_in, &sa_in_sz) < 0)
return;
-
rule = &sa_in[*ri];
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)
+ if (extend_sa_arr(&sa_out, nb_sa_out, &sa_out_sz) < 0)
return;
-
rule = &sa_out[*ri];
rule->direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
}
@@ -1311,13 +1332,24 @@ ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket)
return rc;
}
+static int
+sa_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct ipsec_sa *)p)->spi;
+ uint32_t spi2 = ((const struct ipsec_sa *)q)->spi;
+
+ return (int)(spi1 - spi2);
+}
+
/*
* Walk through all SA rules to find an SA with given SPI
*/
int
sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
{
- uint32_t i, num;
+ uint32_t num;
+ struct ipsec_sa *sa;
+ struct ipsec_sa tmpl;
const struct ipsec_sa *sar;
sar = sa_ctx->sa;
@@ -1326,10 +1358,11 @@ sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
else
num = nb_sa_out;
- for (i = 0; i != num; i++) {
- if (sar[i].spi == spi)
- return i;
- }
+ tmpl.spi = spi;
+
+ sa = bsearch(&tmpl, sar, num, sizeof(struct ipsec_sa), sa_cmp);
+ if (sa != NULL)
+ return RTE_PTR_DIFF(sa, sar) / sizeof(struct ipsec_sa);
return -ENOENT;
}
@@ -1522,3 +1555,10 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
}
return 0;
}
+
+void
+sa_sort_arr(void)
+{
+ qsort(sa_in, nb_sa_in, sizeof(struct ipsec_sa), sa_cmp);
+ qsort(sa_out, nb_sa_out, sizeof(struct ipsec_sa), sa_cmp);
+}
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* Re: [dpdk-dev] [PATCH v4 4/5] examples/ipsec-secgw: get rid of maximum sa limitation
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 4/5] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
@ 2020-01-14 15:56 ` Ananyev, Konstantin
0 siblings, 0 replies; 60+ messages in thread
From: Ananyev, Konstantin @ 2020-01-14 15:56 UTC (permalink / raw)
To: Medvedkin, Vladimir, dev; +Cc: akhil.goyal
> -----Original Message-----
> From: Medvedkin, Vladimir <vladimir.medvedkin@intel.com>
> Sent: Tuesday, January 14, 2020 2:27 PM
> To: dev@dpdk.org
> Cc: Ananyev, Konstantin <konstantin.ananyev@intel.com>; akhil.goyal@nxp.com
> Subject: [PATCH v4 4/5] examples/ipsec-secgw: get rid of maximum sa limitation
>
> 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.
>
> Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
> ---
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
> 2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v4 5/5] examples/ipsec-secgw: get rid of maximum sp limitation
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
` (4 preceding siblings ...)
2020-01-14 14:27 ` [dpdk-dev] [PATCH v4 4/5] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
@ 2020-01-14 14:27 ` Vladimir Medvedkin
2020-01-14 15:57 ` Ananyev, Konstantin
5 siblings, 1 reply; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-14 14:27 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
Get rid of maximum SP limitation.
Keep parsed SP's into the sorted by SPI value array.
Use binary search in the sorted SP array to find appropriate SP
for a given SPI.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
examples/ipsec-secgw/parser.c | 2 +
examples/ipsec-secgw/parser.h | 6 +++
examples/ipsec-secgw/sp4.c | 90 +++++++++++++++++++++++++++++++++----------
examples/ipsec-secgw/sp6.c | 88 ++++++++++++++++++++++++++++++++----------
4 files changed, 144 insertions(+), 42 deletions(-)
diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
index 67df170..65eb7e9 100644
--- a/examples/ipsec-secgw/parser.c
+++ b/examples/ipsec-secgw/parser.c
@@ -643,6 +643,8 @@ parse_cfg_file(const char *cfg_filename)
fclose(f);
sa_sort_arr();
+ sp4_sort_arr();
+ sp6_sort_arr();
return 0;
diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
index 1f8bd3e..6e764fe 100644
--- a/examples/ipsec-secgw/parser.h
+++ b/examples/ipsec-secgw/parser.h
@@ -67,10 +67,16 @@ int
parse_range(const char *token, uint16_t *low, uint16_t *high);
void
+sp4_sort_arr(void);
+
+void
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status);
void
+sp6_sort_arr(void);
+
+void
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status);
diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c
index 1dcec52..beddd7b 100644
--- a/examples/ipsec-secgw/sp4.c
+++ b/examples/ipsec-secgw/sp4.c
@@ -15,7 +15,7 @@
#include "ipsec.h"
#include "parser.h"
-#define MAX_ACL_RULE_NUM 1024
+#define INIT_ACL_RULE_NUM 128
#define IPV4_DST_FROM_SP(acr) \
(rte_cpu_to_be_32((acr).field[DST_FIELD_IPV4].value.u32))
@@ -97,11 +97,39 @@ static struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = {
RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs));
-static struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM];
+static struct acl4_rules *acl4_rules_out;
static uint32_t nb_acl4_rules_out;
+static uint32_t sp_out_sz;
-static struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM];
+static struct acl4_rules *acl4_rules_in;
static uint32_t nb_acl4_rules_in;
+static uint32_t sp_in_sz;
+
+static int
+extend_sp_arr(struct acl4_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sp_tbl == NULL) {
+ *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl4_rules));
+ if (*sp_tbl == NULL)
+ return -1;
+ *cur_sz = INIT_ACL_RULE_NUM;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sp_tbl = realloc(*sp_tbl,
+ *cur_sz * sizeof(struct acl4_rules) * 2);
+ if (*sp_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sp_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct acl4_rules));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
+
void
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
@@ -127,9 +155,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
if (strcmp(tokens[1], "in") == 0) {
ri = &nb_acl4_rules_in;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
- "too many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl4_rules_in, nb_acl4_rules_in,
+ &sp_in_sz) < 0)
return;
rule_ipv4 = &acl4_rules_in[*ri];
@@ -137,9 +164,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
} else if (strcmp(tokens[1], "out") == 0) {
ri = &nb_acl4_rules_out;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
- "too many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl4_rules_out, nb_acl4_rules_out,
+ &sp_out_sz) < 0)
return;
rule_ipv4 = &acl4_rules_out[*ri];
@@ -451,7 +477,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
struct rte_acl_config acl_build_param;
struct rte_acl_ctx *ctx;
- printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
+ printf("Creating SP context with %u rules\n", rules_nb);
memset(&acl_param, 0, sizeof(acl_param));
@@ -464,7 +490,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
acl_param.name = s;
acl_param.socket_id = socketid;
acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip4_defs));
- acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+ acl_param.max_rule_num = rules_nb;
ctx = rte_acl_create(&acl_param);
if (ctx == NULL)
@@ -566,6 +592,16 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id)
"specified\n");
}
+static int
+sp_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct acl4_rules *)p)->data.userdata;
+ uint32_t spi2 = ((const struct acl4_rules *)q)->data.userdata;
+
+ return (int)(spi1 - spi2);
+}
+
+
/*
* Search though SP rules for given SPI.
*/
@@ -573,8 +609,10 @@ int
sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
uint32_t mask[2])
{
- uint32_t i, num;
+ uint32_t num;
+ struct acl4_rules *rule;
const struct acl4_rules *acr;
+ struct acl4_rules tmpl;
if (inbound != 0) {
acr = acl4_rules_in;
@@ -584,17 +622,27 @@ sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
num = nb_acl4_rules_out;
}
- for (i = 0; i != num; i++) {
- if (acr[i].data.userdata == spi) {
- if (NULL != ip_addr && NULL != mask) {
- ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(acr[i]);
- ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(acr[i]);
- mask[0] = IPV4_SRC_MASK_FROM_SP(acr[i]);
- mask[1] = IPV4_DST_MASK_FROM_SP(acr[i]);
- }
- return i;
+ tmpl.data.userdata = spi;
+
+ rule = bsearch(&tmpl, acr, num, sizeof(struct acl4_rules), sp_cmp);
+ if (rule != NULL) {
+ if (NULL != ip_addr && NULL != mask) {
+ ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(*rule);
+ ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(*rule);
+ mask[0] = IPV4_SRC_MASK_FROM_SP(*rule);
+ mask[1] = IPV4_DST_MASK_FROM_SP(*rule);
}
+ return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl4_rules);
}
return -ENOENT;
}
+
+void
+sp4_sort_arr(void)
+{
+ qsort(acl4_rules_in, nb_acl4_rules_in, sizeof(struct acl4_rules),
+ sp_cmp);
+ qsort(acl4_rules_out, nb_acl4_rules_out, sizeof(struct acl4_rules),
+ sp_cmp);
+}
diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c
index b489e15..328e085 100644
--- a/examples/ipsec-secgw/sp6.c
+++ b/examples/ipsec-secgw/sp6.c
@@ -15,7 +15,7 @@
#include "ipsec.h"
#include "parser.h"
-#define MAX_ACL_RULE_NUM 1024
+#define INIT_ACL_RULE_NUM 128
#define IPV6_FROM_SP(acr, fidx_low, fidx_high) \
(((uint64_t)(acr).field[(fidx_high)].value.u32 << 32) | \
@@ -146,11 +146,38 @@ static struct rte_acl_field_def ip6_defs[IP6_NUM] = {
RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
-static struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM];
+static struct acl6_rules *acl6_rules_out;
static uint32_t nb_acl6_rules_out;
+static uint32_t sp_out_sz;
-static struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM];
+static struct acl6_rules *acl6_rules_in;
static uint32_t nb_acl6_rules_in;
+static uint32_t sp_in_sz;
+
+static int
+extend_sp_arr(struct acl6_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sp_tbl == NULL) {
+ *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl6_rules));
+ if (*sp_tbl == NULL)
+ return -1;
+ *cur_sz = INIT_ACL_RULE_NUM;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sp_tbl = realloc(*sp_tbl,
+ *cur_sz * sizeof(struct acl6_rules) * 2);
+ if (*sp_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sp_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct acl6_rules));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
void
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
@@ -176,9 +203,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
if (strcmp(tokens[1], "in") == 0) {
ri = &nb_acl6_rules_in;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl6_rules_in, nb_acl6_rules_in,
+ &sp_in_sz) < 0)
return;
rule_ipv6 = &acl6_rules_in[*ri];
@@ -186,9 +212,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
} else if (strcmp(tokens[1], "out") == 0) {
ri = &nb_acl6_rules_out;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl6_rules_out, nb_acl6_rules_out,
+ &sp_out_sz) < 0)
return;
rule_ipv6 = &acl6_rules_out[*ri];
@@ -583,7 +608,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
struct rte_acl_config acl_build_param;
struct rte_acl_ctx *ctx;
- printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
+ printf("Creating SP context with %u rules\n", rules_nb);
memset(&acl_param, 0, sizeof(acl_param));
@@ -596,7 +621,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
acl_param.name = s;
acl_param.socket_id = socketid;
acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs));
- acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+ acl_param.max_rule_num = rules_nb;
ctx = rte_acl_create(&acl_param);
if (ctx == NULL)
@@ -698,6 +723,15 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
"specified\n");
}
+static int
+sp_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct acl6_rules *)p)->data.userdata;
+ uint32_t spi2 = ((const struct acl6_rules *)q)->data.userdata;
+
+ return (int)(spi1 - spi2);
+}
+
/*
* Search though SP rules for given SPI.
*/
@@ -705,8 +739,10 @@ int
sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
uint32_t mask[2])
{
- uint32_t i, num;
+ uint32_t num;
+ struct acl6_rules *rule;
const struct acl6_rules *acr;
+ struct acl6_rules tmpl;
if (inbound != 0) {
acr = acl6_rules_in;
@@ -716,17 +752,27 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
num = nb_acl6_rules_out;
}
- for (i = 0; i != num; i++) {
- if (acr[i].data.userdata == spi) {
- if (NULL != ip_addr && NULL != mask) {
- IPV6_SRC_FROM_SP(ip_addr[0], acr[i]);
- IPV6_DST_FROM_SP(ip_addr[1], acr[i]);
- IPV6_SRC_MASK_FROM_SP(mask[0], acr[i]);
- IPV6_DST_MASK_FROM_SP(mask[1], acr[i]);
- }
- return i;
+ tmpl.data.userdata = spi;
+
+ rule = bsearch(&tmpl, acr, num, sizeof(struct acl6_rules), sp_cmp);
+ if (rule != NULL) {
+ if (NULL != ip_addr && NULL != mask) {
+ IPV6_SRC_FROM_SP(ip_addr[0], *rule);
+ IPV6_DST_FROM_SP(ip_addr[1], *rule);
+ IPV6_SRC_MASK_FROM_SP(mask[0], *rule);
+ IPV6_DST_MASK_FROM_SP(mask[1], *rule);
}
+ return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl6_rules);
}
return -ENOENT;
}
+
+void
+sp6_sort_arr(void)
+{
+ qsort(acl6_rules_in, nb_acl6_rules_in, sizeof(struct acl6_rules),
+ sp_cmp);
+ qsort(acl6_rules_out, nb_acl6_rules_out, sizeof(struct acl6_rules),
+ sp_cmp);
+}
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v3 1/5] ipsec: move ipsec sad name length into .h
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 0/5] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
@ 2020-01-13 12:55 ` Vladimir Medvedkin
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 2/5] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
` (3 subsequent siblings)
5 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-13 12:55 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] 60+ messages in thread
* [dpdk-dev] [PATCH v3 2/5] examples/ipsec-secgw: implement inbound SAD
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 0/5] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 " Vladimir Medvedkin
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 1/5] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
@ 2020-01-13 12:55 ` Vladimir Medvedkin
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 3/5] examples/ipsec-secgw: integrate " Vladimir Medvedkin
` (2 subsequent siblings)
5 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-13 12:55 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 | 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
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..1445c48
--- /dev/null
+++ b/examples/ipsec-secgw/sad.c
@@ -0,0 +1,94 @@
+/* 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;
+
+ if ((sa_cnt->nb_trn != 0) || (sa_cnt->nb_v4_tun != 0)) {
+ 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;
+
+ if ((sa_cnt->nb_trn != 0) || (sa_cnt->nb_v6_tun != 0)) {
+ 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] 60+ messages in thread
* [dpdk-dev] [PATCH v3 3/5] examples/ipsec-secgw: integrate inbound SAD
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 0/5] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (2 preceding siblings ...)
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 2/5] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
@ 2020-01-13 12:55 ` Vladimir Medvedkin
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 4/5] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 5/5] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
5 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-13 12:55 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 | 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(-)
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..8ca6c2a 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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);
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] 60+ messages in thread
* [dpdk-dev] [PATCH v3 4/5] examples/ipsec-secgw: get rid of maximum sa limitation
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 0/5] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (3 preceding siblings ...)
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 3/5] examples/ipsec-secgw: integrate " Vladimir Medvedkin
@ 2020-01-13 12:55 ` Vladimir Medvedkin
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 5/5] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
5 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-13 12:55 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
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.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
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(-)
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 8ca6c2a..0475a54 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -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
diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
index fc8c238..67df170 100644
--- a/examples/ipsec-secgw/parser.c
+++ b/examples/ipsec-secgw/parser.c
@@ -642,6 +642,8 @@ parse_cfg_file(const char *cfg_filename)
cmdline_stdin_exit(cl);
fclose(f);
+ sa_sort_arr();
+
return 0;
error_exit:
diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
index 6b8a100..1f8bd3e 100644
--- a/examples/ipsec-secgw/parser.h
+++ b/examples/ipsec-secgw/parser.h
@@ -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);
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index 8cc7b17..7346337 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -133,11 +133,15 @@ const struct supported_aead_algo aead_algos[] = {
}
};
-static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
+#define SA_INIT_NB 128
+
+static struct ipsec_sa *sa_out;
+static uint32_t sa_out_sz;
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 ipsec_sa *sa_in;
+static uint32_t sa_in_sz;
static uint32_t nb_sa_in;
static struct ipsec_sa_cnt sa_in_cnt;
@@ -224,6 +228,31 @@ parse_key_string(const char *key_str, uint8_t *key)
return nb_bytes;
}
+static int
+extend_sa_arr(struct ipsec_sa **sa_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sa_tbl == NULL) {
+ *sa_tbl = calloc(SA_INIT_NB, sizeof(struct ipsec_sa));
+ if (*sa_tbl == NULL)
+ return -1;
+ *cur_sz = SA_INIT_NB;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sa_tbl = realloc(*sa_tbl,
+ *cur_sz * sizeof(struct ipsec_sa) * 2);
+ if (*sa_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sa_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct ipsec_sa));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
+
void
parse_sa_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status)
@@ -246,23 +275,15 @@ 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");
- if (status->status < 0)
+ if (extend_sa_arr(&sa_in, nb_sa_in, &sa_in_sz) < 0)
return;
-
rule = &sa_in[*ri];
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)
+ if (extend_sa_arr(&sa_out, nb_sa_out, &sa_out_sz) < 0)
return;
-
rule = &sa_out[*ri];
rule->direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
}
@@ -1310,13 +1331,24 @@ ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, int32_t socket)
return rc;
}
+static int
+sa_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct ipsec_sa *)p)->spi;
+ uint32_t spi2 = ((const struct ipsec_sa *)q)->spi;
+
+ return (int)(spi1 - spi2);
+}
+
/*
* Walk through all SA rules to find an SA with given SPI
*/
int
sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
{
- uint32_t i, num;
+ uint32_t num;
+ struct ipsec_sa *sa;
+ struct ipsec_sa tmpl;
const struct ipsec_sa *sar;
sar = sa_ctx->sa;
@@ -1325,10 +1357,11 @@ sa_spi_present(struct sa_ctx *sa_ctx, uint32_t spi, int inbound)
else
num = nb_sa_out;
- for (i = 0; i != num; i++) {
- if (sar[i].spi == spi)
- return i;
- }
+ tmpl.spi = spi;
+
+ sa = bsearch(&tmpl, sar, num, sizeof(struct ipsec_sa), sa_cmp);
+ if (sa != NULL)
+ return RTE_PTR_DIFF(sa, sar) / sizeof(struct ipsec_sa);
return -ENOENT;
}
@@ -1486,3 +1519,10 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
}
return 0;
}
+
+void
+sa_sort_arr(void)
+{
+ qsort(sa_in, nb_sa_in, sizeof(struct ipsec_sa), sa_cmp);
+ qsort(sa_out, nb_sa_out, sizeof(struct ipsec_sa), sa_cmp);
+}
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v3 5/5] examples/ipsec-secgw: get rid of maximum sp limitation
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 0/5] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (4 preceding siblings ...)
2020-01-13 12:55 ` [dpdk-dev] [PATCH v3 4/5] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
@ 2020-01-13 12:55 ` Vladimir Medvedkin
5 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2020-01-13 12:55 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
Get rid of maximum SP limitation.
Keep parsed SP's into the sorted by SPI value array.
Use binary search in the sorted SP array to find appropriate SP
for a given SPI.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
examples/ipsec-secgw/parser.c | 2 +
examples/ipsec-secgw/parser.h | 6 +++
examples/ipsec-secgw/sp4.c | 90 +++++++++++++++++++++++++++++++++----------
examples/ipsec-secgw/sp6.c | 88 ++++++++++++++++++++++++++++++++----------
4 files changed, 144 insertions(+), 42 deletions(-)
diff --git a/examples/ipsec-secgw/parser.c b/examples/ipsec-secgw/parser.c
index 67df170..65eb7e9 100644
--- a/examples/ipsec-secgw/parser.c
+++ b/examples/ipsec-secgw/parser.c
@@ -643,6 +643,8 @@ parse_cfg_file(const char *cfg_filename)
fclose(f);
sa_sort_arr();
+ sp4_sort_arr();
+ sp6_sort_arr();
return 0;
diff --git a/examples/ipsec-secgw/parser.h b/examples/ipsec-secgw/parser.h
index 1f8bd3e..6e764fe 100644
--- a/examples/ipsec-secgw/parser.h
+++ b/examples/ipsec-secgw/parser.h
@@ -67,10 +67,16 @@ int
parse_range(const char *token, uint16_t *low, uint16_t *high);
void
+sp4_sort_arr(void);
+
+void
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status);
void
+sp6_sort_arr(void);
+
+void
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status);
diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c
index 1dcec52..beddd7b 100644
--- a/examples/ipsec-secgw/sp4.c
+++ b/examples/ipsec-secgw/sp4.c
@@ -15,7 +15,7 @@
#include "ipsec.h"
#include "parser.h"
-#define MAX_ACL_RULE_NUM 1024
+#define INIT_ACL_RULE_NUM 128
#define IPV4_DST_FROM_SP(acr) \
(rte_cpu_to_be_32((acr).field[DST_FIELD_IPV4].value.u32))
@@ -97,11 +97,39 @@ static struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = {
RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs));
-static struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM];
+static struct acl4_rules *acl4_rules_out;
static uint32_t nb_acl4_rules_out;
+static uint32_t sp_out_sz;
-static struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM];
+static struct acl4_rules *acl4_rules_in;
static uint32_t nb_acl4_rules_in;
+static uint32_t sp_in_sz;
+
+static int
+extend_sp_arr(struct acl4_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sp_tbl == NULL) {
+ *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl4_rules));
+ if (*sp_tbl == NULL)
+ return -1;
+ *cur_sz = INIT_ACL_RULE_NUM;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sp_tbl = realloc(*sp_tbl,
+ *cur_sz * sizeof(struct acl4_rules) * 2);
+ if (*sp_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sp_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct acl4_rules));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
+
void
parse_sp4_tokens(char **tokens, uint32_t n_tokens,
@@ -127,9 +155,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
if (strcmp(tokens[1], "in") == 0) {
ri = &nb_acl4_rules_in;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
- "too many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl4_rules_in, nb_acl4_rules_in,
+ &sp_in_sz) < 0)
return;
rule_ipv4 = &acl4_rules_in[*ri];
@@ -137,9 +164,8 @@ parse_sp4_tokens(char **tokens, uint32_t n_tokens,
} else if (strcmp(tokens[1], "out") == 0) {
ri = &nb_acl4_rules_out;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status,
- "too many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl4_rules_out, nb_acl4_rules_out,
+ &sp_out_sz) < 0)
return;
rule_ipv4 = &acl4_rules_out[*ri];
@@ -451,7 +477,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
struct rte_acl_config acl_build_param;
struct rte_acl_ctx *ctx;
- printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
+ printf("Creating SP context with %u rules\n", rules_nb);
memset(&acl_param, 0, sizeof(acl_param));
@@ -464,7 +490,7 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules,
acl_param.name = s;
acl_param.socket_id = socketid;
acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip4_defs));
- acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+ acl_param.max_rule_num = rules_nb;
ctx = rte_acl_create(&acl_param);
if (ctx == NULL)
@@ -566,6 +592,16 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id)
"specified\n");
}
+static int
+sp_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct acl4_rules *)p)->data.userdata;
+ uint32_t spi2 = ((const struct acl4_rules *)q)->data.userdata;
+
+ return (int)(spi1 - spi2);
+}
+
+
/*
* Search though SP rules for given SPI.
*/
@@ -573,8 +609,10 @@ int
sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
uint32_t mask[2])
{
- uint32_t i, num;
+ uint32_t num;
+ struct acl4_rules *rule;
const struct acl4_rules *acr;
+ struct acl4_rules tmpl;
if (inbound != 0) {
acr = acl4_rules_in;
@@ -584,17 +622,27 @@ sp4_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
num = nb_acl4_rules_out;
}
- for (i = 0; i != num; i++) {
- if (acr[i].data.userdata == spi) {
- if (NULL != ip_addr && NULL != mask) {
- ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(acr[i]);
- ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(acr[i]);
- mask[0] = IPV4_SRC_MASK_FROM_SP(acr[i]);
- mask[1] = IPV4_DST_MASK_FROM_SP(acr[i]);
- }
- return i;
+ tmpl.data.userdata = spi;
+
+ rule = bsearch(&tmpl, acr, num, sizeof(struct acl4_rules), sp_cmp);
+ if (rule != NULL) {
+ if (NULL != ip_addr && NULL != mask) {
+ ip_addr[0].ip.ip4 = IPV4_SRC_FROM_SP(*rule);
+ ip_addr[1].ip.ip4 = IPV4_DST_FROM_SP(*rule);
+ mask[0] = IPV4_SRC_MASK_FROM_SP(*rule);
+ mask[1] = IPV4_DST_MASK_FROM_SP(*rule);
}
+ return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl4_rules);
}
return -ENOENT;
}
+
+void
+sp4_sort_arr(void)
+{
+ qsort(acl4_rules_in, nb_acl4_rules_in, sizeof(struct acl4_rules),
+ sp_cmp);
+ qsort(acl4_rules_out, nb_acl4_rules_out, sizeof(struct acl4_rules),
+ sp_cmp);
+}
diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c
index b489e15..328e085 100644
--- a/examples/ipsec-secgw/sp6.c
+++ b/examples/ipsec-secgw/sp6.c
@@ -15,7 +15,7 @@
#include "ipsec.h"
#include "parser.h"
-#define MAX_ACL_RULE_NUM 1024
+#define INIT_ACL_RULE_NUM 128
#define IPV6_FROM_SP(acr, fidx_low, fidx_high) \
(((uint64_t)(acr).field[(fidx_high)].value.u32 << 32) | \
@@ -146,11 +146,38 @@ static struct rte_acl_field_def ip6_defs[IP6_NUM] = {
RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
-static struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM];
+static struct acl6_rules *acl6_rules_out;
static uint32_t nb_acl6_rules_out;
+static uint32_t sp_out_sz;
-static struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM];
+static struct acl6_rules *acl6_rules_in;
static uint32_t nb_acl6_rules_in;
+static uint32_t sp_in_sz;
+
+static int
+extend_sp_arr(struct acl6_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
+{
+ if (*sp_tbl == NULL) {
+ *sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl6_rules));
+ if (*sp_tbl == NULL)
+ return -1;
+ *cur_sz = INIT_ACL_RULE_NUM;
+ return 0;
+ }
+
+ if (cur_cnt >= *cur_sz) {
+ *sp_tbl = realloc(*sp_tbl,
+ *cur_sz * sizeof(struct acl6_rules) * 2);
+ if (*sp_tbl == NULL)
+ return -1;
+ /* clean reallocated extra space */
+ memset(&(*sp_tbl)[*cur_sz], 0,
+ *cur_sz * sizeof(struct acl6_rules));
+ *cur_sz *= 2;
+ }
+
+ return 0;
+}
void
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
@@ -176,9 +203,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
if (strcmp(tokens[1], "in") == 0) {
ri = &nb_acl6_rules_in;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl6_rules_in, nb_acl6_rules_in,
+ &sp_in_sz) < 0)
return;
rule_ipv6 = &acl6_rules_in[*ri];
@@ -186,9 +212,8 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
} else if (strcmp(tokens[1], "out") == 0) {
ri = &nb_acl6_rules_out;
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
+ if (extend_sp_arr(&acl6_rules_out, nb_acl6_rules_out,
+ &sp_out_sz) < 0)
return;
rule_ipv6 = &acl6_rules_out[*ri];
@@ -583,7 +608,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
struct rte_acl_config acl_build_param;
struct rte_acl_ctx *ctx;
- printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
+ printf("Creating SP context with %u rules\n", rules_nb);
memset(&acl_param, 0, sizeof(acl_param));
@@ -596,7 +621,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
acl_param.name = s;
acl_param.socket_id = socketid;
acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs));
- acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+ acl_param.max_rule_num = rules_nb;
ctx = rte_acl_create(&acl_param);
if (ctx == NULL)
@@ -698,6 +723,15 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
"specified\n");
}
+static int
+sp_cmp(const void *p, const void *q)
+{
+ uint32_t spi1 = ((const struct acl6_rules *)p)->data.userdata;
+ uint32_t spi2 = ((const struct acl6_rules *)q)->data.userdata;
+
+ return (int)(spi1 - spi2);
+}
+
/*
* Search though SP rules for given SPI.
*/
@@ -705,8 +739,10 @@ int
sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
uint32_t mask[2])
{
- uint32_t i, num;
+ uint32_t num;
+ struct acl6_rules *rule;
const struct acl6_rules *acr;
+ struct acl6_rules tmpl;
if (inbound != 0) {
acr = acl6_rules_in;
@@ -716,17 +752,27 @@ sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
num = nb_acl6_rules_out;
}
- for (i = 0; i != num; i++) {
- if (acr[i].data.userdata == spi) {
- if (NULL != ip_addr && NULL != mask) {
- IPV6_SRC_FROM_SP(ip_addr[0], acr[i]);
- IPV6_DST_FROM_SP(ip_addr[1], acr[i]);
- IPV6_SRC_MASK_FROM_SP(mask[0], acr[i]);
- IPV6_DST_MASK_FROM_SP(mask[1], acr[i]);
- }
- return i;
+ tmpl.data.userdata = spi;
+
+ rule = bsearch(&tmpl, acr, num, sizeof(struct acl6_rules), sp_cmp);
+ if (rule != NULL) {
+ if (NULL != ip_addr && NULL != mask) {
+ IPV6_SRC_FROM_SP(ip_addr[0], *rule);
+ IPV6_DST_FROM_SP(ip_addr[1], *rule);
+ IPV6_SRC_MASK_FROM_SP(mask[0], *rule);
+ IPV6_DST_MASK_FROM_SP(mask[1], *rule);
}
+ return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl6_rules);
}
return -ENOENT;
}
+
+void
+sp6_sort_arr(void)
+{
+ qsort(acl6_rules_in, nb_acl6_rules_in, sizeof(struct acl6_rules),
+ sp_cmp);
+ qsort(acl6_rules_out, nb_acl6_rules_out, sizeof(struct acl6_rules),
+ sp_cmp);
+}
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread
* [dpdk-dev] [PATCH v2 1/5] ipsec: move ipsec sad name length into .h
2019-12-11 16:45 [dpdk-dev] [PATCH 0/4] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (4 preceding siblings ...)
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 0/5] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
@ 2019-12-18 16:00 ` Vladimir Medvedkin
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 2/5] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
` (3 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2019-12-18 16:00 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] 60+ messages in thread
* [dpdk-dev] [PATCH v2 2/5] 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
` (5 preceding siblings ...)
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 1/5] ipsec: move ipsec sad name length into .h Vladimir Medvedkin
@ 2019-12-18 16:00 ` Vladimir Medvedkin
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 3/5] examples/ipsec-secgw: integrate " Vladimir Medvedkin
` (2 subsequent siblings)
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2019-12-18 16:00 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] 60+ messages in thread
* [dpdk-dev] [PATCH v2 3/5] examples/ipsec-secgw: integrate inbound SAD
2019-12-11 16:45 [dpdk-dev] [PATCH 0/4] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (6 preceding siblings ...)
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 2/5] examples/ipsec-secgw: implement inbound SAD Vladimir Medvedkin
@ 2019-12-18 16:00 ` Vladimir Medvedkin
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 4/5] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 5/5] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2019-12-18 16:00 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] 60+ messages in thread
* [dpdk-dev] [PATCH v2 4/5] examples/ipsec-secgw: get rid of maximum sa limitation
2019-12-11 16:45 [dpdk-dev] [PATCH 0/4] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (7 preceding siblings ...)
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 3/5] examples/ipsec-secgw: integrate " Vladimir Medvedkin
@ 2019-12-18 16:00 ` Vladimir Medvedkin
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 5/5] examples/ipsec-secgw: get rid of maximum sp limitation Vladimir Medvedkin
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2019-12-18 16:00 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] 60+ messages in thread
* [dpdk-dev] [PATCH v2 5/5] examples/ipsec-secgw: get rid of maximum sp limitation
2019-12-11 16:45 [dpdk-dev] [PATCH 0/4] integrate librte_ipsec SAD into ipsec-secgw Vladimir Medvedkin
` (8 preceding siblings ...)
2019-12-18 16:00 ` [dpdk-dev] [PATCH v2 4/5] examples/ipsec-secgw: get rid of maximum sa limitation Vladimir Medvedkin
@ 2019-12-18 16:00 ` Vladimir Medvedkin
9 siblings, 0 replies; 60+ messages in thread
From: Vladimir Medvedkin @ 2019-12-18 16:00 UTC (permalink / raw)
To: dev; +Cc: konstantin.ananyev, akhil.goyal
Parse config file and save SP rules into linked list
instead of flat array with predefined size.
Signed-off-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
---
examples/ipsec-secgw/sp4.c | 121 ++++++++++++++++++++++++++-------------------
examples/ipsec-secgw/sp6.c | 118 +++++++++++++++++++++++--------------------
2 files changed, 134 insertions(+), 105 deletions(-)
diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c
index 1dcec52..f0938c5 100644
--- a/examples/ipsec-secgw/sp4.c
+++ b/examples/ipsec-secgw/sp4.c
@@ -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;
diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c
index b489e15..b931c50 100644
--- a/examples/ipsec-secgw/sp6.c
+++ b/examples/ipsec-secgw/sp6.c
@@ -8,6 +8,7 @@
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip6.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 IPV6_FROM_SP(acr, fidx_low, fidx_high) \
(((uint64_t)(acr).field[(fidx_high)].value.u32 << 32) | \
(acr).field[(fidx_low)].value.u32)
@@ -146,16 +145,24 @@ static struct rte_acl_field_def ip6_defs[IP6_NUM] = {
RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
-static struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM];
+struct ipsec_sp_mgmt {
+ STAILQ_ENTRY(ipsec_sp_mgmt) next;
+ struct acl6_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_acl6_rules_out;
-static struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM];
+static struct sp_head sp_in_head = STAILQ_HEAD_INITIALIZER(sp_in_head);
static uint32_t nb_acl6_rules_in;
void
parse_sp6_tokens(char **tokens, uint32_t n_tokens,
struct parse_status *status)
{
+ struct ipsec_sp_mgmt *sp_mgmt;
+ struct sp_head *head;
struct acl6_rules *rule_ipv6 = NULL;
uint32_t *ri = NULL; /* rule index */
@@ -173,26 +180,18 @@ parse_sp6_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_ipv6 = &sp_mgmt->sp;
+
if (strcmp(tokens[1], "in") == 0) {
ri = &nb_acl6_rules_in;
-
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
- return;
-
- rule_ipv6 = &acl6_rules_in[*ri];
-
+ head = &sp_in_head;
} else if (strcmp(tokens[1], "out") == 0) {
ri = &nb_acl6_rules_out;
-
- APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
- "many sp rules, abort insertion\n");
- if (status->status < 0)
- return;
-
- rule_ipv6 = &acl6_rules_out[*ri];
-
+ head = &sp_out_head;
} else {
APP_CHECK(0, status, "unrecognized input \"%s\", expect"
" \"in\" or \"out\"\n", tokens[ti]);
@@ -201,7 +200,6 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
rule_ipv6->data.category_mask = 1;
-
for (ti = 2; ti < n_tokens; ti++) {
if (strcmp(tokens[ti], "esp") == 0) {
/* currently do nothing */
@@ -506,6 +504,7 @@ parse_sp6_tokens(char **tokens, uint32_t n_tokens,
if (status->status < 0)
return;
+ STAILQ_INSERT_TAIL(head, sp_mgmt, next);
*ri = *ri + 1;
}
@@ -575,18 +574,34 @@ dump_ip6_rules(const struct acl6_rules *rule, int32_t num, int32_t extra)
}
static struct rte_acl_ctx *
-acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
+acl6_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 acl6_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 acl6_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);
@@ -596,7 +611,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
acl_param.name = s;
acl_param.socket_id = socketid;
acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs));
- acl_param.max_rule_num = MAX_ACL_RULE_NUM;
+ acl_param.max_rule_num = rules_nb;
ctx = rte_acl_create(&acl_param);
if (ctx == NULL)
@@ -618,6 +633,7 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
rte_acl_dump(ctx);
+ free(rules);
return ctx;
}
@@ -627,20 +643,18 @@ acl6_init(const char *name, int32_t socketid, const struct acl6_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 acl6_rules *acr;
+ struct ipsec_sp_mgmt *sp_mgmt;
+ struct sp_head *head;
- if (inbound != 0) {
- acr = acl6_rules_in;
- num = nb_acl6_rules_in;
- } else {
- acr = acl6_rules_out;
- num = nb_acl6_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) {
@@ -650,7 +664,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;
}
}
@@ -684,7 +698,7 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
if (nb_acl6_rules_in > 0) {
name = "sp_ip6_in";
ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name,
- socket_id, acl6_rules_in, nb_acl6_rules_in);
+ socket_id, &sp_in_head, nb_acl6_rules_in);
} else
RTE_LOG(WARNING, IPSEC, "No IPv6 SP Inbound rule "
"specified\n");
@@ -692,7 +706,7 @@ sp6_init(struct socket_ctx *ctx, int32_t socket_id)
if (nb_acl6_rules_out > 0) {
name = "sp_ip6_out";
ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name,
- socket_id, acl6_rules_out, nb_acl6_rules_out);
+ socket_id, &sp_out_head, nb_acl6_rules_out);
} else
RTE_LOG(WARNING, IPSEC, "No IPv6 SP Outbound rule "
"specified\n");
@@ -705,24 +719,22 @@ int
sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
uint32_t mask[2])
{
- uint32_t i, num;
- const struct acl6_rules *acr;
+ uint32_t i = 0;
+ struct ipsec_sp_mgmt *sp_mgmt;
+ struct sp_head *head;
- if (inbound != 0) {
- acr = acl6_rules_in;
- num = nb_acl6_rules_in;
- } else {
- acr = acl6_rules_out;
- num = nb_acl6_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) {
- IPV6_SRC_FROM_SP(ip_addr[0], acr[i]);
- IPV6_DST_FROM_SP(ip_addr[1], acr[i]);
- IPV6_SRC_MASK_FROM_SP(mask[0], acr[i]);
- IPV6_DST_MASK_FROM_SP(mask[1], acr[i]);
+ IPV6_SRC_FROM_SP(ip_addr[0], sp_mgmt->sp);
+ IPV6_DST_FROM_SP(ip_addr[1], sp_mgmt->sp);
+ IPV6_SRC_MASK_FROM_SP(mask[0], sp_mgmt->sp);
+ IPV6_DST_MASK_FROM_SP(mask[1], sp_mgmt->sp);
}
return i;
}
--
2.7.4
^ permalink raw reply [flat|nested] 60+ messages in thread