DPDK-dev Archive on lore.kernel.org
 help / color / Atom feed
* [dpdk-dev] [PATCH 0/2] fix SAD selection logic
@ 2019-09-05 12:35 Mariusz Drost
  2019-09-05 12:35 ` [dpdk-dev] [PATCH 1/2] examples/ipsec-secgw: " Mariusz Drost
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Mariusz Drost @ 2019-09-05 12:35 UTC (permalink / raw)
  To: radu.nicolau, akhil.goyal, konstantin.ananyev; +Cc: dev, Mariusz Drost

Code fix for SAD selection logic by splitting SAD into IPv4 SAD and
IPv6 SAD. Test scripts updated to reflect changes.

Mariusz Drost (2):
  examples/ipsec-secgw: fix SAD selection logic
  examples/ipsec-secgw: tests for split SAD

 examples/ipsec-secgw/ipsec-secgw.c            |  48 ++-
 examples/ipsec-secgw/ipsec.c                  |   5 +-
 examples/ipsec-secgw/ipsec.h                  |  21 +-
 examples/ipsec-secgw/sa.c                     | 396 ++++++++++++------
 examples/ipsec-secgw/test/common_defs.sh      |   7 +-
 examples/ipsec-secgw/test/linux_test4.sh      |  78 ----
 examples/ipsec-secgw/test/linux_test6.sh      |  79 ----
 examples/ipsec-secgw/test/run_test.sh         |  42 +-
 .../ipsec-secgw/test/trs_3descbc_sha1_defs.sh |   7 +-
 .../test/trs_3descbc_sha1_esn_defs.sh         |   7 +-
 .../ipsec-secgw/test/trs_aescbc_sha1_defs.sh  |   7 +-
 .../test/trs_aescbc_sha1_esn_defs.sh          |   7 +-
 .../ipsec-secgw/test/trs_aesctr_sha1_defs.sh  |   7 +-
 .../test/trs_aesctr_sha1_esn_defs.sh          |   7 +-
 examples/ipsec-secgw/test/trs_aesgcm_defs.sh  |   7 +-
 .../ipsec-secgw/test/trs_aesgcm_esn_defs.sh   |   7 +-
 .../test/tun_3descbc_sha1_common_defs.sh      |  68 +++
 .../ipsec-secgw/test/tun_3descbc_sha1_defs.sh |  77 +++-
 .../test/tun_3descbc_sha1_esn_defs.sh         |  77 +++-
 .../test/tun_aescbc_sha1_common_defs.sh       |  64 +++
 .../ipsec-secgw/test/tun_aescbc_sha1_defs.sh  |  77 +++-
 .../test/tun_aescbc_sha1_esn_defs.sh          |  77 +++-
 .../test/tun_aesctr_sha1_common_defs.sh       |  64 +++
 .../ipsec-secgw/test/tun_aesctr_sha1_defs.sh  |  77 +++-
 .../test/tun_aesctr_sha1_esn_defs.sh          |  77 +++-
 .../test/tun_aesgcm_common_defs.sh            |  56 +++
 examples/ipsec-secgw/test/tun_aesgcm_defs.sh  |  77 +++-
 .../ipsec-secgw/test/tun_aesgcm_esn_defs.sh   |  77 +++-
 28 files changed, 1222 insertions(+), 378 deletions(-)
 delete mode 100644 examples/ipsec-secgw/test/linux_test4.sh
 delete mode 100644 examples/ipsec-secgw/test/linux_test6.sh

-- 
2.17.1


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

* [dpdk-dev] [PATCH 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-09-05 12:35 [dpdk-dev] [PATCH 0/2] fix SAD selection logic Mariusz Drost
@ 2019-09-05 12:35 ` " Mariusz Drost
  2019-09-05 12:35 ` [dpdk-dev] [PATCH 2/2] examples/ipsec-secgw: tests for split SAD Mariusz Drost
  2019-09-24 10:35 ` [dpdk-dev] [PATCH v2 0/2] fix SAD selection logic Mariusz Drost
  2 siblings, 0 replies; 15+ messages in thread
From: Mariusz Drost @ 2019-09-05 12:35 UTC (permalink / raw)
  To: radu.nicolau, akhil.goyal, konstantin.ananyev
  Cc: dev, Mariusz Drost, Lukasz Bartosik

Ipsec-secgw example application fails to initialize when using default
configuration file (ep0.cfg) in library mode (librte_ipsec enabled).

The reason is that two of SP rules in ep0.cfg, one for IPv4 and one
for IPv6, are using the same SPI number. When SA rules are initialized,
their SPI number is checked against SPIs stored in SPD. For library
mode, it is not allowed for the same SA to handle both IPv4 and IPv6.

Solution is to split SAD into two separate parts - one for IPv4 and one
for IPv6. Usage of SAs stays the same. Only change is to pass correct
SAD (IPv4 or IPv6) in places where previously combined database was
passed.

Split of SA entries is done at initialization stage. Most of given SA
entries are checked against SPD. If matching entry is in IPv4 SPD, SA
rule is added to IPv4 SAD (respectively for IPv6). Different splitting
method is used only when SA entry is for tunnel in inbound direction.
In that case if IPv4 tunnel should be used, SA entry is added to IPv4
SAD (respectively for IPv6). Reasoning is that inner IP version can
be different than outer IP version for tunneled traffic.

Bugzilla ID: 239
Fixes: 5a032a71c6d3 ("examples/ipsec-secgw: make app to use IPsec library")

Reported-by: Lukasz Bartosik <lbartosik@marvell.com>
Signed-off-by: Mariusz Drost <mariuszx.drost@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.c |  48 ++--
 examples/ipsec-secgw/ipsec.c       |   5 +-
 examples/ipsec-secgw/ipsec.h       |  21 +-
 examples/ipsec-secgw/sa.c          | 396 ++++++++++++++++++++---------
 4 files changed, 312 insertions(+), 158 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 0d1fd6af6..2b0b8226b 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -562,11 +562,10 @@ send_single_packet(struct rte_mbuf *m, uint16_t port, uint8_t proto)
 }
 
 static inline void
-inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
-		uint16_t lim)
+inbound_sp_sa(struct sp_ctx *sp, struct traffic_type *ip, uint16_t lim)
 {
 	struct rte_mbuf *m;
-	uint32_t i, j, res, sa_idx;
+	uint32_t i, j, res;
 
 	if (ip->num == 0 || sp == NULL)
 		return;
@@ -593,8 +592,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 			continue;
 		}
 
-		sa_idx = SPI2IDX(res);
-		if (!inbound_sa_check(sa, m, sa_idx)) {
+		if (!inbound_sa_check(m, res)) {
 			rte_pktmbuf_free(m);
 			continue;
 		}
@@ -652,15 +650,16 @@ process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 				traffic->ipsec.num, MAX_PKT_BURST);
 		split46_traffic(traffic, traffic->ipsec.pkts, nb_pkts_in);
 	} else {
-		inbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.pkts,
-			traffic->ipsec.saptr, traffic->ipsec.num);
+		inbound_sa_lookup(ipsec_ctx->sa4_ctx, ipsec_ctx->sa6_ctx,
+			traffic->ipsec.pkts, traffic->ipsec.saptr,
+			traffic->ipsec.num);
 		ipsec_process(ipsec_ctx, traffic);
 	}
 
-	inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4,
+	inbound_sp_sa(ipsec_ctx->sp4_ctx, &traffic->ip4,
 			n_ip4);
 
-	inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6,
+	inbound_sp_sa(ipsec_ctx->sp6_ctx, &traffic->ip6,
 			n_ip6);
 }
 
@@ -728,8 +727,9 @@ process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
 			}
 		}
 	} else {
-		outbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.res,
-			traffic->ipsec.saptr, traffic->ipsec.num);
+		outbound_sa_lookup(ipsec_ctx->sa4_ctx, ipsec_ctx->sa6_ctx,
+			traffic->ipsec.res, traffic->ipsec.saptr,
+			traffic->ipsec.pkts, traffic->ipsec.num);
 		ipsec_process(ipsec_ctx, traffic);
 	}
 }
@@ -770,8 +770,9 @@ process_pkts_inbound_nosp(struct ipsec_ctx *ipsec_ctx,
 			}
 		}
 	} else {
-		inbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.pkts,
-			traffic->ipsec.saptr, traffic->ipsec.num);
+		inbound_sa_lookup(ipsec_ctx->sa4_ctx, ipsec_ctx->sa6_ctx,
+			traffic->ipsec.pkts, traffic->ipsec.saptr,
+			traffic->ipsec.num);
 		ipsec_process(ipsec_ctx, traffic);
 	}
 }
@@ -823,8 +824,9 @@ process_pkts_outbound_nosp(struct ipsec_ctx *ipsec_ctx,
 				traffic->ip6.pkts[i] = traffic->ipsec.pkts[i];
 		}
 	} else {
-		outbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.res,
-			traffic->ipsec.saptr, traffic->ipsec.num);
+		outbound_sa_lookup(ipsec_ctx->sa4_ctx, ipsec_ctx->sa6_ctx,
+			traffic->ipsec.res, traffic->ipsec.saptr,
+			traffic->ipsec.pkts, traffic->ipsec.num);
 		ipsec_process(ipsec_ctx, traffic);
 	}
 }
@@ -1042,13 +1044,13 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 
 	/* process ipv4 packets */
 	if (trf.ip4.num != 0) {
-		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0);
+		inbound_sp_sa(ctx->sp4_ctx, &trf.ip4, 0);
 		route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num);
 	}
 
 	/* process ipv6 packets */
 	if (trf.ip6.num != 0) {
-		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0);
+		inbound_sp_sa(ctx->sp6_ctx, &trf.ip6, 0);
 		route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num);
 	}
 }
@@ -1109,14 +1111,16 @@ main_loop(__attribute__((unused)) void *dummy)
 	qconf->rt6_ctx = socket_ctx[socket_id].rt_ip6;
 	qconf->inbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_in;
 	qconf->inbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_in;
-	qconf->inbound.sa_ctx = socket_ctx[socket_id].sa_in;
+	qconf->inbound.sa4_ctx = socket_ctx[socket_id].sa_ip4_in;
+	qconf->inbound.sa6_ctx = socket_ctx[socket_id].sa_ip6_in;
 	qconf->inbound.cdev_map = cdev_map_in;
 	qconf->inbound.session_pool = socket_ctx[socket_id].session_pool;
 	qconf->inbound.session_priv_pool =
 			socket_ctx[socket_id].session_priv_pool;
 	qconf->outbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_out;
 	qconf->outbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_out;
-	qconf->outbound.sa_ctx = socket_ctx[socket_id].sa_out;
+	qconf->outbound.sa4_ctx = socket_ctx[socket_id].sa_ip4_out;
+	qconf->outbound.sa6_ctx = socket_ctx[socket_id].sa_ip6_out;
 	qconf->outbound.cdev_map = cdev_map_out;
 	qconf->outbound.session_pool = socket_ctx[socket_id].session_pool;
 	qconf->outbound.session_priv_pool =
@@ -2481,8 +2485,10 @@ main(int32_t argc, char **argv)
 	for (i = 0; i < NB_SOCKETS && i < rte_socket_count(); i++) {
 		socket_id = rte_socket_id_by_idx(i);
 		if ((socket_ctx[socket_id].mbuf_pool != NULL) &&
-			(socket_ctx[socket_id].sa_in == NULL) &&
-			(socket_ctx[socket_id].sa_out == NULL)) {
+			(socket_ctx[socket_id].sa_ip4_in == NULL) &&
+			(socket_ctx[socket_id].sa_ip6_in == NULL) &&
+			(socket_ctx[socket_id].sa_ip4_out == NULL) &&
+			(socket_ctx[socket_id].sa_ip6_out == NULL)) {
 			sa_init(&socket_ctx[socket_id], socket_id);
 			sp4_init(&socket_ctx[socket_id], socket_id);
 			sp6_init(&socket_ctx[socket_id], socket_id);
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index dc85adfe5..1d4cb3167 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -581,7 +581,7 @@ ipsec_inbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
 {
 	struct ipsec_sa *sas[nb_pkts];
 
-	inbound_sa_lookup(ctx->sa_ctx, pkts, sas, nb_pkts);
+	inbound_sa_lookup(ctx->sa4_ctx, ctx->sa6_ctx, pkts, sas, nb_pkts);
 
 	ipsec_enqueue(esp_inbound, ctx, pkts, sas, nb_pkts);
 
@@ -601,7 +601,8 @@ ipsec_outbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
 {
 	struct ipsec_sa *sas[nb_pkts];
 
-	outbound_sa_lookup(ctx->sa_ctx, sa_idx, sas, nb_pkts);
+	outbound_sa_lookup(ctx->sa4_ctx, ctx->sa6_ctx, sa_idx, sas, pkts,
+			nb_pkts);
 
 	ipsec_enqueue(esp_outbound, ctx, pkts, sas, nb_pkts);
 
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 1efa6e488..736dec33b 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -174,7 +174,8 @@ struct ipsec_ctx {
 	struct rte_hash *cdev_map;
 	struct sp_ctx *sp4_ctx;
 	struct sp_ctx *sp6_ctx;
-	struct sa_ctx *sa_ctx;
+	struct sa_ctx *sa4_ctx;
+	struct sa_ctx *sa6_ctx;
 	uint16_t nb_qps;
 	uint16_t last_qp;
 	struct cdev_qp tbl[MAX_QP_PER_LCORE];
@@ -194,8 +195,10 @@ struct cdev_key {
 };
 
 struct socket_ctx {
-	struct sa_ctx *sa_in;
-	struct sa_ctx *sa_out;
+	struct sa_ctx *sa_ip4_in;
+	struct sa_ctx *sa_ip4_out;
+	struct sa_ctx *sa_ip6_in;
+	struct sa_ctx *sa_ip6_out;
 	struct sp_ctx *sp_ip4_in;
 	struct sp_ctx *sp_ip4_out;
 	struct sp_ctx *sp_ip6_in;
@@ -285,15 +288,17 @@ get_sym_cop(struct rte_crypto_op *cop)
 }
 
 int
-inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx);
+inbound_sa_check(struct rte_mbuf *m, uint32_t sa_idx);
 
 void
-inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
-		struct ipsec_sa *sa[], uint16_t nb_pkts);
+inbound_sa_lookup(struct sa_ctx *sa4_ctx, struct sa_ctx *sa6_ctx,
+		struct rte_mbuf *pkts[], struct ipsec_sa *sa[],
+		uint16_t nb_pkts);
 
 void
-outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
-		struct ipsec_sa *sa[], uint16_t nb_pkts);
+outbound_sa_lookup(struct sa_ctx *sa4_ctx, struct sa_ctx *sa6_ctx,
+		uint32_t sa_idx[], struct ipsec_sa *sa[],
+		struct rte_mbuf *pkts[], uint16_t nb_pkts);
 
 void
 sp4_init(struct socket_ctx *ctx, int32_t socket_id);
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index c3cf3bd1f..015d5cf01 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -130,11 +130,18 @@ const struct supported_aead_algo aead_algos[] = {
 	}
 };
 
-static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
-static uint32_t nb_sa_out;
+struct ipsec_sa_db {
+	struct ipsec_sa sadb[IPSEC_SA_MAX_ENTRIES];
+	uint32_t nb;
+};
+
+static struct ipsec_sa_db sa_out;
+static struct ipsec_sa_db sa_in;
 
-static struct ipsec_sa sa_in[IPSEC_SA_MAX_ENTRIES];
-static uint32_t nb_sa_in;
+static struct ipsec_sa_db sa_ip4_out;
+static struct ipsec_sa_db sa_ip4_in;
+static struct ipsec_sa_db sa_ip6_out;
+static struct ipsec_sa_db sa_ip6_in;
 
 static const struct supported_cipher_algo *
 find_match_cipher_algo(const char *cipher_keyword)
@@ -236,23 +243,23 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t portid_p = 0;
 
 	if (strcmp(tokens[0], "in") == 0) {
-		ri = &nb_sa_in;
+		ri = &sa_in.nb;
 
 		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];
+		rule = &sa_in.sadb[*ri];
 	} else {
-		ri = &nb_sa_out;
+		ri = &sa_out.nb;
 
 		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];
+		rule = &sa_out.sadb[*ri];
 	}
 
 	/* spi number */
@@ -778,39 +785,6 @@ check_eth_dev_caps(uint16_t portid, uint32_t inbound)
 	return 0;
 }
 
-/*
- * Helper function, tries to determine next_proto for SPI
- * by searching though SP rules.
- */
-static int
-get_spi_proto(uint32_t spi, enum rte_security_ipsec_sa_direction dir,
-		struct ip_addr ip_addr[2], uint32_t mask[2])
-{
-	int32_t rc4, rc6;
-
-	rc4 = sp4_spi_present(spi, dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
-				ip_addr, mask);
-	rc6 = sp6_spi_present(spi, dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
-				ip_addr, mask);
-
-	if (rc4 >= 0) {
-		if (rc6 >= 0) {
-			RTE_LOG(ERR, IPSEC,
-				"%s: SPI %u used simultaeously by "
-				"IPv4(%d) and IPv6 (%d) SP rules\n",
-				__func__, spi, rc4, rc6);
-			return -EINVAL;
-		} else
-			return IPPROTO_IPIP;
-	} else if (rc6 < 0) {
-		RTE_LOG(ERR, IPSEC,
-			"%s: SPI %u is not used by any SP rule\n",
-			__func__, spi);
-		return -EINVAL;
-	} else
-		return IPPROTO_IPV6;
-}
-
 /*
  * Helper function for getting source and destination IP addresses
  * from SP. Needed for inline crypto transport mode, as addresses are not
@@ -819,16 +793,21 @@ get_spi_proto(uint32_t spi, enum rte_security_ipsec_sa_direction dir,
  * addresses got from SP into SA.
  */
 static int
-sa_add_address_inline_crypto(struct ipsec_sa *sa)
+sa_add_address_inline_crypto(struct ipsec_sa *sa, int ip_v)
 {
-	int protocol;
+	int rc4, rc6;
 	struct ip_addr ip_addr[2];
 	uint32_t mask[2];
 
-	protocol = get_spi_proto(sa->spi, sa->direction, ip_addr, mask);
-	if (protocol < 0)
-		return protocol;
-	else if (protocol == IPPROTO_IPIP) {
+	if (ip_v == IPPROTO_IPIP) {
+		rc4 = sp4_spi_present(sa->spi, sa->direction, ip_addr, mask);
+		if (rc4 < 0) {
+			RTE_LOG(ERR, IPSEC,
+			"%s: SPI %u is not used by any SP rule\n",
+			__func__, sa->spi);
+			return rc4;
+		}
+
 		sa->flags |= IP4_TRANSPORT;
 		if (mask[0] == IP4_FULL_MASK &&
 				mask[1] == IP4_FULL_MASK &&
@@ -844,7 +823,15 @@ sa_add_address_inline_crypto(struct ipsec_sa *sa)
 			__func__, sa->spi);
 			return -EINVAL;
 		}
-	} else if (protocol == IPPROTO_IPV6) {
+	} else if (ip_v == IPPROTO_IPV6) {
+		rc6 = sp6_spi_present(sa->spi, sa->direction, ip_addr, mask);
+		if (rc6 < 0) {
+			RTE_LOG(ERR, IPSEC,
+			"%s: SPI %u is not used by any SP rule\n",
+			__func__, sa->spi);
+			return rc6;
+		}
+
 		sa->flags |= IP6_TRANSPORT;
 		if (mask[0] == IP6_FULL_MASK &&
 				mask[1] == IP6_FULL_MASK &&
@@ -866,9 +853,93 @@ sa_add_address_inline_crypto(struct ipsec_sa *sa)
 	return 0;
 }
 
+/*
+ * Determine to what SAD put new SA entry:
+ * 1) tunnel-inbound - check IP address of a tunnel (outer IP header)
+ *	if tunnel is IPv4, add SA entry to IPv4 SAD
+ *	if tunnel is IPv6, add SA entry to IPv6 SAD
+ * 2) transport-inbound - check inbound SPD
+ *	if there is matching entry in IPv4 SPD, add SA entry to IPv4 SAD
+ *	if there is matching entry in IPv6 SPD, add SA entry to IPv6 SAD
+ * 3) tunnel-outbound/transport-outbound - check outbound SPD
+ *	if there is matching entry in IPv4 SPD, add SA entry to IPv4 SAD
+ *	if there is matching entry in IPv6 SPD, add SA entry to IPv6 SAD
+ */
+static int
+sa_split(struct ipsec_sa_db *sa4, struct ipsec_sa_db *sa6,
+		const struct ipsec_sa_db *ent, int sa4_ip_v[],
+		int sa6_ip_v[], uint32_t inbound)
+{
+	uint32_t i, idx4, idx6;
+	int rc4, rc6;
+	idx4 = 0;
+	idx6 = 0;
+
+	for (i = 0; i < ent->nb; i++) {
+		rc4 = sp4_spi_present(ent->sadb[i].spi, inbound, NULL, NULL);
+		rc6 = sp6_spi_present(ent->sadb[i].spi, inbound, NULL, NULL);
+
+		if (rc4 < 0 && rc6 < 0) {
+			RTE_LOG(ERR, IPSEC,
+			"%s: SPI %u is not used by any SP rule\n",
+			__func__, ent->sadb[i].spi);
+			return -EINVAL;
+		}
+
+		if (inbound) {
+			if (rc4 >= 0) {
+				if (IS_IP6_TUNNEL(ent->sadb[i].flags)) {
+					sa6_ip_v[idx6] = IPPROTO_IPIP;
+					sa6->sadb[idx6++] = ent->sadb[i];
+				} else {
+					sa4_ip_v[idx4] = IPPROTO_IPIP;
+					sa4->sadb[idx4++] = ent->sadb[i];
+				}
+			}
+			if (rc6 >= 0) {
+				if (IS_IP4_TUNNEL(ent->sadb[i].flags)) {
+					sa4_ip_v[idx4] = IPPROTO_IPV6;
+					sa4->sadb[idx4++] = ent->sadb[i];
+				} else {
+					sa6_ip_v[idx6] = IPPROTO_IPV6;
+					sa6->sadb[idx6++] = ent->sadb[i];
+				}
+			}
+		} else {
+			if (rc4 >= 0) {
+				sa4_ip_v[idx4] = IPPROTO_IPIP;
+				sa4->sadb[idx4++] = ent->sadb[i];
+			}
+			if (rc6 >= 0) {
+				sa6_ip_v[idx6] = IPPROTO_IPV6;
+				sa6->sadb[idx6++] = ent->sadb[i];
+			}
+		}
+	}
+
+		sa4->nb = idx4;
+		sa6->nb = idx6;
+
+	return 0;
+}
+
+static int
+sa_in_split(struct ipsec_sa_db *sa4, struct ipsec_sa_db *sa6,
+		const struct ipsec_sa_db *ent, int sa4_ip_v[], int sa6_ip_v[])
+{
+	return sa_split(sa4, sa6, ent, sa4_ip_v, sa6_ip_v, 1);
+}
+
+static int
+sa_out_split(struct ipsec_sa_db *sa4, struct ipsec_sa_db *sa6,
+		const struct ipsec_sa_db *ent, int sa4_ip_v[], int sa6_ip_v[])
+{
+	return sa_split(sa4, sa6, ent, sa4_ip_v, sa6_ip_v, 0);
+}
+
 static int
-sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
-		uint32_t nb_entries, uint32_t inbound,
+sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa_db *entries,
+		uint32_t inbound, int ip_v,
 		struct socket_ctx *skt_ctx)
 {
 	struct ipsec_sa *sa;
@@ -880,15 +951,15 @@ 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 = SPI2IDX(entries[i].spi);
+	for (i = 0; i < entries->nb; i++) {
+		idx = SPI2IDX(entries->sadb[i].spi);
 		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 = entries->sadb[i];
 		sa->seq = 0;
 
 		if (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
@@ -910,7 +981,7 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			if (sa->type ==
 				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
 				inline_status =
-					sa_add_address_inline_crypto(sa);
+					sa_add_address_inline_crypto(sa, ip_v);
 				if (inline_status < 0)
 					return inline_status;
 			}
@@ -1023,17 +1094,17 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 }
 
 static inline int
-sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
-		uint32_t nb_entries, struct socket_ctx *skt_ctx)
+sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa_db *entries,
+		int ip_v, struct socket_ctx *skt_ctx)
 {
-	return sa_add_rules(sa_ctx, entries, nb_entries, 0, skt_ctx);
+	return sa_add_rules(sa_ctx, entries, 0, ip_v, skt_ctx);
 }
 
 static inline int
-sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
-		uint32_t nb_entries, struct socket_ctx *skt_ctx)
+sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa_db *entries,
+		int ip_v, struct socket_ctx *skt_ctx)
 {
-	return sa_add_rules(sa_ctx, entries, nb_entries, 1, skt_ctx);
+	return sa_add_rules(sa_ctx, entries, 1, ip_v, skt_ctx);
 }
 
 /*
@@ -1052,19 +1123,8 @@ fill_ipsec_app_sa_prm(struct rte_ipsec_sa_prm *prm,
 
 static int
 fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
-	const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6)
+	const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6, int ip_v)
 {
-	int32_t rc;
-
-	/*
-	 * Try to get SPI next proto by searching that SPI in SPD.
-	 * probably not the optimal way, but there seems nothing
-	 * better right now.
-	 */
-	rc = get_spi_proto(ss->spi, ss->direction, NULL, NULL);
-	if (rc < 0)
-		return rc;
-
 	fill_ipsec_app_sa_prm(prm, &app_sa_prm);
 	prm->userdata = (uintptr_t)ss;
 
@@ -1082,16 +1142,16 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	if (IS_IP4_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
 		prm->tun.hdr_len = sizeof(*v4);
-		prm->tun.next_proto = rc;
+		prm->tun.next_proto = ip_v;
 		prm->tun.hdr = v4;
 	} else if (IS_IP6_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6;
 		prm->tun.hdr_len = sizeof(*v6);
-		prm->tun.next_proto = rc;
+		prm->tun.next_proto = ip_v;
 		prm->tun.hdr = v6;
 	} else {
 		/* transport mode */
-		prm->trs.proto = rc;
+		prm->trs.proto = ip_v;
 	}
 
 	/* setup crypto section */
@@ -1134,7 +1194,8 @@ fill_ipsec_session(struct rte_ipsec_session *ss, struct rte_ipsec_sa *sa,
  * Initialise related rte_ipsec_sa object.
  */
 static int
-ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
+ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size,
+		int ip_v)
 {
 	int rc;
 	struct rte_ipsec_sa_prm prm;
@@ -1156,7 +1217,7 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 		memcpy(v6.dst_addr, lsa->dst.ip.ip6.ip6_b, sizeof(v6.dst_addr));
 	}
 
-	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6);
+	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6, ip_v);
 	if (rc == 0)
 		rc = rte_ipsec_sa_init(sa, &prm, sa_size);
 	if (rc < 0)
@@ -1172,7 +1233,7 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
  */
 static int
 ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
-	uint32_t nb_ent, int32_t socket)
+	uint32_t nb_ent, int32_t socket, int ip_v[])
 {
 	int32_t rc, sz;
 	uint32_t i, idx;
@@ -1183,7 +1244,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
 
 	/* determine SA size */
 	idx = SPI2IDX(ent[0].spi);
-	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL);
+	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL, ip_v[0]);
 	sz = rte_ipsec_sa_size(&prm);
 	if (sz < 0) {
 		RTE_LOG(ERR, IPSEC, "%s(%p, %u, %d): "
@@ -1209,8 +1270,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
 
 		sa = (struct rte_ipsec_sa *)((uintptr_t)ctx->satbl + sz * i);
 		lsa = ctx->sa + idx;
-
-		rc = ipsec_sa_init(lsa, sa, sz);
+		rc = ipsec_sa_init(lsa, sa, sz, ip_v[i]);
 	}
 
 	return rc;
@@ -1226,11 +1286,11 @@ sa_spi_present(uint32_t spi, int inbound)
 	const struct ipsec_sa *sar;
 
 	if (inbound != 0) {
-		sar = sa_in;
-		num = nb_sa_in;
+		sar = sa_in.sadb;
+		num = sa_in.nb;
 	} else {
-		sar = sa_out;
-		num = nb_sa_out;
+		sar = sa_out.sadb;
+		num = sa_out.nb;
 	}
 
 	for (i = 0; i != num; i++) {
@@ -1246,54 +1306,122 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 {
 	int32_t rc;
 	const char *name;
+	int sa4_ip_v[IPSEC_SA_MAX_ENTRIES];
+	int sa6_ip_v[IPSEC_SA_MAX_ENTRIES];
 
 	if (ctx == NULL)
 		rte_exit(EXIT_FAILURE, "NULL context.\n");
 
-	if (ctx->sa_in != NULL)
-		rte_exit(EXIT_FAILURE, "Inbound SA DB for socket %u already "
-				"initialized\n", socket_id);
+	if (ctx->sa_ip4_in != NULL)
+		rte_exit(EXIT_FAILURE, "Inbound IPv4 SA DB for socket %u"
+				" already initialized\n", socket_id);
+
+	if (ctx->sa_ip4_out != NULL)
+		rte_exit(EXIT_FAILURE, "Outbound IPv4 SA DB for socket %u"
+				" already initialized\n", socket_id);
 
-	if (ctx->sa_out != NULL)
-		rte_exit(EXIT_FAILURE, "Outbound SA DB for socket %u already "
-				"initialized\n", socket_id);
+	if (ctx->sa_ip6_in != NULL)
+		rte_exit(EXIT_FAILURE, "Inbound IPv6 SA DB for socket %u"
+				" already initialized\n", socket_id);
 
-	if (nb_sa_in > 0) {
-		name = "sa_in";
-		ctx->sa_in = sa_create(name, socket_id);
-		if (ctx->sa_in == NULL)
+	if (ctx->sa_ip6_out != NULL)
+		rte_exit(EXIT_FAILURE, "Outbound IPv6 SA DB for socket %u"
+				" already initialized\n", socket_id);
+
+	if (sa_in.nb > 0) {
+		sa_in_split(&sa_ip4_in, &sa_ip6_in, &sa_in, sa4_ip_v,
+				sa6_ip_v);
+
+		name = "sa_ip4_in";
+		ctx->sa_ip4_in = sa_create(name, socket_id);
+		if (ctx->sa_ip4_in == NULL)
 			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
 				"context %s in socket %d\n", rte_errno,
 				name, socket_id);
 
-		sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in, ctx);
+		printf("IPv4 %s entries [%u]:\n", name, sa_ip4_in.nb);
+		sa_in_add_rules(ctx->sa_ip4_in, &sa_ip4_in, IPPROTO_IPIP, ctx);
+
+		name = "sa_ip6_in";
+		ctx->sa_ip6_in = sa_create(name, socket_id);
+		if (ctx->sa_ip6_in == NULL)
+			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
+				"context %s in socket %d\n", rte_errno,
+				name, socket_id);
+
+		printf("IPv6 %s entries [%u]:\n", name, sa_ip6_in.nb);
+		sa_in_add_rules(ctx->sa_ip6_in, &sa_ip6_in, IPPROTO_IPV6, ctx);
 
 		if (app_sa_prm.enable != 0) {
-			rc = ipsec_satbl_init(ctx->sa_in, sa_in, nb_sa_in,
-				socket_id);
-			if (rc != 0)
-				rte_exit(EXIT_FAILURE,
-					"failed to init inbound SAs\n");
+			if (sa_ip4_in.nb > 0) {
+				rc = ipsec_satbl_init(ctx->sa_ip4_in,
+					sa_ip4_in.sadb, sa_ip4_in.nb,
+					socket_id, sa4_ip_v);
+				if (rc != 0)
+					rte_exit(EXIT_FAILURE,
+						"failed to init inbound "
+						"IPv4 SAs\n");
+			}
+
+			if (sa_ip6_in.nb > 0) {
+				rc = ipsec_satbl_init(ctx->sa_ip6_in,
+					sa_ip6_in.sadb, sa_ip6_in.nb,
+					socket_id, sa6_ip_v);
+				if (rc != 0)
+					rte_exit(EXIT_FAILURE,
+						"failed to init inbound "
+						"IPv6 SAs\n");
+			}
 		}
 	} else
 		RTE_LOG(WARNING, IPSEC, "No SA Inbound rule specified\n");
 
-	if (nb_sa_out > 0) {
-		name = "sa_out";
-		ctx->sa_out = sa_create(name, socket_id);
-		if (ctx->sa_out == NULL)
+	if (sa_out.nb > 0) {
+		sa_out_split(&sa_ip4_out, &sa_ip6_out, &sa_out,
+				sa4_ip_v, sa6_ip_v);
+
+		name = "sa_ip4_out";
+		ctx->sa_ip4_out = sa_create(name, socket_id);
+		if (ctx->sa_ip4_out == NULL)
 			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
 				"context %s in socket %d\n", rte_errno,
 				name, socket_id);
 
-		sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out, ctx);
+		printf("IPv4 %s entries [%u]:\n", name, sa_ip4_out.nb);
+		sa_out_add_rules(ctx->sa_ip4_out, &sa_ip4_out, IPPROTO_IPIP,
+				ctx);
+
+		name = "sa_ip6_out";
+		ctx->sa_ip6_out = sa_create(name, socket_id);
+		if (ctx->sa_ip6_out == NULL)
+			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
+				"context %s in socket %d\n", rte_errno,
+				name, socket_id);
+
+		printf("IPv6 %s entries [%u]:\n", name, sa_ip6_out.nb);
+		sa_out_add_rules(ctx->sa_ip6_out, &sa_ip6_out, IPPROTO_IPV6,
+				ctx);
 
 		if (app_sa_prm.enable != 0) {
-			rc = ipsec_satbl_init(ctx->sa_out, sa_out, nb_sa_out,
-				socket_id);
-			if (rc != 0)
-				rte_exit(EXIT_FAILURE,
-					"failed to init outbound SAs\n");
+			if (sa_ip4_out.nb > 0) {
+				rc = ipsec_satbl_init(ctx->sa_ip4_out,
+					sa_ip4_out.sadb, sa_ip4_out.nb,
+					socket_id, sa4_ip_v);
+				if (rc != 0)
+					rte_exit(EXIT_FAILURE,
+						"failed to init outbound "
+						"IPv4 SAs\n");
+			}
+
+			if (sa_ip6_out.nb > 0) {
+				rc = ipsec_satbl_init(ctx->sa_ip6_out,
+					sa_ip6_out.sadb, sa_ip6_out.nb,
+					socket_id, sa6_ip_v);
+				if (rc != 0)
+					rte_exit(EXIT_FAILURE,
+						"failed to init outbound "
+						"IPv6 SAs\n");
+			}
 		}
 	} else
 		RTE_LOG(WARNING, IPSEC, "No SA Outbound rule "
@@ -1301,7 +1429,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 }
 
 int
-inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx)
+inbound_sa_check(struct rte_mbuf *m, uint32_t sp_spi)
 {
 	struct ipsec_mbuf_metadata *priv;
 	struct ipsec_sa *sa;
@@ -1309,7 +1437,7 @@ inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx)
 	priv = get_priv(m);
 	sa = priv->sa;
 	if (sa != NULL)
-		return (sa_ctx->sa[sa_idx].spi == sa->spi);
+		return (sp_spi == sa->spi);
 
 	RTE_LOG(ERR, IPSEC, "SA not saved in private data\n");
 	return 0;
@@ -1327,9 +1455,7 @@ single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,
 
 	*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;
 
@@ -1337,6 +1463,8 @@ single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,
 	if (rte_be_to_cpu_32(esp->spi) != sa->spi)
 		return;
 
+	ip = rte_pktmbuf_mtod(pkt, struct ip *);
+
 	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
 	case IP4_TUNNEL:
 		src4_addr = RTE_PTR_ADD(ip, offsetof(struct ip, ip_src));
@@ -1358,23 +1486,37 @@ single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,
 }
 
 void
-inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
-		struct ipsec_sa *sa[], uint16_t nb_pkts)
+inbound_sa_lookup(struct sa_ctx *sa4_ctx, struct sa_ctx *sa6_ctx,
+		struct rte_mbuf *pkts[], struct ipsec_sa *sa[],
+		uint16_t nb_pkts)
 {
 	uint32_t i;
+	struct ip *ip;
 
-	for (i = 0; i < nb_pkts; i++)
-		single_inbound_lookup(sa_ctx->sa, pkts[i], &sa[i]);
+	for (i = 0; i < nb_pkts; i++) {
+		ip = rte_pktmbuf_mtod(pkts[i], struct ip *);
+		if (ip->ip_v == IPVERSION)
+			single_inbound_lookup(sa4_ctx->sa, pkts[i], &sa[i]);
+		else
+			single_inbound_lookup(sa6_ctx->sa, pkts[i], &sa[i]);
+	}
 }
 
 void
-outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
-		struct ipsec_sa *sa[], uint16_t nb_pkts)
+outbound_sa_lookup(struct sa_ctx *sa4_ctx, struct sa_ctx *sa6_ctx,
+		uint32_t sa_idx[], struct ipsec_sa *sa[],
+		struct rte_mbuf *pkts[], uint16_t nb_pkts)
 {
 	uint32_t i;
+	struct ip *ip;
 
-	for (i = 0; i < nb_pkts; i++)
-		sa[i] = &sa_ctx->sa[sa_idx[i]];
+	for (i = 0; i < nb_pkts; i++) {
+		ip = rte_pktmbuf_mtod(pkts[i], struct ip *);
+		if (ip->ip_v == IPVERSION)
+			sa[i] = &sa4_ctx->sa[sa_idx[i]];
+		else
+			sa[i] = &sa6_ctx->sa[sa_idx[i]];
+	}
 }
 
 /*
@@ -1391,8 +1533,8 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
 	*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];
+	for (idx_sa = 0; idx_sa < sa_in.nb; idx_sa++) {
+		rule = &sa_in.sadb[idx_sa];
 		if ((rule->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
 				rule->type ==
 				RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL)
@@ -1401,8 +1543,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];
+	for (idx_sa = 0; idx_sa < sa_out.nb; idx_sa++) {
+		rule = &sa_out.sadb[idx_sa];
 		if ((rule->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
 				rule->type ==
 				RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL)
-- 
2.17.1


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

* [dpdk-dev] [PATCH 2/2] examples/ipsec-secgw: tests for split SAD
  2019-09-05 12:35 [dpdk-dev] [PATCH 0/2] fix SAD selection logic Mariusz Drost
  2019-09-05 12:35 ` [dpdk-dev] [PATCH 1/2] examples/ipsec-secgw: " Mariusz Drost
@ 2019-09-05 12:35 ` Mariusz Drost
  2019-09-24 10:35 ` [dpdk-dev] [PATCH v2 0/2] fix SAD selection logic Mariusz Drost
  2 siblings, 0 replies; 15+ messages in thread
From: Mariusz Drost @ 2019-09-05 12:35 UTC (permalink / raw)
  To: radu.nicolau, akhil.goyal, konstantin.ananyev
  Cc: dev, Mariusz Drost, Lukasz Bartosik

Test scripts updated to reflect change of SAD (split into IPv4 SAD
and IPv6 SAD). New parameter added to run_test.sh for performing tests
with mixed IP version, eg. IPv4 ipsec tunnel with IPv6 traffic.

Bugzilla ID: 239
Fixes: 5a032a71c6d3 ("examples/ipsec-secgw: make app to use IPsec library")

Reported-by: Lukasz Bartosik <lbartosik@marvell.com>
Signed-off-by: Mariusz Drost <mariuszx.drost@intel.com>
---
 examples/ipsec-secgw/test/common_defs.sh      |  7 +-
 examples/ipsec-secgw/test/linux_test4.sh      | 78 ------------------
 examples/ipsec-secgw/test/linux_test6.sh      | 79 -------------------
 examples/ipsec-secgw/test/run_test.sh         | 42 +++++++---
 .../ipsec-secgw/test/trs_3descbc_sha1_defs.sh |  7 +-
 .../test/trs_3descbc_sha1_esn_defs.sh         |  7 +-
 .../ipsec-secgw/test/trs_aescbc_sha1_defs.sh  |  7 +-
 .../test/trs_aescbc_sha1_esn_defs.sh          |  7 +-
 .../ipsec-secgw/test/trs_aesctr_sha1_defs.sh  |  7 +-
 .../test/trs_aesctr_sha1_esn_defs.sh          |  7 +-
 examples/ipsec-secgw/test/trs_aesgcm_defs.sh  |  7 +-
 .../ipsec-secgw/test/trs_aesgcm_esn_defs.sh   |  7 +-
 .../test/tun_3descbc_sha1_common_defs.sh      | 68 ++++++++++++++++
 .../ipsec-secgw/test/tun_3descbc_sha1_defs.sh | 77 +++++++++++++++++-
 .../test/tun_3descbc_sha1_esn_defs.sh         | 77 +++++++++++++++++-
 .../test/tun_aescbc_sha1_common_defs.sh       | 64 +++++++++++++++
 .../ipsec-secgw/test/tun_aescbc_sha1_defs.sh  | 77 +++++++++++++++++-
 .../test/tun_aescbc_sha1_esn_defs.sh          | 77 +++++++++++++++++-
 .../test/tun_aesctr_sha1_common_defs.sh       | 64 +++++++++++++++
 .../ipsec-secgw/test/tun_aesctr_sha1_defs.sh  | 77 +++++++++++++++++-
 .../test/tun_aesctr_sha1_esn_defs.sh          | 77 +++++++++++++++++-
 .../test/tun_aesgcm_common_defs.sh            | 56 +++++++++++++
 examples/ipsec-secgw/test/tun_aesgcm_defs.sh  | 77 +++++++++++++++++-
 .../ipsec-secgw/test/tun_aesgcm_esn_defs.sh   | 77 +++++++++++++++++-
 24 files changed, 910 insertions(+), 220 deletions(-)
 delete mode 100644 examples/ipsec-secgw/test/linux_test4.sh
 delete mode 100644 examples/ipsec-secgw/test/linux_test6.sh

diff --git a/examples/ipsec-secgw/test/common_defs.sh b/examples/ipsec-secgw/test/common_defs.sh
index 09689af78..911857a60 100644
--- a/examples/ipsec-secgw/test/common_defs.sh
+++ b/examples/ipsec-secgw/test/common_defs.sh
@@ -80,11 +80,8 @@ config_remote_iface()
 
 	ssh ${REMOTE_HOST} ip neigh flush dev ${REMOTE_IFACE}
 
-	# by some reason following ip neigh doesn't work for me here properly:
-	#ssh ${REMOTE_HOST} ip neigh add ${LOCAL_IPV4} \
-	#		dev ${REMOTE_IFACE} lladr ${LOCAL_MAC}
-	# so used arp instead.
-	ssh ${REMOTE_HOST} arp -i ${REMOTE_IFACE} -s ${LOCAL_IPV4} ${LOCAL_MAC}
+	ssh ${REMOTE_HOST} ip neigh add ${LOCAL_IPV4} \
+			dev ${REMOTE_IFACE} lladdr ${LOCAL_MAC}
 	ssh ${REMOTE_HOST} ip neigh show dev ${REMOTE_IFACE}
 
 	ssh ${REMOTE_HOST} iptables --flush
diff --git a/examples/ipsec-secgw/test/linux_test4.sh b/examples/ipsec-secgw/test/linux_test4.sh
deleted file mode 100644
index 85efc5d90..000000000
--- a/examples/ipsec-secgw/test/linux_test4.sh
+++ /dev/null
@@ -1,78 +0,0 @@
-#! /bin/bash
-
-# usage:  /bin/bash linux_test4.sh <ipsec_mode>
-# for list of available modes please refer to run_test.sh.
-# ipsec-secgw (IPv4 mode) functional test script.
-#
-# Note that for most of them you required appropriate crypto PMD/device
-# to be avaialble.
-# Also user has to setup properly the following environment variables:
-#  SGW_PATH - path to the ipsec-secgw binary to test
-#  REMOTE_HOST - ip/hostname of the DUT
-#  REMOTE_IFACE - iface name for the test-port on DUT
-#  ETH_DEV - ethernet device to be used on SUT by DPDK ('-w <pci-id>')
-# Also user can optonally setup:
-#  SGW_LCORE - lcore to run ipsec-secgw on (default value is 0)
-#  CRYPTO_DEV - crypto device to be used ('-w <pci-id>')
-#  if none specified appropriate vdevs will be created by the scrit
-#  MULTI_SEG_TEST - ipsec-secgw option to enable reassembly support and
-#  specify size of reassembly table (i.e. MULTI_SEG_TEST="--reassemble 128")
-#
-# The purpose of the script is to automate ipsec-secgw testing
-# using another system running linux as a DUT.
-# It expects that SUT and DUT are connected through at least 2 NICs.
-# One NIC is expected to be managed by linux both machines,
-# and will be used as a control path
-# Make sure user from SUT can ssh to DUT without entering password.
-# Second NIC (test-port) should be reserved for DPDK on SUT,
-# and should be managed by linux on DUT.
-# The script starts ipsec-secgw with 2 NIC devices: test-port and tap vdev.
-# Then configures local tap iface and remote iface and ipsec policies
-# in the following way:
-# traffic going over test-port in both directions has to be
-# protected by ipsec.
-# raffic going over TAP in both directions doesn't have to be protected.
-# I.E:
-# DUT OS(NIC1)--(ipsec)-->(NIC1)ipsec-secgw(TAP)--(plain)-->(TAP)SUT OS
-# SUT OS(TAP)--(plain)-->(TAP)psec-secgw(NIC1)--(ipsec)-->(NIC1)DUT OS
-# Then tries to perorm some data transfer using the scheme decribed above.
-#
-
-DIR=`dirname $0`
-MODE=$1
-
- . ${DIR}/common_defs.sh
- . ${DIR}/${MODE}_defs.sh
-
-#make linux to generate fragmented packets
-if [[ -n "${MULTI_SEG_TEST}" && -n "${SGW_CMD_XPRM}" ]]; then
-	echo "multi-segment test is enabled"
-	SGW_CMD_XPRM="${SGW_CMD_XPRM} ${MULTI_SEG_TEST}"
-	PING_LEN=5000
-	MTU_LEN=1500
-else
-	PING_LEN=${DEF_PING_LEN}
-	MTU_LEN=${DEF_MTU_LEN}
-fi
-
-config_secgw
-
-secgw_start
-
-config_iface
-
-config_remote_xfrm
-
- . ${DIR}/data_rxtx.sh
-
-set_local_mtu ${MTU_LEN}
-ping_test1 ${REMOTE_IPV4} 0 ${PING_LEN}
-st=$?
-if [[ $st -eq 0 ]]; then
-	set_local_mtu ${DEF_MTU_LEN}
-	scp_test1 ${REMOTE_IPV4}
-	st=$?
-fi
-
-secgw_stop
-exit $st
diff --git a/examples/ipsec-secgw/test/linux_test6.sh b/examples/ipsec-secgw/test/linux_test6.sh
deleted file mode 100644
index c749dcef8..000000000
--- a/examples/ipsec-secgw/test/linux_test6.sh
+++ /dev/null
@@ -1,79 +0,0 @@
-#! /bin/bash
-
-# usage:  /bin/bash linux_test6.sh <ipsec_mode>
-# for list of available modes please refer to run_test.sh.
-# ipsec-secgw (IPv6 mode) functional test script.
-#
-# Note that for most of them you required appropriate crypto PMD/device
-# to be avaialble.
-# Also user has to setup properly the following environment variables:
-#  SGW_PATH - path to the ipsec-secgw binary to test
-#  REMOTE_HOST - ip/hostname of the DUT
-#  REMOTE_IFACE - iface name for the test-port on DUT
-#  ETH_DEV - ethernet device to be used on SUT by DPDK ('-w <pci-id>')
-# Also user can optonally setup:
-#  SGW_LCORE - lcore to run ipsec-secgw on (default value is 0)
-#  CRYPTO_DEV - crypto device to be used ('-w <pci-id>')
-#  if none specified appropriate vdevs will be created by the scrit
-#  MULTI_SEG_TEST - ipsec-secgw option to enable reassembly support and
-#  specify size of reassembly table (i.e. MULTI_SEG_TEST="--reassemble 128")
-#
-# The purpose of the script is to automate ipsec-secgw testing
-# using another system running linux as a DUT.
-# It expects that SUT and DUT are connected through at least 2 NICs.
-# One NIC is expected to be managed by linux both machines,
-# and will be used as a control path.
-# Make sure user from SUT can ssh to DUT without entering password,
-# also make sure that sshd over ipv6 is enabled.
-# Second NIC (test-port) should be reserved for DPDK on SUT,
-# and should be managed by linux on DUT.
-# The script starts ipsec-secgw with 2 NIC devices: test-port and tap vdev.
-# Then configures local tap iface and remote iface and ipsec policies
-# in the following way:
-# traffic going over test-port in both directions has to be
-# protected by ipsec.
-# raffic going over TAP in both directions doesn't have to be protected.
-# I.E:
-# DUT OS(NIC1)--(ipsec)-->(NIC1)ipsec-secgw(TAP)--(plain)-->(TAP)SUT OS
-# SUT OS(TAP)--(plain)-->(TAP)psec-secgw(NIC1)--(ipsec)-->(NIC1)DUT OS
-# Then tries to perorm some data transfer using the scheme decribed above.
-#
-
-DIR=`dirname $0`
-MODE=$1
-
- . ${DIR}/common_defs.sh
- . ${DIR}/${MODE}_defs.sh
-
-#make linux to generate fragmented packets
-if [[ -n "${MULTI_SEG_TEST}" && -n "${SGW_CMD_XPRM}" ]]; then
-	echo "multi-segment test is enabled"
-	SGW_CMD_XPRM="${SGW_CMD_XPRM} ${MULTI_SEG_TEST}"
-	PING_LEN=5000
-	MTU_LEN=1500
-else
-	PING_LEN=${DEF_PING_LEN}
-	MTU_LEN=${DEF_MTU_LEN}
-fi
-
-config_secgw
-
-secgw_start
-
-config6_iface
-
-config6_remote_xfrm
-
- . ${DIR}/data_rxtx.sh
-
-set_local_mtu ${MTU_LEN}
-ping6_test1 ${REMOTE_IPV6} 0 ${PING_LEN}
-st=$?
-if [[ $st -eq 0 ]]; then
-	set_local_mtu ${DEF_MTU_LEN}
-	scp_test1 ${REMOTE_IPV6}
-	st=$?
-fi
-
-secgw_stop
-exit $st
diff --git a/examples/ipsec-secgw/test/run_test.sh b/examples/ipsec-secgw/test/run_test.sh
index 8055a4c04..10821e678 100755
--- a/examples/ipsec-secgw/test/run_test.sh
+++ b/examples/ipsec-secgw/test/run_test.sh
@@ -1,7 +1,7 @@
 #! /bin/bash
 
-# usage: /bin/bash run_test.sh [-46]
-# Run all defined linux_test[4,6].sh test-cases one by one
+# usage: /bin/bash run_test.sh [-46mp]
+# Run all defined linux_test.sh test-cases one by one
 # user has to setup properly the following environment variables:
 #  SGW_PATH - path to the ipsec-secgw binary to test
 #  REMOTE_HOST - ip/hostname of the DUT
@@ -13,7 +13,7 @@
 #  if none specified appropriate vdevs will be created by the scrit
 #  MULTI_SEG_TEST - ipsec-secgw option to enable reassembly support and
 #  specify size of reassembly table (i.e. MULTI_SEG_TEST="--reassemble 128")
-# refer to linux_test[4,6].sh for more information
+# refer to linux_test.sh for more information
 
 
 # All supported modes to test.
@@ -24,9 +24,11 @@
 usage()
 {
 	echo "Usage:"
-	echo -e "\t$0 -[46p]"
+	echo -e "\t$0 -[46mp]"
 	echo -e "\t\t-4 Perform Linux IPv4 network tests"
 	echo -e "\t\t-6 Perform Linux IPv6 network tests"
+	echo -e "\t\t-m Add mixed IP protocol tests to IPv4/IPv6 \
+(only with option [-46])"
 	echo -e "\t\t-p Perform packet validation tests"
 	echo -e "\t\t-h Display this help"
 }
@@ -73,7 +75,8 @@ DIR=$(dirname $0)
 run4=0
 run6=0
 runpkt=0
-while getopts ":46ph" opt
+mixed=0
+while getopts ":46mph" opt
 do
 	case $opt in
 		4)
@@ -82,6 +85,9 @@ do
 		6)
 			run6=1
 			;;
+		m)
+			mixed=1
+			;;
 		p)
 			runpkt=1
 			;;
@@ -124,20 +130,36 @@ if [[ ${run4} -eq 1 || ${run6} -eq 1 ]]; then
 		echo "starting test ${i}"
 
 		st4=0
+		st4m=0
 		if [[ ${run4} -ne 0 ]]; then
-			/bin/bash ${DIR}/linux_test4.sh ${i}
+			/bin/bash ${DIR}/linux_test.sh ipv4-ipv4 ${i}
 			st4=$?
-			echo "test4 ${i} finished with status ${st4}"
+			echo "test IPv4 ${i} finished with status ${st4}"
+
+			if [[ ${mixed} -ne 0 ]] && [[ ${i} = "tun"* ]]; then
+				/bin/bash ${DIR}/linux_test.sh ipv4-ipv6 ${i}
+				st4m=$?
+				echo "test IPv4-IPv6 ${i} finished with \
+status ${st4m}"
+			fi
 		fi
 
 		st6=0
+		st6m=0
 		if [[ ${run6} -ne 0 ]]; then
-			/bin/bash ${DIR}/linux_test6.sh ${i}
+			/bin/bash ${DIR}/linux_test.sh ipv6-ipv6 ${i}
 			st6=$?
-			echo "test6 ${i} finished with status ${st6}"
+			echo "test IPv6 ${i} finished with status ${st6}"
+
+			if [[ ${mixed} -ne 0 ]] && [[ ${i} = "tun"* ]]; then
+				/bin/bash ${DIR}/linux_test.sh ipv6-ipv4 ${i}
+				st6m=$?
+				echo "test IPv6-IPv4 ${i} finished with \
+status ${st6m}"
+			fi
 		fi
 
-		let "st = st4 + st6"
+		let "st = st4 + st6 + st4m + st6m"
 		if [[ $st -ne 0 ]]; then
 			echo "ERROR test ${i} FAILED"
 			exit $st
diff --git a/examples/ipsec-secgw/test/trs_3descbc_sha1_defs.sh b/examples/ipsec-secgw/test/trs_3descbc_sha1_defs.sh
index 31f94492f..b124d7888 100644
--- a/examples/ipsec-secgw/test/trs_3descbc_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/trs_3descbc_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_3descbc_sha1_esn_defs.sh b/examples/ipsec-secgw/test/trs_3descbc_sha1_esn_defs.sh
index e4283f3dd..255acbb32 100644
--- a/examples/ipsec-secgw/test/trs_3descbc_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/trs_3descbc_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aescbc_sha1_defs.sh b/examples/ipsec-secgw/test/trs_aescbc_sha1_defs.sh
index d68552fce..55f696cbc 100644
--- a/examples/ipsec-secgw/test/trs_aescbc_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aescbc_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aescbc_sha1_esn_defs.sh b/examples/ipsec-secgw/test/trs_aescbc_sha1_esn_defs.sh
index ce7c977a3..851b38d59 100644
--- a/examples/ipsec-secgw/test/trs_aescbc_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aescbc_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aesctr_sha1_defs.sh b/examples/ipsec-secgw/test/trs_aesctr_sha1_defs.sh
index 73642f881..50f778ae5 100644
--- a/examples/ipsec-secgw/test/trs_aesctr_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aesctr_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aesctr_sha1_esn_defs.sh b/examples/ipsec-secgw/test/trs_aesctr_sha1_esn_defs.sh
index e401a4bed..88e2eed08 100644
--- a/examples/ipsec-secgw/test/trs_aesctr_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aesctr_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aesgcm_defs.sh b/examples/ipsec-secgw/test/trs_aesgcm_defs.sh
index 8382d3d52..c47578a38 100644
--- a/examples/ipsec-secgw/test/trs_aesgcm_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aesgcm_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ aead "rfc4106\(gcm\(aes\)\)" \
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aesgcm_esn_defs.sh b/examples/ipsec-secgw/test/trs_aesgcm_esn_defs.sh
index 94958d199..182f05a34 100644
--- a/examples/ipsec-secgw/test/trs_aesgcm_esn_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aesgcm_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ aead "rfc4106\(gcm\(aes\)\)" \
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_3descbc_sha1_common_defs.sh b/examples/ipsec-secgw/test/tun_3descbc_sha1_common_defs.sh
index dd802d6be..704c0c57f 100644
--- a/examples/ipsec-secgw/test/tun_3descbc_sha1_common_defs.sh
+++ b/examples/ipsec-secgw/test/tun_3descbc_sha1_common_defs.sh
@@ -70,3 +70,71 @@ EOF
 
 	cat ${SGW_CFG_FILE}
 }
+
+config_secgw_mixed()
+{
+	cat <<EOF > ${SGW_CFG_FILE}
+#sp in IPv4 rules
+sp ipv4 in esp protect 6 pri 2 src ${REMOTE_IPV4}/32 dst ${LOCAL_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv4 rules
+sp ipv4 out esp protect 6 pri 2 src ${LOCAL_IPV4}/32 dst ${REMOTE_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#sp in IPv6 rules
+sp ipv6 in esp protect 8 pri 2 src ${REMOTE_IPV6}/128 dst ${LOCAL_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv6 rules
+sp ipv6 out esp protect 8 pri 2 src ${LOCAL_IPV6}/128 dst ${REMOTE_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SA in rules
+sa in 8 cipher_algo 3des-cbc \
+cipher_key \
+de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+sa in 6 cipher_algo 3des-cbc \
+cipher_key \
+de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+#SA out rules
+sa out 8 cipher_algo 3des-cbc \
+cipher_key \
+de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+sa out 6 cipher_algo 3des-cbc \
+cipher_key \
+de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+#Routing rules
+rt ipv4 dst ${REMOTE_IPV4}/32 port 0
+rt ipv4 dst ${LOCAL_IPV4}/32 port 1
+
+rt ipv6 dst ${REMOTE_IPV6}/128 port 0
+rt ipv6 dst ${LOCAL_IPV6}/128 port 1
+
+#neighbours
+neigh port 0 ${REMOTE_MAC}
+neigh port 1 ${LOCAL_MAC}
+EOF
+
+	cat ${SGW_CFG_FILE}
+}
diff --git a/examples/ipsec-secgw/test/tun_3descbc_sha1_defs.sh b/examples/ipsec-secgw/test/tun_3descbc_sha1_defs.sh
index 2bbe14292..3df050c00 100644
--- a/examples/ipsec-secgw/test/tun_3descbc_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/tun_3descbc_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_3descbc_sha1_esn_defs.sh b/examples/ipsec-secgw/test/tun_3descbc_sha1_esn_defs.sh
index 98349c7bc..349969ceb 100644
--- a/examples/ipsec-secgw/test/tun_3descbc_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/tun_3descbc_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aescbc_sha1_common_defs.sh b/examples/ipsec-secgw/test/tun_aescbc_sha1_common_defs.sh
index 4025da232..65150e389 100644
--- a/examples/ipsec-secgw/test/tun_aescbc_sha1_common_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aescbc_sha1_common_defs.sh
@@ -66,3 +66,67 @@ EOF
 
 	cat ${SGW_CFG_FILE}
 }
+
+config_secgw_mixed()
+{
+	cat <<EOF > ${SGW_CFG_FILE}
+#sp in IPv4 rules
+sp ipv4 in esp protect 6 pri 2 src ${REMOTE_IPV4}/32 dst ${LOCAL_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv4 rules
+sp ipv4 out esp protect 6 pri 2 src ${LOCAL_IPV4}/32 dst ${REMOTE_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#sp in IPv6 rules
+sp ipv6 in esp protect 8 pri 2 src ${REMOTE_IPV6}/128 dst ${LOCAL_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv6 rules
+sp ipv6 out esp protect 8 pri 2 src ${LOCAL_IPV6}/128 dst ${REMOTE_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SA in rules
+sa in 8 cipher_algo aes-128-cbc \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+sa in 6 cipher_algo aes-128-cbc \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+#SA out rules
+sa out 8 cipher_algo aes-128-cbc \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+sa out 6 cipher_algo aes-128-cbc \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+#Routing rules
+rt ipv4 dst ${REMOTE_IPV4}/32 port 0
+rt ipv4 dst ${LOCAL_IPV4}/32 port 1
+
+rt ipv6 dst ${REMOTE_IPV6}/128 port 0
+rt ipv6 dst ${LOCAL_IPV6}/128 port 1
+
+#neighbours
+neigh port 0 ${REMOTE_MAC}
+neigh port 1 ${LOCAL_MAC}
+EOF
+
+	cat ${SGW_CFG_FILE}
+}
diff --git a/examples/ipsec-secgw/test/tun_aescbc_sha1_defs.sh b/examples/ipsec-secgw/test/tun_aescbc_sha1_defs.sh
index 18aade3a9..aa1e6a4c4 100644
--- a/examples/ipsec-secgw/test/tun_aescbc_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aescbc_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aescbc_sha1_esn_defs.sh b/examples/ipsec-secgw/test/tun_aescbc_sha1_esn_defs.sh
index 28c1125d6..dda8a082a 100644
--- a/examples/ipsec-secgw/test/tun_aescbc_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aescbc_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aesctr_sha1_common_defs.sh b/examples/ipsec-secgw/test/tun_aesctr_sha1_common_defs.sh
index a3ac3a698..13db66b6f 100644
--- a/examples/ipsec-secgw/test/tun_aesctr_sha1_common_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesctr_sha1_common_defs.sh
@@ -66,3 +66,67 @@ EOF
 
 	cat ${SGW_CFG_FILE}
 }
+
+config_secgw_mixed()
+{
+	cat <<EOF > ${SGW_CFG_FILE}
+#sp in IPv4 rules
+sp ipv4 in esp protect 6 pri 2 src ${REMOTE_IPV4}/32 dst ${LOCAL_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv4 rules
+sp ipv4 out esp protect 6 pri 2 src ${LOCAL_IPV4}/32 dst ${REMOTE_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#sp in IPv6 rules
+sp ipv6 in esp protect 8 pri 2 src ${REMOTE_IPV6}/128 dst ${LOCAL_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv6 rules
+sp ipv6 out esp protect 8 pri 2 src ${LOCAL_IPV6}/128 dst ${REMOTE_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SA in rules
+sa in 8 cipher_algo aes-128-ctr \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+sa in 6 cipher_algo aes-128-ctr \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+#SA out rules
+sa out 8 cipher_algo aes-128-ctr \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+sa out 6 cipher_algo aes-128-ctr \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+#Routing rules
+rt ipv4 dst ${REMOTE_IPV4}/32 port 0
+rt ipv4 dst ${LOCAL_IPV4}/32 port 1
+
+rt ipv6 dst ${REMOTE_IPV6}/128 port 0
+rt ipv6 dst ${LOCAL_IPV6}/128 port 1
+
+#neighbours
+neigh port 0 ${REMOTE_MAC}
+neigh port 1 ${LOCAL_MAC}
+EOF
+
+	cat ${SGW_CFG_FILE}
+}
diff --git a/examples/ipsec-secgw/test/tun_aesctr_sha1_defs.sh b/examples/ipsec-secgw/test/tun_aesctr_sha1_defs.sh
index 3710f897c..5712ee9bd 100644
--- a/examples/ipsec-secgw/test/tun_aesctr_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesctr_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aesctr_sha1_esn_defs.sh b/examples/ipsec-secgw/test/tun_aesctr_sha1_esn_defs.sh
index c3ce11da1..5fbe2cfe3 100644
--- a/examples/ipsec-secgw/test/tun_aesctr_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesctr_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aesgcm_common_defs.sh b/examples/ipsec-secgw/test/tun_aesgcm_common_defs.sh
index 278377967..f39a8e4bc 100644
--- a/examples/ipsec-secgw/test/tun_aesgcm_common_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesgcm_common_defs.sh
@@ -58,3 +58,59 @@ EOF
 
 	cat ${SGW_CFG_FILE}
 }
+
+config_secgw_mixed()
+{
+	cat <<EOF > ${SGW_CFG_FILE}
+#sp in IPv4 rules
+sp ipv4 in esp protect 6 pri 2 src ${REMOTE_IPV4}/32 dst ${LOCAL_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv4 rules
+sp ipv4 out esp protect 6 pri 2 src ${LOCAL_IPV4}/32 dst ${REMOTE_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#sp in IPv6 rules
+sp ipv6 in esp protect 8 pri 2 src ${REMOTE_IPV6}/128 dst ${LOCAL_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv6 rules
+sp ipv6 out esp protect 8 pri 2 src ${LOCAL_IPV6}/128 dst ${REMOTE_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SA in rules
+sa in 8 aead_algo aes-128-gcm \
+aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${REMOTE_IPV4} dst ${LOCAL_IPV4} ${SGW_CFG_XPRM}
+
+sa in 6 aead_algo aes-128-gcm \
+aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${REMOTE_IPV6} dst ${LOCAL_IPV6} ${SGW_CFG_XPRM}
+
+#SA out rules
+sa out 8 aead_algo aes-128-gcm \
+aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${LOCAL_IPV4} dst ${REMOTE_IPV4} ${SGW_CFG_XPRM}
+
+sa out 6 aead_algo aes-128-gcm \
+aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${LOCAL_IPV6} dst ${REMOTE_IPV6} ${SGW_CFG_XPRM}
+
+#Routing rules
+rt ipv4 dst ${REMOTE_IPV4}/32 port 0
+rt ipv4 dst ${LOCAL_IPV4}/32 port 1
+
+rt ipv6 dst ${REMOTE_IPV6}/128 port 0
+rt ipv6 dst ${LOCAL_IPV6}/128 port 1
+
+#neighbours
+neigh port 0 ${REMOTE_MAC}
+neigh port 1 ${LOCAL_MAC}
+EOF
+
+	cat ${SGW_CFG_FILE}
+}
diff --git a/examples/ipsec-secgw/test/tun_aesgcm_defs.sh b/examples/ipsec-secgw/test/tun_aesgcm_defs.sh
index 8ae65321b..6fb8aa6b3 100644
--- a/examples/ipsec-secgw/test/tun_aesgcm_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesgcm_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ aead "rfc4106\(gcm\(aes\)\)" \
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aesgcm_esn_defs.sh b/examples/ipsec-secgw/test/tun_aesgcm_esn_defs.sh
index 606232349..84a666342 100644
--- a/examples/ipsec-secgw/test/tun_aesgcm_esn_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesgcm_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ aead "rfc4106\(gcm\(aes\)\)" \
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 flag esn \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 flag esn \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 flag esn \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 flag esn \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 0/2] fix SAD selection logic
  2019-09-05 12:35 [dpdk-dev] [PATCH 0/2] fix SAD selection logic Mariusz Drost
  2019-09-05 12:35 ` [dpdk-dev] [PATCH 1/2] examples/ipsec-secgw: " Mariusz Drost
  2019-09-05 12:35 ` [dpdk-dev] [PATCH 2/2] examples/ipsec-secgw: tests for split SAD Mariusz Drost
@ 2019-09-24 10:35 ` Mariusz Drost
  2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: " Mariusz Drost
  2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 2/2] examples/ipsec-secgw: tests for split SAD Mariusz Drost
  2 siblings, 2 replies; 15+ messages in thread
From: Mariusz Drost @ 2019-09-24 10:35 UTC (permalink / raw)
  To: radu.nicolau, akhil.goyal, konstantin.ananyev; +Cc: dev, Mariusz Drost

Code fix for SAD selection logic by splitting SAD into IPv4 SAD and
IPv6 SAD. Test scripts updated to reflect changes.

v2:
* Added linux_test.sh
* Modified ep0.cfg and ep1.cfg files to run with ipsec-secgw app

Mariusz Drost (2):
  examples/ipsec-secgw: fix SAD selection logic
  examples/ipsec-secgw: tests for split SAD

 examples/ipsec-secgw/ep0.cfg                  |  58 ++-
 examples/ipsec-secgw/ep1.cfg                  |  62 ++-
 examples/ipsec-secgw/ipsec-secgw.c            |  48 ++-
 examples/ipsec-secgw/ipsec.c                  |   5 +-
 examples/ipsec-secgw/ipsec.h                  |  21 +-
 examples/ipsec-secgw/sa.c                     | 396 ++++++++++++------
 examples/ipsec-secgw/test/common_defs.sh      |   7 +-
 .../test/{linux_test6.sh => linux_test.sh}    |  94 ++++-
 examples/ipsec-secgw/test/linux_test4.sh      |  78 ----
 examples/ipsec-secgw/test/run_test.sh         |  42 +-
 .../ipsec-secgw/test/trs_3descbc_sha1_defs.sh |   7 +-
 .../test/trs_3descbc_sha1_esn_defs.sh         |   7 +-
 .../ipsec-secgw/test/trs_aescbc_sha1_defs.sh  |   7 +-
 .../test/trs_aescbc_sha1_esn_defs.sh          |   7 +-
 .../ipsec-secgw/test/trs_aesctr_sha1_defs.sh  |   7 +-
 .../test/trs_aesctr_sha1_esn_defs.sh          |   7 +-
 examples/ipsec-secgw/test/trs_aesgcm_defs.sh  |   7 +-
 .../ipsec-secgw/test/trs_aesgcm_esn_defs.sh   |   7 +-
 .../test/tun_3descbc_sha1_common_defs.sh      |  68 +++
 .../ipsec-secgw/test/tun_3descbc_sha1_defs.sh |  77 +++-
 .../test/tun_3descbc_sha1_esn_defs.sh         |  77 +++-
 .../test/tun_aescbc_sha1_common_defs.sh       |  64 +++
 .../ipsec-secgw/test/tun_aescbc_sha1_defs.sh  |  77 +++-
 .../test/tun_aescbc_sha1_esn_defs.sh          |  77 +++-
 .../test/tun_aesctr_sha1_common_defs.sh       |  64 +++
 .../ipsec-secgw/test/tun_aesctr_sha1_defs.sh  |  77 +++-
 .../test/tun_aesctr_sha1_esn_defs.sh          |  77 +++-
 .../test/tun_aesgcm_common_defs.sh            |  56 +++
 examples/ipsec-secgw/test/tun_aesgcm_defs.sh  |  77 +++-
 .../ipsec-secgw/test/tun_aesgcm_esn_defs.sh   |  77 +++-
 30 files changed, 1397 insertions(+), 338 deletions(-)
 rename examples/ipsec-secgw/test/{linux_test6.sh => linux_test.sh} (50%)
 delete mode 100644 examples/ipsec-secgw/test/linux_test4.sh

-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-09-24 10:35 ` [dpdk-dev] [PATCH v2 0/2] fix SAD selection logic Mariusz Drost
@ 2019-09-24 10:35   ` " Mariusz Drost
  2019-09-24 12:18     ` Ananyev, Konstantin
                       ` (2 more replies)
  2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 2/2] examples/ipsec-secgw: tests for split SAD Mariusz Drost
  1 sibling, 3 replies; 15+ messages in thread
From: Mariusz Drost @ 2019-09-24 10:35 UTC (permalink / raw)
  To: radu.nicolau, akhil.goyal, konstantin.ananyev
  Cc: dev, Mariusz Drost, Lukasz Bartosik

Ipsec-secgw example application fails to initialize when using default
configuration file (ep0.cfg) in library mode (librte_ipsec enabled).

The reason is that two of SP rules in ep0.cfg, one for IPv4 and one
for IPv6, are using the same SPI number. When SA rules are initialized,
their SPI number is checked against SPIs stored in SPD. For library
mode, it is not allowed for the same SA to handle both IPv4 and IPv6.

Solution is to split SAD into two separate parts - one for IPv4 and one
for IPv6. Usage of SAs stays the same. Only change is to pass correct
SAD (IPv4 or IPv6) in places where previously combined database was
passed.

Split of SA entries is done at initialization stage. Most of given SA
entries are checked against SPD. If matching entry is in IPv4 SPD, SA
rule is added to IPv4 SAD (respectively for IPv6). Different splitting
method is used only when SA entry is for tunnel in inbound direction.
In that case if IPv4 tunnel should be used, SA entry is added to IPv4
SAD (respectively for IPv6). Reasoning is that inner IP version can
be different than outer IP version for tunneled traffic.

Bugzilla ID: 239
Fixes: 5a032a71c6d3 ("examples/ipsec-secgw: make app to use IPsec library")

Reported-by: Lukasz Bartosik <lbartosik@marvell.com>
Signed-off-by: Mariusz Drost <mariuszx.drost@intel.com>
---
 examples/ipsec-secgw/ipsec-secgw.c |  48 ++--
 examples/ipsec-secgw/ipsec.c       |   5 +-
 examples/ipsec-secgw/ipsec.h       |  21 +-
 examples/ipsec-secgw/sa.c          | 396 ++++++++++++++++++++---------
 4 files changed, 312 insertions(+), 158 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c
index 0d1fd6af6..2b0b8226b 100644
--- a/examples/ipsec-secgw/ipsec-secgw.c
+++ b/examples/ipsec-secgw/ipsec-secgw.c
@@ -562,11 +562,10 @@ send_single_packet(struct rte_mbuf *m, uint16_t port, uint8_t proto)
 }
 
 static inline void
-inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
-		uint16_t lim)
+inbound_sp_sa(struct sp_ctx *sp, struct traffic_type *ip, uint16_t lim)
 {
 	struct rte_mbuf *m;
-	uint32_t i, j, res, sa_idx;
+	uint32_t i, j, res;
 
 	if (ip->num == 0 || sp == NULL)
 		return;
@@ -593,8 +592,7 @@ inbound_sp_sa(struct sp_ctx *sp, struct sa_ctx *sa, struct traffic_type *ip,
 			continue;
 		}
 
-		sa_idx = SPI2IDX(res);
-		if (!inbound_sa_check(sa, m, sa_idx)) {
+		if (!inbound_sa_check(m, res)) {
 			rte_pktmbuf_free(m);
 			continue;
 		}
@@ -652,15 +650,16 @@ process_pkts_inbound(struct ipsec_ctx *ipsec_ctx,
 				traffic->ipsec.num, MAX_PKT_BURST);
 		split46_traffic(traffic, traffic->ipsec.pkts, nb_pkts_in);
 	} else {
-		inbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.pkts,
-			traffic->ipsec.saptr, traffic->ipsec.num);
+		inbound_sa_lookup(ipsec_ctx->sa4_ctx, ipsec_ctx->sa6_ctx,
+			traffic->ipsec.pkts, traffic->ipsec.saptr,
+			traffic->ipsec.num);
 		ipsec_process(ipsec_ctx, traffic);
 	}
 
-	inbound_sp_sa(ipsec_ctx->sp4_ctx, ipsec_ctx->sa_ctx, &traffic->ip4,
+	inbound_sp_sa(ipsec_ctx->sp4_ctx, &traffic->ip4,
 			n_ip4);
 
-	inbound_sp_sa(ipsec_ctx->sp6_ctx, ipsec_ctx->sa_ctx, &traffic->ip6,
+	inbound_sp_sa(ipsec_ctx->sp6_ctx, &traffic->ip6,
 			n_ip6);
 }
 
@@ -728,8 +727,9 @@ process_pkts_outbound(struct ipsec_ctx *ipsec_ctx,
 			}
 		}
 	} else {
-		outbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.res,
-			traffic->ipsec.saptr, traffic->ipsec.num);
+		outbound_sa_lookup(ipsec_ctx->sa4_ctx, ipsec_ctx->sa6_ctx,
+			traffic->ipsec.res, traffic->ipsec.saptr,
+			traffic->ipsec.pkts, traffic->ipsec.num);
 		ipsec_process(ipsec_ctx, traffic);
 	}
 }
@@ -770,8 +770,9 @@ process_pkts_inbound_nosp(struct ipsec_ctx *ipsec_ctx,
 			}
 		}
 	} else {
-		inbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.pkts,
-			traffic->ipsec.saptr, traffic->ipsec.num);
+		inbound_sa_lookup(ipsec_ctx->sa4_ctx, ipsec_ctx->sa6_ctx,
+			traffic->ipsec.pkts, traffic->ipsec.saptr,
+			traffic->ipsec.num);
 		ipsec_process(ipsec_ctx, traffic);
 	}
 }
@@ -823,8 +824,9 @@ process_pkts_outbound_nosp(struct ipsec_ctx *ipsec_ctx,
 				traffic->ip6.pkts[i] = traffic->ipsec.pkts[i];
 		}
 	} else {
-		outbound_sa_lookup(ipsec_ctx->sa_ctx, traffic->ipsec.res,
-			traffic->ipsec.saptr, traffic->ipsec.num);
+		outbound_sa_lookup(ipsec_ctx->sa4_ctx, ipsec_ctx->sa6_ctx,
+			traffic->ipsec.res, traffic->ipsec.saptr,
+			traffic->ipsec.pkts, traffic->ipsec.num);
 		ipsec_process(ipsec_ctx, traffic);
 	}
 }
@@ -1042,13 +1044,13 @@ drain_inbound_crypto_queues(const struct lcore_conf *qconf,
 
 	/* process ipv4 packets */
 	if (trf.ip4.num != 0) {
-		inbound_sp_sa(ctx->sp4_ctx, ctx->sa_ctx, &trf.ip4, 0);
+		inbound_sp_sa(ctx->sp4_ctx, &trf.ip4, 0);
 		route4_pkts(qconf->rt4_ctx, trf.ip4.pkts, trf.ip4.num);
 	}
 
 	/* process ipv6 packets */
 	if (trf.ip6.num != 0) {
-		inbound_sp_sa(ctx->sp6_ctx, ctx->sa_ctx, &trf.ip6, 0);
+		inbound_sp_sa(ctx->sp6_ctx, &trf.ip6, 0);
 		route6_pkts(qconf->rt6_ctx, trf.ip6.pkts, trf.ip6.num);
 	}
 }
@@ -1109,14 +1111,16 @@ main_loop(__attribute__((unused)) void *dummy)
 	qconf->rt6_ctx = socket_ctx[socket_id].rt_ip6;
 	qconf->inbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_in;
 	qconf->inbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_in;
-	qconf->inbound.sa_ctx = socket_ctx[socket_id].sa_in;
+	qconf->inbound.sa4_ctx = socket_ctx[socket_id].sa_ip4_in;
+	qconf->inbound.sa6_ctx = socket_ctx[socket_id].sa_ip6_in;
 	qconf->inbound.cdev_map = cdev_map_in;
 	qconf->inbound.session_pool = socket_ctx[socket_id].session_pool;
 	qconf->inbound.session_priv_pool =
 			socket_ctx[socket_id].session_priv_pool;
 	qconf->outbound.sp4_ctx = socket_ctx[socket_id].sp_ip4_out;
 	qconf->outbound.sp6_ctx = socket_ctx[socket_id].sp_ip6_out;
-	qconf->outbound.sa_ctx = socket_ctx[socket_id].sa_out;
+	qconf->outbound.sa4_ctx = socket_ctx[socket_id].sa_ip4_out;
+	qconf->outbound.sa6_ctx = socket_ctx[socket_id].sa_ip6_out;
 	qconf->outbound.cdev_map = cdev_map_out;
 	qconf->outbound.session_pool = socket_ctx[socket_id].session_pool;
 	qconf->outbound.session_priv_pool =
@@ -2481,8 +2485,10 @@ main(int32_t argc, char **argv)
 	for (i = 0; i < NB_SOCKETS && i < rte_socket_count(); i++) {
 		socket_id = rte_socket_id_by_idx(i);
 		if ((socket_ctx[socket_id].mbuf_pool != NULL) &&
-			(socket_ctx[socket_id].sa_in == NULL) &&
-			(socket_ctx[socket_id].sa_out == NULL)) {
+			(socket_ctx[socket_id].sa_ip4_in == NULL) &&
+			(socket_ctx[socket_id].sa_ip6_in == NULL) &&
+			(socket_ctx[socket_id].sa_ip4_out == NULL) &&
+			(socket_ctx[socket_id].sa_ip6_out == NULL)) {
 			sa_init(&socket_ctx[socket_id], socket_id);
 			sp4_init(&socket_ctx[socket_id], socket_id);
 			sp6_init(&socket_ctx[socket_id], socket_id);
diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index dc85adfe5..1d4cb3167 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -581,7 +581,7 @@ ipsec_inbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
 {
 	struct ipsec_sa *sas[nb_pkts];
 
-	inbound_sa_lookup(ctx->sa_ctx, pkts, sas, nb_pkts);
+	inbound_sa_lookup(ctx->sa4_ctx, ctx->sa6_ctx, pkts, sas, nb_pkts);
 
 	ipsec_enqueue(esp_inbound, ctx, pkts, sas, nb_pkts);
 
@@ -601,7 +601,8 @@ ipsec_outbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[],
 {
 	struct ipsec_sa *sas[nb_pkts];
 
-	outbound_sa_lookup(ctx->sa_ctx, sa_idx, sas, nb_pkts);
+	outbound_sa_lookup(ctx->sa4_ctx, ctx->sa6_ctx, sa_idx, sas, pkts,
+			nb_pkts);
 
 	ipsec_enqueue(esp_outbound, ctx, pkts, sas, nb_pkts);
 
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 1efa6e488..736dec33b 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -174,7 +174,8 @@ struct ipsec_ctx {
 	struct rte_hash *cdev_map;
 	struct sp_ctx *sp4_ctx;
 	struct sp_ctx *sp6_ctx;
-	struct sa_ctx *sa_ctx;
+	struct sa_ctx *sa4_ctx;
+	struct sa_ctx *sa6_ctx;
 	uint16_t nb_qps;
 	uint16_t last_qp;
 	struct cdev_qp tbl[MAX_QP_PER_LCORE];
@@ -194,8 +195,10 @@ struct cdev_key {
 };
 
 struct socket_ctx {
-	struct sa_ctx *sa_in;
-	struct sa_ctx *sa_out;
+	struct sa_ctx *sa_ip4_in;
+	struct sa_ctx *sa_ip4_out;
+	struct sa_ctx *sa_ip6_in;
+	struct sa_ctx *sa_ip6_out;
 	struct sp_ctx *sp_ip4_in;
 	struct sp_ctx *sp_ip4_out;
 	struct sp_ctx *sp_ip6_in;
@@ -285,15 +288,17 @@ get_sym_cop(struct rte_crypto_op *cop)
 }
 
 int
-inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx);
+inbound_sa_check(struct rte_mbuf *m, uint32_t sa_idx);
 
 void
-inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
-		struct ipsec_sa *sa[], uint16_t nb_pkts);
+inbound_sa_lookup(struct sa_ctx *sa4_ctx, struct sa_ctx *sa6_ctx,
+		struct rte_mbuf *pkts[], struct ipsec_sa *sa[],
+		uint16_t nb_pkts);
 
 void
-outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
-		struct ipsec_sa *sa[], uint16_t nb_pkts);
+outbound_sa_lookup(struct sa_ctx *sa4_ctx, struct sa_ctx *sa6_ctx,
+		uint32_t sa_idx[], struct ipsec_sa *sa[],
+		struct rte_mbuf *pkts[], uint16_t nb_pkts);
 
 void
 sp4_init(struct socket_ctx *ctx, int32_t socket_id);
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index c3cf3bd1f..015d5cf01 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -130,11 +130,18 @@ const struct supported_aead_algo aead_algos[] = {
 	}
 };
 
-static struct ipsec_sa sa_out[IPSEC_SA_MAX_ENTRIES];
-static uint32_t nb_sa_out;
+struct ipsec_sa_db {
+	struct ipsec_sa sadb[IPSEC_SA_MAX_ENTRIES];
+	uint32_t nb;
+};
+
+static struct ipsec_sa_db sa_out;
+static struct ipsec_sa_db sa_in;
 
-static struct ipsec_sa sa_in[IPSEC_SA_MAX_ENTRIES];
-static uint32_t nb_sa_in;
+static struct ipsec_sa_db sa_ip4_out;
+static struct ipsec_sa_db sa_ip4_in;
+static struct ipsec_sa_db sa_ip6_out;
+static struct ipsec_sa_db sa_ip6_in;
 
 static const struct supported_cipher_algo *
 find_match_cipher_algo(const char *cipher_keyword)
@@ -236,23 +243,23 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 	uint32_t portid_p = 0;
 
 	if (strcmp(tokens[0], "in") == 0) {
-		ri = &nb_sa_in;
+		ri = &sa_in.nb;
 
 		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];
+		rule = &sa_in.sadb[*ri];
 	} else {
-		ri = &nb_sa_out;
+		ri = &sa_out.nb;
 
 		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];
+		rule = &sa_out.sadb[*ri];
 	}
 
 	/* spi number */
@@ -778,39 +785,6 @@ check_eth_dev_caps(uint16_t portid, uint32_t inbound)
 	return 0;
 }
 
-/*
- * Helper function, tries to determine next_proto for SPI
- * by searching though SP rules.
- */
-static int
-get_spi_proto(uint32_t spi, enum rte_security_ipsec_sa_direction dir,
-		struct ip_addr ip_addr[2], uint32_t mask[2])
-{
-	int32_t rc4, rc6;
-
-	rc4 = sp4_spi_present(spi, dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
-				ip_addr, mask);
-	rc6 = sp6_spi_present(spi, dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
-				ip_addr, mask);
-
-	if (rc4 >= 0) {
-		if (rc6 >= 0) {
-			RTE_LOG(ERR, IPSEC,
-				"%s: SPI %u used simultaeously by "
-				"IPv4(%d) and IPv6 (%d) SP rules\n",
-				__func__, spi, rc4, rc6);
-			return -EINVAL;
-		} else
-			return IPPROTO_IPIP;
-	} else if (rc6 < 0) {
-		RTE_LOG(ERR, IPSEC,
-			"%s: SPI %u is not used by any SP rule\n",
-			__func__, spi);
-		return -EINVAL;
-	} else
-		return IPPROTO_IPV6;
-}
-
 /*
  * Helper function for getting source and destination IP addresses
  * from SP. Needed for inline crypto transport mode, as addresses are not
@@ -819,16 +793,21 @@ get_spi_proto(uint32_t spi, enum rte_security_ipsec_sa_direction dir,
  * addresses got from SP into SA.
  */
 static int
-sa_add_address_inline_crypto(struct ipsec_sa *sa)
+sa_add_address_inline_crypto(struct ipsec_sa *sa, int ip_v)
 {
-	int protocol;
+	int rc4, rc6;
 	struct ip_addr ip_addr[2];
 	uint32_t mask[2];
 
-	protocol = get_spi_proto(sa->spi, sa->direction, ip_addr, mask);
-	if (protocol < 0)
-		return protocol;
-	else if (protocol == IPPROTO_IPIP) {
+	if (ip_v == IPPROTO_IPIP) {
+		rc4 = sp4_spi_present(sa->spi, sa->direction, ip_addr, mask);
+		if (rc4 < 0) {
+			RTE_LOG(ERR, IPSEC,
+			"%s: SPI %u is not used by any SP rule\n",
+			__func__, sa->spi);
+			return rc4;
+		}
+
 		sa->flags |= IP4_TRANSPORT;
 		if (mask[0] == IP4_FULL_MASK &&
 				mask[1] == IP4_FULL_MASK &&
@@ -844,7 +823,15 @@ sa_add_address_inline_crypto(struct ipsec_sa *sa)
 			__func__, sa->spi);
 			return -EINVAL;
 		}
-	} else if (protocol == IPPROTO_IPV6) {
+	} else if (ip_v == IPPROTO_IPV6) {
+		rc6 = sp6_spi_present(sa->spi, sa->direction, ip_addr, mask);
+		if (rc6 < 0) {
+			RTE_LOG(ERR, IPSEC,
+			"%s: SPI %u is not used by any SP rule\n",
+			__func__, sa->spi);
+			return rc6;
+		}
+
 		sa->flags |= IP6_TRANSPORT;
 		if (mask[0] == IP6_FULL_MASK &&
 				mask[1] == IP6_FULL_MASK &&
@@ -866,9 +853,93 @@ sa_add_address_inline_crypto(struct ipsec_sa *sa)
 	return 0;
 }
 
+/*
+ * Determine to what SAD put new SA entry:
+ * 1) tunnel-inbound - check IP address of a tunnel (outer IP header)
+ *	if tunnel is IPv4, add SA entry to IPv4 SAD
+ *	if tunnel is IPv6, add SA entry to IPv6 SAD
+ * 2) transport-inbound - check inbound SPD
+ *	if there is matching entry in IPv4 SPD, add SA entry to IPv4 SAD
+ *	if there is matching entry in IPv6 SPD, add SA entry to IPv6 SAD
+ * 3) tunnel-outbound/transport-outbound - check outbound SPD
+ *	if there is matching entry in IPv4 SPD, add SA entry to IPv4 SAD
+ *	if there is matching entry in IPv6 SPD, add SA entry to IPv6 SAD
+ */
+static int
+sa_split(struct ipsec_sa_db *sa4, struct ipsec_sa_db *sa6,
+		const struct ipsec_sa_db *ent, int sa4_ip_v[],
+		int sa6_ip_v[], uint32_t inbound)
+{
+	uint32_t i, idx4, idx6;
+	int rc4, rc6;
+	idx4 = 0;
+	idx6 = 0;
+
+	for (i = 0; i < ent->nb; i++) {
+		rc4 = sp4_spi_present(ent->sadb[i].spi, inbound, NULL, NULL);
+		rc6 = sp6_spi_present(ent->sadb[i].spi, inbound, NULL, NULL);
+
+		if (rc4 < 0 && rc6 < 0) {
+			RTE_LOG(ERR, IPSEC,
+			"%s: SPI %u is not used by any SP rule\n",
+			__func__, ent->sadb[i].spi);
+			return -EINVAL;
+		}
+
+		if (inbound) {
+			if (rc4 >= 0) {
+				if (IS_IP6_TUNNEL(ent->sadb[i].flags)) {
+					sa6_ip_v[idx6] = IPPROTO_IPIP;
+					sa6->sadb[idx6++] = ent->sadb[i];
+				} else {
+					sa4_ip_v[idx4] = IPPROTO_IPIP;
+					sa4->sadb[idx4++] = ent->sadb[i];
+				}
+			}
+			if (rc6 >= 0) {
+				if (IS_IP4_TUNNEL(ent->sadb[i].flags)) {
+					sa4_ip_v[idx4] = IPPROTO_IPV6;
+					sa4->sadb[idx4++] = ent->sadb[i];
+				} else {
+					sa6_ip_v[idx6] = IPPROTO_IPV6;
+					sa6->sadb[idx6++] = ent->sadb[i];
+				}
+			}
+		} else {
+			if (rc4 >= 0) {
+				sa4_ip_v[idx4] = IPPROTO_IPIP;
+				sa4->sadb[idx4++] = ent->sadb[i];
+			}
+			if (rc6 >= 0) {
+				sa6_ip_v[idx6] = IPPROTO_IPV6;
+				sa6->sadb[idx6++] = ent->sadb[i];
+			}
+		}
+	}
+
+		sa4->nb = idx4;
+		sa6->nb = idx6;
+
+	return 0;
+}
+
+static int
+sa_in_split(struct ipsec_sa_db *sa4, struct ipsec_sa_db *sa6,
+		const struct ipsec_sa_db *ent, int sa4_ip_v[], int sa6_ip_v[])
+{
+	return sa_split(sa4, sa6, ent, sa4_ip_v, sa6_ip_v, 1);
+}
+
+static int
+sa_out_split(struct ipsec_sa_db *sa4, struct ipsec_sa_db *sa6,
+		const struct ipsec_sa_db *ent, int sa4_ip_v[], int sa6_ip_v[])
+{
+	return sa_split(sa4, sa6, ent, sa4_ip_v, sa6_ip_v, 0);
+}
+
 static int
-sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
-		uint32_t nb_entries, uint32_t inbound,
+sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa_db *entries,
+		uint32_t inbound, int ip_v,
 		struct socket_ctx *skt_ctx)
 {
 	struct ipsec_sa *sa;
@@ -880,15 +951,15 @@ 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 = SPI2IDX(entries[i].spi);
+	for (i = 0; i < entries->nb; i++) {
+		idx = SPI2IDX(entries->sadb[i].spi);
 		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 = entries->sadb[i];
 		sa->seq = 0;
 
 		if (sa->type == RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
@@ -910,7 +981,7 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			if (sa->type ==
 				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
 				inline_status =
-					sa_add_address_inline_crypto(sa);
+					sa_add_address_inline_crypto(sa, ip_v);
 				if (inline_status < 0)
 					return inline_status;
 			}
@@ -1023,17 +1094,17 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 }
 
 static inline int
-sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
-		uint32_t nb_entries, struct socket_ctx *skt_ctx)
+sa_out_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa_db *entries,
+		int ip_v, struct socket_ctx *skt_ctx)
 {
-	return sa_add_rules(sa_ctx, entries, nb_entries, 0, skt_ctx);
+	return sa_add_rules(sa_ctx, entries, 0, ip_v, skt_ctx);
 }
 
 static inline int
-sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
-		uint32_t nb_entries, struct socket_ctx *skt_ctx)
+sa_in_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa_db *entries,
+		int ip_v, struct socket_ctx *skt_ctx)
 {
-	return sa_add_rules(sa_ctx, entries, nb_entries, 1, skt_ctx);
+	return sa_add_rules(sa_ctx, entries, 1, ip_v, skt_ctx);
 }
 
 /*
@@ -1052,19 +1123,8 @@ fill_ipsec_app_sa_prm(struct rte_ipsec_sa_prm *prm,
 
 static int
 fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
-	const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6)
+	const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6, int ip_v)
 {
-	int32_t rc;
-
-	/*
-	 * Try to get SPI next proto by searching that SPI in SPD.
-	 * probably not the optimal way, but there seems nothing
-	 * better right now.
-	 */
-	rc = get_spi_proto(ss->spi, ss->direction, NULL, NULL);
-	if (rc < 0)
-		return rc;
-
 	fill_ipsec_app_sa_prm(prm, &app_sa_prm);
 	prm->userdata = (uintptr_t)ss;
 
@@ -1082,16 +1142,16 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
 	if (IS_IP4_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
 		prm->tun.hdr_len = sizeof(*v4);
-		prm->tun.next_proto = rc;
+		prm->tun.next_proto = ip_v;
 		prm->tun.hdr = v4;
 	} else if (IS_IP6_TUNNEL(ss->flags)) {
 		prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6;
 		prm->tun.hdr_len = sizeof(*v6);
-		prm->tun.next_proto = rc;
+		prm->tun.next_proto = ip_v;
 		prm->tun.hdr = v6;
 	} else {
 		/* transport mode */
-		prm->trs.proto = rc;
+		prm->trs.proto = ip_v;
 	}
 
 	/* setup crypto section */
@@ -1134,7 +1194,8 @@ fill_ipsec_session(struct rte_ipsec_session *ss, struct rte_ipsec_sa *sa,
  * Initialise related rte_ipsec_sa object.
  */
 static int
-ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
+ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size,
+		int ip_v)
 {
 	int rc;
 	struct rte_ipsec_sa_prm prm;
@@ -1156,7 +1217,7 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
 		memcpy(v6.dst_addr, lsa->dst.ip.ip6.ip6_b, sizeof(v6.dst_addr));
 	}
 
-	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6);
+	rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6, ip_v);
 	if (rc == 0)
 		rc = rte_ipsec_sa_init(sa, &prm, sa_size);
 	if (rc < 0)
@@ -1172,7 +1233,7 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa *sa, uint32_t sa_size)
  */
 static int
 ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
-	uint32_t nb_ent, int32_t socket)
+	uint32_t nb_ent, int32_t socket, int ip_v[])
 {
 	int32_t rc, sz;
 	uint32_t i, idx;
@@ -1183,7 +1244,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
 
 	/* determine SA size */
 	idx = SPI2IDX(ent[0].spi);
-	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL);
+	fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL, ip_v[0]);
 	sz = rte_ipsec_sa_size(&prm);
 	if (sz < 0) {
 		RTE_LOG(ERR, IPSEC, "%s(%p, %u, %d): "
@@ -1209,8 +1270,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, const struct ipsec_sa *ent,
 
 		sa = (struct rte_ipsec_sa *)((uintptr_t)ctx->satbl + sz * i);
 		lsa = ctx->sa + idx;
-
-		rc = ipsec_sa_init(lsa, sa, sz);
+		rc = ipsec_sa_init(lsa, sa, sz, ip_v[i]);
 	}
 
 	return rc;
@@ -1226,11 +1286,11 @@ sa_spi_present(uint32_t spi, int inbound)
 	const struct ipsec_sa *sar;
 
 	if (inbound != 0) {
-		sar = sa_in;
-		num = nb_sa_in;
+		sar = sa_in.sadb;
+		num = sa_in.nb;
 	} else {
-		sar = sa_out;
-		num = nb_sa_out;
+		sar = sa_out.sadb;
+		num = sa_out.nb;
 	}
 
 	for (i = 0; i != num; i++) {
@@ -1246,54 +1306,122 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 {
 	int32_t rc;
 	const char *name;
+	int sa4_ip_v[IPSEC_SA_MAX_ENTRIES];
+	int sa6_ip_v[IPSEC_SA_MAX_ENTRIES];
 
 	if (ctx == NULL)
 		rte_exit(EXIT_FAILURE, "NULL context.\n");
 
-	if (ctx->sa_in != NULL)
-		rte_exit(EXIT_FAILURE, "Inbound SA DB for socket %u already "
-				"initialized\n", socket_id);
+	if (ctx->sa_ip4_in != NULL)
+		rte_exit(EXIT_FAILURE, "Inbound IPv4 SA DB for socket %u"
+				" already initialized\n", socket_id);
+
+	if (ctx->sa_ip4_out != NULL)
+		rte_exit(EXIT_FAILURE, "Outbound IPv4 SA DB for socket %u"
+				" already initialized\n", socket_id);
 
-	if (ctx->sa_out != NULL)
-		rte_exit(EXIT_FAILURE, "Outbound SA DB for socket %u already "
-				"initialized\n", socket_id);
+	if (ctx->sa_ip6_in != NULL)
+		rte_exit(EXIT_FAILURE, "Inbound IPv6 SA DB for socket %u"
+				" already initialized\n", socket_id);
 
-	if (nb_sa_in > 0) {
-		name = "sa_in";
-		ctx->sa_in = sa_create(name, socket_id);
-		if (ctx->sa_in == NULL)
+	if (ctx->sa_ip6_out != NULL)
+		rte_exit(EXIT_FAILURE, "Outbound IPv6 SA DB for socket %u"
+				" already initialized\n", socket_id);
+
+	if (sa_in.nb > 0) {
+		sa_in_split(&sa_ip4_in, &sa_ip6_in, &sa_in, sa4_ip_v,
+				sa6_ip_v);
+
+		name = "sa_ip4_in";
+		ctx->sa_ip4_in = sa_create(name, socket_id);
+		if (ctx->sa_ip4_in == NULL)
 			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
 				"context %s in socket %d\n", rte_errno,
 				name, socket_id);
 
-		sa_in_add_rules(ctx->sa_in, sa_in, nb_sa_in, ctx);
+		printf("IPv4 %s entries [%u]:\n", name, sa_ip4_in.nb);
+		sa_in_add_rules(ctx->sa_ip4_in, &sa_ip4_in, IPPROTO_IPIP, ctx);
+
+		name = "sa_ip6_in";
+		ctx->sa_ip6_in = sa_create(name, socket_id);
+		if (ctx->sa_ip6_in == NULL)
+			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
+				"context %s in socket %d\n", rte_errno,
+				name, socket_id);
+
+		printf("IPv6 %s entries [%u]:\n", name, sa_ip6_in.nb);
+		sa_in_add_rules(ctx->sa_ip6_in, &sa_ip6_in, IPPROTO_IPV6, ctx);
 
 		if (app_sa_prm.enable != 0) {
-			rc = ipsec_satbl_init(ctx->sa_in, sa_in, nb_sa_in,
-				socket_id);
-			if (rc != 0)
-				rte_exit(EXIT_FAILURE,
-					"failed to init inbound SAs\n");
+			if (sa_ip4_in.nb > 0) {
+				rc = ipsec_satbl_init(ctx->sa_ip4_in,
+					sa_ip4_in.sadb, sa_ip4_in.nb,
+					socket_id, sa4_ip_v);
+				if (rc != 0)
+					rte_exit(EXIT_FAILURE,
+						"failed to init inbound "
+						"IPv4 SAs\n");
+			}
+
+			if (sa_ip6_in.nb > 0) {
+				rc = ipsec_satbl_init(ctx->sa_ip6_in,
+					sa_ip6_in.sadb, sa_ip6_in.nb,
+					socket_id, sa6_ip_v);
+				if (rc != 0)
+					rte_exit(EXIT_FAILURE,
+						"failed to init inbound "
+						"IPv6 SAs\n");
+			}
 		}
 	} else
 		RTE_LOG(WARNING, IPSEC, "No SA Inbound rule specified\n");
 
-	if (nb_sa_out > 0) {
-		name = "sa_out";
-		ctx->sa_out = sa_create(name, socket_id);
-		if (ctx->sa_out == NULL)
+	if (sa_out.nb > 0) {
+		sa_out_split(&sa_ip4_out, &sa_ip6_out, &sa_out,
+				sa4_ip_v, sa6_ip_v);
+
+		name = "sa_ip4_out";
+		ctx->sa_ip4_out = sa_create(name, socket_id);
+		if (ctx->sa_ip4_out == NULL)
 			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
 				"context %s in socket %d\n", rte_errno,
 				name, socket_id);
 
-		sa_out_add_rules(ctx->sa_out, sa_out, nb_sa_out, ctx);
+		printf("IPv4 %s entries [%u]:\n", name, sa_ip4_out.nb);
+		sa_out_add_rules(ctx->sa_ip4_out, &sa_ip4_out, IPPROTO_IPIP,
+				ctx);
+
+		name = "sa_ip6_out";
+		ctx->sa_ip6_out = sa_create(name, socket_id);
+		if (ctx->sa_ip6_out == NULL)
+			rte_exit(EXIT_FAILURE, "Error [%d] creating SA "
+				"context %s in socket %d\n", rte_errno,
+				name, socket_id);
+
+		printf("IPv6 %s entries [%u]:\n", name, sa_ip6_out.nb);
+		sa_out_add_rules(ctx->sa_ip6_out, &sa_ip6_out, IPPROTO_IPV6,
+				ctx);
 
 		if (app_sa_prm.enable != 0) {
-			rc = ipsec_satbl_init(ctx->sa_out, sa_out, nb_sa_out,
-				socket_id);
-			if (rc != 0)
-				rte_exit(EXIT_FAILURE,
-					"failed to init outbound SAs\n");
+			if (sa_ip4_out.nb > 0) {
+				rc = ipsec_satbl_init(ctx->sa_ip4_out,
+					sa_ip4_out.sadb, sa_ip4_out.nb,
+					socket_id, sa4_ip_v);
+				if (rc != 0)
+					rte_exit(EXIT_FAILURE,
+						"failed to init outbound "
+						"IPv4 SAs\n");
+			}
+
+			if (sa_ip6_out.nb > 0) {
+				rc = ipsec_satbl_init(ctx->sa_ip6_out,
+					sa_ip6_out.sadb, sa_ip6_out.nb,
+					socket_id, sa6_ip_v);
+				if (rc != 0)
+					rte_exit(EXIT_FAILURE,
+						"failed to init outbound "
+						"IPv6 SAs\n");
+			}
 		}
 	} else
 		RTE_LOG(WARNING, IPSEC, "No SA Outbound rule "
@@ -1301,7 +1429,7 @@ sa_init(struct socket_ctx *ctx, int32_t socket_id)
 }
 
 int
-inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx)
+inbound_sa_check(struct rte_mbuf *m, uint32_t sp_spi)
 {
 	struct ipsec_mbuf_metadata *priv;
 	struct ipsec_sa *sa;
@@ -1309,7 +1437,7 @@ inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx)
 	priv = get_priv(m);
 	sa = priv->sa;
 	if (sa != NULL)
-		return (sa_ctx->sa[sa_idx].spi == sa->spi);
+		return (sp_spi == sa->spi);
 
 	RTE_LOG(ERR, IPSEC, "SA not saved in private data\n");
 	return 0;
@@ -1327,9 +1455,7 @@ single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,
 
 	*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;
 
@@ -1337,6 +1463,8 @@ single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,
 	if (rte_be_to_cpu_32(esp->spi) != sa->spi)
 		return;
 
+	ip = rte_pktmbuf_mtod(pkt, struct ip *);
+
 	switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
 	case IP4_TUNNEL:
 		src4_addr = RTE_PTR_ADD(ip, offsetof(struct ip, ip_src));
@@ -1358,23 +1486,37 @@ single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt,
 }
 
 void
-inbound_sa_lookup(struct sa_ctx *sa_ctx, struct rte_mbuf *pkts[],
-		struct ipsec_sa *sa[], uint16_t nb_pkts)
+inbound_sa_lookup(struct sa_ctx *sa4_ctx, struct sa_ctx *sa6_ctx,
+		struct rte_mbuf *pkts[], struct ipsec_sa *sa[],
+		uint16_t nb_pkts)
 {
 	uint32_t i;
+	struct ip *ip;
 
-	for (i = 0; i < nb_pkts; i++)
-		single_inbound_lookup(sa_ctx->sa, pkts[i], &sa[i]);
+	for (i = 0; i < nb_pkts; i++) {
+		ip = rte_pktmbuf_mtod(pkts[i], struct ip *);
+		if (ip->ip_v == IPVERSION)
+			single_inbound_lookup(sa4_ctx->sa, pkts[i], &sa[i]);
+		else
+			single_inbound_lookup(sa6_ctx->sa, pkts[i], &sa[i]);
+	}
 }
 
 void
-outbound_sa_lookup(struct sa_ctx *sa_ctx, uint32_t sa_idx[],
-		struct ipsec_sa *sa[], uint16_t nb_pkts)
+outbound_sa_lookup(struct sa_ctx *sa4_ctx, struct sa_ctx *sa6_ctx,
+		uint32_t sa_idx[], struct ipsec_sa *sa[],
+		struct rte_mbuf *pkts[], uint16_t nb_pkts)
 {
 	uint32_t i;
+	struct ip *ip;
 
-	for (i = 0; i < nb_pkts; i++)
-		sa[i] = &sa_ctx->sa[sa_idx[i]];
+	for (i = 0; i < nb_pkts; i++) {
+		ip = rte_pktmbuf_mtod(pkts[i], struct ip *);
+		if (ip->ip_v == IPVERSION)
+			sa[i] = &sa4_ctx->sa[sa_idx[i]];
+		else
+			sa[i] = &sa6_ctx->sa[sa_idx[i]];
+	}
 }
 
 /*
@@ -1391,8 +1533,8 @@ sa_check_offloads(uint16_t port_id, uint64_t *rx_offloads,
 	*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];
+	for (idx_sa = 0; idx_sa < sa_in.nb; idx_sa++) {
+		rule = &sa_in.sadb[idx_sa];
 		if ((rule->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
 				rule->type ==
 				RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL)
@@ -1401,8 +1543,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];
+	for (idx_sa = 0; idx_sa < sa_out.nb; idx_sa++) {
+		rule = &sa_out.sadb[idx_sa];
 		if ((rule->type == RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO ||
 				rule->type ==
 				RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL)
-- 
2.17.1


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

* [dpdk-dev] [PATCH v2 2/2] examples/ipsec-secgw: tests for split SAD
  2019-09-24 10:35 ` [dpdk-dev] [PATCH v2 0/2] fix SAD selection logic Mariusz Drost
  2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: " Mariusz Drost
@ 2019-09-24 10:35   ` Mariusz Drost
  2019-09-24 12:47     ` Ananyev, Konstantin
  1 sibling, 1 reply; 15+ messages in thread
From: Mariusz Drost @ 2019-09-24 10:35 UTC (permalink / raw)
  To: radu.nicolau, akhil.goyal, konstantin.ananyev
  Cc: dev, Mariusz Drost, Lukasz Bartosik

Test scripts updated to reflect change of SAD (split into IPv4 SAD
and IPv6 SAD). New parameter added to run_test.sh for performing tests
with mixed IP version, eg. IPv4 ipsec tunnel with IPv6 traffic.

Bugzilla ID: 239
Fixes: 5a032a71c6d3 ("examples/ipsec-secgw: make app to use IPsec library")

Reported-by: Lukasz Bartosik <lbartosik@marvell.com>
Signed-off-by: Mariusz Drost <mariuszx.drost@intel.com>
---
 examples/ipsec-secgw/ep0.cfg                  | 58 ++++++++++--
 examples/ipsec-secgw/ep1.cfg                  | 62 +++++++++---
 examples/ipsec-secgw/test/common_defs.sh      |  7 +-
 .../test/{linux_test6.sh => linux_test.sh}    | 94 +++++++++++++++----
 examples/ipsec-secgw/test/linux_test4.sh      | 78 ---------------
 examples/ipsec-secgw/test/run_test.sh         | 42 +++++++--
 .../ipsec-secgw/test/trs_3descbc_sha1_defs.sh |  7 +-
 .../test/trs_3descbc_sha1_esn_defs.sh         |  7 +-
 .../ipsec-secgw/test/trs_aescbc_sha1_defs.sh  |  7 +-
 .../test/trs_aescbc_sha1_esn_defs.sh          |  7 +-
 .../ipsec-secgw/test/trs_aesctr_sha1_defs.sh  |  7 +-
 .../test/trs_aesctr_sha1_esn_defs.sh          |  7 +-
 examples/ipsec-secgw/test/trs_aesgcm_defs.sh  |  7 +-
 .../ipsec-secgw/test/trs_aesgcm_esn_defs.sh   |  7 +-
 .../test/tun_3descbc_sha1_common_defs.sh      | 68 ++++++++++++++
 .../ipsec-secgw/test/tun_3descbc_sha1_defs.sh | 77 ++++++++++++++-
 .../test/tun_3descbc_sha1_esn_defs.sh         | 77 ++++++++++++++-
 .../test/tun_aescbc_sha1_common_defs.sh       | 64 +++++++++++++
 .../ipsec-secgw/test/tun_aescbc_sha1_defs.sh  | 77 ++++++++++++++-
 .../test/tun_aescbc_sha1_esn_defs.sh          | 77 ++++++++++++++-
 .../test/tun_aesctr_sha1_common_defs.sh       | 64 +++++++++++++
 .../ipsec-secgw/test/tun_aesctr_sha1_defs.sh  | 77 ++++++++++++++-
 .../test/tun_aesctr_sha1_esn_defs.sh          | 77 ++++++++++++++-
 .../test/tun_aesgcm_common_defs.sh            | 56 +++++++++++
 examples/ipsec-secgw/test/tun_aesgcm_defs.sh  | 77 ++++++++++++++-
 .../ipsec-secgw/test/tun_aesgcm_esn_defs.sh   | 77 ++++++++++++++-
 26 files changed, 1085 insertions(+), 180 deletions(-)
 rename examples/ipsec-secgw/test/{linux_test6.sh => linux_test.sh} (50%)
 delete mode 100644 examples/ipsec-secgw/test/linux_test4.sh

diff --git a/examples/ipsec-secgw/ep0.cfg b/examples/ipsec-secgw/ep0.cfg
index 299aa9e06..ffd09156a 100644
--- a/examples/ipsec-secgw/ep0.cfg
+++ b/examples/ipsec-secgw/ep0.cfg
@@ -28,38 +28,36 @@ sp ipv4 in esp protect 110 pri 1 dst 192.168.185.0/24 sport 0:65535 dport 0:6553
 sp ipv4 in esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
-sp ipv4 in esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
-sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp bypass pri 1 dst 192.168.245.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp bypass pri 1 dst 192.168.246.0/24 sport 0:65535 dport 0:65535
 
 #SP IPv6 rules
-sp ipv6 out esp protect 5 pri 1 dst 0000:0000:0000:0000:5555:5555:0000:0000/96 \
+sp ipv6 out esp protect 7 pri 1 dst 0000:0000:0000:0000:5555:5555:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 out esp protect 6 pri 1 dst 0000:0000:0000:0000:6666:6666:0000:0000/96 \
+sp ipv6 out esp protect 8 pri 1 dst 0000:0000:0000:0000:6666:6666:0000:0000/96 \
 sport 0:65535 dport 0:65535
 sp ipv6 out esp protect 10 pri 1 dst 0000:0000:1111:1111:0000:0000:0000:0000/96 \
 sport 0:65535 dport 0:65535
 sp ipv6 out esp protect 11 pri 1 dst 0000:0000:1111:1111:1111:1111:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 out esp protect 25 pri 1 dst 0000:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
+sp ipv6 out esp protect 27 pri 1 dst 0000:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 out esp protect 26 pri 1 dst 0000:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
+sp ipv6 out esp protect 28 pri 1 dst 0000:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
 
-sp ipv6 in esp protect 15 pri 1 dst ffff:0000:0000:0000:5555:5555:0000:0000/96 \
+sp ipv6 in esp protect 107 pri 1 dst ffff:0000:0000:0000:5555:5555:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 in esp protect 16 pri 1 dst ffff:0000:0000:0000:6666:6666:0000:0000/96 \
+sp ipv6 in esp protect 108 pri 1 dst ffff:0000:0000:0000:6666:6666:0000:0000/96 \
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 110 pri 1 dst ffff:0000:1111:1111:0000:0000:0000:0000/96 \
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 111 pri 1 dst ffff:0000:1111:1111:1111:1111:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 in esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
+sp ipv6 in esp protect 127 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 in esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
+sp ipv6 in esp protect 128 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
 
 #SA rules
@@ -71,6 +69,14 @@ sa out 6 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
 a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
 a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.1.6 dst 172.16.2.6
 
+sa out 7 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+mode ipv4-tunnel src 172.16.1.5 dst 172.16.2.5
+
+sa out 8 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.1.6 dst 172.16.2.6
+
 sa out 10 cipher_algo aes-128-cbc cipher_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
 a1:a1:a1:a1:a1 auth_algo sha1-hmac auth_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
 a1:a1:a1:a1:a1:a1:a1:a1:a1 mode transport
@@ -97,6 +103,18 @@ sa out 26 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 1111:1111:1111:1111:1111:1111:1111:6666 \
 dst 2222:2222:2222:2222:2222:2222:2222:6666
 
+sa out 27 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
+src 1111:1111:1111:1111:1111:1111:1111:5555 \
+dst 2222:2222:2222:2222:2222:2222:2222:5555
+
+sa out 28 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d auth_algo sha1-hmac auth_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d:4d:4d:4d:4d mode ipv6-tunnel \
+src 1111:1111:1111:1111:1111:1111:1111:6666 \
+dst 2222:2222:2222:2222:2222:2222:2222:6666
+
 sa in 105 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
 auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
 mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5
@@ -105,6 +123,14 @@ sa in 106 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
 a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
 a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
 
+sa in 107 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5
+
+sa in 108 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
+
 sa in 110 cipher_algo aes-128-cbc cipher_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
 a1:a1:a1:a1:a1 auth_algo sha1-hmac auth_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
 a1:a1:a1:a1:a1:a1:a1:a1:a1 mode transport
@@ -130,6 +156,18 @@ sa in 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 2222:2222:2222:2222:2222:2222:2222:6666 \
 dst 1111:1111:1111:1111:1111:1111:1111:6666
 
+sa in 127 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:5555 \
+dst 1111:1111:1111:1111:1111:1111:1111:5555
+
+sa in 128 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d auth_algo sha1-hmac auth_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d:4d:4d:4d:4d mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:6666 \
+dst 1111:1111:1111:1111:1111:1111:1111:6666
+
 #Routing rules
 rt ipv4 dst 172.16.2.5/32 port 0
 rt ipv4 dst 172.16.2.6/32 port 1
diff --git a/examples/ipsec-secgw/ep1.cfg b/examples/ipsec-secgw/ep1.cfg
index 3f6ff8111..c66a6b24c 100644
--- a/examples/ipsec-secgw/ep1.cfg
+++ b/examples/ipsec-secgw/ep1.cfg
@@ -19,8 +19,8 @@ sp ipv4 in esp protect 15 pri 1 dst 192.168.200.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 16 pri 1 dst 192.168.201.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 25 pri 1 dst 192.168.55.0/24 sport 0:65535 dport 0:65535
 sp ipv4 in esp protect 26 pri 1 dst 192.168.56.0/24 sport 0:65535 dport 0:65535
-sp ipv4 in esp bypass dst 192.168.240.0/24 sport 0:65535 dport 0:65535
-sp ipv4 in esp bypass dst 192.168.241.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 dst 192.168.240.0/24 sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 dst 192.168.241.0/24 sport 0:65535 dport 0:65535
 
 sp ipv4 out esp protect 105 pri 1 dst 192.168.115.0/24 sport 0:65535 dport 0:65535
 sp ipv4 out esp protect 106 pri 1 dst 192.168.116.0/24 sport 0:65535 dport 0:65535
@@ -28,38 +28,36 @@ sp ipv4 out esp protect 110 pri 1 dst 192.168.185.0/24 sport 0:65535 dport 0:655
 sp ipv4 out esp protect 111 pri 1 dst 192.168.186.0/24 sport 0:65535 dport 0:65535
 sp ipv4 out esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
 sp ipv4 out esp protect 116 pri 1 dst 192.168.211.0/24 sport 0:65535 dport 0:65535
-sp ipv4 out esp protect 115 pri 1 dst 192.168.210.0/24 sport 0:65535 dport 0:65535
-sp ipv4 out esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 out esp protect 125 pri 1 dst 192.168.65.0/24 sport 0:65535 dport 0:65535
 sp ipv4 out esp protect 126 pri 1 dst 192.168.66.0/24 sport 0:65535 dport 0:65535
 sp ipv4 out esp bypass pri 1 dst 192.168.245.0/24 sport 0:65535 dport 0:65535
 sp ipv4 out esp bypass pri 1 dst 192.168.246.0/24 sport 0:65535 dport 0:65535
 
 #SP IPv6 rules
-sp ipv6 in esp protect 5 pri 1 dst 0000:0000:0000:0000:5555:5555:0000:0000/96 \
+sp ipv6 in esp protect 7 pri 1 dst 0000:0000:0000:0000:5555:5555:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 in esp protect 6 pri 1 dst 0000:0000:0000:0000:6666:6666:0000:0000/96 \
+sp ipv6 in esp protect 8 pri 1 dst 0000:0000:0000:0000:6666:6666:0000:0000/96 \
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 10 pri 1 dst 0000:0000:1111:1111:0000:0000:0000:0000/96 \
 sport 0:65535 dport 0:65535
 sp ipv6 in esp protect 11 pri 1 dst 0000:0000:1111:1111:1111:1111:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 in esp protect 25 pri 1 dst 0000:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
+sp ipv6 in esp protect 27 pri 1 dst 0000:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 in esp protect 26 pri 1 dst 0000:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
+sp ipv6 in esp protect 28 pri 1 dst 0000:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
 
-sp ipv6 out esp protect 15 pri 1 dst ffff:0000:0000:0000:5555:5555:0000:0000/96 \
+sp ipv6 out esp protect 107 pri 1 dst ffff:0000:0000:0000:5555:5555:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 out esp protect 16 pri 1 dst ffff:0000:0000:0000:6666:6666:0000:0000/96 \
+sp ipv6 out esp protect 108 pri 1 dst ffff:0000:0000:0000:6666:6666:0000:0000/96 \
 sport 0:65535 dport 0:65535
 sp ipv6 out esp protect 110 pri 1 dst ffff:0000:1111:1111:0000:0000:0000:0000/96 \
 sport 0:65535 dport 0:65535
 sp ipv6 out esp protect 111 pri 1 dst ffff:0000:1111:1111:1111:1111:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 out esp protect 125 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
+sp ipv6 out esp protect 127 pri 1 dst ffff:0000:0000:0000:aaaa:aaaa:0000:0000/96 \
 sport 0:65535 dport 0:65535
-sp ipv6 out esp protect 126 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
+sp ipv6 out esp protect 128 pri 1 dst ffff:0000:0000:0000:bbbb:bbbb:0000:0000/96 \
 sport 0:65535 dport 0:65535
 
 #SA rules
@@ -71,6 +69,14 @@ sa in 6 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
 a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
 a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.1.6 dst 172.16.2.6
 
+sa in 7 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+mode ipv4-tunnel src 172.16.1.5 dst 172.16.2.5
+
+sa in 8 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.1.6 dst 172.16.2.6
+
 sa in 10 cipher_algo aes-128-cbc cipher_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
 a1:a1:a1:a1:a1 auth_algo sha1-hmac auth_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
 a1:a1:a1:a1:a1:a1:a1:a1:a1 mode transport
@@ -97,6 +103,18 @@ sa in 26 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 1111:1111:1111:1111:1111:1111:1111:6666 \
 dst 2222:2222:2222:2222:2222:2222:2222:6666
 
+sa in 27 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
+src 1111:1111:1111:1111:1111:1111:1111:5555 \
+dst 2222:2222:2222:2222:2222:2222:2222:5555
+
+sa in 28 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d auth_algo sha1-hmac auth_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d:4d:4d:4d:4d mode ipv6-tunnel \
+src 1111:1111:1111:1111:1111:1111:1111:6666 \
+dst 2222:2222:2222:2222:2222:2222:2222:6666
+
 sa out 105 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
 auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
 mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5
@@ -105,6 +123,14 @@ sa out 106 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
 a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
 a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
 
+sa out 107 cipher_algo aes-128-cbc cipher_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+auth_algo sha1-hmac auth_key 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 \
+mode ipv4-tunnel src 172.16.2.5 dst 172.16.1.5
+
+sa out 108 cipher_algo aes-128-cbc cipher_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0 auth_algo sha1-hmac auth_key a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:a0:\
+a0:a0:a0:a0:a0:a0:a0:a0:a0 mode ipv4-tunnel src 172.16.2.6 dst 172.16.1.6
+
 sa out 110 cipher_algo aes-128-cbc cipher_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
 a1:a1:a1:a1:a1 auth_algo sha1-hmac auth_key a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:\
 a1:a1:a1:a1:a1:a1:a1:a1:a1 mode transport
@@ -130,6 +156,18 @@ sa out 126 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
 src 2222:2222:2222:2222:2222:2222:2222:6666 \
 dst 1111:1111:1111:1111:1111:1111:1111:6666
 
+sa out 127 cipher_algo aes-128-cbc cipher_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3 auth_algo sha1-hmac auth_key c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:c3:\
+c3:c3:c3:c3:c3:c3:c3:c3:c3 mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:5555 \
+dst 1111:1111:1111:1111:1111:1111:1111:5555
+
+sa out 128 cipher_algo aes-128-cbc cipher_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d auth_algo sha1-hmac auth_key 4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:4d:\
+4d:4d:4d:4d:4d:4d:4d:4d:4d mode ipv6-tunnel \
+src 2222:2222:2222:2222:2222:2222:2222:6666 \
+dst 1111:1111:1111:1111:1111:1111:1111:6666
+
 #Routing rules
 rt ipv4 dst 172.16.1.5/32 port 0
 rt ipv4 dst 172.16.1.6/32 port 1
diff --git a/examples/ipsec-secgw/test/common_defs.sh b/examples/ipsec-secgw/test/common_defs.sh
index 09689af78..911857a60 100644
--- a/examples/ipsec-secgw/test/common_defs.sh
+++ b/examples/ipsec-secgw/test/common_defs.sh
@@ -80,11 +80,8 @@ config_remote_iface()
 
 	ssh ${REMOTE_HOST} ip neigh flush dev ${REMOTE_IFACE}
 
-	# by some reason following ip neigh doesn't work for me here properly:
-	#ssh ${REMOTE_HOST} ip neigh add ${LOCAL_IPV4} \
-	#		dev ${REMOTE_IFACE} lladr ${LOCAL_MAC}
-	# so used arp instead.
-	ssh ${REMOTE_HOST} arp -i ${REMOTE_IFACE} -s ${LOCAL_IPV4} ${LOCAL_MAC}
+	ssh ${REMOTE_HOST} ip neigh add ${LOCAL_IPV4} \
+			dev ${REMOTE_IFACE} lladdr ${LOCAL_MAC}
 	ssh ${REMOTE_HOST} ip neigh show dev ${REMOTE_IFACE}
 
 	ssh ${REMOTE_HOST} iptables --flush
diff --git a/examples/ipsec-secgw/test/linux_test6.sh b/examples/ipsec-secgw/test/linux_test.sh
similarity index 50%
rename from examples/ipsec-secgw/test/linux_test6.sh
rename to examples/ipsec-secgw/test/linux_test.sh
index c749dcef8..e3a8d3fa4 100644
--- a/examples/ipsec-secgw/test/linux_test6.sh
+++ b/examples/ipsec-secgw/test/linux_test.sh
@@ -1,8 +1,13 @@
 #! /bin/bash
 
-# usage:  /bin/bash linux_test6.sh <ipsec_mode>
-# for list of available modes please refer to run_test.sh.
-# ipsec-secgw (IPv6 mode) functional test script.
+# usage:  /bin/bash linux_test.sh <ip_protocol> <ipsec_mode>
+# <ip_protocol> can be set to:
+#  ipv4-ipv4 - only IPv4 traffic
+#  ipv4-ipv6 - IPv4 traffic over IPv6 ipsec tunnel (only for tunnel mode)
+#  ipv6-ipv4 - IPv6 traffic over IPv4 ipsec tunnel (only for tunnel mode)
+#  ipv6-ipv6 - only IPv6 traffic
+# For list of available modes please refer to run_test.sh.
+# ipsec-secgw functional test script.
 #
 # Note that for most of them you required appropriate crypto PMD/device
 # to be avaialble.
@@ -24,7 +29,7 @@
 # One NIC is expected to be managed by linux both machines,
 # and will be used as a control path.
 # Make sure user from SUT can ssh to DUT without entering password,
-# also make sure that sshd over ipv6 is enabled.
+# also make sure that ssh over ipv6 is enabled.
 # Second NIC (test-port) should be reserved for DPDK on SUT,
 # and should be managed by linux on DUT.
 # The script starts ipsec-secgw with 2 NIC devices: test-port and tap vdev.
@@ -32,15 +37,16 @@
 # in the following way:
 # traffic going over test-port in both directions has to be
 # protected by ipsec.
-# raffic going over TAP in both directions doesn't have to be protected.
+# Traffic going over TAP in both directions doesn't have to be protected.
 # I.E:
 # DUT OS(NIC1)--(ipsec)-->(NIC1)ipsec-secgw(TAP)--(plain)-->(TAP)SUT OS
 # SUT OS(TAP)--(plain)-->(TAP)psec-secgw(NIC1)--(ipsec)-->(NIC1)DUT OS
-# Then tries to perorm some data transfer using the scheme decribed above.
+# Then tries to perform some data transfer using the scheme decribed above.
 #
 
 DIR=`dirname $0`
-MODE=$1
+PROTO=$1
+MODE=$2
 
  . ${DIR}/common_defs.sh
  . ${DIR}/${MODE}_defs.sh
@@ -56,23 +62,77 @@ else
 	MTU_LEN=${DEF_MTU_LEN}
 fi
 
-config_secgw
+if [[ ${PROTO} = "ipv4-ipv4" ]] || [[ ${PROTO} = "ipv6-ipv6" ]]; then
+	config_secgw
+else
+	config_secgw_mixed
+fi
 
 secgw_start
 
-config6_iface
+ . ${DIR}/data_rxtx.sh
 
-config6_remote_xfrm
+if [[ ${PROTO} = "ipv4-ipv4"  ]]; then
+	config_iface
+	config_remote_xfrm_44
 
- . ${DIR}/data_rxtx.sh
+	set_local_mtu ${MTU_LEN}
+	ping_test1 ${REMOTE_IPV4} 0 ${PING_LEN}
+	st=$?
+	if [[ $st -eq 0 ]]; then
+		set_local_mtu ${DEF_MTU_LEN}
+		scp_test1 ${REMOTE_IPV4}
+		st=$?
+	fi
+elif [[ ${PROTO} = "ipv4-ipv6" ]]; then
+	if [[ ${MODE} = "trs"* ]]; then
+		echo "Cannot mix protocols in transport mode"
+		secgw_stop
+		exit 1
+	fi
+	config6_iface
+	config_remote_xfrm_46
 
-set_local_mtu ${MTU_LEN}
-ping6_test1 ${REMOTE_IPV6} 0 ${PING_LEN}
-st=$?
-if [[ $st -eq 0 ]]; then
-	set_local_mtu ${DEF_MTU_LEN}
-	scp_test1 ${REMOTE_IPV6}
+	set_local_mtu ${MTU_LEN}
+	ping_test1 ${REMOTE_IPV4} 0 ${PING_LEN}
 	st=$?
+	if [[ $st -eq 0 ]]; then
+		set_local_mtu ${DEF_MTU_LEN}
+		scp_test1 ${REMOTE_IPV4}
+		st=$?
+	fi
+elif [[ ${PROTO} = "ipv6-ipv4" ]]; then
+	if [[ ${MODE} = "trs"* ]]; then
+		echo "Cannot mix protocols in transport mode"
+		secgw_stop
+		exit 1
+	fi
+	config6_iface
+	config_remote_xfrm_64
+
+	set_local_mtu ${MTU_LEN}
+	ping6_test1 ${REMOTE_IPV6} 0 ${PING_LEN}
+	st=$?
+	if [[ $st -eq 0 ]]; then
+		set_local_mtu ${DEF_MTU_LEN}
+		scp_test1 ${REMOTE_IPV6}
+		st=$?
+	fi
+elif [[ ${PROTO} = "ipv6-ipv6" ]]; then
+	config6_iface
+	config_remote_xfrm_66
+
+	set_local_mtu ${MTU_LEN}
+	ping6_test1 ${REMOTE_IPV6} 0 ${PING_LEN}
+	st=$?
+	if [[ $st -eq 0 ]]; then
+		set_local_mtu ${DEF_MTU_LEN}
+		scp_test1 ${REMOTE_IPV6}
+		st=$?
+	fi
+else
+	echo "Invalid <proto>"
+	st=128
 fi
 
 secgw_stop
diff --git a/examples/ipsec-secgw/test/linux_test4.sh b/examples/ipsec-secgw/test/linux_test4.sh
deleted file mode 100644
index 85efc5d90..000000000
--- a/examples/ipsec-secgw/test/linux_test4.sh
+++ /dev/null
@@ -1,78 +0,0 @@
-#! /bin/bash
-
-# usage:  /bin/bash linux_test4.sh <ipsec_mode>
-# for list of available modes please refer to run_test.sh.
-# ipsec-secgw (IPv4 mode) functional test script.
-#
-# Note that for most of them you required appropriate crypto PMD/device
-# to be avaialble.
-# Also user has to setup properly the following environment variables:
-#  SGW_PATH - path to the ipsec-secgw binary to test
-#  REMOTE_HOST - ip/hostname of the DUT
-#  REMOTE_IFACE - iface name for the test-port on DUT
-#  ETH_DEV - ethernet device to be used on SUT by DPDK ('-w <pci-id>')
-# Also user can optonally setup:
-#  SGW_LCORE - lcore to run ipsec-secgw on (default value is 0)
-#  CRYPTO_DEV - crypto device to be used ('-w <pci-id>')
-#  if none specified appropriate vdevs will be created by the scrit
-#  MULTI_SEG_TEST - ipsec-secgw option to enable reassembly support and
-#  specify size of reassembly table (i.e. MULTI_SEG_TEST="--reassemble 128")
-#
-# The purpose of the script is to automate ipsec-secgw testing
-# using another system running linux as a DUT.
-# It expects that SUT and DUT are connected through at least 2 NICs.
-# One NIC is expected to be managed by linux both machines,
-# and will be used as a control path
-# Make sure user from SUT can ssh to DUT without entering password.
-# Second NIC (test-port) should be reserved for DPDK on SUT,
-# and should be managed by linux on DUT.
-# The script starts ipsec-secgw with 2 NIC devices: test-port and tap vdev.
-# Then configures local tap iface and remote iface and ipsec policies
-# in the following way:
-# traffic going over test-port in both directions has to be
-# protected by ipsec.
-# raffic going over TAP in both directions doesn't have to be protected.
-# I.E:
-# DUT OS(NIC1)--(ipsec)-->(NIC1)ipsec-secgw(TAP)--(plain)-->(TAP)SUT OS
-# SUT OS(TAP)--(plain)-->(TAP)psec-secgw(NIC1)--(ipsec)-->(NIC1)DUT OS
-# Then tries to perorm some data transfer using the scheme decribed above.
-#
-
-DIR=`dirname $0`
-MODE=$1
-
- . ${DIR}/common_defs.sh
- . ${DIR}/${MODE}_defs.sh
-
-#make linux to generate fragmented packets
-if [[ -n "${MULTI_SEG_TEST}" && -n "${SGW_CMD_XPRM}" ]]; then
-	echo "multi-segment test is enabled"
-	SGW_CMD_XPRM="${SGW_CMD_XPRM} ${MULTI_SEG_TEST}"
-	PING_LEN=5000
-	MTU_LEN=1500
-else
-	PING_LEN=${DEF_PING_LEN}
-	MTU_LEN=${DEF_MTU_LEN}
-fi
-
-config_secgw
-
-secgw_start
-
-config_iface
-
-config_remote_xfrm
-
- . ${DIR}/data_rxtx.sh
-
-set_local_mtu ${MTU_LEN}
-ping_test1 ${REMOTE_IPV4} 0 ${PING_LEN}
-st=$?
-if [[ $st -eq 0 ]]; then
-	set_local_mtu ${DEF_MTU_LEN}
-	scp_test1 ${REMOTE_IPV4}
-	st=$?
-fi
-
-secgw_stop
-exit $st
diff --git a/examples/ipsec-secgw/test/run_test.sh b/examples/ipsec-secgw/test/run_test.sh
index 8055a4c04..10821e678 100755
--- a/examples/ipsec-secgw/test/run_test.sh
+++ b/examples/ipsec-secgw/test/run_test.sh
@@ -1,7 +1,7 @@
 #! /bin/bash
 
-# usage: /bin/bash run_test.sh [-46]
-# Run all defined linux_test[4,6].sh test-cases one by one
+# usage: /bin/bash run_test.sh [-46mp]
+# Run all defined linux_test.sh test-cases one by one
 # user has to setup properly the following environment variables:
 #  SGW_PATH - path to the ipsec-secgw binary to test
 #  REMOTE_HOST - ip/hostname of the DUT
@@ -13,7 +13,7 @@
 #  if none specified appropriate vdevs will be created by the scrit
 #  MULTI_SEG_TEST - ipsec-secgw option to enable reassembly support and
 #  specify size of reassembly table (i.e. MULTI_SEG_TEST="--reassemble 128")
-# refer to linux_test[4,6].sh for more information
+# refer to linux_test.sh for more information
 
 
 # All supported modes to test.
@@ -24,9 +24,11 @@
 usage()
 {
 	echo "Usage:"
-	echo -e "\t$0 -[46p]"
+	echo -e "\t$0 -[46mp]"
 	echo -e "\t\t-4 Perform Linux IPv4 network tests"
 	echo -e "\t\t-6 Perform Linux IPv6 network tests"
+	echo -e "\t\t-m Add mixed IP protocol tests to IPv4/IPv6 \
+(only with option [-46])"
 	echo -e "\t\t-p Perform packet validation tests"
 	echo -e "\t\t-h Display this help"
 }
@@ -73,7 +75,8 @@ DIR=$(dirname $0)
 run4=0
 run6=0
 runpkt=0
-while getopts ":46ph" opt
+mixed=0
+while getopts ":46mph" opt
 do
 	case $opt in
 		4)
@@ -82,6 +85,9 @@ do
 		6)
 			run6=1
 			;;
+		m)
+			mixed=1
+			;;
 		p)
 			runpkt=1
 			;;
@@ -124,20 +130,36 @@ if [[ ${run4} -eq 1 || ${run6} -eq 1 ]]; then
 		echo "starting test ${i}"
 
 		st4=0
+		st4m=0
 		if [[ ${run4} -ne 0 ]]; then
-			/bin/bash ${DIR}/linux_test4.sh ${i}
+			/bin/bash ${DIR}/linux_test.sh ipv4-ipv4 ${i}
 			st4=$?
-			echo "test4 ${i} finished with status ${st4}"
+			echo "test IPv4 ${i} finished with status ${st4}"
+
+			if [[ ${mixed} -ne 0 ]] && [[ ${i} = "tun"* ]]; then
+				/bin/bash ${DIR}/linux_test.sh ipv4-ipv6 ${i}
+				st4m=$?
+				echo "test IPv4-IPv6 ${i} finished with \
+status ${st4m}"
+			fi
 		fi
 
 		st6=0
+		st6m=0
 		if [[ ${run6} -ne 0 ]]; then
-			/bin/bash ${DIR}/linux_test6.sh ${i}
+			/bin/bash ${DIR}/linux_test.sh ipv6-ipv6 ${i}
 			st6=$?
-			echo "test6 ${i} finished with status ${st6}"
+			echo "test IPv6 ${i} finished with status ${st6}"
+
+			if [[ ${mixed} -ne 0 ]] && [[ ${i} = "tun"* ]]; then
+				/bin/bash ${DIR}/linux_test.sh ipv6-ipv4 ${i}
+				st6m=$?
+				echo "test IPv6-IPv4 ${i} finished with \
+status ${st6m}"
+			fi
 		fi
 
-		let "st = st4 + st6"
+		let "st = st4 + st6 + st4m + st6m"
 		if [[ $st -ne 0 ]]; then
 			echo "ERROR test ${i} FAILED"
 			exit $st
diff --git a/examples/ipsec-secgw/test/trs_3descbc_sha1_defs.sh b/examples/ipsec-secgw/test/trs_3descbc_sha1_defs.sh
index 31f94492f..b124d7888 100644
--- a/examples/ipsec-secgw/test/trs_3descbc_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/trs_3descbc_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_3descbc_sha1_esn_defs.sh b/examples/ipsec-secgw/test/trs_3descbc_sha1_esn_defs.sh
index e4283f3dd..255acbb32 100644
--- a/examples/ipsec-secgw/test/trs_3descbc_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/trs_3descbc_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aescbc_sha1_defs.sh b/examples/ipsec-secgw/test/trs_aescbc_sha1_defs.sh
index d68552fce..55f696cbc 100644
--- a/examples/ipsec-secgw/test/trs_aescbc_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aescbc_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aescbc_sha1_esn_defs.sh b/examples/ipsec-secgw/test/trs_aescbc_sha1_esn_defs.sh
index ce7c977a3..851b38d59 100644
--- a/examples/ipsec-secgw/test/trs_aescbc_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aescbc_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aesctr_sha1_defs.sh b/examples/ipsec-secgw/test/trs_aesctr_sha1_defs.sh
index 73642f881..50f778ae5 100644
--- a/examples/ipsec-secgw/test/trs_aesctr_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aesctr_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aesctr_sha1_esn_defs.sh b/examples/ipsec-secgw/test/trs_aesctr_sha1_esn_defs.sh
index e401a4bed..88e2eed08 100644
--- a/examples/ipsec-secgw/test/trs_aesctr_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aesctr_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aesgcm_defs.sh b/examples/ipsec-secgw/test/trs_aesgcm_defs.sh
index 8382d3d52..c47578a38 100644
--- a/examples/ipsec-secgw/test/trs_aesgcm_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aesgcm_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ aead "rfc4106\(gcm\(aes\)\)" \
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/trs_aesgcm_esn_defs.sh b/examples/ipsec-secgw/test/trs_aesgcm_esn_defs.sh
index 94958d199..182f05a34 100644
--- a/examples/ipsec-secgw/test/trs_aesgcm_esn_defs.sh
+++ b/examples/ipsec-secgw/test/trs_aesgcm_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -35,9 +35,10 @@ aead "rfc4106\(gcm\(aes\)\)" \
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_66()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_3descbc_sha1_common_defs.sh b/examples/ipsec-secgw/test/tun_3descbc_sha1_common_defs.sh
index dd802d6be..704c0c57f 100644
--- a/examples/ipsec-secgw/test/tun_3descbc_sha1_common_defs.sh
+++ b/examples/ipsec-secgw/test/tun_3descbc_sha1_common_defs.sh
@@ -70,3 +70,71 @@ EOF
 
 	cat ${SGW_CFG_FILE}
 }
+
+config_secgw_mixed()
+{
+	cat <<EOF > ${SGW_CFG_FILE}
+#sp in IPv4 rules
+sp ipv4 in esp protect 6 pri 2 src ${REMOTE_IPV4}/32 dst ${LOCAL_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv4 rules
+sp ipv4 out esp protect 6 pri 2 src ${LOCAL_IPV4}/32 dst ${REMOTE_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#sp in IPv6 rules
+sp ipv6 in esp protect 8 pri 2 src ${REMOTE_IPV6}/128 dst ${LOCAL_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv6 rules
+sp ipv6 out esp protect 8 pri 2 src ${LOCAL_IPV6}/128 dst ${REMOTE_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SA in rules
+sa in 8 cipher_algo 3des-cbc \
+cipher_key \
+de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+sa in 6 cipher_algo 3des-cbc \
+cipher_key \
+de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+#SA out rules
+sa out 8 cipher_algo 3des-cbc \
+cipher_key \
+de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+sa out 6 cipher_algo 3des-cbc \
+cipher_key \
+de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+#Routing rules
+rt ipv4 dst ${REMOTE_IPV4}/32 port 0
+rt ipv4 dst ${LOCAL_IPV4}/32 port 1
+
+rt ipv6 dst ${REMOTE_IPV6}/128 port 0
+rt ipv6 dst ${LOCAL_IPV6}/128 port 1
+
+#neighbours
+neigh port 0 ${REMOTE_MAC}
+neigh port 1 ${LOCAL_MAC}
+EOF
+
+	cat ${SGW_CFG_FILE}
+}
diff --git a/examples/ipsec-secgw/test/tun_3descbc_sha1_defs.sh b/examples/ipsec-secgw/test/tun_3descbc_sha1_defs.sh
index 2bbe14292..3df050c00 100644
--- a/examples/ipsec-secgw/test/tun_3descbc_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/tun_3descbc_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_3descbc_sha1_esn_defs.sh b/examples/ipsec-secgw/test/tun_3descbc_sha1_esn_defs.sh
index 98349c7bc..349969ceb 100644
--- a/examples/ipsec-secgw/test/tun_3descbc_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/tun_3descbc_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "cbc\(des3_ede\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aescbc_sha1_common_defs.sh b/examples/ipsec-secgw/test/tun_aescbc_sha1_common_defs.sh
index 4025da232..65150e389 100644
--- a/examples/ipsec-secgw/test/tun_aescbc_sha1_common_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aescbc_sha1_common_defs.sh
@@ -66,3 +66,67 @@ EOF
 
 	cat ${SGW_CFG_FILE}
 }
+
+config_secgw_mixed()
+{
+	cat <<EOF > ${SGW_CFG_FILE}
+#sp in IPv4 rules
+sp ipv4 in esp protect 6 pri 2 src ${REMOTE_IPV4}/32 dst ${LOCAL_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv4 rules
+sp ipv4 out esp protect 6 pri 2 src ${LOCAL_IPV4}/32 dst ${REMOTE_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#sp in IPv6 rules
+sp ipv6 in esp protect 8 pri 2 src ${REMOTE_IPV6}/128 dst ${LOCAL_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv6 rules
+sp ipv6 out esp protect 8 pri 2 src ${LOCAL_IPV6}/128 dst ${REMOTE_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SA in rules
+sa in 8 cipher_algo aes-128-cbc \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+sa in 6 cipher_algo aes-128-cbc \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+#SA out rules
+sa out 8 cipher_algo aes-128-cbc \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+sa out 6 cipher_algo aes-128-cbc \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+#Routing rules
+rt ipv4 dst ${REMOTE_IPV4}/32 port 0
+rt ipv4 dst ${LOCAL_IPV4}/32 port 1
+
+rt ipv6 dst ${REMOTE_IPV6}/128 port 0
+rt ipv6 dst ${LOCAL_IPV6}/128 port 1
+
+#neighbours
+neigh port 0 ${REMOTE_MAC}
+neigh port 1 ${LOCAL_MAC}
+EOF
+
+	cat ${SGW_CFG_FILE}
+}
diff --git a/examples/ipsec-secgw/test/tun_aescbc_sha1_defs.sh b/examples/ipsec-secgw/test/tun_aescbc_sha1_defs.sh
index 18aade3a9..aa1e6a4c4 100644
--- a/examples/ipsec-secgw/test/tun_aescbc_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aescbc_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aescbc_sha1_esn_defs.sh b/examples/ipsec-secgw/test/tun_aescbc_sha1_esn_defs.sh
index 28c1125d6..dda8a082a 100644
--- a/examples/ipsec-secgw/test/tun_aescbc_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aescbc_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc aes 0xdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aesctr_sha1_common_defs.sh b/examples/ipsec-secgw/test/tun_aesctr_sha1_common_defs.sh
index a3ac3a698..13db66b6f 100644
--- a/examples/ipsec-secgw/test/tun_aesctr_sha1_common_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesctr_sha1_common_defs.sh
@@ -66,3 +66,67 @@ EOF
 
 	cat ${SGW_CFG_FILE}
 }
+
+config_secgw_mixed()
+{
+	cat <<EOF > ${SGW_CFG_FILE}
+#sp in IPv4 rules
+sp ipv4 in esp protect 6 pri 2 src ${REMOTE_IPV4}/32 dst ${LOCAL_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv4 rules
+sp ipv4 out esp protect 6 pri 2 src ${LOCAL_IPV4}/32 dst ${REMOTE_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#sp in IPv6 rules
+sp ipv6 in esp protect 8 pri 2 src ${REMOTE_IPV6}/128 dst ${LOCAL_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv6 rules
+sp ipv6 out esp protect 8 pri 2 src ${LOCAL_IPV6}/128 dst ${REMOTE_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SA in rules
+sa in 8 cipher_algo aes-128-ctr \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+sa in 6 cipher_algo aes-128-ctr \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+#SA out rules
+sa out 8 cipher_algo aes-128-ctr \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+sa out 6 cipher_algo aes-128-ctr \
+cipher_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+auth_algo sha1-hmac \
+auth_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+#Routing rules
+rt ipv4 dst ${REMOTE_IPV4}/32 port 0
+rt ipv4 dst ${LOCAL_IPV4}/32 port 1
+
+rt ipv6 dst ${REMOTE_IPV6}/128 port 0
+rt ipv6 dst ${LOCAL_IPV6}/128 port 1
+
+#neighbours
+neigh port 0 ${REMOTE_MAC}
+neigh port 1 ${LOCAL_MAC}
+EOF
+
+	cat ${SGW_CFG_FILE}
+}
diff --git a/examples/ipsec-secgw/test/tun_aesctr_sha1_defs.sh b/examples/ipsec-secgw/test/tun_aesctr_sha1_defs.sh
index 3710f897c..5712ee9bd 100644
--- a/examples/ipsec-secgw/test/tun_aesctr_sha1_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesctr_sha1_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aesctr_sha1_esn_defs.sh b/examples/ipsec-secgw/test/tun_aesctr_sha1_esn_defs.sh
index c3ce11da1..5fbe2cfe3 100644
--- a/examples/ipsec-secgw/test/tun_aesctr_sha1_esn_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesctr_sha1_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 flag esn \
+auth sha1 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+enc "rfc3686\(ctr\(aes\)\)" 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aesgcm_common_defs.sh b/examples/ipsec-secgw/test/tun_aesgcm_common_defs.sh
index 278377967..f39a8e4bc 100644
--- a/examples/ipsec-secgw/test/tun_aesgcm_common_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesgcm_common_defs.sh
@@ -58,3 +58,59 @@ EOF
 
 	cat ${SGW_CFG_FILE}
 }
+
+config_secgw_mixed()
+{
+	cat <<EOF > ${SGW_CFG_FILE}
+#sp in IPv4 rules
+sp ipv4 in esp protect 6 pri 2 src ${REMOTE_IPV4}/32 dst ${LOCAL_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv4 rules
+sp ipv4 out esp protect 6 pri 2 src ${LOCAL_IPV4}/32 dst ${REMOTE_IPV4}/32 \
+sport 0:65535 dport 0:65535
+sp ipv4 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#sp in IPv6 rules
+sp ipv6 in esp protect 8 pri 2 src ${REMOTE_IPV6}/128 dst ${LOCAL_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 in esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SP out IPv6 rules
+sp ipv6 out esp protect 8 pri 2 src ${LOCAL_IPV6}/128 dst ${REMOTE_IPV6}/128 \
+sport 0:65535 dport 0:65535
+sp ipv6 out esp bypass pri 1 sport 0:65535 dport 0:65535
+
+#SA in rules
+sa in 8 aead_algo aes-128-gcm \
+aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${REMOTE_IPV4} dst ${LOCAL_IPV4} ${SGW_CFG_XPRM}
+
+sa in 6 aead_algo aes-128-gcm \
+aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${REMOTE_IPV6} dst ${LOCAL_IPV6} ${SGW_CFG_XPRM}
+
+#SA out rules
+sa out 8 aead_algo aes-128-gcm \
+aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv4-tunnel src ${LOCAL_IPV4} dst ${REMOTE_IPV4} ${SGW_CFG_XPRM}
+
+sa out 6 aead_algo aes-128-gcm \
+aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
+mode ipv6-tunnel src ${LOCAL_IPV6} dst ${REMOTE_IPV6} ${SGW_CFG_XPRM}
+
+#Routing rules
+rt ipv4 dst ${REMOTE_IPV4}/32 port 0
+rt ipv4 dst ${LOCAL_IPV4}/32 port 1
+
+rt ipv6 dst ${REMOTE_IPV6}/128 port 0
+rt ipv6 dst ${LOCAL_IPV6}/128 port 1
+
+#neighbours
+neigh port 0 ${REMOTE_MAC}
+neigh port 1 ${LOCAL_MAC}
+EOF
+
+	cat ${SGW_CFG_FILE}
+}
diff --git a/examples/ipsec-secgw/test/tun_aesgcm_defs.sh b/examples/ipsec-secgw/test/tun_aesgcm_defs.sh
index 8ae65321b..6fb8aa6b3 100644
--- a/examples/ipsec-secgw/test/tun_aesgcm_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesgcm_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ aead "rfc4106\(gcm\(aes\)\)" \
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
diff --git a/examples/ipsec-secgw/test/tun_aesgcm_esn_defs.sh b/examples/ipsec-secgw/test/tun_aesgcm_esn_defs.sh
index 606232349..84a666342 100644
--- a/examples/ipsec-secgw/test/tun_aesgcm_esn_defs.sh
+++ b/examples/ipsec-secgw/test/tun_aesgcm_esn_defs.sh
@@ -4,7 +4,7 @@
 
 SGW_CMD_XPRM='-e -w 300'
 
-config_remote_xfrm()
+config_remote_xfrm_44()
 {
 	ssh ${REMOTE_HOST} ip xfrm policy flush
 	ssh ${REMOTE_HOST} ip xfrm state flush
@@ -37,9 +37,80 @@ aead "rfc4106\(gcm\(aes\)\)" \
 	ssh ${REMOTE_HOST} ip xfrm state list
 }
 
-config6_remote_xfrm()
+config_remote_xfrm_46()
 {
-	config_remote_xfrm
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+proto esp spi 6 reqid 1 mode tunnel replay-window 64 flag esn \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${REMOTE_IPV4} dst ${LOCAL_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+proto esp spi 6 reqid 2 mode tunnel replay-window 64 flag esn \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${LOCAL_IPV4} dst ${REMOTE_IPV4}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_64()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
+dir out ptype main action allow \
+tmpl src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp mode tunnel reqid 1
+
+	ssh ${REMOTE_HOST} ip xfrm policy add \
+src ${LOCAL_IPV6} dst ${REMOTE_IPV6} \
+dir in ptype main action allow \
+tmpl src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp mode tunnel reqid 2
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${REMOTE_IPV4} dst ${LOCAL_IPV4} \
+proto esp spi 8 reqid 1 mode tunnel replay-window 64 flag esn \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${REMOTE_IPV6} dst ${LOCAL_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm state add \
+src ${LOCAL_IPV4} dst ${REMOTE_IPV4} \
+proto esp spi 8 reqid 2 mode tunnel replay-window 64 flag esn \
+aead "rfc4106\(gcm\(aes\)\)" \
+0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef 128 \
+sel src ${LOCAL_IPV6} dst ${REMOTE_IPV6}
+
+	ssh ${REMOTE_HOST} ip xfrm policy list
+	ssh ${REMOTE_HOST} ip xfrm state list
+}
+
+config_remote_xfrm_66()
+{
+	ssh ${REMOTE_HOST} ip xfrm policy flush
+	ssh ${REMOTE_HOST} ip xfrm state flush
 
 	ssh ${REMOTE_HOST} ip xfrm policy add \
 src ${REMOTE_IPV6} dst ${LOCAL_IPV6} \
-- 
2.17.1


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

* Re: [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: " Mariusz Drost
@ 2019-09-24 12:18     ` Ananyev, Konstantin
  2019-10-02 15:43     ` Nicolau, Radu
  2019-10-10 13:43     ` Akhil Goyal
  2 siblings, 0 replies; 15+ messages in thread
From: Ananyev, Konstantin @ 2019-09-24 12:18 UTC (permalink / raw)
  To: Drost, MariuszX, Nicolau, Radu, akhil.goyal; +Cc: dev, Lukasz Bartosik


> Ipsec-secgw example application fails to initialize when using default
> configuration file (ep0.cfg) in library mode (librte_ipsec enabled).
> 
> The reason is that two of SP rules in ep0.cfg, one for IPv4 and one
> for IPv6, are using the same SPI number. When SA rules are initialized,
> their SPI number is checked against SPIs stored in SPD. For library
> mode, it is not allowed for the same SA to handle both IPv4 and IPv6.
> 
> Solution is to split SAD into two separate parts - one for IPv4 and one
> for IPv6. Usage of SAs stays the same. Only change is to pass correct
> SAD (IPv4 or IPv6) in places where previously combined database was
> passed.
> 
> Split of SA entries is done at initialization stage. Most of given SA
> entries are checked against SPD. If matching entry is in IPv4 SPD, SA
> rule is added to IPv4 SAD (respectively for IPv6). Different splitting
> method is used only when SA entry is for tunnel in inbound direction.
> In that case if IPv4 tunnel should be used, SA entry is added to IPv4
> SAD (respectively for IPv6). Reasoning is that inner IP version can
> be different than outer IP version for tunneled traffic.
> 
> Bugzilla ID: 239
> Fixes: 5a032a71c6d3 ("examples/ipsec-secgw: make app to use IPsec library")
> 
> Reported-by: Lukasz Bartosik <lbartosik@marvell.com>
> Signed-off-by: Mariusz Drost <mariuszx.drost@intel.com>

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Tested-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> --
> 2.17.1


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

* Re: [dpdk-dev] [PATCH v2 2/2] examples/ipsec-secgw: tests for split SAD
  2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 2/2] examples/ipsec-secgw: tests for split SAD Mariusz Drost
@ 2019-09-24 12:47     ` Ananyev, Konstantin
  0 siblings, 0 replies; 15+ messages in thread
From: Ananyev, Konstantin @ 2019-09-24 12:47 UTC (permalink / raw)
  To: Drost, MariuszX, Nicolau, Radu, akhil.goyal; +Cc: dev, Lukasz Bartosik



> 
> Test scripts updated to reflect change of SAD (split into IPv4 SAD
> and IPv6 SAD). New parameter added to run_test.sh for performing tests
> with mixed IP version, eg. IPv4 ipsec tunnel with IPv6 traffic.
> 
> Bugzilla ID: 239
> Fixes: 5a032a71c6d3 ("examples/ipsec-secgw: make app to use IPsec library")
> 
> Reported-by: Lukasz Bartosik <lbartosik@marvell.com>
> Signed-off-by: Mariusz Drost <mariuszx.drost@intel.com>
> ---

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Tested-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

> 2.17.1


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

* Re: [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: " Mariusz Drost
  2019-09-24 12:18     ` Ananyev, Konstantin
@ 2019-10-02 15:43     ` Nicolau, Radu
  2019-10-10 13:43     ` Akhil Goyal
  2 siblings, 0 replies; 15+ messages in thread
From: Nicolau, Radu @ 2019-10-02 15:43 UTC (permalink / raw)
  To: Drost, MariuszX, akhil.goyal, Ananyev, Konstantin; +Cc: dev, Lukasz Bartosik


On 9/24/2019 11:35 AM, Drost, MariuszX wrote:
> Ipsec-secgw example application fails to initialize when using default
> configuration file (ep0.cfg) in library mode (librte_ipsec enabled).
>
> The reason is that two of SP rules in ep0.cfg, one for IPv4 and one
> for IPv6, are using the same SPI number. When SA rules are initialized,
> their SPI number is checked against SPIs stored in SPD. For library
> mode, it is not allowed for the same SA to handle both IPv4 and IPv6.
>
> Solution is to split SAD into two separate parts - one for IPv4 and one
> for IPv6. Usage of SAs stays the same. Only change is to pass correct
> SAD (IPv4 or IPv6) in places where previously combined database was
> passed.
>
> Split of SA entries is done at initialization stage. Most of given SA
> entries are checked against SPD. If matching entry is in IPv4 SPD, SA
> rule is added to IPv4 SAD (respectively for IPv6). Different splitting
> method is used only when SA entry is for tunnel in inbound direction.
> In that case if IPv4 tunnel should be used, SA entry is added to IPv4
> SAD (respectively for IPv6). Reasoning is that inner IP version can
> be different than outer IP version for tunneled traffic.
>
> Bugzilla ID: 239
> Fixes: 5a032a71c6d3 ("examples/ipsec-secgw: make app to use IPsec library")
>
> Reported-by: Lukasz Bartosik <lbartosik@marvell.com>
> Signed-off-by: Mariusz Drost <mariuszx.drost@intel.com>
> ---
Acked-by: Radu Nicolau <radu.nicolau@intel.com>

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

* Re: [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: " Mariusz Drost
  2019-09-24 12:18     ` Ananyev, Konstantin
  2019-10-02 15:43     ` Nicolau, Radu
@ 2019-10-10 13:43     ` Akhil Goyal
  2019-10-11 13:24       ` Ananyev, Konstantin
  2 siblings, 1 reply; 15+ messages in thread
From: Akhil Goyal @ 2019-10-10 13:43 UTC (permalink / raw)
  To: Mariusz Drost, radu.nicolau, konstantin.ananyev; +Cc: dev, Lukasz Bartosik

Hi Mariusz,


> -----Original Message-----
> From: Mariusz Drost <mariuszx.drost@intel.com>
> Sent: Tuesday, September 24, 2019 4:06 PM
> To: radu.nicolau@intel.com; Akhil Goyal <akhil.goyal@nxp.com>;
> konstantin.ananyev@intel.com
> Cc: dev@dpdk.org; Mariusz Drost <mariuszx.drost@intel.com>; Lukasz Bartosik
> <lbartosik@marvell.com>
> Subject: [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
> 
> Ipsec-secgw example application fails to initialize when using default
> configuration file (ep0.cfg) in library mode (librte_ipsec enabled).
> 
> The reason is that two of SP rules in ep0.cfg, one for IPv4 and one
> for IPv6, are using the same SPI number. When SA rules are initialized,
> their SPI number is checked against SPIs stored in SPD. For library
> mode, it is not allowed for the same SA to handle both IPv4 and IPv6.
> 
> Solution is to split SAD into two separate parts - one for IPv4 and one
> for IPv6. Usage of SAs stays the same. Only change is to pass correct
> SAD (IPv4 or IPv6) in places where previously combined database was
> passed.

Can we have 2 different SAs with same SPI value and with different IPv4 addresses?

Will the IPSec library be able to handle this case. With Setkey it is possible in linux.
Now that we have IPSEC library we should be compatible with what linux can do.

So splitting the SADB with IPv4 and IPv6 will just avoid the issue for IPv4 and IPv6 but the
Issue will still be there. I believe this should be fixed in library rather than application maintaining
Two different databases. Library's intent is to reduce the application overhead for maintaining
IPSec specific stuff.

> 
> Split of SA entries is done at initialization stage. Most of given SA
> entries are checked against SPD. If matching entry is in IPv4 SPD, SA
> rule is added to IPv4 SAD (respectively for IPv6). Different splitting
> method is used only when SA entry is for tunnel in inbound direction.
> In that case if IPv4 tunnel should be used, SA entry is added to IPv4
> SAD (respectively for IPv6). Reasoning is that inner IP version can
> be different than outer IP version for tunneled traffic.
> 
> Bugzilla ID: 239
> Fixes: 5a032a71c6d3 ("examples/ipsec-secgw: make app to use IPsec library")
> 
> Reported-by: Lukasz Bartosik <lbartosik@marvell.com>
> Signed-off-by: Mariusz Drost <mariuszx.drost@intel.com>
> ---
>  examples/ipsec-secgw/ipsec-secgw.c |  48 ++--
>  examples/ipsec-secgw/ipsec.c       |   5 +-
>  examples/ipsec-secgw/ipsec.h       |  21 +-
>  examples/ipsec-secgw/sa.c          | 396 ++++++++++++++++++++---------
>  4 files changed, 312 insertions(+), 158 deletions(-)
> 


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

* Re: [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-10-10 13:43     ` Akhil Goyal
@ 2019-10-11 13:24       ` Ananyev, Konstantin
  2019-10-11 14:02         ` Akhil Goyal
  0 siblings, 1 reply; 15+ messages in thread
From: Ananyev, Konstantin @ 2019-10-11 13:24 UTC (permalink / raw)
  To: Akhil Goyal, Drost, MariuszX, Nicolau, Radu; +Cc: dev, Lukasz Bartosik


Hi Akhil,

> > Ipsec-secgw example application fails to initialize when using default
> > configuration file (ep0.cfg) in library mode (librte_ipsec enabled).
> >
> > The reason is that two of SP rules in ep0.cfg, one for IPv4 and one
> > for IPv6, are using the same SPI number. When SA rules are initialized,
> > their SPI number is checked against SPIs stored in SPD. For library
> > mode, it is not allowed for the same SA to handle both IPv4 and IPv6.
> >
> > Solution is to split SAD into two separate parts - one for IPv4 and one
> > for IPv6. Usage of SAs stays the same. Only change is to pass correct
> > SAD (IPv4 or IPv6) in places where previously combined database was
> > passed.
> 
> Can we have 2 different SAs with same SPI value and with different IPv4 addresses?
> 
> Will the IPSec library be able to handle this case. With Setkey it is possible in linux.
> Now that we have IPSEC library we should be compatible with what linux can do.

For sure, SADB implementation has to be inside librte_ipsec.
In fact Vladimir submitted patches for that:
http://patches.dpdk.org/cover/60910/
I think we already looked at them.
We also plan to integrate it into ipsec-secgw, it would be a separate patch.
We aim for 19.11 right now but might slip to 20.02.

This patch is not about improve/change ipsec-secgw SAD implementation,
see description below.

> 
> So splitting the SADB with IPv4 and IPv6 will just avoid the issue for IPv4 and IPv6 but the
> Issue will still be there.
> I believe this should be fixed in library rather than application maintaining
> Two different databases. Library's intent is to reduce the application overhead for maintaining
> IPSec specific stuff.

Probably we didn't put enough effort to describe the patch goals and methods.
Let me try again:
Right now there is an inconsistency in ipsec-secgw behavior.
In some cases it allows two different IPv4 and IPv6 SP rules to refer to the same SPI (SA),
in other it doesn't.  
So for same config-file ipsec-secgw can either fail or not depending on
 - legacy/library mode
 - selected security action type  

As an example with config file:

sp ipv4 in esp protect 11 pri 2 src 192.168.0.0/16 dst 192.168.0.0/16 sport 0:65535 dport 0:65535
sp ipv6 in esp protect 11 pri 2 src fd12:3456:789a:0031:0000:0000:0000:0092/64 dst fd12:3456:789a:0031:0000:0000:0000:0014/64 sport 0:65535 dport 0:65535
sa out 11 cipher_algo null auth_algo null mode transport
sa in 11 aead_algo aes-128-gcm \
aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
mode transport port_id 0 type inline-crypto-offload

library mode would fail to start, legacy mode would start but wouldn't be able to work correctly.

That is the issue that Lukasz reported:
https://bugs.dpdk.org/show_bug.cgi?id=239

The reason for that: in some cases we do need to know SA IP type (and SIP/DIP values) at SA creation time.
The way ipsec-secgw obtains that information - search for given SPI value across SPDs (IPv4 and IPv6).
So when it finds entries in both IPv4 and IPv6 it is not clear which one to use and exits with an error.
To avoid such situation that patch does the following:
 - search for given SPI value across both SPDs (IPv4 and IPv6)
 - for each positive result create a new SA.
So if we have same SPI in both IPv4 and IPv6 SPDs instead of one SA that
would be referred by both SPD tables (current situation), 
we will create 2 independent SAs - one for IPv4, second for IPv6.
For each one a separate rte_security/crypto session will be created and programmed.   
 
As side effect of that - we have to split ipsec-secgw SADB into two,
as right now it is just a raw array indexed by (SPI%N) value.     

> 
> >
> > Split of SA entries is done at initialization stage. Most of given SA
> > entries are checked against SPD. If matching entry is in IPv4 SPD, SA
> > rule is added to IPv4 SAD (respectively for IPv6). Different splitting
> > method is used only when SA entry is for tunnel in inbound direction.
> > In that case if IPv4 tunnel should be used, SA entry is added to IPv4
> > SAD (respectively for IPv6). Reasoning is that inner IP version can
> > be different than outer IP version for tunneled traffic.
> >
> > Bugzilla ID: 239
> > Fixes: 5a032a71c6d3 ("examples/ipsec-secgw: make app to use IPsec library")
> >
> > Reported-by: Lukasz Bartosik <lbartosik@marvell.com>
> > Signed-off-by: Mariusz Drost <mariuszx.drost@intel.com>
> > ---
> >  examples/ipsec-secgw/ipsec-secgw.c |  48 ++--
> >  examples/ipsec-secgw/ipsec.c       |   5 +-
> >  examples/ipsec-secgw/ipsec.h       |  21 +-
> >  examples/ipsec-secgw/sa.c          | 396 ++++++++++++++++++++---------
> >  4 files changed, 312 insertions(+), 158 deletions(-)
> >


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

* Re: [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-10-11 13:24       ` Ananyev, Konstantin
@ 2019-10-11 14:02         ` Akhil Goyal
  2019-10-11 16:38           ` Ananyev, Konstantin
  0 siblings, 1 reply; 15+ messages in thread
From: Akhil Goyal @ 2019-10-11 14:02 UTC (permalink / raw)
  To: Ananyev, Konstantin, Drost, MariuszX, Nicolau, Radu; +Cc: dev, Lukasz Bartosik

Hi Konstantin,
> 
> Hi Akhil,
> 
> > > Ipsec-secgw example application fails to initialize when using default
> > > configuration file (ep0.cfg) in library mode (librte_ipsec enabled).
> > >
> > > The reason is that two of SP rules in ep0.cfg, one for IPv4 and one
> > > for IPv6, are using the same SPI number. When SA rules are initialized,
> > > their SPI number is checked against SPIs stored in SPD. For library
> > > mode, it is not allowed for the same SA to handle both IPv4 and IPv6.
> > >
> > > Solution is to split SAD into two separate parts - one for IPv4 and one
> > > for IPv6. Usage of SAs stays the same. Only change is to pass correct
> > > SAD (IPv4 or IPv6) in places where previously combined database was
> > > passed.
> >
> > Can we have 2 different SAs with same SPI value and with different IPv4
> addresses?
> >
> > Will the IPSec library be able to handle this case. With Setkey it is possible in
> linux.
> > Now that we have IPSEC library we should be compatible with what linux can
> do.
> 
> For sure, SADB implementation has to be inside librte_ipsec.
> In fact Vladimir submitted patches for that:
> http://patches.dpdk.org/cover/60910/
> I think we already looked at them.
> We also plan to integrate it into ipsec-secgw, it would be a separate patch.
> We aim for 19.11 right now but might slip to 20.02.
> 
> This patch is not about improve/change ipsec-secgw SAD implementation,
> see description below.
> 
> >
> > So splitting the SADB with IPv4 and IPv6 will just avoid the issue for IPv4 and
> IPv6 but the
> > Issue will still be there.
> > I believe this should be fixed in library rather than application maintaining
> > Two different databases. Library's intent is to reduce the application overhead
> for maintaining
> > IPSec specific stuff.
> 
> Probably we didn't put enough effort to describe the patch goals and methods.
> Let me try again:
> Right now there is an inconsistency in ipsec-secgw behavior.
> In some cases it allows two different IPv4 and IPv6 SP rules to refer to the same
> SPI (SA),
> in other it doesn't.
> So for same config-file ipsec-secgw can either fail or not depending on
>  - legacy/library mode
>  - selected security action type
> 
> As an example with config file:
> 
> sp ipv4 in esp protect 11 pri 2 src 192.168.0.0/16 dst 192.168.0.0/16 sport
> 0:65535 dport 0:65535
> sp ipv6 in esp protect 11 pri 2 src fd12:3456:789a:0031:0000:0000:0000:0092/64
> dst fd12:3456:789a:0031:0000:0000:0000:0014/64 sport 0:65535 dport 0:65535
> sa out 11 cipher_algo null auth_algo null mode transport
> sa in 11 aead_algo aes-128-gcm \
> aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
> mode transport port_id 0 type inline-crypto-offload
> 
> library mode would fail to start, legacy mode would start but wouldn't be able to
> work correctly.
> 
> That is the issue that Lukasz reported:
> https://bugs.dpdk.org/show_bug.cgi?id=239
> 
> The reason for that: in some cases we do need to know SA IP type (and SIP/DIP
> values) at SA creation time.
> The way ipsec-secgw obtains that information - search for given SPI value across
> SPDs (IPv4 and IPv6).
> So when it finds entries in both IPv4 and IPv6 it is not clear which one to use and
> exits with an error.
> To avoid such situation that patch does the following:
>  - search for given SPI value across both SPDs (IPv4 and IPv6)
>  - for each positive result create a new SA.
> So if we have same SPI in both IPv4 and IPv6 SPDs instead of one SA that
> would be referred by both SPD tables (current situation),
> we will create 2 independent SAs - one for IPv4, second for IPv6.
> For each one a separate rte_security/crypto session will be created and
> programmed.
> 
> As side effect of that - we have to split ipsec-secgw SADB into two,
> as right now it is just a raw array indexed by (SPI%N) value.

I got the intent of this patch in first place.
I agree that there is a bug in the current application, but this patch is not fixing
it. Rather it is just avoiding it. I have seen the patch for the SAD support in IPSEC.
That is the correct solution and we should pursue that. When you have that logic in place
You would be replacing this code entirely.
You have time till RC2. Application patches are acceptable till RC2 which is close to
3 weeks from now.

Regards,
Akhil


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

* Re: [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-10-11 14:02         ` Akhil Goyal
@ 2019-10-11 16:38           ` Ananyev, Konstantin
  2019-10-15 13:53             ` Akhil Goyal
  0 siblings, 1 reply; 15+ messages in thread
From: Ananyev, Konstantin @ 2019-10-11 16:38 UTC (permalink / raw)
  To: Akhil Goyal, Drost, MariuszX, Nicolau, Radu; +Cc: dev, Lukasz Bartosik


> > > > Ipsec-secgw example application fails to initialize when using default
> > > > configuration file (ep0.cfg) in library mode (librte_ipsec enabled).
> > > >
> > > > The reason is that two of SP rules in ep0.cfg, one for IPv4 and one
> > > > for IPv6, are using the same SPI number. When SA rules are initialized,
> > > > their SPI number is checked against SPIs stored in SPD. For library
> > > > mode, it is not allowed for the same SA to handle both IPv4 and IPv6.
> > > >
> > > > Solution is to split SAD into two separate parts - one for IPv4 and one
> > > > for IPv6. Usage of SAs stays the same. Only change is to pass correct
> > > > SAD (IPv4 or IPv6) in places where previously combined database was
> > > > passed.
> > >
> > > Can we have 2 different SAs with same SPI value and with different IPv4
> > addresses?
> > >
> > > Will the IPSec library be able to handle this case. With Setkey it is possible in
> > linux.
> > > Now that we have IPSEC library we should be compatible with what linux can
> > do.
> >
> > For sure, SADB implementation has to be inside librte_ipsec.
> > In fact Vladimir submitted patches for that:
> > http://patches.dpdk.org/cover/60910/
> > I think we already looked at them.
> > We also plan to integrate it into ipsec-secgw, it would be a separate patch.
> > We aim for 19.11 right now but might slip to 20.02.
> >
> > This patch is not about improve/change ipsec-secgw SAD implementation,
> > see description below.
> >
> > >
> > > So splitting the SADB with IPv4 and IPv6 will just avoid the issue for IPv4 and
> > IPv6 but the
> > > Issue will still be there.
> > > I believe this should be fixed in library rather than application maintaining
> > > Two different databases. Library's intent is to reduce the application overhead
> > for maintaining
> > > IPSec specific stuff.
> >
> > Probably we didn't put enough effort to describe the patch goals and methods.
> > Let me try again:
> > Right now there is an inconsistency in ipsec-secgw behavior.
> > In some cases it allows two different IPv4 and IPv6 SP rules to refer to the same
> > SPI (SA),
> > in other it doesn't.
> > So for same config-file ipsec-secgw can either fail or not depending on
> >  - legacy/library mode
> >  - selected security action type
> >
> > As an example with config file:
> >
> > sp ipv4 in esp protect 11 pri 2 src 192.168.0.0/16 dst 192.168.0.0/16 sport
> > 0:65535 dport 0:65535
> > sp ipv6 in esp protect 11 pri 2 src fd12:3456:789a:0031:0000:0000:0000:0092/64
> > dst fd12:3456:789a:0031:0000:0000:0000:0014/64 sport 0:65535 dport 0:65535
> > sa out 11 cipher_algo null auth_algo null mode transport
> > sa in 11 aead_algo aes-128-gcm \
> > aead_key de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef \
> > mode transport port_id 0 type inline-crypto-offload
> >
> > library mode would fail to start, legacy mode would start but wouldn't be able to
> > work correctly.
> >
> > That is the issue that Lukasz reported:
> > https://bugs.dpdk.org/show_bug.cgi?id=239
> >
> > The reason for that: in some cases we do need to know SA IP type (and SIP/DIP
> > values) at SA creation time.
> > The way ipsec-secgw obtains that information - search for given SPI value across
> > SPDs (IPv4 and IPv6).
> > So when it finds entries in both IPv4 and IPv6 it is not clear which one to use and
> > exits with an error.
> > To avoid such situation that patch does the following:
> >  - search for given SPI value across both SPDs (IPv4 and IPv6)
> >  - for each positive result create a new SA.
> > So if we have same SPI in both IPv4 and IPv6 SPDs instead of one SA that
> > would be referred by both SPD tables (current situation),
> > we will create 2 independent SAs - one for IPv4, second for IPv6.
> > For each one a separate rte_security/crypto session will be created and
> > programmed.
> >
> > As side effect of that - we have to split ipsec-secgw SADB into two,
> > as right now it is just a raw array indexed by (SPI%N) value.
> 
> I got the intent of this patch in first place.
> I agree that there is a bug in the current application, but this patch is not fixing
> it. Rather it is just avoiding it. I have seen the patch for the SAD support in IPSEC.
> That is the correct solution and we should pursue that. When you have that logic in place
> You would be replacing this code entirely.
> You have time till RC2. Application patches are acceptable till RC2 which is close to
> 3 weeks from now.

Ok, so to confirm:
Your only issue here is that patch is that we have to split ipsec-secgw SADB into two?

No objections to other part:
- search for given SPI value across both SPDs (IPv4 and IPv6)
 - for each positive result create a new SA.
So if we have same SPI in both IPv4 and IPv6 SPDs instead of one SA that
would be referred by both SPD tables (current situation),
we will create 2 independent SAs - one for IPv4, second for IPv6.
For each one a separate rte_security/crypto session will be created and programmed.
?

Because, I think that part will still be needed even when will have new SAD in place.
Konstantin



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

* Re: [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-10-11 16:38           ` Ananyev, Konstantin
@ 2019-10-15 13:53             ` Akhil Goyal
  2019-10-16 10:20               ` Ananyev, Konstantin
  0 siblings, 1 reply; 15+ messages in thread
From: Akhil Goyal @ 2019-10-15 13:53 UTC (permalink / raw)
  To: Ananyev, Konstantin, Drost, MariuszX, Nicolau, Radu; +Cc: dev, Lukasz Bartosik

> 
> Ok, so to confirm:
> Your only issue here is that patch is that we have to split ipsec-secgw SADB into
> two?
> 
> No objections to other part:
> - search for given SPI value across both SPDs (IPv4 and IPv6)
>  - for each positive result create a new SA.
> So if we have same SPI in both IPv4 and IPv6 SPDs instead of one SA that
> would be referred by both SPD tables (current situation),
> we will create 2 independent SAs - one for IPv4, second for IPv6.
> For each one a separate rte_security/crypto session will be created and
> programmed.
> ?
> 
> Because, I think that part will still be needed even when will have new SAD in
> place.
Agreed.

> Konstantin
> 


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

* Re: [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: fix SAD selection logic
  2019-10-15 13:53             ` Akhil Goyal
@ 2019-10-16 10:20               ` Ananyev, Konstantin
  0 siblings, 0 replies; 15+ messages in thread
From: Ananyev, Konstantin @ 2019-10-16 10:20 UTC (permalink / raw)
  To: Akhil Goyal, Drost, MariuszX, Nicolau, Radu; +Cc: dev, Lukasz Bartosik


> 
> >
> > Ok, so to confirm:
> > Your only issue here is that patch is that we have to split ipsec-secgw SADB into
> > two?
> >
> > No objections to other part:
> > - search for given SPI value across both SPDs (IPv4 and IPv6)
> >  - for each positive result create a new SA.
> > So if we have same SPI in both IPv4 and IPv6 SPDs instead of one SA that
> > would be referred by both SPD tables (current situation),
> > we will create 2 independent SAs - one for IPv4, second for IPv6.
> > For each one a separate rte_security/crypto session will be created and
> > programmed.
> > ?
> >
> > Because, I think that part will still be needed even when will have new SAD in
> > place.
> Agreed.

Ok, then let's postpone this patch till new SAD will be in ipsec-secgw.
Konstantin

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

end of thread, back to index

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-05 12:35 [dpdk-dev] [PATCH 0/2] fix SAD selection logic Mariusz Drost
2019-09-05 12:35 ` [dpdk-dev] [PATCH 1/2] examples/ipsec-secgw: " Mariusz Drost
2019-09-05 12:35 ` [dpdk-dev] [PATCH 2/2] examples/ipsec-secgw: tests for split SAD Mariusz Drost
2019-09-24 10:35 ` [dpdk-dev] [PATCH v2 0/2] fix SAD selection logic Mariusz Drost
2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 1/2] examples/ipsec-secgw: " Mariusz Drost
2019-09-24 12:18     ` Ananyev, Konstantin
2019-10-02 15:43     ` Nicolau, Radu
2019-10-10 13:43     ` Akhil Goyal
2019-10-11 13:24       ` Ananyev, Konstantin
2019-10-11 14:02         ` Akhil Goyal
2019-10-11 16:38           ` Ananyev, Konstantin
2019-10-15 13:53             ` Akhil Goyal
2019-10-16 10:20               ` Ananyev, Konstantin
2019-09-24 10:35   ` [dpdk-dev] [PATCH v2 2/2] examples/ipsec-secgw: tests for split SAD Mariusz Drost
2019-09-24 12:47     ` Ananyev, Konstantin

DPDK-dev Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/dpdk-dev/0 dpdk-dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dpdk-dev dpdk-dev/ https://lore.kernel.org/dpdk-dev \
		dev@dpdk.org dpdk-dev@archiver.kernel.org
	public-inbox-index dpdk-dev

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/ public-inbox