All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Chained Mbufs support in SW PMDs
@ 2016-12-02 17:07 Tomasz Kulasek
  2016-12-02 17:07 ` [PATCH 1/4] rte_mbuf: add rte_pktmbuf_coalesce Tomasz Kulasek
                   ` (4 more replies)
  0 siblings, 5 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-02 17:07 UTC (permalink / raw)
  To: dev

This patch set adds support of scattered-gather list for SW PMDs.

As of now, application needs to reserve continuous block of memory for
mbufs which is not always the case. Hence needed to support chaining of
mbufs which are smaller in size but can be used if chained.

Above work involves:

 a) Create mbuf functions to coalesce mbuf chains into a single mbuf.
 b) For each software poll mode driver code to detect chained mbufs
    support and coalesce these before preforming crypto.
 c) Add relevant unit tests to test the functionality.


Tomasz Kulasek (4):
  rte_mbuf: add rte_pktmbuf_coalesce
  test: add rte_pktmbuf_coalesce unit tests
  crypto: add sgl support for sw PMDs
  test: add sgl unit tests for crypto devices

 app/test/test_cryptodev.c                  |  456 ++++++++++++++++++++++++++++
 app/test/test_cryptodev.h                  |  111 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   32 +-
 app/test/test_cryptodev_blockcipher.c      |  170 +++++++----
 app/test/test_cryptodev_blockcipher.h      |    1 +
 app/test/test_mbuf.c                       |  134 ++++++++
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 +
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 +-
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +
 drivers/crypto/null/null_crypto_pmd.c      |    3 +-
 drivers/crypto/openssl/rte_openssl_pmd.c   |   11 +
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +
 lib/librte_cryptodev/rte_cryptodev.c       |    4 +-
 lib/librte_cryptodev/rte_cryptodev.h       |    3 +-
 lib/librte_mbuf/rte_mbuf.h                 |   34 +++
 16 files changed, 966 insertions(+), 67 deletions(-)

-- 
1.7.9.5

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

* [PATCH 1/4] rte_mbuf: add rte_pktmbuf_coalesce
  2016-12-02 17:07 [PATCH 0/4] Chained Mbufs support in SW PMDs Tomasz Kulasek
@ 2016-12-02 17:07 ` Tomasz Kulasek
  2016-12-16 10:06   ` Olivier Matz
  2016-12-02 17:07 ` [PATCH 2/4] test: add rte_pktmbuf_coalesce unit tests Tomasz Kulasek
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-02 17:07 UTC (permalink / raw)
  To: dev

This patch adds function rte_pktmbuf_coalesce to let crypto PMD coalesce
chained mbuf before crypto operation and extend their capabilities to
support segmented mbufs when device cannot handle them natively.


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 lib/librte_mbuf/rte_mbuf.h |   34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ead7c6e..f048681 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -1647,6 +1647,40 @@ static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail
 }
 
 /**
+ * Coalesce data from mbuf to the continuous buffer.
+ *
+ * @param mbuf_dst
+ *   Contiguous destination mbuf
+ * @param mbuf_src
+ *   Uncontiguous source mbuf
+ *
+ * @return
+ *   - 0, on success
+ *   - -EINVAL, on error
+ */
+
+#include <rte_hexdump.h>
+
+static inline int
+rte_pktmbuf_coalesce(struct rte_mbuf *mbuf_dst, struct rte_mbuf *mbuf_src)
+{
+	char *dst;
+
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst) ||
+			rte_pktmbuf_data_len(mbuf_dst) >=
+			rte_pktmbuf_pkt_len(mbuf_src))
+		return -EINVAL;
+
+	dst = rte_pktmbuf_mtod(mbuf_dst, char *);
+
+	if (!__rte_pktmbuf_read(mbuf_src, 0, rte_pktmbuf_pkt_len(mbuf_src),
+			dst))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
  * Dump an mbuf structure to a file.
  *
  * Dump all fields for the given packet mbuf and all its associated
-- 
1.7.9.5

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

* [PATCH 2/4] test: add rte_pktmbuf_coalesce unit tests
  2016-12-02 17:07 [PATCH 0/4] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2016-12-02 17:07 ` [PATCH 1/4] rte_mbuf: add rte_pktmbuf_coalesce Tomasz Kulasek
@ 2016-12-02 17:07 ` Tomasz Kulasek
  2016-12-02 17:07 ` [PATCH 3/4] crypto: add sgl support for sw PMDs Tomasz Kulasek
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-02 17:07 UTC (permalink / raw)
  To: dev

This patch tests rte_pktmbuf_coalesce functionality:

 1) Creates banch of segmented mbufs with different size and number of
    segments.
 2) Generates pkt_len bytes of random data.
 3) Fills noncontigouos mbuf with randomly generated data.
 4) Uses rte_pktmbuf_coalesce to coalesce segmented buffer into one
    contiguous.
 5) Verifies data in destination buffer.


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_mbuf.c |  134 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 134 insertions(+)

diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c
index c0823ea..e3c7657 100644
--- a/app/test/test_mbuf.c
+++ b/app/test/test_mbuf.c
@@ -930,6 +930,135 @@
 	return 0;
 }
 
+static int
+test_mbuf_coalesce(int pkt_len, int nb_segs) {
+
+	struct rte_mbuf *m = NULL, *mbuf_src = NULL, *mbuf_dst = NULL;
+	uint8_t data[pkt_len], *src, *dst;
+	int data_len = 0;
+	int i, size;
+	int t_len;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return -1;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return -1;
+	}
+
+	/* Setup buffer */
+	for (i = 0; i < pkt_len; i++)
+		data[i] = (uint8_t) rte_rand();
+
+	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+	src = data;
+	size = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (i = 0; size > 0; i++) {
+
+		m = rte_pktmbuf_alloc(pktmbuf_pool);
+		if (i == 0)
+			mbuf_src = m;
+
+		if (!m) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+				rte_pktmbuf_tailroom(m));
+
+		data_len = size > t_len ? t_len : size;
+		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (!dst) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		rte_memcpy(dst, src, data_len);
+		src += data_len;
+
+		if (mbuf_src != m)
+			rte_pktmbuf_chain(mbuf_src, m);
+
+		size -= data_len;
+
+	}
+
+	/* Create destination buffer to store coalesced data */
+	mbuf_dst = rte_pktmbuf_alloc(pktmbuf_pool);
+	if (!mbuf_dst) {
+		printf("Cannot create destination buffer\n");
+		goto fail;
+	}
+
+	dst = (uint8_t *)rte_pktmbuf_append(m, rte_pktmbuf_pkt_len(mbuf_dst));
+
+	if (rte_pktmbuf_coalesce(mbuf_dst, mbuf_src)) {
+		printf("Mbuf coalesce failed\n");
+		goto fail;
+	}
+
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+		printf("Destination buffer should be contiguous\n");
+		goto fail;
+	}
+
+	dst = rte_pktmbuf_mtod(mbuf_dst, uint8_t *);
+
+	if (memcmp(dst, data, rte_pktmbuf_pkt_len(mbuf_src))) {
+		printf("Incorrect data in coalesced mbuf\n");
+		goto fail;
+	}
+
+	if (mbuf_src)
+		rte_pktmbuf_free(mbuf_src);
+	if (mbuf_dst)
+		rte_pktmbuf_free(mbuf_dst);
+	return 0;
+
+fail:
+	if (mbuf_src)
+		rte_pktmbuf_free(mbuf_src);
+	if (mbuf_dst)
+		rte_pktmbuf_free(mbuf_dst);
+	return -1;
+}
+
+static int
+test_mbuf_coalesce_check(void)
+{
+	struct test_mbuf_array {
+		int size;
+		int nb_segs;
+	} mbuf_array[5] = {
+			{ 128, 2 },
+			{ 64, 64 },
+			{ 512, 10 },
+			{ 250, 11 },
+			{ 123, 8 },
+	};
+	unsigned i;
+
+	printf("Test mbuf coalesce API\n");
+
+	for (i = 0; i < RTE_DIM(mbuf_array); i++)
+		if (test_mbuf_coalesce(mbuf_array[i].size,
+				mbuf_array[i].nb_segs)) {
+			printf("Test failed for %d, %d\n", mbuf_array[i].size,
+					mbuf_array[i].nb_segs);
+			return -1;
+		}
+
+	return 0;
+}
 
 static int
 test_mbuf(void)
@@ -1023,6 +1152,11 @@
 		printf("test_failing_mbuf_sanity_check() failed\n");
 		return -1;
 	}
+
+	if (test_mbuf_coalesce_check() < 0) {
+		printf("test_mbuf_coalesce_check() failed\n");
+		return -1;
+	}
 	return 0;
 }
 
-- 
1.7.9.5

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

* [PATCH 3/4] crypto: add sgl support for sw PMDs
  2016-12-02 17:07 [PATCH 0/4] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2016-12-02 17:07 ` [PATCH 1/4] rte_mbuf: add rte_pktmbuf_coalesce Tomasz Kulasek
  2016-12-02 17:07 ` [PATCH 2/4] test: add rte_pktmbuf_coalesce unit tests Tomasz Kulasek
@ 2016-12-02 17:07 ` Tomasz Kulasek
  2016-12-03  8:28   ` Michał Mirosław
  2016-12-02 17:07 ` [PATCH 4/4] test: add sgl unit tests for crypto devices Tomasz Kulasek
  2016-12-29 17:12 ` [PATCH v2 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
  4 siblings, 1 reply; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-02 17:07 UTC (permalink / raw)
  To: dev

This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature flag
informing that selected crypto device supports segmented mbufs natively
and doesn't need to be coalesced before crypto operation.

While using segmented buffers in crypto devices may have unpredictable
results, for PMDs which doesn't support it natively, additional check is
made for debug compilation.


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 ++++++++++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 ++++++++++++++++---
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +++++++++++++
 drivers/crypto/null/null_crypto_pmd.c      |    3 ++-
 drivers/crypto/openssl/rte_openssl_pmd.c   |   11 +++++++++++
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +++++++++++++++
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +++++++++++++
 lib/librte_cryptodev/rte_cryptodev.c       |    4 ++--
 lib/librte_cryptodev/rte_cryptodev.h       |    3 ++-
 9 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index dba5e15..1a6120c 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -375,6 +375,20 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_AESNI_GCM_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			GCM_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			qp->qp_stats.enqueue_err_count++;
+			break;
+		}
+#endif
+
 		retval = process_gcm_crypto_op(qp, ops[i]->sym, sess);
 		if (retval < 0) {
 			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index f07cd07..b5e115e 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -529,15 +529,28 @@
 	int i, processed_jobs = 0;
 
 	for (i = 0; i < nb_ops; i++) {
-#ifdef RTE_LIBRTE_AESNI_MB_DEBUG
-		if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
+#ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
+		if (unlikely(ops[i]->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
 			MB_LOG_ERR("PMD only supports symmetric crypto "
 				"operation requests, op (%p) is not a "
-				"symmetric operation.", op);
+				"symmetric operation.", ops[i]);
+			qp->stats.enqueue_err_count++;
+			goto flush_jobs;
+		}
+
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			MB_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 			qp->stats.enqueue_err_count++;
 			goto flush_jobs;
 		}
 #endif
+
 		sess = get_session(qp, ops[i]);
 		if (unlikely(sess == NULL)) {
 			qp->stats.enqueue_err_count++;
diff --git a/drivers/crypto/kasumi/rte_kasumi_pmd.c b/drivers/crypto/kasumi/rte_kasumi_pmd.c
index b119da2..4bdd7bb 100644
--- a/drivers/crypto/kasumi/rte_kasumi_pmd.c
+++ b/drivers/crypto/kasumi/rte_kasumi_pmd.c
@@ -455,6 +455,19 @@
 	for (i = 0; i < nb_ops; i++) {
 		curr_c_op = ops[i];
 
+#ifdef RTE_LIBRTE_PMD_KASUMI_DEBUG
+		if (!rte_pktmbuf_is_contiguous(curr_c_op->sym->m_src) ||
+				(curr_c_op->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						curr_c_op->sym->m_dst))) {
+			KASUMI_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", curr_c_op);
+			curr_c_op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		/* Set status as enqueued (not processed yet) by default. */
 		curr_c_op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
 
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index c69606b..c37d3d6 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -216,7 +216,8 @@
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
-			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
 
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 5f8fa33..b57588e 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -868,6 +868,17 @@
 	msrc = op->sym->m_src;
 	mdst = op->sym->m_dst ? op->sym->m_dst : op->sym->m_src;
 
+#ifdef RTE_LIBRTE_PMD_OPENSSL_DEBUG
+	if (!rte_pktmbuf_is_contiguous(msrc) ||
+			!rte_pktmbuf_is_contiguous(mdst)) {
+		OPENSSL_LOG_ERR("PMD supports only contiguous mbufs, "
+			"op (%p) provides noncontiguous mbuf as "
+			"source/destination buffer.\n", op);
+		op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+		return -1;
+	}
+#endif
+
 	op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
 
 	switch (sess->chain_order) {
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 3b4292a..9a6f16d 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -330,6 +330,21 @@
 	unsigned i;
 	unsigned enqueued_ops, processed_ops;
 
+#ifdef RTE_LIBRTE_PMD_SNOW3G_DEBUG
+	for (i = 0; i < num_ops; i++) {
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			SNOW3G_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			return 0;
+		}
+	}
+#endif
+
 	switch (session->op) {
 	case SNOW3G_OP_ONLY_CIPHER:
 		processed_ops = process_snow3g_cipher_op(ops,
diff --git a/drivers/crypto/zuc/rte_zuc_pmd.c b/drivers/crypto/zuc/rte_zuc_pmd.c
index 3849119..bf53f76 100644
--- a/drivers/crypto/zuc/rte_zuc_pmd.c
+++ b/drivers/crypto/zuc/rte_zuc_pmd.c
@@ -211,6 +211,19 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_ZUC_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ZUC_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		src[i] = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
 				(ops[i]->sym->cipher.data.offset >> 3);
 		dst[i] = ops[i]->sym->m_dst ?
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 127e8d0..ebbb822 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -211,13 +211,13 @@ struct rte_cryptodev_callback {
 		return "CPU_AESNI";
 	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
 		return "HW_ACCELERATED";
-
+	case RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER:
+		return "MBUF_SCATTER_GATHER";
 	default:
 		return NULL;
 	}
 }
 
-
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)
 {
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 8f63e8f..70ff7fc 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -225,7 +225,8 @@ struct rte_cryptodev_capabilities {
 /**< Utilises CPU AES-NI instructions */
 #define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL << 7)
 /**< Operations are off-loaded to an external hardware accelerator */
-
+#define	RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER	(1ULL << 8)
+/**< Scatter-gather mbufs are supported */
 
 /**
  * Get the name of a crypto device feature flag
-- 
1.7.9.5

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

* [PATCH 4/4] test: add sgl unit tests for crypto devices
  2016-12-02 17:07 [PATCH 0/4] Chained Mbufs support in SW PMDs Tomasz Kulasek
                   ` (2 preceding siblings ...)
  2016-12-02 17:07 ` [PATCH 3/4] crypto: add sgl support for sw PMDs Tomasz Kulasek
@ 2016-12-02 17:07 ` Tomasz Kulasek
  2016-12-29 17:12 ` [PATCH v2 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
  4 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-02 17:07 UTC (permalink / raw)
  To: dev; +Cc: Daniel Mrzyglod

This patch provides unit tests for set of cipher/hash combinations covering
currently implemented crypto PMD's and allowing to verify scatter gather
support.


Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_cryptodev.c                  |  456 ++++++++++++++++++++++++++++
 app/test/test_cryptodev.h                  |  111 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   32 +-
 app/test/test_cryptodev_blockcipher.c      |  170 +++++++----
 app/test/test_cryptodev_blockcipher.h      |    1 +
 5 files changed, 710 insertions(+), 60 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 872f8b4..613dae9 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -1688,6 +1688,10 @@ struct crypto_unittest_params {
 
 	TEST_ASSERT_NOT_NULL(sym_op->cipher.iv.data, "no room to prepend iv");
 
+	/* For OOP operation both buffers must have the same size */
+	if (ut_params->obuf)
+		rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+
 	memset(sym_op->cipher.iv.data, 0, iv_pad_len);
 	sym_op->cipher.iv.phys_addr = rte_pktmbuf_mtophys(ut_params->ibuf);
 	sym_op->cipher.iv.length = iv_pad_len;
@@ -2509,6 +2513,84 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned plaintext_pad_len;
+	unsigned plaintext_len;
+
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+		/* Validate obuf */
+		TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+			ciphertext,
+			tdata->ciphertext.data,
+			tdata->validCipherLenInBits.len,
+			"KASUMI Ciphertext data not as expected");
+		return 0;
+}
+
+
+static int
 test_kasumi_encryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2577,6 +2659,81 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_oop_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned plaintext_pad_len;
+	unsigned plaintext_len;
+
+	const uint8_t *ciphertext;
+	uint8_t buffer[2048];
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"KASUMI Ciphertext data not as expected");
+	return 0;
+}
+
+
+static int
 test_kasumi_decryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2849,6 +3006,85 @@ struct crypto_unittest_params {
 	return 0;
 }
 
+static int
+test_snow3g_encryption_oop_sgl(const struct snow3g_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned plaintext_pad_len;
+	unsigned plaintext_len;
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create SNOW 3G session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple of */
+	/* the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3);
+
+	TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+			"Failed to allocate input buffer in mempool");
+	TEST_ASSERT_NOT_NULL(ut_params->obuf,
+			"Failed to allocate output buffer in mempool");
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create SNOW 3G operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->validCipherLenInBits.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validDataLenInBits.len,
+		"SNOW 3G Ciphertext data not as expected");
+
+	return 0;
+}
+
 /* Shift right a buffer by "offset" bits, "offset" < 8 */
 static void
 buffer_shift_right(uint8_t *buffer, uint32_t length, uint8_t offset)
@@ -3504,6 +3740,84 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_sgl(const struct zuc_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned plaintext_pad_len;
+	unsigned plaintext_len;
+	const uint8_t *ciphertext;
+	uint8_t ciphertext_buffer[2048];
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+			tdata->plaintext.data);
+
+	/* Create ZUC session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3,
+			tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	/* Clear mbuf payload */
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create ZUC operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+			tdata->iv.len, tdata->plaintext.len,
+			tdata->validCipherOffsetLenInBits.len,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"ZUC Ciphertext data not as expected");
+
+	return 0;
+}
+
+static int
 test_zuc_authentication(const struct zuc_hash_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -3571,12 +3885,24 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_kasumi_encryption_test_case_1_sgl(void)
+{
+	return test_kasumi_encryption_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_1_oop(void)
 {
 	return test_kasumi_encryption_oop(&kasumi_test_case_1);
 }
 
 static int
+test_kasumi_encryption_test_case_1_oop_sgl(void)
+{
+	return test_kasumi_encryption_oop_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_2(void)
 {
 	return test_kasumi_encryption(&kasumi_test_case_2);
@@ -3648,6 +3974,13 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_snow3g_encryption_test_case_1_oop_sgl(void)
+{
+	return test_snow3g_encryption_oop_sgl(&snow3g_test_case_1);
+}
+
+
+static int
 test_snow3g_encryption_test_case_1_offset_oop(void)
 {
 	return test_snow3g_encryption_offset_oop(&snow3g_test_case_1);
@@ -3767,6 +4100,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_test_case_6_sgl(void)
+{
+	return test_zuc_encryption_sgl(&zuc_test_case_1);
+}
+
+static int
 test_zuc_hash_generate_test_case_1(void)
 {
 	return test_zuc_authentication(&zuc_hash_test_case_1);
@@ -4085,6 +4424,104 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_mb_AES_GCM_authenticated_encryption_sgl(const struct gcm_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	int retval;
+
+	unsigned plaintext_len;
+	uint16_t plaintext_pad_len;
+	uint8_t ciphertext_buffer[2048], auth_tag_buffer[2048];
+	const uint8_t *ciphertext, *auth_tag;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create GCM session */
+	retval = create_gcm_session(ts_params->valid_devs[0],
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+			tdata->key.data, tdata->key.len,
+			tdata->aad.len, tdata->auth_tag.len,
+			RTE_CRYPTO_AUTH_OP_GENERATE);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = tdata->plaintext.len;
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create GCM opertaion */
+	retval = create_gcm_operation(RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+			tdata->auth_tag.data, tdata->auth_tag.len,
+			tdata->iv.data, tdata->iv.len,
+			tdata->aad.data, tdata->aad.len,
+			tdata->plaintext.len, plaintext_pad_len);
+	if (retval < 0) {
+		printf("create operation failed\n");
+		return retval;
+	}
+
+	rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+	ut_params->op->sym->m_src = ut_params->ibuf;
+
+	/* Process crypto operation */
+	TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+			ut_params->op), "failed to process sym crypto op");
+
+	TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+			"crypto op processing failed");
+
+	/* Validate obuf */
+	if (ut_params->op->sym->m_dst) {
+		ciphertext = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+				tdata->iv.len, plaintext_pad_len,
+				ciphertext_buffer);
+		auth_tag = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+				plaintext_pad_len, tdata->auth_tag.len,
+				auth_tag_buffer);
+	} else {
+		ciphertext = rte_pktmbuf_read(ut_params->op->sym->m_src,
+				RTE_ALIGN_CEIL(tdata->iv.len, 16) +
+				ALIGN_POW2_ROUNDUP(tdata->aad.len, 16),
+				plaintext_pad_len, ciphertext_buffer);
+		auth_tag = rte_pktmbuf_read(ut_params->op->sym->m_src,
+				plaintext_pad_len +
+				RTE_ALIGN_CEIL(tdata->iv.len, 16) +
+				ALIGN_POW2_ROUNDUP(tdata->aad.len, 16),
+				tdata->auth_tag.len, auth_tag_buffer);
+	}
+
+	TEST_ASSERT_BUFFERS_ARE_EQUAL(
+			ciphertext,
+			tdata->ciphertext.data,
+			tdata->ciphertext.len,
+			"GCM Ciphertext data not as expected");
+
+	TEST_ASSERT_BUFFERS_ARE_EQUAL(
+			auth_tag,
+			tdata->auth_tag.data,
+			tdata->auth_tag.len,
+			"GCM Generated auth tag not as expected");
+
+	return 0;
+
+}
+
+static int
 test_mb_AES_GCM_authenticated_encryption_test_case_1(void)
 {
 	return test_mb_AES_GCM_authenticated_encryption(&gcm_test_case_1);
@@ -4127,6 +4564,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_mb_AES_GCM_authenticated_encryption_test_case_8(void)
+{
+	return test_mb_AES_GCM_authenticated_encryption_sgl(&gcm_test_case_2);
+}
+
+static int
 test_mb_AES_GCM_authenticated_decryption(const struct gcm_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -6297,6 +6740,9 @@ struct test_crypto_vector {
 			test_mb_AES_GCM_authenticated_encryption_test_case_6),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_mb_AES_GCM_authenticated_encryption_test_case_7),
+			/** chained mbuf encrypt tests **/
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_mb_AES_GCM_authenticated_encryption_test_case_8),
 
 		/** AES GCM Authenticated Decryption */
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6327,6 +6773,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_2),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_3),
@@ -6349,6 +6797,10 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_oop_sgl),
+
+
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_decryption_test_case_1_oop),
 
 		/** KASUMI hash only (UIA1) */
@@ -6401,6 +6853,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_snow3g_encryption_test_case_1_oop_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_decryption_test_case_1_oop),
 
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6478,6 +6932,8 @@ struct test_crypto_vector {
 			test_zuc_hash_generate_test_case_4),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_zuc_hash_generate_test_case_5),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_zuc_encryption_test_case_6_sgl),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
 };
diff --git a/app/test/test_cryptodev.h b/app/test/test_cryptodev.h
index a9089aa..f68ad0a 100644
--- a/app/test/test_cryptodev.h
+++ b/app/test/test_cryptodev.h
@@ -71,4 +71,115 @@
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA384		(24)
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA512		(32)
 
+/**
+ * Write (spread) data from buffer to mbuf data
+ *
+ * @param mbuf
+ *   Destination mbuf
+ * @param offset
+ *   Start offset in mbuf
+ * @param len
+ *   Number of bytes to copy
+ * @param buffer
+ *   Continuous source buffer
+ */
+static inline void
+pktmbuf_write(struct rte_mbuf *mbuf, int offset, int len, const uint8_t *buffer)
+{
+	int n = len;
+	int l;
+	struct rte_mbuf *m;
+	char *dst;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	l = m->data_len - offset;
+
+	/* copy data from first segment */
+	dst = rte_pktmbuf_mtod_offset(m, char *, offset);
+	if (len <= l) {
+		rte_memcpy(dst, buffer, len);
+		return;
+	}
+
+	rte_memcpy(dst, buffer, l);
+	buffer += l;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		dst = rte_pktmbuf_mtod(m, char *);
+		l = m->data_len;
+		if (n < l) {
+			rte_memcpy(dst, buffer, n);
+			return;
+		}
+		rte_memcpy(dst, buffer, l);
+		buffer += l;
+		n -= l;
+	}
+}
+
+static inline struct rte_mbuf *
+create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
+		int nb_segs) {
+
+	struct rte_mbuf *m = NULL, *mbuf = NULL;
+	uint8_t *dst;
+	int data_len = 0;
+	int i, size;
+	int t_len;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return NULL;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return NULL;
+	}
+
+	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+	size = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (i = 0; size > 0; i++) {
+
+		m = rte_pktmbuf_alloc(mbuf_pool);
+		if (i == 0)
+			mbuf = m;
+
+		if (!m) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+				rte_pktmbuf_tailroom(m));
+
+		data_len = size > t_len ? t_len : size;
+		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (!dst) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		if (mbuf != m)
+			rte_pktmbuf_chain(mbuf, m);
+
+		size -= data_len;
+
+	}
+	return mbuf;
+
+fail:
+	if (mbuf)
+		rte_pktmbuf_free(mbuf);
+	return NULL;
+}
+
 #endif /* TEST_CRYPTODEV_H_ */
diff --git a/app/test/test_cryptodev_aes_test_vectors.h b/app/test/test_cryptodev_aes_test_vectors.h
index 1c68f93..ed63c0a 100644
--- a/app/test/test_cryptodev_aes_test_vectors.h
+++ b/app/test/test_cryptodev_aes_test_vectors.h
@@ -883,6 +883,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+				"Scatter Gather",
+		.test_data = &aes_test_data_4,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_4,
@@ -926,6 +937,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest "
+				"Scatter Gather Sessionless",
+		.test_data = &aes_test_data_6,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS |
+			BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_6,
@@ -1033,9 +1055,17 @@
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
-		.test_descr = "AES-192-CBC Encryption",
+		.test_descr = "AES-192-CBC",
+		.test_data = &aes_test_data_10,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
+		.test_descr = "AES-192-CBC Encryption Scater gather",
 		.test_data = &aes_test_data_10,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
diff --git a/app/test/test_cryptodev_blockcipher.c b/app/test/test_cryptodev_blockcipher.c
index 37b10cf..9933ca3 100644
--- a/app/test/test_cryptodev_blockcipher.c
+++ b/app/test/test_cryptodev_blockcipher.c
@@ -41,6 +41,7 @@
 #include <rte_cryptodev_pmd.h>
 
 #include "test.h"
+#include "test_cryptodev.h"
 #include "test_cryptodev_blockcipher.h"
 #include "test_cryptodev_aes_test_vectors.h"
 #include "test_cryptodev_des_test_vectors.h"
@@ -63,6 +64,7 @@
 	struct rte_crypto_sym_op *sym_op = NULL;
 	struct rte_crypto_op *op = NULL;
 	struct rte_cryptodev_sym_session *sess = NULL;
+	struct rte_cryptodev_info dev_info;
 
 	int status = TEST_SUCCESS;
 	const struct blockcipher_test_data *tdata = t->test_data;
@@ -72,6 +74,19 @@
 	uint32_t digest_len = 0;
 	char *buf_p = NULL;
 
+	int nb_segs = 3;
+	int nb_segs_oop = 1;
+
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+		rte_cryptodev_info_get(dev_id, &dev_info);
+		if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+			printf("Device doesn't support scatter-gather. "
+					"Test Skipped.\n");
+			return 0;
+		}
+	}
+
 	if (tdata->cipher_key.len)
 		memcpy(cipher_key, tdata->cipher_key.data,
 			tdata->cipher_key.len);
@@ -96,72 +111,112 @@
 	}
 
 	/* preparing data */
-	ibuf = rte_pktmbuf_alloc(mbuf_pool);
-	if (!ibuf) {
-		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-			"line %u FAILED: %s",
-			__LINE__, "Allocation of rte_mbuf failed");
-		status = TEST_FAILED;
-		goto error_exit;
-	}
 
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
-		buf_len += tdata->iv.len;
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
-		buf_len += digest_len;
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
 
-	buf_p = rte_pktmbuf_append(ibuf, buf_len);
-	if (!buf_p) {
-		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-			"line %u FAILED: %s",
-			__LINE__, "No room to append mbuf");
-		status = TEST_FAILED;
-		goto error_exit;
-	}
-
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
-		buf_p += tdata->iv.len;
-	}
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+			ibuf = create_segmented_mbuf(mbuf_pool,
+					tdata->plaintext.len, nb_segs);
+			pktmbuf_write(ibuf, 0, tdata->plaintext.len,
+					tdata->plaintext.data);
+		} else {
+			ibuf = create_segmented_mbuf(mbuf_pool,
+					tdata->ciphertext.len, nb_segs);
+			pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
+					tdata->ciphertext.data);
+		}
 
-	/* only encryption requires plaintext.data input,
-	 * decryption/(digest gen)/(digest verify) use ciphertext.data
-	 * to be computed
-	 */
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
-		rte_memcpy(buf_p, tdata->plaintext.data,
-			tdata->plaintext.len);
-		buf_p += tdata->plaintext.len;
-	} else {
-		rte_memcpy(buf_p, tdata->ciphertext.data,
-			tdata->ciphertext.len);
-		buf_p += tdata->ciphertext.len;
-	}
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+			rte_memcpy(rte_pktmbuf_prepend(ibuf, tdata->iv.len),
+					tdata->iv.data, tdata->iv.len);
+		}
 
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
-		rte_memcpy(buf_p, tdata->digest.data, digest_len);
-	else
-		memset(buf_p, 0, digest_len);
+		buf_p = rte_pktmbuf_append(ibuf, digest_len);
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+			rte_memcpy(buf_p, tdata->digest.data, digest_len);
+		else
+			memset(buf_p, 0, digest_len);
 
-	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
-		obuf = rte_pktmbuf_alloc(mbuf_pool);
-		if (!obuf) {
-			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-				"FAILED: %s", __LINE__,
-				"Allocation of rte_mbuf failed");
+	} else {
+		ibuf = rte_pktmbuf_alloc(mbuf_pool);
+		if (!ibuf) {
+			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+					"line %u FAILED: %s",
+					__LINE__,
+					"Allocation of rte_mbuf failed");
 			status = TEST_FAILED;
 			goto error_exit;
 		}
 
-		buf_p = rte_pktmbuf_append(obuf, buf_len);
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
+			buf_len += tdata->iv.len;
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
+			buf_len += digest_len;
+
+		buf_p = rte_pktmbuf_append(ibuf, buf_len);
 		if (!buf_p) {
-			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-				"FAILED: %s", __LINE__,
-				"No room to append mbuf");
+			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+					"line %u FAILED: %s",
+					__LINE__, "No room to append mbuf");
 			status = TEST_FAILED;
 			goto error_exit;
 		}
-		memset(buf_p, 0, buf_len);
+
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+			rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
+			buf_p += tdata->iv.len;
+		}
+
+		/* only encryption requires plaintext.data input,
+		 * decryption/(digest gen)/(digest verify) use ciphertext.data
+		 * to be computed
+		 */
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+			rte_memcpy(buf_p, tdata->plaintext.data,
+					tdata->plaintext.len);
+			buf_p += tdata->plaintext.len;
+		} else {
+			rte_memcpy(buf_p, tdata->ciphertext.data,
+					tdata->ciphertext.len);
+			buf_p += tdata->ciphertext.len;
+		}
+
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+			rte_memcpy(buf_p, tdata->digest.data, digest_len);
+		else
+			memset(buf_p, 0, digest_len);
+	}
+
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+			obuf = create_segmented_mbuf(mbuf_pool, buf_len,
+					nb_segs_oop);
+			if (!obuf) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"Allocation of rte_mbuf failed");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+		} else {
+			obuf = rte_pktmbuf_alloc(mbuf_pool);
+			if (!obuf) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"Allocation of rte_mbuf failed");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+			buf_p = rte_pktmbuf_append(obuf, buf_len);
+			if (!buf_p) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"No room to append mbuf");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+			memset(buf_p, 0, buf_len);
+		}
 	}
 
 	/* Generate Crypto op data structure */
@@ -176,7 +231,6 @@
 	}
 
 	sym_op = op->sym;
-
 	sym_op->m_src = ibuf;
 
 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
@@ -386,13 +440,10 @@
 	}
 
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		uint8_t *crypto_res;
+		uint8_t buffer[2048];
 		const uint8_t *compare_ref;
 		uint32_t compare_len;
 
-		crypto_res = rte_pktmbuf_mtod_offset(iobuf, uint8_t *,
-			tdata->iv.len);
-
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
 			compare_ref = tdata->ciphertext.data;
 			compare_len = tdata->ciphertext.len;
@@ -401,7 +452,8 @@
 			compare_len = tdata->plaintext.len;
 		}
 
-		if (memcmp(crypto_res, compare_ref, compare_len)) {
+		if (memcmp(rte_pktmbuf_read(iobuf, tdata->iv.len, compare_len,
+				buffer), compare_ref, compare_len)) {
 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
 				"FAILED: %s", __LINE__,
 				"Crypto data not as expected");
diff --git a/app/test/test_cryptodev_blockcipher.h b/app/test/test_cryptodev_blockcipher.h
index 04ff1ee..87a0683 100644
--- a/app/test/test_cryptodev_blockcipher.h
+++ b/app/test/test_cryptodev_blockcipher.h
@@ -45,6 +45,7 @@
 #define BLOCKCIPHER_TEST_FEATURE_OOP			0x01
 #define BLOCKCIPHER_TEST_FEATURE_SESSIONLESS	0x02
 #define BLOCKCIPHER_TEST_FEATURE_STOPPER	0x04 /* stop upon failing */
+#define BLOCKCIPHER_TEST_FEATURE_SG		0x08 /* Scatter Gather */
 
 #define BLOCKCIPHER_TEST_TARGET_PMD_MB		0x0001 /* Multi-buffer flag */
 #define BLOCKCIPHER_TEST_TARGET_PMD_QAT			0x0002 /* QAT flag */
-- 
1.7.9.5

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

* Re: [PATCH 3/4] crypto: add sgl support for sw PMDs
  2016-12-02 17:07 ` [PATCH 3/4] crypto: add sgl support for sw PMDs Tomasz Kulasek
@ 2016-12-03  8:28   ` Michał Mirosław
  2016-12-12 10:01     ` Kulasek, TomaszX
  0 siblings, 1 reply; 41+ messages in thread
From: Michał Mirosław @ 2016-12-03  8:28 UTC (permalink / raw)
  To: Tomasz Kulasek; +Cc: dev

2016-12-02 18:07 GMT+01:00 Tomasz Kulasek <tomaszx.kulasek@intel.com>:
> This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature flag
> informing that selected crypto device supports segmented mbufs natively
> and doesn't need to be coalesced before crypto operation.
>
> While using segmented buffers in crypto devices may have unpredictable
> results, for PMDs which doesn't support it natively, additional check is
> made for debug compilation.
>
[...]
> +#ifdef RTE_LIBRTE_PMD_AESNI_GCM_DEBUG
> +               if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
> +                               (ops[i]->sym->m_dst != NULL &&
> +                               !rte_pktmbuf_is_contiguous(
> +                                               ops[i]->sym->m_dst))) {
> +                       ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
> +                       GCM_LOG_ERR("PMD supports only contiguous mbufs, "
> +                               "op (%p) provides noncontiguous mbuf as "
> +                               "source/destination buffer.\n", ops[i]);
> +                       qp->qp_stats.enqueue_err_count++;
> +                       break;
> +               }
> +#endif
[...]

Why are there so many copies of this code?

Best Regards,
Michał Mirosław

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

* Re: [PATCH 3/4] crypto: add sgl support for sw PMDs
  2016-12-03  8:28   ` Michał Mirosław
@ 2016-12-12 10:01     ` Kulasek, TomaszX
  0 siblings, 0 replies; 41+ messages in thread
From: Kulasek, TomaszX @ 2016-12-12 10:01 UTC (permalink / raw)
  To: Michał Mirosław; +Cc: dev

Hi Michał,

> -----Original Message-----
> From: Michał Mirosław [mailto:mirqus@gmail.com]
> Sent: Saturday, December 3, 2016 09:28
> To: Kulasek, TomaszX <tomaszx.kulasek@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 3/4] crypto: add sgl support for sw PMDs
> 
> 2016-12-02 18:07 GMT+01:00 Tomasz Kulasek <tomaszx.kulasek@intel.com>:
> > This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature
> > flag informing that selected crypto device supports segmented mbufs
> > natively and doesn't need to be coalesced before crypto operation.
> >
> > While using segmented buffers in crypto devices may have unpredictable
> > results, for PMDs which doesn't support it natively, additional check
> > is made for debug compilation.
> >
> [...]
> > +#ifdef RTE_LIBRTE_PMD_AESNI_GCM_DEBUG
> > +               if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
> > +                               (ops[i]->sym->m_dst != NULL &&
> > +                               !rte_pktmbuf_is_contiguous(
> > +                                               ops[i]->sym->m_dst))) {
> > +                       ops[i]->status =
> RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
> > +                       GCM_LOG_ERR("PMD supports only contiguous mbufs,
> "
> > +                               "op (%p) provides noncontiguous mbuf as
> "
> > +                               "source/destination buffer.\n", ops[i]);
> > +                       qp->qp_stats.enqueue_err_count++;
> > +                       break;
> > +               }
> > +#endif
> [...]
> 
> Why are there so many copies of this code?
> 
> Best Regards,
> Michał Mirosław

This is one check per crypto PMD: aesni-gcm, aesni-mb, openssl and so on, enabled per PMD.

Tomasz

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

* Re: [PATCH 1/4] rte_mbuf: add rte_pktmbuf_coalesce
  2016-12-02 17:07 ` [PATCH 1/4] rte_mbuf: add rte_pktmbuf_coalesce Tomasz Kulasek
@ 2016-12-16 10:06   ` Olivier Matz
  2016-12-29 15:58     ` Kulasek, TomaszX
  0 siblings, 1 reply; 41+ messages in thread
From: Olivier Matz @ 2016-12-16 10:06 UTC (permalink / raw)
  To: Tomasz Kulasek; +Cc: dev

Hi Tomasz,

On Fri,  2 Dec 2016 18:07:43 +0100, Tomasz Kulasek
<tomaszx.kulasek@intel.com> wrote:
> This patch adds function rte_pktmbuf_coalesce to let crypto PMD
> coalesce chained mbuf before crypto operation and extend their
> capabilities to support segmented mbufs when device cannot handle
> them natively.
> 
> 
> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
> ---
>  lib/librte_mbuf/rte_mbuf.h |   34 ++++++++++++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
> 
> diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> index ead7c6e..f048681 100644
> --- a/lib/librte_mbuf/rte_mbuf.h
> +++ b/lib/librte_mbuf/rte_mbuf.h
> @@ -1647,6 +1647,40 @@ static inline int rte_pktmbuf_chain(struct
> rte_mbuf *head, struct rte_mbuf *tail }
>  
>  /**
> + * Coalesce data from mbuf to the continuous buffer.
> + *
> + * @param mbuf_dst
> + *   Contiguous destination mbuf
> + * @param mbuf_src
> + *   Uncontiguous source mbuf
> + *
> + * @return
> + *   - 0, on success
> + *   - -EINVAL, on error
> + */

I think the API should be clarified. In your case, it is expected that the
destination mbuf is already filled with uninitialized data (i.e. that
rte_pktmbuf_append() has been called).

We could wonder if a better API wouldn't be to allocate the dst mbuf in
the function, call append()/prepend(), and do the copy.

Even better, we could have:

  int rte_pktmbuf_linearize(struct rte_mbuf *m)

It will reuse the same mbuf (maybe moving the data).


> +
> +#include <rte_hexdump.h>

This should be removed.

> +
> +static inline int
> +rte_pktmbuf_coalesce(struct rte_mbuf *mbuf_dst, struct rte_mbuf *mbuf_src) {

Source mbuf should be const.

> +	char *dst;
> +
> +	if (!rte_pktmbuf_is_contiguous(mbuf_dst) ||
> +			rte_pktmbuf_data_len(mbuf_dst) >=
> +			rte_pktmbuf_pkt_len(mbuf_src))
> +		return -EINVAL;

Why >= ?

> +
> +	dst = rte_pktmbuf_mtod(mbuf_dst, char *);
> +
> +	if (!__rte_pktmbuf_read(mbuf_src, 0, rte_pktmbuf_pkt_len(mbuf_src),
> +			dst))

When a function returns a pointer, I think it is clearer to do:
  if (func() == NULL)
than:
  if (!func())


> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +/**
>   * Dump an mbuf structure to a file.
>   *
>   * Dump all fields for the given packet mbuf and all its associated


One more question, I don't see where this function is used in your
patchset. What is your use-case?

Regards,
Olivier

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

* Re: [PATCH 1/4] rte_mbuf: add rte_pktmbuf_coalesce
  2016-12-16 10:06   ` Olivier Matz
@ 2016-12-29 15:58     ` Kulasek, TomaszX
  0 siblings, 0 replies; 41+ messages in thread
From: Kulasek, TomaszX @ 2016-12-29 15:58 UTC (permalink / raw)
  To: Olivier Matz; +Cc: dev

Hi Olivier,

> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Friday, December 16, 2016 11:06
> To: Kulasek, TomaszX <tomaszx.kulasek@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 1/4] rte_mbuf: add rte_pktmbuf_coalesce
> 
> Hi Tomasz,
> 
> On Fri,  2 Dec 2016 18:07:43 +0100, Tomasz Kulasek
> <tomaszx.kulasek@intel.com> wrote:
> > This patch adds function rte_pktmbuf_coalesce to let crypto PMD
> > coalesce chained mbuf before crypto operation and extend their
> > capabilities to support segmented mbufs when device cannot handle
> > them natively.
> >
> >
> > Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
> > ---
> >  lib/librte_mbuf/rte_mbuf.h |   34 ++++++++++++++++++++++++++++++++++
> >  1 file changed, 34 insertions(+)
> >
> > diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> > index ead7c6e..f048681 100644
> > --- a/lib/librte_mbuf/rte_mbuf.h
> > +++ b/lib/librte_mbuf/rte_mbuf.h
> > @@ -1647,6 +1647,40 @@ static inline int rte_pktmbuf_chain(struct
> > rte_mbuf *head, struct rte_mbuf *tail }
> >
> >  /**
> > + * Coalesce data from mbuf to the continuous buffer.
> > + *
> > + * @param mbuf_dst
> > + *   Contiguous destination mbuf
> > + * @param mbuf_src
> > + *   Uncontiguous source mbuf
> > + *
> > + * @return
> > + *   - 0, on success
> > + *   - -EINVAL, on error
> > + */
> 
> I think the API should be clarified. In your case, it is expected that the
> destination mbuf is already filled with uninitialized data (i.e. that
> rte_pktmbuf_append() has been called).
> 
> We could wonder if a better API wouldn't be to allocate the dst mbuf in
> the function, call append()/prepend(), and do the copy.
> 
> Even better, we could have:
> 
>   int rte_pktmbuf_linearize(struct rte_mbuf *m)
> 
> It will reuse the same mbuf (maybe moving the data).
> 
> 
> > +
> > +#include <rte_hexdump.h>
> 
> This should be removed.
> 
> > +
> > +static inline int
> > +rte_pktmbuf_coalesce(struct rte_mbuf *mbuf_dst, struct rte_mbuf
> *mbuf_src) {
> 
> Source mbuf should be const.
> 
> > +	char *dst;
> > +
> > +	if (!rte_pktmbuf_is_contiguous(mbuf_dst) ||
> > +			rte_pktmbuf_data_len(mbuf_dst) >=
> > +			rte_pktmbuf_pkt_len(mbuf_src))
> > +		return -EINVAL;
> 
> Why >= ?
> 
> > +
> > +	dst = rte_pktmbuf_mtod(mbuf_dst, char *);
> > +
> > +	if (!__rte_pktmbuf_read(mbuf_src, 0, rte_pktmbuf_pkt_len(mbuf_src),
> > +			dst))
> 
> When a function returns a pointer, I think it is clearer to do:
>   if (func() == NULL)
> than:
>   if (!func())
> 
> 
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> >   * Dump an mbuf structure to a file.
> >   *
> >   * Dump all fields for the given packet mbuf and all its associated
> 
> 
> One more question, I don't see where this function is used in your
> patchset. What is your use-case?
> 
> Regards,
> Olivier

This function is needed for crypto-perf application: http://dpdk.org/dev/patchwork/patch/17492/ to compare performance of crypto operations on segmented mbufs, when scatter gather is or is not supported by crypto PMD. It will be introduced with v2.

When device doesn't support scatter-gather, we want to know an overhead of manual coalescing mbuf.


	struct rte_cryptodev_info dev_info;
	int linearize = 0;

	/* Check if source mbufs require coalescing */
	if (ctx->options->segments_nb > 1) {
		rte_cryptodev_info_get(ctx->dev_id, &dev_info);
		if ((dev_info.feature_flags &
				RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
			linearize = 1;
	}

	// ...
 
	if (linearize) {
		/* PMD doesn't support scatter-gather and source buffer
		 * is segmented.
		 * We need to linearize it before enqueuing.
		 */
		for (i = 0; i < burst_size; i++)
			rte_pktmbuf_linearize(ops[i]->sym->m_src);
	}

	/* Enqueue burst of ops on crypto device */
	ops_enqd = rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id,
			ops, burst_size);


I have checked this use case (in crypto-perf application), and you're right, using rte_pktmbuf_linearize() function here is better and more straightforward. I will change it in v2.

Thanks for suggestions
Tomasz.

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

* [PATCH v2 0/5] Chained Mbufs support in SW PMDs
  2016-12-02 17:07 [PATCH 0/4] Chained Mbufs support in SW PMDs Tomasz Kulasek
                   ` (3 preceding siblings ...)
  2016-12-02 17:07 ` [PATCH 4/4] test: add sgl unit tests for crypto devices Tomasz Kulasek
@ 2016-12-29 17:12 ` Tomasz Kulasek
  2016-12-29 17:12   ` [PATCH v2 1/5] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
                     ` (5 more replies)
  4 siblings, 6 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
  To: dev; +Cc: olivier.matz

This patch set adds support of scattered-gather list for SW PMDs.

As of now, application needs to reserve continuous block of memory for
mbufs which is not always the case. Hence needed to support chaining of
mbufs which are smaller in size but can be used if chained.


Above work involves:

 a) Create mbuf functions to coalesce mbuf chains into a single mbuf.
 b) For each software poll mode driver code to detect chained mbufs
    support and coalesce these before preforming crypto.
 c) Add relevant unit tests to test the functionality.


Known limitations for openssl PMD:

While libcrypto library expects continuous destination buffer for
output of cipher operations, implementation of openssl PMD is limited
the same way, and requires contigous destination mbuf.


changes in v2:
 - add support for sgl in openssl PMD
 - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
 - extended test vector data for aes gcm from 60 to 2048 bytes

Tomasz Kulasek (5):
  rte_mbuf: add rte_pktmbuf_linearize
  test: add rte_pktmbuf_linearize unit tests
  crypto: add sgl support in sw PMDs
  crypto: add sgl support in openssl PMD
  test: add sgl unit tests for crypto devices

 app/test/test_cryptodev.c                  |  589 +++++++++++++++++++++++++++-
 app/test/test_cryptodev.h                  |  139 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   54 ++-
 app/test/test_cryptodev_blockcipher.c      |  181 ++++++---
 app/test/test_cryptodev_blockcipher.h      |    3 +-
 app/test/test_cryptodev_des_test_vectors.h |   29 ++
 app/test/test_cryptodev_gcm_test_vectors.h |  557 +++++++++++++++++++++++++-
 app/test/test_mbuf.c                       |  123 ++++++
 doc/guides/cryptodevs/openssl.rst          |    2 +-
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 +
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 +-
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +
 drivers/crypto/null/null_crypto_pmd.c      |    3 +-
 drivers/crypto/openssl/rte_openssl_pmd.c   |  329 ++++++++++++----
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +
 lib/librte_cryptodev/rte_cryptodev.c       |    4 +-
 lib/librte_cryptodev/rte_cryptodev.h       |    3 +-
 lib/librte_mbuf/rte_mbuf.h                 |   56 +++
 19 files changed, 1991 insertions(+), 155 deletions(-)

-- 
1.7.9.5

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

* [PATCH v2 1/5] rte_mbuf: add rte_pktmbuf_linearize
  2016-12-29 17:12 ` [PATCH v2 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
@ 2016-12-29 17:12   ` Tomasz Kulasek
  2016-12-29 17:12   ` [PATCH v2 2/5] test: add rte_pktmbuf_linearize unit tests Tomasz Kulasek
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
  To: dev; +Cc: olivier.matz

This patch adds function rte_pktmbuf_linearize to let crypto PMD coalesce
chained mbuf before crypto operation and extend their capabilities to
support segmented mbufs when device cannot handle them natively.


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 lib/librte_mbuf/rte_mbuf.h |   56 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ead7c6e..b11a31d 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -1647,6 +1647,62 @@ static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail
 }
 
 /**
+ * Linearize data in mbuf.
+ *
+ * This function coalesce mbuf merging data in the first segment, unchaining
+ * rest, and then frees them.
+ *
+ * All operations are done in-place, so the structure of incoming mbuf
+ * is changed.
+ *
+ * @param mbuf
+ *   mbuf to linearize
+ * @return
+ *   - 0, on success
+ *   - -1, on error
+ */
+static inline int
+rte_pktmbuf_linearize(struct rte_mbuf *mbuf)
+{
+	int l, n;
+	struct rte_mbuf *m;
+	struct rte_mbuf *m_next;
+	char *buffer;
+
+	if (rte_pktmbuf_is_contiguous(mbuf))
+		return 0;
+
+	/* Extend first segment to the total packet length
+	 */
+	n = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
+
+	if (unlikely(n > rte_pktmbuf_tailroom(mbuf)))
+		return -1;
+
+	buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
+	mbuf->data_len = (uint16_t)(mbuf->pkt_len);
+
+	/* Append data from next segments to the first one
+	 */
+	m = mbuf->next;
+	while (m != NULL) {
+		m_next = m->next;
+
+		l = rte_pktmbuf_data_len(m);
+		rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), l);
+		buffer += l;
+
+		rte_pktmbuf_free_seg(m);
+		m = m_next;
+	}
+
+	mbuf->next = NULL;
+	mbuf->nb_segs = 1;
+
+	return 0;
+}
+
+/**
  * Dump an mbuf structure to a file.
  *
  * Dump all fields for the given packet mbuf and all its associated
-- 
1.7.9.5

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

* [PATCH v2 2/5] test: add rte_pktmbuf_linearize unit tests
  2016-12-29 17:12 ` [PATCH v2 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2016-12-29 17:12   ` [PATCH v2 1/5] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
@ 2016-12-29 17:12   ` Tomasz Kulasek
  2016-12-29 17:12   ` [PATCH v2 3/5] crypto: add sgl support in sw PMDs Tomasz Kulasek
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
  To: dev; +Cc: olivier.matz

This patch tests rte_pktmbuf_coalesce functionality:

 1) Creates banch of segmented mbufs with different size and number of
    segments.
 2) Generates pkt_len bytes of random data.
 3) Fills noncontigouos mbuf with randomly generated data.
 4) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one
    contiguous.
 5) Verifies data in linearized buffer.


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_mbuf.c |  123 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 123 insertions(+)

diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c
index c0823ea..39577e7 100644
--- a/app/test/test_mbuf.c
+++ b/app/test/test_mbuf.c
@@ -930,6 +930,124 @@
 	return 0;
 }
 
+static int
+test_mbuf_linearize(int pkt_len, int nb_segs) {
+
+	struct rte_mbuf *m = NULL, *mbuf_src = NULL;
+	uint8_t data[pkt_len], *src, *dst;
+	int data_len = 0;
+	int i, size;
+	int t_len;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return -1;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return -1;
+	}
+
+	/* Setup buffer */
+	for (i = 0; i < pkt_len; i++)
+		data[i] = (uint8_t) rte_rand();
+
+	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+	src = data;
+	size = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (i = 0; size > 0; i++) {
+
+		m = rte_pktmbuf_alloc(pktmbuf_pool);
+		if (i == 0)
+			mbuf_src = m;
+
+		if (!m) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+				rte_pktmbuf_tailroom(m));
+
+		data_len = size > t_len ? t_len : size;
+		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (!dst) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		rte_memcpy(dst, src, data_len);
+		src += data_len;
+
+		if (mbuf_src != m)
+			rte_pktmbuf_chain(mbuf_src, m);
+
+		size -= data_len;
+
+	}
+
+	/* Create destination buffer to store coalesced data */
+	if (rte_pktmbuf_linearize(mbuf_src)) {
+		printf("Mbuf linearization failed\n");
+		goto fail;
+	}
+
+	if (!rte_pktmbuf_is_contiguous(mbuf_src)) {
+		printf("Source buffer should be contiguous after "
+				"linearization\n");
+		goto fail;
+	}
+
+	src = rte_pktmbuf_mtod(mbuf_src, uint8_t *);
+
+	if (memcmp(src, data, rte_pktmbuf_pkt_len(mbuf_src))) {
+		printf("Incorrect data in coalesced mbuf\n");
+		goto fail;
+	}
+
+	if (mbuf_src)
+		rte_pktmbuf_free(mbuf_src);
+	return 0;
+
+fail:
+	if (mbuf_src)
+		rte_pktmbuf_free(mbuf_src);
+	return -1;
+}
+
+static int
+test_mbuf_linearize_check(void)
+{
+	struct test_mbuf_array {
+		int size;
+		int nb_segs;
+	} mbuf_array[5] = {
+			{ 128, 1 },
+			{ 64, 64 },
+			{ 512, 10 },
+			{ 250, 11 },
+			{ 123, 8 },
+	};
+	unsigned int i;
+
+	printf("Test mbuf linearize API\n");
+
+	for (i = 0; i < RTE_DIM(mbuf_array); i++)
+		if (test_mbuf_linearize(mbuf_array[i].size,
+				mbuf_array[i].nb_segs)) {
+			printf("Test failed for %d, %d\n", mbuf_array[i].size,
+					mbuf_array[i].nb_segs);
+			return -1;
+		}
+
+	return 0;
+}
 
 static int
 test_mbuf(void)
@@ -1023,6 +1141,11 @@
 		printf("test_failing_mbuf_sanity_check() failed\n");
 		return -1;
 	}
+
+	if (test_mbuf_linearize_check() < 0) {
+		printf("test_mbuf_linearize_check() failed\n");
+		return -1;
+	}
 	return 0;
 }
 
-- 
1.7.9.5

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

* [PATCH v2 3/5] crypto: add sgl support in sw PMDs
  2016-12-29 17:12 ` [PATCH v2 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2016-12-29 17:12   ` [PATCH v2 1/5] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
  2016-12-29 17:12   ` [PATCH v2 2/5] test: add rte_pktmbuf_linearize unit tests Tomasz Kulasek
@ 2016-12-29 17:12   ` Tomasz Kulasek
  2016-12-29 17:12   ` [PATCH v2 4/5] crypto: add sgl support in openssl PMD Tomasz Kulasek
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
  To: dev; +Cc: olivier.matz

This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature flag
informing that selected crypto device supports segmented mbufs natively
and doesn't need to be coalesced before crypto operation.

While using segmented buffers in crypto devices may have unpredictable
results, for PMDs which doesn't support it natively, additional check is
made for debug compilation.


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 ++++++++++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 ++++++++++++++++---
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +++++++++++++
 drivers/crypto/null/null_crypto_pmd.c      |    3 ++-
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +++++++++++++++
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +++++++++++++
 lib/librte_cryptodev/rte_cryptodev.c       |    4 ++--
 lib/librte_cryptodev/rte_cryptodev.h       |    3 ++-
 8 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index dba5e15..1a6120c 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -375,6 +375,20 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_AESNI_GCM_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			GCM_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			qp->qp_stats.enqueue_err_count++;
+			break;
+		}
+#endif
+
 		retval = process_gcm_crypto_op(qp, ops[i]->sym, sess);
 		if (retval < 0) {
 			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index f07cd07..b5e115e 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -529,15 +529,28 @@
 	int i, processed_jobs = 0;
 
 	for (i = 0; i < nb_ops; i++) {
-#ifdef RTE_LIBRTE_AESNI_MB_DEBUG
-		if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
+#ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
+		if (unlikely(ops[i]->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
 			MB_LOG_ERR("PMD only supports symmetric crypto "
 				"operation requests, op (%p) is not a "
-				"symmetric operation.", op);
+				"symmetric operation.", ops[i]);
+			qp->stats.enqueue_err_count++;
+			goto flush_jobs;
+		}
+
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			MB_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 			qp->stats.enqueue_err_count++;
 			goto flush_jobs;
 		}
 #endif
+
 		sess = get_session(qp, ops[i]);
 		if (unlikely(sess == NULL)) {
 			qp->stats.enqueue_err_count++;
diff --git a/drivers/crypto/kasumi/rte_kasumi_pmd.c b/drivers/crypto/kasumi/rte_kasumi_pmd.c
index b119da2..4bdd7bb 100644
--- a/drivers/crypto/kasumi/rte_kasumi_pmd.c
+++ b/drivers/crypto/kasumi/rte_kasumi_pmd.c
@@ -455,6 +455,19 @@
 	for (i = 0; i < nb_ops; i++) {
 		curr_c_op = ops[i];
 
+#ifdef RTE_LIBRTE_PMD_KASUMI_DEBUG
+		if (!rte_pktmbuf_is_contiguous(curr_c_op->sym->m_src) ||
+				(curr_c_op->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						curr_c_op->sym->m_dst))) {
+			KASUMI_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", curr_c_op);
+			curr_c_op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		/* Set status as enqueued (not processed yet) by default. */
 		curr_c_op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
 
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index c69606b..c37d3d6 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -216,7 +216,8 @@
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
-			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
 
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 3b4292a..9a6f16d 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -330,6 +330,21 @@
 	unsigned i;
 	unsigned enqueued_ops, processed_ops;
 
+#ifdef RTE_LIBRTE_PMD_SNOW3G_DEBUG
+	for (i = 0; i < num_ops; i++) {
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			SNOW3G_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			return 0;
+		}
+	}
+#endif
+
 	switch (session->op) {
 	case SNOW3G_OP_ONLY_CIPHER:
 		processed_ops = process_snow3g_cipher_op(ops,
diff --git a/drivers/crypto/zuc/rte_zuc_pmd.c b/drivers/crypto/zuc/rte_zuc_pmd.c
index 3849119..bf53f76 100644
--- a/drivers/crypto/zuc/rte_zuc_pmd.c
+++ b/drivers/crypto/zuc/rte_zuc_pmd.c
@@ -211,6 +211,19 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_ZUC_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ZUC_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		src[i] = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
 				(ops[i]->sym->cipher.data.offset >> 3);
 		dst[i] = ops[i]->sym->m_dst ?
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 127e8d0..ebbb822 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -211,13 +211,13 @@ struct rte_cryptodev_callback {
 		return "CPU_AESNI";
 	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
 		return "HW_ACCELERATED";
-
+	case RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER:
+		return "MBUF_SCATTER_GATHER";
 	default:
 		return NULL;
 	}
 }
 
-
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)
 {
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 8f63e8f..70ff7fc 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -225,7 +225,8 @@ struct rte_cryptodev_capabilities {
 /**< Utilises CPU AES-NI instructions */
 #define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL << 7)
 /**< Operations are off-loaded to an external hardware accelerator */
-
+#define	RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER	(1ULL << 8)
+/**< Scatter-gather mbufs are supported */
 
 /**
  * Get the name of a crypto device feature flag
-- 
1.7.9.5

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

* [PATCH v2 4/5] crypto: add sgl support in openssl PMD
  2016-12-29 17:12 ` [PATCH v2 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
                     ` (2 preceding siblings ...)
  2016-12-29 17:12   ` [PATCH v2 3/5] crypto: add sgl support in sw PMDs Tomasz Kulasek
@ 2016-12-29 17:12   ` Tomasz Kulasek
  2016-12-29 17:12   ` [PATCH v2 5/5] test: add sgl unit tests for crypto devices Tomasz Kulasek
  2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
  5 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
  To: dev; +Cc: olivier.matz

Previous implementation uses EVP_EncryptUpdate() on whole source buffer
limiting its usage to the contiguous buffers.

This implementation calls EVP_EncryptUpdate() on each segment for cipher
operations in continous mode, before finalization allowing to provide
chained mbuf as a source.

However, libcrypto library expects continuous destination buffer for
output of cipher operations and implementation of openssl PMD is limited
the same way, requiring contiguous destination mbuf.


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 doc/guides/cryptodevs/openssl.rst        |    2 +-
 drivers/crypto/openssl/rte_openssl_pmd.c |  329 +++++++++++++++++++++++-------
 2 files changed, 258 insertions(+), 73 deletions(-)

diff --git a/doc/guides/cryptodevs/openssl.rst b/doc/guides/cryptodevs/openssl.rst
index d2b5906..05e6d67 100644
--- a/doc/guides/cryptodevs/openssl.rst
+++ b/doc/guides/cryptodevs/openssl.rst
@@ -112,6 +112,6 @@ Limitations
 -----------
 
 * Maximum number of sessions is 2048.
-* Chained mbufs are not supported.
+* Chained mbufs are supported only for source mbuf (destination must be contiguous).
 * Hash only is not supported for GCM and GMAC.
 * Cipher only is not supported for GCM and GMAC.
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 5f8fa33..22639b4 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -484,22 +484,110 @@
  * Process Operations
  *------------------------------------------------------------------------------
  */
+static inline int
+process_openssl_encryption_update(struct rte_mbuf *mbuf_src, int offset,
+		uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+	struct rte_mbuf *m;
+	int dstlen;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		return -1;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+			return -1;
+		*dst += l;
+		return 0;
+	}
+
+	if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+		return -1;
+
+	*dst += dstlen;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+			return -1;
+		*dst += dstlen;
+		n -= l;
+	}
+
+	return 0;
+}
+
+static inline int
+process_openssl_decryption_update(struct rte_mbuf *mbuf_src, int offset,
+		uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+	struct rte_mbuf *m;
+	int dstlen;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		return -1;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+			return -1;
+		*dst += l;
+		return 0;
+	}
+
+	if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+		return -1;
+
+	*dst += dstlen;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+			return -1;
+		*dst += dstlen;
+		n -= l;
+	}
+
+	return 0;
+}
 
 /** Process standard openssl cipher encryption */
 static int
-process_openssl_cipher_encrypt(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_encrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
-	int dstlen, totlen;
+	int totlen;
 
 	if (EVP_EncryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
 		goto process_cipher_encrypt_err;
 
-	if (EVP_EncryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+	if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+			srclen, ctx))
 		goto process_cipher_encrypt_err;
 
-	if (EVP_EncryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+	if (EVP_EncryptFinal_ex(ctx, dst, &totlen) <= 0)
 		goto process_cipher_encrypt_err;
 
 	return 0;
@@ -511,11 +599,11 @@
 
 /** Process standard openssl cipher decryption */
 static int
-process_openssl_cipher_decrypt(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_decrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
-	int dstlen, totlen;
+	int totlen;
 
 	if (EVP_DecryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
 		goto process_cipher_decrypt_err;
@@ -523,12 +611,12 @@
 	if (EVP_CIPHER_CTX_set_padding(ctx, 0) <= 0)
 		goto process_cipher_decrypt_err;
 
-	if (EVP_DecryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+	if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+			srclen, ctx))
 		goto process_cipher_decrypt_err;
 
-	if (EVP_DecryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+	if (EVP_DecryptFinal_ex(ctx, dst, &totlen) <= 0)
 		goto process_cipher_decrypt_err;
-
 	return 0;
 
 process_cipher_decrypt_err:
@@ -538,11 +626,25 @@
 
 /** Process cipher des 3 ctr encryption, decryption algorithm */
 static int
-process_openssl_cipher_des3ctr(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen, EVP_CIPHER_CTX *ctx)
+process_openssl_cipher_des3ctr(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
+		EVP_CIPHER_CTX *ctx)
 {
 	uint8_t ebuf[8], ctr[8];
 	int unused, n;
+	struct rte_mbuf *m;
+	uint8_t *src;
+	int l;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_cipher_des3ctr_err;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+	l = rte_pktmbuf_data_len(m) - offset;
 
 	/* We use 3DES encryption also for decryption.
 	 * IV is not important for 3DES ecb
@@ -551,9 +653,8 @@
 		goto process_cipher_des3ctr_err;
 
 	memcpy(ctr, iv, 8);
-	n = 0;
 
-	while (n < srclen) {
+	for (n = 0; n < srclen; n++) {
 		if (n % 8 == 0) {
 			if (EVP_EncryptUpdate(ctx,
 					(unsigned char *)&ebuf, &unused,
@@ -561,8 +662,16 @@
 				goto process_cipher_des3ctr_err;
 			ctr_inc(ctr);
 		}
-		dst[n] = src[n] ^ ebuf[n % 8];
-		n++;
+		dst[n] = *(src++) ^ ebuf[n % 8];
+
+		l--;
+		if (!l) {
+			m = m->next;
+			if (m) {
+				src = rte_pktmbuf_mtod(m, uint8_t *);
+				l = rte_pktmbuf_data_len(m);
+			}
+		}
 	}
 
 	return 0;
@@ -574,9 +683,9 @@
 
 /** Process auth/encription aes-gcm algorithm */
 static int
-process_openssl_auth_encryption_gcm(uint8_t *src, int srclen,
-		uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
-		uint8_t *key, uint8_t *dst,	uint8_t *tag,
+process_openssl_auth_encryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+		int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+		uint8_t *key, uint8_t *dst, uint8_t *tag,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
 	int len = 0, unused = 0;
@@ -591,20 +700,20 @@
 	if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
 		goto process_auth_encryption_gcm_err;
 
-	if (aadlen > 0) {
+	if (aadlen > 0)
 		if (EVP_EncryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
 			goto process_auth_encryption_gcm_err;
 
-		/* Workaround open ssl bug in version less then 1.0.1f */
-		if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
-			goto process_auth_encryption_gcm_err;
-	}
-
 	if (srclen > 0)
-		if (EVP_EncryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+		if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+				srclen, ctx))
 			goto process_auth_encryption_gcm_err;
 
-	if (EVP_EncryptFinal_ex(ctx, dst + len, &len) <= 0)
+	/* Workaround open ssl bug in version less then 1.0.1f */
+	if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+		goto process_auth_encryption_gcm_err;
+
+	if (EVP_EncryptFinal_ex(ctx, dst, &len) <= 0)
 		goto process_auth_encryption_gcm_err;
 
 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) <= 0)
@@ -618,10 +727,10 @@
 }
 
 static int
-process_openssl_auth_decryption_gcm(uint8_t *src, int srclen,
-		uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
-		uint8_t *key, uint8_t *dst, uint8_t *tag,
-		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
+process_openssl_auth_decryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+		int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+		uint8_t *key, uint8_t *dst, uint8_t *tag, EVP_CIPHER_CTX *ctx,
+		const EVP_CIPHER *algo)
 {
 	int len = 0, unused = 0;
 	uint8_t empty[] = {};
@@ -638,20 +747,20 @@
 	if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
 		goto process_auth_decryption_gcm_err;
 
-	if (aadlen > 0) {
+	if (aadlen > 0)
 		if (EVP_DecryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
 			goto process_auth_decryption_gcm_err;
 
-		/* Workaround open ssl bug in version less then 1.0.1f */
-		if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
-			goto process_auth_decryption_gcm_err;
-	}
-
 	if (srclen > 0)
-		if (EVP_DecryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+		if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+				srclen, ctx))
 			goto process_auth_decryption_gcm_err;
 
-	if (EVP_DecryptFinal_ex(ctx, dst + len, &len) <= 0)
+	/* Workaround open ssl bug in version less then 1.0.1f */
+	if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+		goto process_auth_decryption_gcm_err;
+
+	if (EVP_DecryptFinal_ex(ctx, dst, &len) <= 0)
 		goto process_auth_decryption_gcm_final_err;
 
 	return 0;
@@ -666,21 +775,50 @@
 
 /** Process standard openssl auth algorithms */
 static int
-process_openssl_auth(uint8_t *src, uint8_t *dst,
+process_openssl_auth(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
 		__rte_unused uint8_t *iv, __rte_unused EVP_PKEY * pkey,
 		int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
 {
 	size_t dstlen;
+	struct rte_mbuf *m;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_auth_err;
 
 	if (EVP_DigestInit_ex(ctx, algo, NULL) <= 0)
 		goto process_auth_err;
 
-	if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+			goto process_auth_err;
+		goto process_auth_final;
+	}
+
+	if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
 		goto process_auth_err;
 
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
+			goto process_auth_err;
+		n -= l;
+	}
+
+process_auth_final:
 	if (EVP_DigestFinal_ex(ctx, dst, (unsigned int *)&dstlen) <= 0)
 		goto process_auth_err;
-
 	return 0;
 
 process_auth_err:
@@ -690,18 +828,48 @@
 
 /** Process standard openssl auth algorithms with hmac */
 static int
-process_openssl_auth_hmac(uint8_t *src, uint8_t *dst,
+process_openssl_auth_hmac(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
 		__rte_unused uint8_t *iv, EVP_PKEY *pkey,
-		int srclen,	EVP_MD_CTX *ctx, const EVP_MD *algo)
+		int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
 {
 	size_t dstlen;
+	struct rte_mbuf *m;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_auth_err;
 
 	if (EVP_DigestSignInit(ctx, NULL, algo, NULL, pkey) <= 0)
 		goto process_auth_err;
 
-	if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+			goto process_auth_err;
+		goto process_auth_final;
+	}
+
+	if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
 		goto process_auth_err;
 
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
+			goto process_auth_err;
+		n -= l;
+	}
+
+process_auth_final:
 	if (EVP_DigestSignFinal(ctx, dst, &dstlen) <= 0)
 		goto process_auth_err;
 
@@ -721,9 +889,18 @@
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
 	/* cipher */
-	uint8_t *src = NULL, *dst = NULL, *iv, *tag, *aad;
+	uint8_t *dst = NULL, *iv, *tag, *aad;
 	int srclen, ivlen, aadlen, status = -1;
 
+	/*
+	 * Segmented destination buffer is not supported for
+	 * encryption/decryption
+	 */
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return;
+	}
+
 	iv = op->sym->cipher.iv.data;
 	ivlen = op->sym->cipher.iv.length;
 	aad = op->sym->auth.aad.data;
@@ -739,22 +916,22 @@
 		srclen = 0;
 	else {
 		srclen = op->sym->cipher.data.length;
-		src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-				op->sym->cipher.data.offset);
 		dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
 				op->sym->cipher.data.offset);
 	}
 
 	if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
 		status = process_openssl_auth_encryption_gcm(
-				src, srclen, aad, aadlen, iv, ivlen,
-				sess->cipher.key.data, dst, tag,
-				sess->cipher.ctx, sess->cipher.evp_algo);
+				mbuf_src, op->sym->cipher.data.offset, srclen,
+				aad, aadlen, iv, ivlen, sess->cipher.key.data,
+				dst, tag, sess->cipher.ctx,
+				sess->cipher.evp_algo);
 	else
 		status = process_openssl_auth_decryption_gcm(
-				src, srclen, aad, aadlen, iv, ivlen,
-				sess->cipher.key.data, dst, tag,
-				sess->cipher.ctx, sess->cipher.evp_algo);
+				mbuf_src, op->sym->cipher.data.offset, srclen,
+				aad, aadlen, iv, ivlen, sess->cipher.key.data,
+				dst, tag, sess->cipher.ctx,
+				sess->cipher.evp_algo);
 
 	if (status != 0) {
 		if (status == (-EFAULT) &&
@@ -772,12 +949,19 @@
 		(struct rte_crypto_op *op, struct openssl_session *sess,
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
-	uint8_t *src, *dst, *iv;
+	uint8_t *dst, *iv;
 	int srclen, status;
 
+	/*
+	 * Segmented destination buffer is not supported for
+	 * encryption/decryption
+	 */
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return;
+	}
+
 	srclen = op->sym->cipher.data.length;
-	src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-			op->sym->cipher.data.offset);
 	dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
 			op->sym->cipher.data.offset);
 
@@ -785,17 +969,20 @@
 
 	if (sess->cipher.mode == OPENSSL_CIPHER_LIB)
 		if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
-			status = process_openssl_cipher_encrypt(src, dst, iv,
+			status = process_openssl_cipher_encrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
 					sess->cipher.key.data, srclen,
 					sess->cipher.ctx,
 					sess->cipher.evp_algo);
 		else
-			status = process_openssl_cipher_decrypt(src, dst, iv,
+			status = process_openssl_cipher_decrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
 					sess->cipher.key.data, srclen,
 					sess->cipher.ctx,
 					sess->cipher.evp_algo);
 	else
-		status = process_openssl_cipher_des3ctr(src, dst, iv,
+		status = process_openssl_cipher_des3ctr(mbuf_src, dst,
+				op->sym->cipher.data.offset, iv,
 				sess->cipher.key.data, srclen,
 				sess->cipher.ctx);
 
@@ -809,12 +996,10 @@
 		(struct rte_crypto_op *op, struct openssl_session *sess,
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
-	uint8_t *src, *dst;
+	uint8_t *dst;
 	int srclen, status;
 
 	srclen = op->sym->auth.data.length;
-	src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-			op->sym->auth.data.offset);
 
 	if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY)
 		dst = (uint8_t *)rte_pktmbuf_append(mbuf_src,
@@ -829,13 +1014,14 @@
 
 	switch (sess->auth.mode) {
 	case OPENSSL_AUTH_AS_AUTH:
-		status = process_openssl_auth(src, dst,
-				NULL, NULL,	srclen,
+		status = process_openssl_auth(mbuf_src, dst,
+				op->sym->auth.data.offset, NULL, NULL, srclen,
 				sess->auth.auth.ctx, sess->auth.auth.evp_algo);
 		break;
 	case OPENSSL_AUTH_AS_HMAC:
-		status = process_openssl_auth_hmac(src, dst,
-				NULL, sess->auth.hmac.pkey, srclen,
+		status = process_openssl_auth_hmac(mbuf_src, dst,
+				op->sym->auth.data.offset, NULL,
+				sess->auth.hmac.pkey, srclen,
 				sess->auth.hmac.ctx, sess->auth.hmac.evp_algo);
 		break;
 	default:
@@ -849,8 +1035,7 @@
 			op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
 		}
 		/* Trim area used for digest from mbuf. */
-		rte_pktmbuf_trim(mbuf_src,
-				op->sym->auth.digest.length);
+		rte_pktmbuf_trim(mbuf_src, op->sym->auth.digest.length);
 	}
 
 	if (status != 0)
@@ -901,7 +1086,6 @@
 		op->sym->session = NULL;
 	}
 
-
 	if (op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)
 		op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
 
@@ -995,7 +1179,8 @@
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
-			RTE_CRYPTODEV_FF_CPU_AESNI;
+			RTE_CRYPTODEV_FF_CPU_AESNI |
+			RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
 
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
-- 
1.7.9.5

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

* [PATCH v2 5/5] test: add sgl unit tests for crypto devices
  2016-12-29 17:12 ` [PATCH v2 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
                     ` (3 preceding siblings ...)
  2016-12-29 17:12   ` [PATCH v2 4/5] crypto: add sgl support in openssl PMD Tomasz Kulasek
@ 2016-12-29 17:12   ` Tomasz Kulasek
  2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
  5 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2016-12-29 17:12 UTC (permalink / raw)
  To: dev; +Cc: olivier.matz

This patch provides unit tests for set of cipher/hash combinations covering
currently implemented crypto PMD's and allowing to verify scatter gather
support.

Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_cryptodev.c                  |  589 +++++++++++++++++++++++++++-
 app/test/test_cryptodev.h                  |  139 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   54 ++-
 app/test/test_cryptodev_blockcipher.c      |  181 ++++++---
 app/test/test_cryptodev_blockcipher.h      |    3 +-
 app/test/test_cryptodev_des_test_vectors.h |   29 ++
 app/test/test_cryptodev_gcm_test_vectors.h |  557 +++++++++++++++++++++++++-
 7 files changed, 1477 insertions(+), 75 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 872f8b4..e419f80 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -1688,6 +1688,10 @@ struct crypto_unittest_params {
 
 	TEST_ASSERT_NOT_NULL(sym_op->cipher.iv.data, "no room to prepend iv");
 
+	/* For OOP operation both buffers must have the same size */
+	if (ut_params->obuf)
+		rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+
 	memset(sym_op->cipher.iv.data, 0, iv_pad_len);
 	sym_op->cipher.iv.phys_addr = rte_pktmbuf_mtophys(ut_params->ibuf);
 	sym_op->cipher.iv.length = iv_pad_len;
@@ -2509,6 +2513,84 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+		/* Validate obuf */
+		TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+			ciphertext,
+			tdata->ciphertext.data,
+			tdata->validCipherLenInBits.len,
+			"KASUMI Ciphertext data not as expected");
+		return 0;
+}
+
+
+static int
 test_kasumi_encryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2577,6 +2659,81 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_oop_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+
+	const uint8_t *ciphertext;
+	uint8_t buffer[2048];
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"KASUMI Ciphertext data not as expected");
+	return 0;
+}
+
+
+static int
 test_kasumi_decryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2849,6 +3006,85 @@ struct crypto_unittest_params {
 	return 0;
 }
 
+static int
+test_snow3g_encryption_oop_sgl(const struct snow3g_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create SNOW 3G session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple of */
+	/* the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3);
+
+	TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+			"Failed to allocate input buffer in mempool");
+	TEST_ASSERT_NOT_NULL(ut_params->obuf,
+			"Failed to allocate output buffer in mempool");
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create SNOW 3G operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->validCipherLenInBits.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validDataLenInBits.len,
+		"SNOW 3G Ciphertext data not as expected");
+
+	return 0;
+}
+
 /* Shift right a buffer by "offset" bits, "offset" < 8 */
 static void
 buffer_shift_right(uint8_t *buffer, uint32_t length, uint8_t offset)
@@ -3504,6 +3740,84 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_sgl(const struct zuc_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+	const uint8_t *ciphertext;
+	uint8_t ciphertext_buffer[2048];
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+			tdata->plaintext.data);
+
+	/* Create ZUC session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3,
+			tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	/* Clear mbuf payload */
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create ZUC operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+			tdata->iv.len, tdata->plaintext.len,
+			tdata->validCipherOffsetLenInBits.len,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"ZUC Ciphertext data not as expected");
+
+	return 0;
+}
+
+static int
 test_zuc_authentication(const struct zuc_hash_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -3571,12 +3885,24 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_kasumi_encryption_test_case_1_sgl(void)
+{
+	return test_kasumi_encryption_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_1_oop(void)
 {
 	return test_kasumi_encryption_oop(&kasumi_test_case_1);
 }
 
 static int
+test_kasumi_encryption_test_case_1_oop_sgl(void)
+{
+	return test_kasumi_encryption_oop_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_2(void)
 {
 	return test_kasumi_encryption(&kasumi_test_case_2);
@@ -3648,6 +3974,13 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_snow3g_encryption_test_case_1_oop_sgl(void)
+{
+	return test_snow3g_encryption_oop_sgl(&snow3g_test_case_1);
+}
+
+
+static int
 test_snow3g_encryption_test_case_1_offset_oop(void)
 {
 	return test_snow3g_encryption_offset_oop(&snow3g_test_case_1);
@@ -3767,6 +4100,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_test_case_6_sgl(void)
+{
+	return test_zuc_encryption_sgl(&zuc_test_case_1);
+}
+
+static int
 test_zuc_hash_generate_test_case_1(void)
 {
 	return test_zuc_authentication(&zuc_hash_test_case_1);
@@ -3934,12 +4273,21 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 
 	struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
 
-	sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
-			ut_params->ibuf, auth_tag_len);
-	TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
-			"no room to append digest");
-	sym_op->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
-			ut_params->ibuf, data_pad_len);
+	if (ut_params->obuf) {
+		sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+				ut_params->obuf, auth_tag_len);
+		TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+				"no room to append digest");
+		sym_op->auth.digest.phys_addr = sgl_pktmbuf_mtophys_offset(
+				ut_params->obuf, data_pad_len);
+	} else {
+		sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+				ut_params->ibuf, auth_tag_len);
+		TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+				"no room to append digest");
+		sym_op->auth.digest.phys_addr = sgl_pktmbuf_mtophys_offset(
+				ut_params->ibuf, data_pad_len);
+	}
 	sym_op->auth.digest.length = auth_tag_len;
 
 	if (op == RTE_CRYPTO_CIPHER_OP_DECRYPT) {
@@ -3986,6 +4334,11 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 	TEST_HEXDUMP(stdout, "aad:",
 			sym_op->auth.aad.data, aad_len);
 
+	if (ut_params->obuf) {
+		rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+		rte_pktmbuf_prepend(ut_params->obuf, aad_buffer_len);
+	}
+
 	sym_op->cipher.data.length = data_len;
 	sym_op->cipher.data.offset = aad_buffer_len + iv_pad_len;
 
@@ -4085,6 +4438,109 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_mb_AES_GCM_authenticated_encryption_sgl(const struct gcm_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	int retval;
+
+	unsigned int plaintext_len;
+	uint16_t plaintext_pad_len;
+	uint8_t ciphertext_buffer[2048], auth_tag_buffer[2048];
+	const uint8_t *ciphertext, *auth_tag;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create GCM session */
+	retval = create_gcm_session(ts_params->valid_devs[0],
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+			tdata->key.data, tdata->key.len,
+			tdata->aad.len, tdata->auth_tag.len,
+			RTE_CRYPTO_AUTH_OP_GENERATE);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = tdata->plaintext.len;
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 5);
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	rte_pktmbuf_append(ut_params->obuf, plaintext_pad_len);
+
+	/* Create GCM operation */
+	retval = create_gcm_operation(RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+			tdata->auth_tag.data, tdata->auth_tag.len,
+			tdata->iv.data, tdata->iv.len,
+			tdata->aad.data, tdata->aad.len,
+			tdata->plaintext.len, plaintext_pad_len);
+	if (retval < 0) {
+		printf("create operation failed\n");
+		return retval;
+	}
+
+	rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+	ut_params->op->sym->m_src = ut_params->ibuf;
+	ut_params->op->sym->m_dst = ut_params->obuf;
+
+	/* Process crypto operation */
+	TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+			ut_params->op), "failed to process sym crypto op");
+
+	TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+			"crypto op processing failed");
+
+	/* Validate obuf */
+	if (ut_params->op->sym->m_dst) {
+		ciphertext = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+				ut_params->op->sym->cipher.data.offset,
+				plaintext_pad_len, ciphertext_buffer);
+		auth_tag = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+				plaintext_pad_len +
+				RTE_ALIGN_CEIL(tdata->iv.len, 16) +
+				ALIGN_POW2_ROUNDUP(tdata->aad.len, 16),
+				tdata->auth_tag.len, auth_tag_buffer);
+	} else {
+		ciphertext = rte_pktmbuf_read(ut_params->op->sym->m_src,
+				ut_params->op->sym->cipher.data.offset,
+				plaintext_pad_len, ciphertext_buffer);
+		auth_tag = rte_pktmbuf_read(ut_params->op->sym->m_src,
+				plaintext_pad_len +
+				RTE_ALIGN_CEIL(tdata->iv.len, 16) +
+				ALIGN_POW2_ROUNDUP(tdata->aad.len, 16),
+				tdata->auth_tag.len, auth_tag_buffer);
+	}
+
+	TEST_ASSERT_BUFFERS_ARE_EQUAL(
+			ciphertext,
+			tdata->ciphertext.data,
+			tdata->ciphertext.len,
+			"GCM Ciphertext data not as expected");
+
+	TEST_ASSERT_BUFFERS_ARE_EQUAL(
+			auth_tag,
+			tdata->auth_tag.data,
+			tdata->auth_tag.len,
+			"GCM Generated auth tag not as expected");
+
+	return 0;
+
+}
+
+static int
 test_mb_AES_GCM_authenticated_encryption_test_case_1(void)
 {
 	return test_mb_AES_GCM_authenticated_encryption(&gcm_test_case_1);
@@ -4127,6 +4583,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_mb_AES_GCM_authenticated_encryption_test_case_8(void)
+{
+	return test_mb_AES_GCM_authenticated_encryption_sgl(&gcm_test_case_7);
+}
+
+static int
 test_mb_AES_GCM_authenticated_decryption(const struct gcm_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -4204,6 +4666,97 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_mb_AES_GCM_authenticated_decryption_sgl(const struct gcm_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	int retval;
+
+	unsigned int ciphertext_len;
+	uint16_t ciphertext_pad_len;
+	uint8_t plaintext_buffer[2048];
+	const uint8_t *plaintext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create GCM session */
+	retval = create_gcm_session(ts_params->valid_devs[0],
+			RTE_CRYPTO_CIPHER_OP_DECRYPT,
+			tdata->key.data, tdata->key.len,
+			tdata->aad.len, tdata->auth_tag.len,
+			RTE_CRYPTO_AUTH_OP_VERIFY);
+	if (retval < 0)
+		return retval;
+
+	ciphertext_len = tdata->ciphertext.len;
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			ciphertext_pad_len, 5);
+	pktmbuf_write(ut_params->ibuf, 0, ciphertext_len,
+			tdata->ciphertext.data);
+
+	ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	rte_pktmbuf_append(ut_params->obuf, ciphertext_pad_len);
+
+	/* Create GCM operation */
+	retval = create_gcm_operation(RTE_CRYPTO_CIPHER_OP_DECRYPT,
+			tdata->auth_tag.data, tdata->auth_tag.len,
+			tdata->iv.data, tdata->iv.len,
+			tdata->aad.data, tdata->aad.len,
+			tdata->ciphertext.len, ciphertext_pad_len);
+	if (retval < 0) {
+		printf("create operation failed\n");
+		return retval;
+	}
+
+	rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+	ut_params->op->sym->m_src = ut_params->ibuf;
+	ut_params->op->sym->m_dst = ut_params->obuf;
+
+	/* Process crypto operation */
+	TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+			ut_params->op), "failed to process sym crypto op");
+
+	TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+			"crypto op processing failed");
+
+	/* Validate obuf */
+	if (ut_params->op->sym->m_dst)
+		plaintext = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+				ut_params->op->sym->cipher.data.offset,
+				ciphertext_pad_len, plaintext_buffer);
+	else
+		plaintext = rte_pktmbuf_read(ut_params->op->sym->m_src,
+				ut_params->op->sym->cipher.data.offset,
+				ciphertext_pad_len, plaintext_buffer);
+
+	TEST_ASSERT_BUFFERS_ARE_EQUAL(
+			plaintext,
+			tdata->plaintext.data,
+			tdata->plaintext.len,
+			"GCM Ciphertext data not as expected");
+
+	TEST_ASSERT_EQUAL(ut_params->op->status,
+			RTE_CRYPTO_OP_STATUS_SUCCESS,
+			"GCM authentication failed");
+
+	return 0;
+
+}
+
+static int
 test_mb_AES_GCM_authenticated_decryption_test_case_1(void)
 {
 	return test_mb_AES_GCM_authenticated_decryption(&gcm_test_case_1);
@@ -4246,6 +4799,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_mb_AES_GCM_authenticated_decryption_test_case_8(void)
+{
+	return test_mb_AES_GCM_authenticated_decryption_sgl(&gcm_test_case_8);
+}
+
+static int
 test_stats(void)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -6224,6 +6783,9 @@ struct test_crypto_vector {
 			test_mb_AES_GCM_authenticated_encryption_test_case_6),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_mb_AES_GCM_authenticated_encryption_test_case_7),
+		/** chained mbuf encrypt tests **/
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_mb_AES_GCM_authenticated_encryption_test_case_8),
 
 		/** AES GCM Authenticated Decryption */
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6240,6 +6802,8 @@ struct test_crypto_vector {
 			test_mb_AES_GCM_authenticated_decryption_test_case_6),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_mb_AES_GCM_authenticated_decryption_test_case_7),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_mb_AES_GCM_authenticated_decryption_test_case_8),
 
 		/** AES GMAC Authentication */
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6297,6 +6861,9 @@ struct test_crypto_vector {
 			test_mb_AES_GCM_authenticated_encryption_test_case_6),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_mb_AES_GCM_authenticated_encryption_test_case_7),
+		/** chained mbuf encrypt tests **/
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_mb_AES_GCM_authenticated_encryption_test_case_8),
 
 		/** AES GCM Authenticated Decryption */
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6327,6 +6894,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_2),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_3),
@@ -6349,6 +6918,10 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_oop_sgl),
+
+
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_decryption_test_case_1_oop),
 
 		/** KASUMI hash only (UIA1) */
@@ -6401,6 +6974,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_snow3g_encryption_test_case_1_oop_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_decryption_test_case_1_oop),
 
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6478,6 +7053,8 @@ struct test_crypto_vector {
 			test_zuc_hash_generate_test_case_4),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_zuc_hash_generate_test_case_5),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_zuc_encryption_test_case_6_sgl),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
 };
diff --git a/app/test/test_cryptodev.h b/app/test/test_cryptodev.h
index a9089aa..77cd826 100644
--- a/app/test/test_cryptodev.h
+++ b/app/test/test_cryptodev.h
@@ -71,4 +71,143 @@
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA384		(24)
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA512		(32)
 
+/**
+ * Write (spread) data from buffer to mbuf data
+ *
+ * @param mbuf
+ *   Destination mbuf
+ * @param offset
+ *   Start offset in mbuf
+ * @param len
+ *   Number of bytes to copy
+ * @param buffer
+ *   Continuous source buffer
+ */
+static inline void
+pktmbuf_write(struct rte_mbuf *mbuf, int offset, int len, const uint8_t *buffer)
+{
+	int n = len;
+	int l;
+	struct rte_mbuf *m;
+	char *dst;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	l = m->data_len - offset;
+
+	/* copy data from first segment */
+	dst = rte_pktmbuf_mtod_offset(m, char *, offset);
+	if (len <= l) {
+		rte_memcpy(dst, buffer, len);
+		return;
+	}
+
+	rte_memcpy(dst, buffer, l);
+	buffer += l;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		dst = rte_pktmbuf_mtod(m, char *);
+		l = m->data_len;
+		if (n < l) {
+			rte_memcpy(dst, buffer, n);
+			return;
+		}
+		rte_memcpy(dst, buffer, l);
+		buffer += l;
+		n -= l;
+	}
+}
+
+static inline uint8_t *
+sgl_pktmbuf_mtod_offset(struct rte_mbuf *mbuf, int offset) {
+	struct rte_mbuf *m;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	if (!m) {
+		printf("sgl_pktmbuf_mtod_offset: offset out of buffer\n");
+		return NULL;
+	}
+	return rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+}
+
+static inline phys_addr_t
+sgl_pktmbuf_mtophys_offset(struct rte_mbuf *mbuf, int offset) {
+	struct rte_mbuf *m;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	if (!m) {
+		printf("sgl_pktmbuf_mtophys_offset: offset out of buffer\n");
+		return 0;
+	}
+	return rte_pktmbuf_mtophys_offset(m, offset);
+}
+
+static inline struct rte_mbuf *
+create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
+		int nb_segs) {
+
+	struct rte_mbuf *m = NULL, *mbuf = NULL;
+	uint8_t *dst;
+	int data_len = 0;
+	int i, size;
+	int t_len;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return NULL;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return NULL;
+	}
+
+	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+	size = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (i = 0; size > 0; i++) {
+
+		m = rte_pktmbuf_alloc(mbuf_pool);
+		if (i == 0)
+			mbuf = m;
+
+		if (!m) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+				rte_pktmbuf_tailroom(m));
+
+		data_len = size > t_len ? t_len : size;
+		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (!dst) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		if (mbuf != m)
+			rte_pktmbuf_chain(mbuf, m);
+
+		size -= data_len;
+
+	}
+	return mbuf;
+
+fail:
+	if (mbuf)
+		rte_pktmbuf_free(mbuf);
+	return NULL;
+}
+
 #endif /* TEST_CRYPTODEV_H_ */
diff --git a/app/test/test_cryptodev_aes_test_vectors.h b/app/test/test_cryptodev_aes_test_vectors.h
index 1c68f93..901412f 100644
--- a/app/test/test_cryptodev_aes_test_vectors.h
+++ b/app/test/test_cryptodev_aes_test_vectors.h
@@ -858,6 +858,16 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-192-CTR XCBC Decryption Digest Verify "
+				"Scatter Gather",
+		.test_data = &aes_test_data_2,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "AES-256-CTR HMAC-SHA1 Encryption Digest",
 		.test_data = &aes_test_data_3,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -883,6 +893,18 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+				"Scatter Gather",
+		.test_data = &aes_test_data_4,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_4,
@@ -926,6 +948,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest "
+				"Scatter Gather Sessionless",
+		.test_data = &aes_test_data_6,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS |
+			BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_6,
@@ -935,6 +968,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
+			"Verify Scatter Gather",
+		.test_data = &aes_test_data_6,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "AES-128-CBC XCBC Encryption Digest",
 		.test_data = &aes_test_data_7,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -1033,9 +1077,17 @@
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
-		.test_descr = "AES-192-CBC Encryption",
+		.test_descr = "AES-192-CBC",
+		.test_data = &aes_test_data_10,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
+		.test_descr = "AES-192-CBC Encryption Scater gather",
 		.test_data = &aes_test_data_10,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
diff --git a/app/test/test_cryptodev_blockcipher.c b/app/test/test_cryptodev_blockcipher.c
index 37b10cf..bdf97d3 100644
--- a/app/test/test_cryptodev_blockcipher.c
+++ b/app/test/test_cryptodev_blockcipher.c
@@ -41,6 +41,7 @@
 #include <rte_cryptodev_pmd.h>
 
 #include "test.h"
+#include "test_cryptodev.h"
 #include "test_cryptodev_blockcipher.h"
 #include "test_cryptodev_aes_test_vectors.h"
 #include "test_cryptodev_des_test_vectors.h"
@@ -63,6 +64,7 @@
 	struct rte_crypto_sym_op *sym_op = NULL;
 	struct rte_crypto_op *op = NULL;
 	struct rte_cryptodev_sym_session *sess = NULL;
+	struct rte_cryptodev_info dev_info;
 
 	int status = TEST_SUCCESS;
 	const struct blockcipher_test_data *tdata = t->test_data;
@@ -72,6 +74,19 @@
 	uint32_t digest_len = 0;
 	char *buf_p = NULL;
 
+	int nb_segs = 3;
+	int nb_segs_oop = 1;
+
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+		rte_cryptodev_info_get(dev_id, &dev_info);
+		if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+			printf("Device doesn't support scatter-gather. "
+					"Test Skipped.\n");
+			return 0;
+		}
+	}
+
 	if (tdata->cipher_key.len)
 		memcpy(cipher_key, tdata->cipher_key.data,
 			tdata->cipher_key.len);
@@ -96,72 +111,112 @@
 	}
 
 	/* preparing data */
-	ibuf = rte_pktmbuf_alloc(mbuf_pool);
-	if (!ibuf) {
-		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-			"line %u FAILED: %s",
-			__LINE__, "Allocation of rte_mbuf failed");
-		status = TEST_FAILED;
-		goto error_exit;
-	}
 
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
 		buf_len += tdata->iv.len;
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
 		buf_len += digest_len;
 
-	buf_p = rte_pktmbuf_append(ibuf, buf_len);
-	if (!buf_p) {
-		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-			"line %u FAILED: %s",
-			__LINE__, "No room to append mbuf");
-		status = TEST_FAILED;
-		goto error_exit;
-	}
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
 
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
-		buf_p += tdata->iv.len;
-	}
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+			ibuf = create_segmented_mbuf(mbuf_pool,
+					tdata->plaintext.len, nb_segs);
+			pktmbuf_write(ibuf, 0, tdata->plaintext.len,
+					tdata->plaintext.data);
+		} else {
+			ibuf = create_segmented_mbuf(mbuf_pool,
+					tdata->ciphertext.len, nb_segs);
+			pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
+					tdata->ciphertext.data);
+		}
 
-	/* only encryption requires plaintext.data input,
-	 * decryption/(digest gen)/(digest verify) use ciphertext.data
-	 * to be computed
-	 */
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
-		rte_memcpy(buf_p, tdata->plaintext.data,
-			tdata->plaintext.len);
-		buf_p += tdata->plaintext.len;
-	} else {
-		rte_memcpy(buf_p, tdata->ciphertext.data,
-			tdata->ciphertext.len);
-		buf_p += tdata->ciphertext.len;
-	}
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+			rte_memcpy(rte_pktmbuf_prepend(ibuf, tdata->iv.len),
+					tdata->iv.data, tdata->iv.len);
+		}
 
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
-		rte_memcpy(buf_p, tdata->digest.data, digest_len);
-	else
-		memset(buf_p, 0, digest_len);
+		buf_p = rte_pktmbuf_append(ibuf, digest_len);
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+			rte_memcpy(buf_p, tdata->digest.data, digest_len);
+		else
+			memset(buf_p, 0, digest_len);
 
-	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
-		obuf = rte_pktmbuf_alloc(mbuf_pool);
-		if (!obuf) {
-			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-				"FAILED: %s", __LINE__,
-				"Allocation of rte_mbuf failed");
+	} else {
+		ibuf = rte_pktmbuf_alloc(mbuf_pool);
+		if (!ibuf) {
+			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+					"line %u FAILED: %s",
+					__LINE__,
+					"Allocation of rte_mbuf failed");
 			status = TEST_FAILED;
 			goto error_exit;
 		}
 
-		buf_p = rte_pktmbuf_append(obuf, buf_len);
+		buf_p = rte_pktmbuf_append(ibuf, buf_len);
 		if (!buf_p) {
-			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-				"FAILED: %s", __LINE__,
-				"No room to append mbuf");
+			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+					"line %u FAILED: %s",
+					__LINE__, "No room to append mbuf");
 			status = TEST_FAILED;
 			goto error_exit;
 		}
-		memset(buf_p, 0, buf_len);
+
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+			rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
+			buf_p += tdata->iv.len;
+		}
+
+		/* only encryption requires plaintext.data input,
+		 * decryption/(digest gen)/(digest verify) use ciphertext.data
+		 * to be computed
+		 */
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+			rte_memcpy(buf_p, tdata->plaintext.data,
+					tdata->plaintext.len);
+			buf_p += tdata->plaintext.len;
+		} else {
+			rte_memcpy(buf_p, tdata->ciphertext.data,
+					tdata->ciphertext.len);
+			buf_p += tdata->ciphertext.len;
+		}
+
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+			rte_memcpy(buf_p, tdata->digest.data, digest_len);
+		else
+			memset(buf_p, 0, digest_len);
+	}
+
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+			obuf = create_segmented_mbuf(mbuf_pool, buf_len,
+					nb_segs_oop);
+			if (!obuf) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"Allocation of rte_mbuf failed");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+		} else {
+			obuf = rte_pktmbuf_alloc(mbuf_pool);
+			if (!obuf) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"Allocation of rte_mbuf failed");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+			buf_p = rte_pktmbuf_append(obuf, buf_len);
+			if (!buf_p) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"No room to append mbuf");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+			memset(buf_p, 0, buf_len);
+		}
 	}
 
 	/* Generate Crypto op data structure */
@@ -176,7 +231,6 @@
 	}
 
 	sym_op = op->sym;
-
 	sym_op->m_src = ibuf;
 
 	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
@@ -307,17 +361,17 @@
 
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
-			sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
-				(iobuf, uint8_t *, digest_offset);
+			sym_op->auth.digest.data = sgl_pktmbuf_mtod_offset
+				(iobuf, digest_offset);
 			sym_op->auth.digest.phys_addr =
-				rte_pktmbuf_mtophys_offset(iobuf,
+				sgl_pktmbuf_mtophys_offset(iobuf,
 					digest_offset);
 		} else {
 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
-			sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
-				(sym_op->m_src, uint8_t *, digest_offset);
+			sym_op->auth.digest.data = sgl_pktmbuf_mtod_offset
+				(sym_op->m_src, digest_offset);
 			sym_op->auth.digest.phys_addr =
-				rte_pktmbuf_mtophys_offset(sym_op->m_src,
+				sgl_pktmbuf_mtophys_offset(sym_op->m_src,
 					digest_offset);
 		}
 
@@ -386,13 +440,10 @@
 	}
 
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		uint8_t *crypto_res;
+		uint8_t buffer[2048];
 		const uint8_t *compare_ref;
 		uint32_t compare_len;
 
-		crypto_res = rte_pktmbuf_mtod_offset(iobuf, uint8_t *,
-			tdata->iv.len);
-
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
 			compare_ref = tdata->ciphertext.data;
 			compare_len = tdata->ciphertext.len;
@@ -401,7 +452,8 @@
 			compare_len = tdata->plaintext.len;
 		}
 
-		if (memcmp(crypto_res, compare_ref, compare_len)) {
+		if (memcmp(rte_pktmbuf_read(iobuf, tdata->iv.len, compare_len,
+				buffer), compare_ref, compare_len)) {
 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
 				"FAILED: %s", __LINE__,
 				"Crypto data not as expected");
@@ -414,12 +466,11 @@
 		uint8_t *auth_res;
 
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
-			auth_res = rte_pktmbuf_mtod_offset(iobuf,
-				uint8_t *,
-				tdata->iv.len + tdata->ciphertext.len);
+			auth_res = sgl_pktmbuf_mtod_offset(iobuf,
+					tdata->iv.len + tdata->ciphertext.len);
 		else
-			auth_res = rte_pktmbuf_mtod_offset(iobuf,
-				uint8_t *, tdata->ciphertext.len);
+			auth_res = sgl_pktmbuf_mtod_offset(iobuf,
+					tdata->ciphertext.len);
 
 		if (memcmp(auth_res, tdata->digest.data, digest_len)) {
 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
diff --git a/app/test/test_cryptodev_blockcipher.h b/app/test/test_cryptodev_blockcipher.h
index 04ff1ee..148fc6d 100644
--- a/app/test/test_cryptodev_blockcipher.h
+++ b/app/test/test_cryptodev_blockcipher.h
@@ -42,9 +42,10 @@
 #define BLOCKCIPHER_TEST_OP_AUTH_GEN	0x04
 #define BLOCKCIPHER_TEST_OP_AUTH_VERIFY	0x08
 
-#define BLOCKCIPHER_TEST_FEATURE_OOP			0x01
+#define BLOCKCIPHER_TEST_FEATURE_OOP		0x01
 #define BLOCKCIPHER_TEST_FEATURE_SESSIONLESS	0x02
 #define BLOCKCIPHER_TEST_FEATURE_STOPPER	0x04 /* stop upon failing */
+#define BLOCKCIPHER_TEST_FEATURE_SG		0x08 /* Scatter Gather */
 
 #define BLOCKCIPHER_TEST_TARGET_PMD_MB		0x0001 /* Multi-buffer flag */
 #define BLOCKCIPHER_TEST_TARGET_PMD_QAT			0x0002 /* QAT flag */
diff --git a/app/test/test_cryptodev_des_test_vectors.h b/app/test/test_cryptodev_des_test_vectors.h
index a1d2d97..17bd064 100644
--- a/app/test/test_cryptodev_des_test_vectors.h
+++ b/app/test/test_cryptodev_des_test_vectors.h
@@ -800,6 +800,15 @@
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
+		.test_descr = "3DES-192-CBC SHA1 Encryption Digest "
+				"Scatter Gather",
+		.test_data = &triple_des192cbc_sha1_test_vector,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
 		.test_descr = "3DES-192-CBC SHA1 Decryption Digest Verify",
 		.test_data = &triple_des192cbc_sha1_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
@@ -813,6 +822,16 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "3DES-128-CTR HMAC-SHA1 Encryption Digest "
+				"Scatter Gather",
+		.test_data = &triple_des128ctr_hmac_sha1_test_vector,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "3DES-128-CTR HMAC-SHA1 Decryption Digest Verify",
 		.test_data = &triple_des128ctr_hmac_sha1_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
@@ -820,6 +839,16 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "3DES-128-CTR HMAC-SHA1 Decryption "
+				"Digest Verify Scatter Gather",
+		.test_data = &triple_des128ctr_hmac_sha1_test_vector,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "3DES-128-CTR SHA1 Encryption Digest",
 		.test_data = &triple_des128ctr_sha1_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
diff --git a/app/test/test_cryptodev_gcm_test_vectors.h b/app/test/test_cryptodev_gcm_test_vectors.h
index b404242..b2138a2 100644
--- a/app/test/test_cryptodev_gcm_test_vectors.h
+++ b/app/test/test_cryptodev_gcm_test_vectors.h
@@ -52,12 +52,12 @@ struct gcm_test_data {
 	} aad;
 
 	struct {
-		uint8_t data[1024];
+		uint8_t data[2048];
 		unsigned len;
 	} plaintext;
 
 	struct {
-		uint8_t data[1024];
+		uint8_t data[2048];
 		unsigned len;
 	} ciphertext;
 
@@ -450,6 +450,559 @@ struct gmac_test_data {
 	}
 };
 
+static const struct gcm_test_data gcm_test_case_8 = {
+	.key = {
+		.data = {
+			0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+			0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+			0xde, 0xca, 0xf8, 0x88
+		},
+		.len = 12
+	},
+	.aad = {
+		.data = {
+			0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+			0xfe, 0xed, 0xfa, 0xce
+		},
+		.len = 12
+	},
+	.plaintext = {
+		.data = {
+			0xC5, 0x34, 0x2E, 0x83, 0xEB, 0x4C, 0x02, 0x03,
+			0xF7, 0xB2, 0x57, 0x35, 0x26, 0x81, 0x63, 0xAE,
+			0x1F, 0xCD, 0x2D, 0x02, 0x91, 0x5A, 0xDB, 0x3A,
+			0xF1, 0x38, 0xD8, 0x75, 0x86, 0x20, 0xCC, 0x1E,
+			0xE6, 0xDC, 0xFF, 0xB5, 0xEA, 0x0E, 0x18, 0x7A,
+			0x86, 0x6C, 0xAB, 0x39, 0x2D, 0x90, 0xAC, 0x77,
+			0x5D, 0xED, 0x65, 0xB3, 0x05, 0x29, 0xBB, 0x09,
+			0xD0, 0x21, 0x74, 0x6A, 0x67, 0x1C, 0x95, 0x42,
+			0x55, 0xAD, 0xC8, 0x91, 0x28, 0xFE, 0x16, 0x9A,
+			0xE1, 0xCB, 0xCD, 0x68, 0x3B, 0xDF, 0x3E, 0x3A,
+			0x34, 0xFE, 0x9B, 0xFB, 0xF5, 0x15, 0x2A, 0x29,
+			0x18, 0x99, 0x24, 0xBF, 0xB6, 0x43, 0xDB, 0xD1,
+			0x69, 0x26, 0x1E, 0x31, 0x2C, 0x8C, 0x3C, 0x6B,
+			0x7F, 0x06, 0xA6, 0x03, 0xE2, 0x1A, 0x50, 0xFE,
+			0x7C, 0x69, 0xE5, 0x5F, 0x35, 0x93, 0xE9, 0x20,
+			0x14, 0xB1, 0xCA, 0x61, 0xE7, 0x9C, 0x89, 0x08,
+			0xD6, 0xB1, 0xC2, 0x63, 0x1B, 0x86, 0x5E, 0xF1,
+			0xF5, 0x23, 0x0E, 0x9B, 0xE5, 0xBD, 0x5D, 0x04,
+			0xF7, 0xEF, 0x8E, 0x46, 0xB0, 0x11, 0x4F, 0x69,
+			0x62, 0x35, 0x51, 0xB7, 0x24, 0xA2, 0x31, 0xD0,
+			0x32, 0x4E, 0xB8, 0x44, 0xC7, 0x59, 0xDE, 0x25,
+			0xEA, 0x2D, 0x00, 0x0E, 0xF1, 0x07, 0xBA, 0xBB,
+			0x9A, 0xBC, 0x4F, 0x57, 0xB7, 0x13, 0x57, 0xEF,
+			0xD9, 0xF6, 0x80, 0x69, 0xEA, 0xE8, 0x47, 0x9C,
+			0x51, 0x71, 0xE6, 0x8F, 0x69, 0x29, 0xB4, 0x60,
+			0xE8, 0x50, 0xE5, 0xD0, 0x9B, 0xD2, 0x62, 0x6F,
+			0x09, 0x5C, 0xD1, 0x4B, 0x85, 0xE2, 0xFD, 0xD3,
+			0xEB, 0x28, 0x55, 0x77, 0x97, 0xCA, 0xD6, 0xA8,
+			0xDC, 0x35, 0x68, 0xF7, 0x6A, 0xCF, 0x48, 0x3F,
+			0x49, 0x31, 0x00, 0x65, 0xB7, 0x31, 0x1A, 0x49,
+			0x75, 0xDE, 0xCE, 0x7F, 0x18, 0xB5, 0x31, 0x9A,
+			0x64, 0x6D, 0xE5, 0x49, 0x1D, 0x6D, 0xF2, 0x21,
+			0x9F, 0xF5, 0xFF, 0x7C, 0x41, 0x30, 0x33, 0x06,
+			0x7B, 0xA4, 0xD8, 0x99, 0xF6, 0xCC, 0xDF, 0xC4,
+			0x3F, 0xF3, 0xCD, 0xE7, 0x74, 0xC4, 0x4A, 0x19,
+			0x5C, 0xCA, 0x42, 0x31, 0xF1, 0x3B, 0x65, 0x1C,
+			0x3D, 0x56, 0x08, 0xBE, 0x15, 0x37, 0x23, 0x50,
+			0xD6, 0xA3, 0x57, 0x64, 0x25, 0xBE, 0xDA, 0xC2,
+			0x4E, 0xF5, 0x1A, 0xAD, 0x6F, 0x43, 0x78, 0x21,
+			0xF9, 0x36, 0x39, 0x1F, 0x5F, 0xF7, 0x1B, 0xA0,
+			0xEE, 0x8B, 0x4F, 0x8A, 0x9D, 0xD8, 0xED, 0x37,
+			0xCE, 0x0D, 0x70, 0xE0, 0x3F, 0xE7, 0x11, 0x30,
+			0x17, 0x1D, 0x03, 0x5E, 0xA0, 0x3D, 0x3F, 0x9E,
+			0xF5, 0xD3, 0x74, 0x2E, 0xC1, 0xD6, 0xFF, 0xF7,
+			0x2E, 0xE7, 0x80, 0x88, 0xCF, 0x0E, 0x7F, 0x12,
+			0x71, 0x62, 0xC7, 0xF1, 0xC4, 0x2B, 0x64, 0x5D,
+			0x1C, 0x9A, 0xB4, 0xCB, 0xB8, 0x24, 0xB3, 0x0B,
+			0x33, 0xF2, 0x8A, 0x8F, 0x76, 0xC8, 0x81, 0xDA,
+			0x1A, 0x10, 0xB5, 0xA9, 0xCD, 0xDC, 0x1A, 0x02,
+			0xC1, 0xAE, 0x4F, 0x02, 0x1B, 0x13, 0x96, 0x5A,
+			0x2E, 0x03, 0xA2, 0x68, 0xB2, 0x29, 0xAC, 0x28,
+			0xB8, 0xDC, 0xD5, 0x27, 0x55, 0xEC, 0x43, 0xDC,
+			0xB7, 0x49, 0x1D, 0xE1, 0x30, 0x25, 0x81, 0xA6,
+			0x90, 0x1F, 0x75, 0xBA, 0x19, 0x1E, 0xF7, 0xC5,
+			0x77, 0x35, 0xEE, 0x68, 0x71, 0x22, 0xA0, 0xB4,
+			0xCC, 0x99, 0x86, 0x1B, 0x1B, 0xC8, 0x27, 0xFC,
+			0x6D, 0x8D, 0xE7, 0x8B, 0xC3, 0x40, 0x3D, 0xA8,
+			0xCB, 0x9B, 0xC4, 0x12, 0x07, 0xDD, 0xA1, 0x92,
+			0xE5, 0x80, 0x7A, 0xF4, 0xDB, 0x4C, 0xE6, 0xEE,
+			0xF9, 0xD5, 0x1C, 0x20, 0x18, 0xD3, 0x8F, 0xDF,
+			0x1C, 0xD3, 0x51, 0x4E, 0x0E, 0xED, 0x06, 0x61,
+			0xF7, 0xBA, 0x81, 0x3A, 0x2F, 0xEA, 0xED, 0x70,
+			0xA9, 0xD9, 0x54, 0x4D, 0xFC, 0x1D, 0x19, 0xEA,
+			0xA6, 0x39, 0x8C, 0x6C, 0x78, 0xA8, 0x05, 0xEB,
+			0xF2, 0xB5, 0xDE, 0x06, 0x9D, 0x8A, 0x78, 0x2A,
+			0xF5, 0x50, 0xA4, 0xBD, 0x9B, 0xDA, 0xCA, 0x66,
+			0xC0, 0x23, 0xAB, 0xE8, 0x95, 0x7E, 0xC9, 0xD2,
+			0x6F, 0x09, 0xF2, 0x9A, 0x17, 0x89, 0xDA, 0x47,
+			0x65, 0x8C, 0x20, 0xFA, 0x4E, 0x86, 0x18, 0xEB,
+			0x7C, 0x08, 0xEC, 0x8A, 0x05, 0x54, 0x96, 0xD2,
+			0x7A, 0x8A, 0x81, 0x58, 0x75, 0x8C, 0x7B, 0x02,
+			0xEE, 0x1F, 0x51, 0x88, 0xD0, 0xD1, 0x90, 0x99,
+			0x0C, 0xAE, 0x51, 0x2E, 0x54, 0x3E, 0xB1, 0x7D,
+			0xBC, 0xE8, 0x54, 0x93, 0x6D, 0x10, 0x3C, 0xC6,
+			0x71, 0xF6, 0xF5, 0x0B, 0x07, 0x0A, 0x6E, 0x59,
+			0x20, 0x45, 0x21, 0x7D, 0x37, 0x64, 0x92, 0x09,
+			0xA7, 0xE2, 0x34, 0x6F, 0xFC, 0xCC, 0x66, 0x0E,
+			0x88, 0x1B, 0x19, 0x86, 0x11, 0xD7, 0x81, 0x25,
+			0xF1, 0x8A, 0x03, 0xB7, 0x7A, 0xF0, 0x98, 0x4A,
+			0x5C, 0xA1, 0x6D, 0x85, 0xA4, 0x8C, 0x4B, 0x65,
+			0x9F, 0x72, 0x64, 0x14, 0xBA, 0x74, 0xEE, 0xA3,
+			0x88, 0xFE, 0x1B, 0xCF, 0x11, 0x4F, 0xD1, 0xAC,
+			0xFA, 0x14, 0xC3, 0xA7, 0xDD, 0x06, 0x85, 0x4E,
+			0x64, 0x06, 0x92, 0x9C, 0xDF, 0x06, 0x09, 0xF1,
+			0x4D, 0xE8, 0xF8, 0x2F, 0x69, 0xB6, 0x8A, 0xAF,
+			0x25, 0x21, 0xB5, 0x48, 0x59, 0xF8, 0x9D, 0x60,
+			0xAE, 0x42, 0x11, 0x7A, 0x68, 0x4D, 0x7E, 0x76,
+			0xB0, 0xD2, 0xE3, 0xD9, 0x24, 0x16, 0x20, 0x0A,
+			0xEB, 0xE0, 0x68, 0xCB, 0xBC, 0xAB, 0x67, 0xE4,
+			0xF3, 0x25, 0x1F, 0xD3, 0x85, 0xA7, 0x1D, 0x7E,
+			0x3C, 0x63, 0xCB, 0xC2, 0x50, 0x90, 0x0F, 0x4B,
+			0x6E, 0x68, 0x06, 0x84, 0x65, 0xF7, 0xD0, 0xD4,
+			0x12, 0xED, 0xFA, 0xC9, 0x40, 0xE2, 0xC0, 0xC9,
+			0x46, 0x22, 0x47, 0x5E, 0x6D, 0xC1, 0x63, 0xDB,
+			0x51, 0x98, 0xDA, 0x1A, 0xC4, 0xB9, 0xED, 0xE9,
+			0x09, 0xB9, 0xCF, 0x91, 0x04, 0x1C, 0x63, 0xD8,
+			0xC5, 0xA5, 0xAE, 0x53, 0x7B, 0xA1, 0x29, 0x83,
+			0x37, 0xFB, 0xBF, 0x96, 0xBB, 0x24, 0x3D, 0x77,
+			0x8C, 0x0F, 0xB3, 0x4B, 0x66, 0x9C, 0x54, 0xBB,
+			0xF6, 0xDD, 0xD1, 0xB4, 0xD2, 0xF6, 0xAA, 0xED,
+			0x18, 0x56, 0x63, 0x3E, 0x0B, 0xCA, 0xAB, 0x70,
+			0xBB, 0x63, 0xEA, 0xB1, 0x00, 0x65, 0x90, 0x18,
+			0xB8, 0x63, 0xA2, 0xF2, 0xB6, 0x1E, 0x61, 0x7B,
+			0xD5, 0x01, 0xD9, 0x4D, 0xC9, 0x9D, 0x99, 0xC1,
+			0x57, 0x9D, 0x6F, 0xAE, 0x64, 0xE4, 0x0C, 0x7E,
+			0xFA, 0x15, 0x5E, 0xB6, 0x43, 0xB8, 0x8B, 0x89,
+			0x87, 0xCD, 0x4F, 0xAD, 0x30, 0x1E, 0xA5, 0x03,
+			0x7A, 0xC2, 0x10, 0x42, 0x14, 0x88, 0xD6, 0x7A,
+			0x6D, 0x56, 0x52, 0x2E, 0x8D, 0x1B, 0x5D, 0x36,
+			0x27, 0xA0, 0x21, 0x4B, 0x64, 0xF0, 0xC5, 0x41,
+			0xAD, 0x05, 0x4A, 0x24, 0xE4, 0x70, 0x88, 0x63,
+			0x12, 0xD0, 0xBC, 0x05, 0x38, 0xD9, 0x41, 0x68,
+			0x9F, 0x16, 0x9A, 0x54, 0x09, 0x21, 0x64, 0x36,
+			0x63, 0x97, 0x3A, 0xB5, 0xE0, 0x25, 0x43, 0x8A,
+			0x6A, 0x59, 0x97, 0xC1, 0x31, 0xA5, 0x66, 0xD2,
+			0xF0, 0x1C, 0xDF, 0x97, 0x51, 0xD0, 0x61, 0xBA,
+			0x55, 0x5F, 0xD7, 0x0D, 0xD4, 0x75, 0x8E, 0x79,
+			0x04, 0x75, 0x00, 0xB9, 0xC0, 0x7A, 0x66, 0x05,
+			0x9F, 0x2B, 0x44, 0x42, 0x75, 0x0F, 0xD5, 0x15,
+			0xD6, 0x16, 0x8F, 0x6C, 0x6E, 0xD4, 0x37, 0xCF,
+			0xB4, 0xDA, 0x93, 0x00, 0x11, 0xFB, 0xBE, 0xEE,
+			0x3B, 0x6D, 0x1D, 0xBA, 0x33, 0xD1, 0x52, 0x8B,
+			0x16, 0x39, 0x42, 0x27, 0xE6, 0x56, 0x4C, 0x41,
+			0x91, 0xB0, 0x98, 0xAE, 0x9B, 0x2D, 0x9B, 0x23,
+			0x80, 0x4C, 0xEA, 0x98, 0x57, 0x95, 0x28, 0x94,
+			0x43, 0xD3, 0x88, 0x12, 0xDF, 0x89, 0x5A, 0x7B,
+			0xC5, 0xCB, 0x36, 0x54, 0x65, 0x74, 0xB8, 0x4E,
+			0xE2, 0x4D, 0x01, 0xD5, 0x9C, 0x82, 0xB9, 0x1A,
+			0x09, 0xD2, 0xCE, 0x04, 0x36, 0xD8, 0x41, 0xAC,
+			0x4C, 0xAD, 0xC6, 0x52, 0x91, 0x1A, 0x06, 0x6D,
+			0xFC, 0xAB, 0x29, 0x93, 0x87, 0x88, 0xB9, 0x8C,
+			0xFA, 0x57, 0x2B, 0x05, 0x03, 0xD0, 0x18, 0xED,
+			0x7A, 0x7B, 0x81, 0x6A, 0x97, 0x65, 0x5B, 0x90,
+			0xDE, 0xA9, 0xFC, 0x8F, 0xFC, 0xBB, 0x98, 0xD8,
+			0xFA, 0x32, 0x3F, 0x3F, 0x7F, 0x74, 0x65, 0x38,
+			0xC4, 0x28, 0xEC, 0x27, 0x1F, 0x28, 0x01, 0xB1,
+			0xAF, 0x2B, 0x8A, 0x05, 0x38, 0x7B, 0x77, 0xC9,
+			0x61, 0x77, 0x34, 0x2C, 0x22, 0xE5, 0xEB, 0xDC,
+			0x9D, 0x18, 0x6E, 0x23, 0x25, 0x52, 0x69, 0xB7,
+			0x05, 0xDB, 0x66, 0x5D, 0xEA, 0x76, 0x83, 0x82,
+			0x97, 0x39, 0xAF, 0xC0, 0x50, 0x81, 0x18, 0x0D,
+			0x22, 0xFA, 0xB7, 0x44, 0x5C, 0x3F, 0x69, 0xF3,
+			0xAC, 0xC5, 0x63, 0x9F, 0xD8, 0x72, 0x7E, 0x9A,
+			0xC2, 0xEB, 0x79, 0xD0, 0x74, 0x65, 0xE8, 0xCA,
+			0xFD, 0xA8, 0x7D, 0x23, 0x07, 0x99, 0x3E, 0xAF,
+			0xDB, 0x67, 0x10, 0xC0, 0xE5, 0x61, 0x77, 0xC6,
+			0x8D, 0xC4, 0x0E, 0xAA, 0x55, 0xE3, 0xC0, 0xC7,
+			0xA5, 0x36, 0x28, 0x61, 0xDB, 0x16, 0x96, 0x5E,
+			0x01, 0x47, 0x82, 0xE3, 0xEB, 0x20, 0x3F, 0x10,
+			0xFA, 0x5A, 0xBC, 0xD3, 0xF9, 0xCE, 0x04, 0x87,
+			0x51, 0x07, 0xF9, 0xD0, 0xE7, 0x6D, 0xCB, 0xCC,
+			0xC4, 0x15, 0x00, 0xE2, 0xDC, 0x8E, 0x7B, 0x5C,
+			0x9A, 0xF2, 0x78, 0x70, 0x4D, 0xA1, 0xAA, 0xB5,
+			0x13, 0xCC, 0x71, 0x66, 0x5A, 0x79, 0x13, 0x3B,
+			0x12, 0xCD, 0x40, 0x30, 0x5A, 0x49, 0xD4, 0x20,
+			0xED, 0xCF, 0x4A, 0x75, 0xE6, 0xD5, 0xDD, 0x0F,
+			0xD4, 0xBE, 0x98, 0x9F, 0xD7, 0x1F, 0xC0, 0x02,
+			0x31, 0xFA, 0x67, 0x37, 0x25, 0x86, 0x56, 0x85,
+			0x2B, 0xA2, 0x57, 0xCD, 0x8E, 0x74, 0xE7, 0x69,
+			0xEE, 0x33, 0x5A, 0x3F, 0xCD, 0x1E, 0xE3, 0xB9,
+			0xAA, 0x52, 0xF5, 0x22, 0x4E, 0xE3, 0xFF, 0xC8,
+			0xE3, 0x13, 0xA3, 0x9A, 0x63, 0x23, 0xC3, 0xD7,
+			0xE5, 0x88, 0x3E, 0x0A, 0x4B, 0xA5, 0x01, 0xE6,
+			0x13, 0xCF, 0xED, 0xEE, 0x2A, 0x58, 0x09, 0x3F,
+			0x2F, 0x28, 0xE7, 0xC4, 0x6B, 0xEC, 0x49, 0x51,
+			0x79, 0x8F, 0xD5, 0x19, 0x5D, 0xA5, 0x10, 0xCE,
+			0x8E, 0xF6, 0x26, 0x78, 0x7A, 0xA8, 0x11, 0x52,
+			0x5F, 0x97, 0x14, 0xC9, 0x29, 0x87, 0xB8, 0xA0,
+			0x2D, 0xE6, 0xA7, 0x2A, 0xD4, 0xFF, 0xEB, 0xBA,
+			0xFD, 0x58, 0x39, 0x33, 0xB1, 0xCE, 0x0E, 0x78,
+			0x67, 0x1E, 0xA1, 0x92, 0x77, 0x63, 0xF8, 0xC0,
+			0x02, 0x49, 0x73, 0xC0, 0xA1, 0x26, 0x83, 0x04,
+			0x9A, 0x5D, 0x85, 0x68, 0x2A, 0x2F, 0xCB, 0x88,
+			0x8D, 0x14, 0xB1, 0x33, 0xFA, 0xFB, 0xE9, 0x05,
+			0xBE, 0x24, 0x1A, 0x6B, 0x29, 0x2B, 0x3F, 0x52,
+			0x8F, 0xFB, 0xE6, 0x02, 0x77, 0x50, 0x71, 0xDB,
+			0xE9, 0x92, 0x3F, 0xE1, 0x20, 0x62, 0x80, 0xAE,
+			0xA4, 0x98, 0xC6, 0xCD, 0xE0, 0xB1, 0xC3, 0x33,
+			0xB1, 0xC5, 0x91, 0x3C, 0x19, 0x34, 0xA8, 0xD9,
+			0xB3, 0x25, 0x69, 0xE3, 0x9C, 0x5F, 0x78, 0xD0,
+			0x83, 0x1F, 0xAB, 0x85, 0x13, 0x56, 0x69, 0xB5,
+			0x06, 0x47, 0x62, 0x37, 0x27, 0x15, 0x14, 0x05,
+			0x4A, 0xF4, 0x6A, 0x68, 0x2A, 0x6A, 0xC3, 0x5A,
+			0xDF, 0xB5, 0xAE, 0x2F, 0x8D, 0x8F, 0x21, 0xDB,
+			0x33, 0x00, 0x9B, 0xD4, 0xC4, 0x08, 0x3B, 0x81,
+			0x63, 0x4C, 0xB0, 0x39, 0x4C, 0x0A, 0xD5, 0x71,
+			0x3E, 0x5A, 0x50, 0x58, 0x9C, 0x07, 0x89, 0x79,
+			0x79, 0x2F, 0x0B, 0xD9, 0x50, 0xBC, 0xCF, 0x46,
+			0x7A, 0x68, 0x5C, 0xBF, 0x1E, 0x49, 0x77, 0x92,
+			0x85, 0x11, 0x39, 0xA6, 0x2F, 0xDA, 0x7B, 0xFA,
+			0x72, 0x87, 0x06, 0xCD, 0x84, 0x41, 0x20, 0x1B,
+			0x66, 0x3F, 0x42, 0x0C, 0x9E, 0x19, 0xD3, 0x18,
+			0x57, 0xA0, 0xEE, 0x16, 0x3A, 0xC7, 0xF9, 0xD3,
+			0x8B, 0xC9, 0x24, 0x70, 0x70, 0x51, 0x7C, 0x06,
+			0x68, 0xD3, 0x29, 0xC9, 0x85, 0x9A, 0x1C, 0xE6,
+			0x8C, 0x17, 0xF4, 0x88, 0xDF, 0xEA, 0xFF, 0x44,
+			0x8D, 0x54, 0xBE, 0x22, 0x07, 0xA5, 0x7C, 0x0C,
+			0xF4, 0x8D, 0xB1, 0x0C, 0x07, 0xED, 0xBD, 0x28,
+			0x19, 0xDA, 0x07, 0x71, 0xA8, 0xA1, 0xE0, 0xDD,
+			0xEE, 0x08, 0x18, 0xA5, 0xBD, 0xDD, 0x32, 0x0B,
+			0x70, 0x1C, 0xD9, 0xEE, 0x19, 0xC2, 0xAE, 0x5C,
+			0xE3, 0x02, 0x74, 0x70, 0x96, 0x61, 0xB1, 0x73,
+			0x3B, 0xD6, 0x74, 0xC0, 0x82, 0xA9, 0x1F, 0xE0,
+			0xF1, 0x22, 0x50, 0xF3, 0x9F, 0xE5, 0x13, 0x92,
+			0xFC, 0x0A, 0x1A, 0x3C, 0xB4, 0x46, 0xFB, 0x81,
+			0x00, 0x84, 0xA4, 0x5E, 0x6B, 0x8C, 0x25, 0x6E,
+			0xD7, 0xB7, 0x3B, 0x01, 0x65, 0xFB, 0x0B, 0x46,
+			0x67, 0x27, 0x2D, 0x51, 0xAD, 0xB5, 0xE0, 0x85,
+			0xC2, 0x95, 0xA3, 0xE3, 0x68, 0x4D, 0x9E, 0x8C,
+			0x11, 0x53, 0xF0, 0xB2, 0x85, 0xFA, 0x52, 0x4E,
+			0xEC, 0xF9, 0xB7, 0x3C, 0x89, 0x2C, 0x4D, 0x32,
+			0x9A, 0xCB, 0x17, 0xF3, 0x16, 0xBF, 0x44, 0x40,
+			0xE9, 0x5E, 0x51, 0x8C, 0x1E, 0x52, 0x0A, 0xC2,
+			0xCD, 0xA5, 0xAA, 0x03, 0x27, 0xB0, 0x8F, 0x64,
+			0xDB, 0xD7, 0x03, 0x01, 0x8A, 0x24, 0x28, 0x7E,
+			0x53, 0x6F, 0x24, 0xFD, 0xAA, 0xE3, 0x78, 0xB6,
+			0xA5, 0x5D, 0x5A, 0x67, 0x20, 0xE2, 0xBE, 0x3A,
+			0x2B, 0xE7, 0x86, 0x11, 0xDD, 0x96, 0xCB, 0x09,
+			0x65, 0xA0, 0x36, 0xF9, 0xB0, 0x20, 0x21, 0x8E,
+			0xDB, 0xC0, 0x73, 0xC7, 0x79, 0xD8, 0xDA, 0xC2,
+			0x66, 0x13, 0x64, 0x34, 0x0C, 0xE1, 0x22, 0x24,
+			0x61, 0x67, 0x08, 0x39, 0x97, 0x3F, 0x33, 0x96,
+			0xF2, 0x44, 0x18, 0x75, 0xBB, 0xF5, 0x6A, 0x5C,
+			0x2C, 0xAE, 0x2A, 0x79, 0x3D, 0x47, 0x19, 0x53,
+			0x50, 0x6C, 0x9F, 0xB3, 0x82, 0x55, 0x09, 0x78,
+			0x7B, 0xAD, 0xBC, 0x05, 0x6F, 0xC8, 0x3D, 0xB6,
+			0x7B, 0x30, 0xE6, 0xBB, 0x8B, 0xD0, 0x2F, 0xA6,
+			0x15, 0xCC, 0x77, 0x8C, 0x21, 0xBA, 0x03, 0xED,
+			0x56, 0x85, 0x82, 0x4F, 0x97, 0x8C, 0x59, 0x4F,
+			0x53, 0x5A, 0xD2, 0x70, 0xD9, 0x07, 0xB3, 0xBD,
+			0x1D, 0x3E, 0x97, 0xD4, 0x7D, 0x93, 0x35, 0xA4,
+			0x82, 0x6E, 0xEA, 0x4B, 0xC8, 0x6C, 0xF5, 0xE6,
+			0xEB, 0xAF, 0x11, 0xB0, 0xB4, 0x71, 0x8F, 0x7B,
+			0xC4, 0x8C, 0xE2, 0x66, 0x51, 0x31, 0x99, 0x01,
+			0x5B, 0xE7, 0x48, 0xF8, 0x4C, 0xE3, 0x9A, 0x77,
+			0xF1, 0xC6, 0x09, 0xDE, 0x76, 0xD4, 0xE3, 0x5C,
+			0xDF, 0xA3, 0xEC, 0x3C, 0x86, 0x7C, 0xA5, 0x3F,
+			0x8D, 0x2A, 0xF3, 0x0B, 0x54, 0xB7, 0x54, 0xA2,
+			0xC1, 0x69, 0xC0, 0x6F, 0x1C, 0x1C, 0x76, 0xD8,
+			0x9F, 0x7A, 0x32, 0xB0, 0xA1, 0xA6, 0x9B, 0xB7,
+			0x21, 0x56, 0x28, 0x2D, 0xB6, 0x97, 0x03, 0x5E,
+			0x65, 0xE3, 0x74, 0x9A, 0x96, 0x7A, 0xF9, 0xF5,
+			0xDD, 0x85, 0xCA, 0x4C, 0xB4, 0x03, 0x6A, 0xCD,
+			0xB6, 0x01, 0xDC, 0x8B, 0xD8, 0x73, 0x8F, 0x4D,
+			0x7F, 0xD6, 0x71, 0xEC, 0xD7, 0xC6, 0x0B, 0x5F,
+			0x09, 0x21, 0xB2, 0x78, 0xA8, 0xAF, 0xAD, 0x2C,
+			0xD4, 0x93, 0x9F, 0x71, 0xF7, 0x05, 0x89, 0x42,
+			0xC9, 0x15, 0x6F, 0x2D, 0xE0, 0xBA, 0xC3, 0xD6,
+			0xBF, 0xAC, 0xF8, 0x24, 0x58, 0x79, 0xA9, 0xC4,
+			0xB4, 0x49, 0x3E, 0x0B, 0x9E, 0x5E, 0xE4, 0xA6,
+			0x8B, 0xE8, 0xDE, 0xFB, 0x4A, 0xF1, 0x69, 0x9D,
+			0x4F, 0x77, 0x83, 0x78, 0x55, 0x19, 0x42, 0x45,
+			0xBF, 0xBD, 0xBD, 0x12, 0x0F, 0xEF, 0x8D, 0x04,
+			0xD8, 0x5C, 0xF2, 0xC9, 0xF1, 0xA6, 0xE0, 0x3E,
+			0x22, 0xA8, 0xA2, 0x5E, 0x66, 0xE9, 0xAB, 0xB4,
+			0x71, 0xBE, 0x4B, 0x3F, 0xBE, 0xC4, 0xBA, 0x4A
+		},
+		.len = 2048
+	},
+	.ciphertext = {
+		.data = {
+			0x5E, 0x86, 0x02, 0x64, 0x32, 0xBF, 0x70, 0xC2,
+			0x19, 0x99, 0x7F, 0x47, 0x0D, 0xA4, 0x91, 0xA8,
+			0x7A, 0xC0, 0xA5, 0x7E, 0xA8, 0x6C, 0x88, 0x00,
+			0xEA, 0xB5, 0x96, 0x6B, 0x25, 0xBD, 0xE7, 0x42,
+			0xDB, 0x35, 0xE7, 0x92, 0x2B, 0x00, 0x82, 0x35,
+			0xD4, 0x2C, 0xCF, 0x47, 0xC8, 0xB2, 0xB3, 0x57,
+			0xF7, 0x24, 0x83, 0x7F, 0xC5, 0x2E, 0xF1, 0xC9,
+			0x57, 0x1A, 0xEF, 0xC2, 0x3A, 0x8C, 0x1E, 0x92,
+			0x88, 0x05, 0xAF, 0x55, 0xE6, 0x0C, 0xA7, 0x6B,
+			0x59, 0x62, 0x32, 0x21, 0xF1, 0xFF, 0xB5, 0x5B,
+			0x22, 0x26, 0x6F, 0x0A, 0x36, 0xDC, 0x0D, 0x16,
+			0x3B, 0x4E, 0x7C, 0xA3, 0x75, 0x30, 0x3F, 0xB0,
+			0x99, 0x38, 0x42, 0x8E, 0x89, 0xA3, 0x7C, 0x99,
+			0x2F, 0x0A, 0xA1, 0xC7, 0xFD, 0x2D, 0x21, 0x8F,
+			0xBD, 0xD4, 0x11, 0xEA, 0x55, 0xF5, 0x6A, 0x50,
+			0x90, 0x3B, 0x60, 0x57, 0xE1, 0x86, 0x1E, 0x50,
+			0x28, 0x67, 0x3F, 0xD2, 0xF3, 0xBD, 0xFA, 0xEE,
+			0xD6, 0x5A, 0x38, 0x30, 0xA3, 0xDD, 0x78, 0xC4,
+			0x37, 0x59, 0x52, 0xC0, 0x92, 0x54, 0xC7, 0x53,
+			0xF0, 0xE6, 0xA9, 0x63, 0x1F, 0x9B, 0x97, 0xFB,
+			0x40, 0x23, 0xFE, 0x52, 0x6A, 0xF0, 0x3A, 0x94,
+			0xEB, 0x6A, 0x9E, 0x8F, 0xC5, 0x05, 0x9C, 0x04,
+			0x1B, 0x00, 0x34, 0x96, 0x12, 0xDA, 0x60, 0xC6,
+			0xAA, 0x1A, 0x3E, 0xEB, 0x70, 0x17, 0x10, 0xBC,
+			0xF5, 0xC2, 0xE2, 0x71, 0xF3, 0xB8, 0x1D, 0xCE,
+			0x47, 0x94, 0x21, 0x71, 0x34, 0x8C, 0xCC, 0xDD,
+			0x27, 0xCE, 0x6F, 0x68, 0xFF, 0x91, 0x4E, 0xC4,
+			0xA0, 0xCA, 0xB0, 0x4F, 0x17, 0x53, 0x73, 0x92,
+			0x6C, 0xA8, 0x16, 0x06, 0xE3, 0xD9, 0x92, 0x99,
+			0xBE, 0xB0, 0x7D, 0x56, 0xF2, 0x72, 0x30, 0xDA,
+			0xC4, 0x4E, 0xF4, 0xA6, 0x8F, 0xD2, 0xC7, 0x8A,
+			0xA2, 0xFC, 0xF5, 0x63, 0x17, 0x48, 0x56, 0x4D,
+			0xBE, 0x94, 0xFE, 0xF5, 0xB1, 0xA9, 0x96, 0xAB,
+			0x3F, 0x2D, 0xD4, 0x15, 0xEE, 0x4F, 0xFA, 0x2C,
+			0xBE, 0x91, 0xB7, 0xBC, 0x18, 0xC8, 0xDB, 0x02,
+			0x20, 0x29, 0xF1, 0xC1, 0x88, 0x8C, 0x8D, 0xD1,
+			0xB3, 0x4E, 0x93, 0x96, 0xDD, 0x22, 0xAB, 0x55,
+			0xB5, 0x9F, 0x8B, 0x20, 0xAE, 0xC6, 0x0E, 0x26,
+			0xC6, 0xFE, 0x2D, 0x5F, 0x95, 0x89, 0x06, 0x15,
+			0x3D, 0x88, 0x16, 0xEC, 0x9B, 0x4A, 0x1B, 0x5D,
+			0x2E, 0xB2, 0x13, 0x56, 0x9F, 0x33, 0xB3, 0x45,
+			0xBF, 0x5F, 0x25, 0x7E, 0x75, 0x22, 0xD2, 0xE6,
+			0x9F, 0xAC, 0x2D, 0xFD, 0x99, 0xC2, 0x9B, 0xFC,
+			0xD7, 0x7A, 0x9B, 0x05, 0x30, 0x0F, 0xB7, 0x4A,
+			0xFE, 0x24, 0xDD, 0x39, 0x9B, 0xBB, 0x2F, 0xDD,
+			0xF9, 0xFB, 0xCA, 0x6C, 0x87, 0xBA, 0x73, 0xD4,
+			0x85, 0x7B, 0xB2, 0x6F, 0x5C, 0xD8, 0xFB, 0xE9,
+			0x41, 0x24, 0x3A, 0x3B, 0x4F, 0x91, 0x77, 0xA2,
+			0x35, 0x78, 0xE5, 0x4C, 0xFE, 0x8B, 0x04, 0x03,
+			0xD3, 0x84, 0xA9, 0x1C, 0xA7, 0x7C, 0x45, 0x13,
+			0x7D, 0xC5, 0x0A, 0x2F, 0x02, 0xF8, 0x56, 0xD5,
+			0x5F, 0x35, 0xED, 0x06, 0xBF, 0x67, 0xBA, 0x51,
+			0x02, 0x95, 0x36, 0xF2, 0x9A, 0xBA, 0x9D, 0xF6,
+			0xD6, 0x77, 0x50, 0xC9, 0xFC, 0x1E, 0x32, 0xB5,
+			0x2F, 0xEA, 0x3C, 0x76, 0xB4, 0xE1, 0xCC, 0x42,
+			0xEB, 0x71, 0x79, 0xD3, 0x7D, 0xB7, 0xC0, 0x88,
+			0x25, 0x81, 0xE8, 0xC0, 0xB8, 0x38, 0x7E, 0x7B,
+			0xFD, 0x18, 0xAB, 0x08, 0xB2, 0x71, 0xA5, 0xAD,
+			0xA7, 0xBE, 0x48, 0x5F, 0x86, 0xE2, 0x41, 0x3D,
+			0x7C, 0x37, 0x7A, 0xAB, 0xDB, 0xE0, 0x3B, 0x3D,
+			0xB6, 0xE8, 0x23, 0x7C, 0xF1, 0x8F, 0xBA, 0xB7,
+			0xE9, 0x78, 0x0B, 0xCA, 0x67, 0xA8, 0x10, 0x36,
+			0xEB, 0x72, 0xED, 0xDD, 0xF0, 0x5C, 0x74, 0x8E,
+			0xE5, 0x2A, 0xAE, 0x6E, 0xC4, 0xF1, 0xFC, 0xD8,
+			0xEE, 0x56, 0x07, 0x88, 0x02, 0xDC, 0x9D, 0xB7,
+			0xF9, 0x13, 0xE1, 0xE1, 0x9D, 0x89, 0x26, 0x0B,
+			0x23, 0x74, 0x4A, 0x43, 0xAA, 0xA0, 0xA8, 0x97,
+			0x85, 0x15, 0x58, 0xAB, 0x2B, 0xB5, 0xDA, 0x1A,
+			0xBA, 0x29, 0x62, 0xCF, 0xDD, 0xA3, 0xBA, 0x9D,
+			0x7D, 0x83, 0xA5, 0x18, 0xD4, 0x03, 0x0F, 0x61,
+			0x9F, 0xB1, 0x7E, 0xEC, 0xD2, 0x6E, 0xAF, 0xCF,
+			0x1E, 0xC1, 0x88, 0x97, 0x99, 0xD6, 0xBF, 0x47,
+			0xB9, 0x0A, 0x69, 0x11, 0x3A, 0x55, 0x8B, 0x1D,
+			0x2D, 0xFF, 0x78, 0xC8, 0xDE, 0x82, 0x29, 0xD6,
+			0x08, 0x3C, 0xC4, 0xCB, 0x2F, 0x01, 0xD0, 0xE8,
+			0xB1, 0x75, 0x5E, 0x23, 0xE0, 0x37, 0x7C, 0x1C,
+			0xB6, 0xD9, 0x47, 0xDE, 0x23, 0x87, 0xD3, 0x68,
+			0x47, 0x46, 0x78, 0xF3, 0xBF, 0x54, 0xA3, 0xB9,
+			0x54, 0xD5, 0xC5, 0x0A, 0x7C, 0x92, 0x2A, 0xC2,
+			0x14, 0x76, 0xA6, 0x5C, 0x6D, 0x0B, 0x94, 0x56,
+			0x00, 0x6B, 0x5C, 0x27, 0xDE, 0x77, 0x9B, 0xF1,
+			0xB1, 0x8C, 0xA7, 0x49, 0x77, 0xFC, 0x4E, 0x29,
+			0x23, 0x8F, 0x2F, 0xF7, 0x83, 0x8D, 0x36, 0xD9,
+			0xAB, 0x0E, 0x78, 0xF5, 0x90, 0x05, 0xB9, 0x79,
+			0x70, 0x88, 0x59, 0x6F, 0xE2, 0xC5, 0xD7, 0x80,
+			0x95, 0x04, 0x29, 0xE0, 0xFA, 0x37, 0xE8, 0x8B,
+			0xC5, 0x21, 0x51, 0x1A, 0x62, 0xCE, 0x93, 0xAF,
+			0x1A, 0xFE, 0xC3, 0x6F, 0x86, 0x94, 0x5E, 0x13,
+			0xA6, 0x9A, 0x26, 0xF0, 0xB5, 0x7C, 0x41, 0x9A,
+			0x80, 0xB8, 0x84, 0x5A, 0x55, 0xA9, 0xB0, 0x6A,
+			0xFA, 0xEB, 0x46, 0x32, 0x0B, 0xE2, 0x9C, 0x65,
+			0x86, 0x11, 0x39, 0x7E, 0xAF, 0x93, 0x19, 0x09,
+			0x70, 0x40, 0x80, 0x14, 0xBA, 0x1D, 0xB3, 0x62,
+			0x5B, 0xF3, 0x9A, 0x21, 0x98, 0x7E, 0x63, 0xB6,
+			0x1A, 0xBD, 0x65, 0x98, 0x35, 0x2A, 0xA9, 0x76,
+			0x29, 0x59, 0x84, 0x25, 0x81, 0xB8, 0xDE, 0x25,
+			0x32, 0x10, 0x50, 0xB7, 0xD3, 0xB3, 0x69, 0xC8,
+			0xE1, 0x33, 0xCB, 0x9E, 0x9C, 0x7A, 0x7C, 0xD2,
+			0x6C, 0x92, 0x97, 0xA9, 0xFA, 0xAF, 0x30, 0xBA,
+			0x9A, 0xB3, 0x3D, 0x9A, 0xE5, 0x0A, 0x9B, 0x8D,
+			0x89, 0xE2, 0x2B, 0xB8, 0xBC, 0xF0, 0x23, 0xFF,
+			0x7B, 0x0D, 0x00, 0x36, 0xEE, 0x79, 0xCB, 0xA5,
+			0x70, 0x4C, 0x66, 0x02, 0x79, 0x2E, 0x5B, 0x83,
+			0xCE, 0x55, 0x8B, 0x89, 0xD6, 0xE3, 0x71, 0x63,
+			0xBC, 0xB1, 0x5F, 0x67, 0xB4, 0x7E, 0x05, 0x0D,
+			0xAC, 0x6D, 0x4E, 0x2C, 0xA5, 0xF4, 0x47, 0x89,
+			0xAC, 0x5E, 0xBE, 0x2F, 0xFC, 0x9B, 0x2F, 0x0B,
+			0xBE, 0x63, 0x54, 0x97, 0xBB, 0x23, 0x27, 0xCD,
+			0xB9, 0xB2, 0x28, 0x0D, 0xA4, 0x78, 0x2C, 0xAB,
+			0xD1, 0xC9, 0x94, 0x40, 0x54, 0xF2, 0x35, 0x61,
+			0x49, 0x01, 0x87, 0x55, 0xA5, 0xB5, 0x1E, 0x84,
+			0x92, 0x9E, 0xC1, 0xA4, 0x0B, 0x66, 0x2B, 0xF8,
+			0xAF, 0xC3, 0x1E, 0xAF, 0x66, 0x3F, 0x6F, 0x5F,
+			0x70, 0xEC, 0x25, 0x29, 0xE4, 0x65, 0xB2, 0x04,
+			0x47, 0xF6, 0x3C, 0xB5, 0x5F, 0x66, 0x9F, 0xA4,
+			0x1B, 0xFC, 0xA2, 0xD5, 0x3E, 0x84, 0xBA, 0x88,
+			0x0D, 0xF1, 0x6A, 0xF2, 0xF6, 0x1D, 0xF1, 0xA3,
+			0x45, 0xB2, 0x51, 0xD8, 0xA2, 0x8F, 0x55, 0xA6,
+			0x89, 0xC4, 0x15, 0xD5, 0x73, 0xA8, 0xB1, 0x31,
+			0x66, 0x9E, 0xC1, 0x43, 0xE1, 0x5D, 0x4E, 0x04,
+			0x84, 0x8F, 0xF2, 0xBC, 0xE1, 0x4E, 0x4D, 0x60,
+			0x81, 0xCA, 0x53, 0x34, 0x95, 0x17, 0x3B, 0xAE,
+			0x8F, 0x95, 0xA7, 0xC6, 0x47, 0xC6, 0xAC, 0x32,
+			0x12, 0x39, 0xCA, 0xEF, 0xE0, 0x07, 0xBF, 0x17,
+			0x4F, 0xDC, 0x1B, 0x4E, 0x3C, 0x84, 0xF1, 0x9F,
+			0x43, 0x70, 0x19, 0xE6, 0xF3, 0x8B, 0x8B, 0x5D,
+			0xDB, 0xD2, 0x9D, 0xD4, 0xB2, 0x30, 0x45, 0x55,
+			0xA2, 0x67, 0xA2, 0x76, 0x4A, 0x74, 0xAD, 0x88,
+			0x71, 0xE6, 0x3E, 0x13, 0x06, 0x30, 0x17, 0xE1,
+			0xEF, 0xAC, 0x71, 0xFB, 0x43, 0xCD, 0xF6, 0xFA,
+			0x0E, 0x4C, 0x4E, 0x16, 0xF6, 0x6A, 0x09, 0x86,
+			0x6B, 0xEA, 0x47, 0x6C, 0x70, 0xE7, 0xAD, 0xA2,
+			0xE0, 0xFD, 0x7F, 0xF0, 0x5C, 0x21, 0x53, 0x0F,
+			0x28, 0xA1, 0x43, 0xE1, 0x06, 0xCA, 0x0B, 0x31,
+			0x88, 0x22, 0xA6, 0xE6, 0x34, 0x5B, 0xE6, 0xCF,
+			0x25, 0x81, 0x63, 0xFF, 0x78, 0x66, 0x85, 0x19,
+			0xE2, 0x0A, 0x7E, 0x81, 0x8A, 0x17, 0x1A, 0x18,
+			0x8A, 0x5F, 0x5D, 0x9E, 0x82, 0x13, 0x10, 0xB9,
+			0xD3, 0xE6, 0x93, 0x1C, 0xE4, 0x2C, 0xCB, 0x49,
+			0x1E, 0xB6, 0x36, 0x13, 0xBF, 0x28, 0xEE, 0xCC,
+			0x49, 0xF5, 0x79, 0xFC, 0x20, 0x65, 0xBD, 0xE8,
+			0xF0, 0x1B, 0x4E, 0xC0, 0x0D, 0x3E, 0x89, 0x91,
+			0xCC, 0x64, 0x10, 0xC0, 0x2A, 0x2B, 0xA3, 0xFA,
+			0x60, 0x3D, 0xC3, 0x52, 0x2F, 0x93, 0xDE, 0xB7,
+			0x6E, 0x8A, 0xDF, 0x6C, 0x08, 0xCC, 0x8B, 0x3B,
+			0xC8, 0x50, 0xEF, 0x58, 0x64, 0x9A, 0x3D, 0x16,
+			0x70, 0x94, 0x11, 0xD8, 0x94, 0x2B, 0x70, 0x91,
+			0x10, 0x70, 0x88, 0xF0, 0x40, 0x75, 0x9A, 0x2B,
+			0x39, 0xA1, 0x27, 0x3F, 0x2E, 0x91, 0xEA, 0xA1,
+			0xCC, 0x12, 0xC1, 0x7F, 0x73, 0x8C, 0x5C, 0x6B,
+			0xFC, 0xC5, 0x6A, 0x1C, 0x05, 0xF1, 0x3D, 0x30,
+			0x82, 0x4A, 0x65, 0x35, 0xCE, 0x80, 0x10, 0xBB,
+			0x41, 0x94, 0xFB, 0x84, 0x80, 0x7B, 0x91, 0xC4,
+			0x4D, 0xA3, 0x5F, 0xB9, 0xFB, 0xF9, 0xC9, 0x1D,
+			0x4F, 0x99, 0x1C, 0x1F, 0x47, 0x44, 0x89, 0x0E,
+			0xED, 0x6D, 0xB5, 0x85, 0x41, 0x94, 0xEF, 0xF9,
+			0x2E, 0xA0, 0xC8, 0xCA, 0xFB, 0x44, 0x02, 0xC6,
+			0xBF, 0x96, 0x87, 0x80, 0x1D, 0xEF, 0x2A, 0x81,
+			0xAB, 0xB2, 0x56, 0xDF, 0x54, 0x8B, 0xAB, 0xAF,
+			0xFE, 0x18, 0x8C, 0xAA, 0xD4, 0x00, 0x17, 0xBE,
+			0xCF, 0x06, 0xE5, 0xA6, 0xBF, 0x5A, 0x52, 0x3B,
+			0x4E, 0xF5, 0x65, 0x60, 0x95, 0xDE, 0x8A, 0x25,
+			0x88, 0xA5, 0x24, 0x96, 0x29, 0x13, 0x0D, 0x19,
+			0x45, 0x95, 0x91, 0x08, 0xD2, 0x9C, 0x4C, 0x34,
+			0x42, 0xF0, 0xA5, 0x72, 0xEB, 0xFB, 0x5E, 0xAA,
+			0x68, 0x80, 0x82, 0xAC, 0x34, 0xAD, 0x89, 0xF6,
+			0xAF, 0x54, 0x82, 0xCF, 0x98, 0x8C, 0x75, 0x63,
+			0x8D, 0xBD, 0x1C, 0x2A, 0xD7, 0x00, 0xA7, 0x8E,
+			0xB9, 0x33, 0xB6, 0x3B, 0x95, 0x9A, 0x59, 0x1D,
+			0x3F, 0x23, 0x6B, 0x18, 0xF8, 0x4F, 0x1A, 0x8D,
+			0xC0, 0x26, 0x9F, 0x87, 0x61, 0xB6, 0xC6, 0x60,
+			0x38, 0x22, 0x73, 0x1C, 0x99, 0x23, 0xEF, 0xD9,
+			0xFD, 0xCB, 0x54, 0x74, 0xBB, 0x77, 0x14, 0xA3,
+			0xA9, 0xE6, 0x7C, 0x7E, 0x03, 0x3A, 0x13, 0x6E,
+			0x1D, 0x6F, 0x64, 0xB3, 0xFA, 0xFB, 0x52, 0xDE,
+			0xDF, 0x08, 0xFB, 0x6F, 0xC5, 0xFA, 0x51, 0x6A,
+			0x69, 0x29, 0x9B, 0x96, 0xE8, 0x16, 0xC8, 0xD1,
+			0xE4, 0x19, 0xBD, 0x14, 0x74, 0x27, 0xE7, 0x10,
+			0xF0, 0xC3, 0xE2, 0xA7, 0x60, 0x48, 0xBF, 0xDD,
+			0xC4, 0x0D, 0xD0, 0xF2, 0xEF, 0xA6, 0xC9, 0xA2,
+			0x73, 0xD1, 0xCF, 0x41, 0xE1, 0x3B, 0xE5, 0x49,
+			0x91, 0x5D, 0x09, 0xFD, 0x1D, 0x95, 0x29, 0xDB,
+			0x52, 0x48, 0xEB, 0xF5, 0x1D, 0xF8, 0x06, 0x67,
+			0x75, 0xF2, 0x57, 0xA4, 0x20, 0x60, 0xEA, 0xB0,
+			0x85, 0x93, 0x7C, 0xDD, 0x52, 0x01, 0xD4, 0x57,
+			0xA8, 0x31, 0x2D, 0xF9, 0x0A, 0xD2, 0x2A, 0xD1,
+			0x34, 0x18, 0x35, 0x16, 0xB6, 0x8B, 0x0F, 0x0B,
+			0xCF, 0x50, 0x80, 0xFE, 0x76, 0xCC, 0x4F, 0x30,
+			0x98, 0x19, 0x16, 0x3D, 0x01, 0xEA, 0x8D, 0x8A,
+			0x3D, 0xDC, 0xFB, 0x1F, 0x77, 0x8D, 0x72, 0x76,
+			0x02, 0x3C, 0x5D, 0xEE, 0x55, 0x13, 0x5B, 0x6E,
+			0x5A, 0x2D, 0xD5, 0x77, 0xD7, 0x01, 0x84, 0x7D,
+			0x21, 0x8C, 0xDD, 0x94, 0x7D, 0x31, 0x3D, 0xF0,
+			0xE7, 0x28, 0xF5, 0x72, 0x36, 0x60, 0xE0, 0x59,
+			0x5F, 0xFE, 0x38, 0xF8, 0x2F, 0xDB, 0x9E, 0x55,
+			0x5A, 0xD6, 0xBA, 0x6C, 0x87, 0xF3, 0xC0, 0x76,
+			0x5F, 0xA3, 0x0A, 0xC3, 0xA3, 0x8D, 0x0E, 0x52,
+			0xA8, 0xDA, 0x26, 0x3A, 0xF9, 0x3E, 0x36, 0xB1,
+			0x06, 0xF8, 0x20, 0x2D, 0x1C, 0x0B, 0x93, 0xBB,
+			0xD3, 0x64, 0x77, 0xCE, 0x11, 0xFC, 0xA2, 0x0E,
+			0x1B, 0x5B, 0x9E, 0x13, 0x9F, 0x20, 0x8B, 0xAA,
+			0xCD, 0x72, 0xD7, 0xA6, 0xF3, 0x1E, 0x4F, 0x72,
+			0xC6, 0x49, 0x0F, 0x7B, 0xF0, 0x4C, 0x61, 0x1F,
+			0x43, 0x0D, 0x4F, 0x0D, 0x33, 0x13, 0xED, 0x63,
+			0xE5, 0xDB, 0x71, 0xAB, 0xA4, 0x83, 0xEF, 0xDC,
+			0x86, 0x9D, 0x4B, 0xBD, 0x1B, 0x8A, 0xFE, 0x39,
+			0xA8, 0x8B, 0xBA, 0x4C, 0x85, 0x28, 0xFC, 0xB3,
+			0x62, 0x85, 0xD2, 0xF0, 0x38, 0xD0, 0x4B, 0xA4,
+			0xD1, 0x3B, 0xD4, 0xD0, 0x2C, 0x78, 0x6C, 0x6A,
+			0xC2, 0x64, 0x2C, 0x31, 0x4A, 0xD8, 0x69, 0x24,
+			0xED, 0x77, 0x7D, 0x68, 0x9A, 0xA1, 0x78, 0x81,
+			0xD9, 0x7E, 0x6C, 0xFE, 0x0A, 0x0D, 0x76, 0xF7,
+			0x4B, 0x58, 0xE7, 0xC9, 0xB5, 0x11, 0x07, 0x87,
+			0x88, 0x6A, 0x9F, 0x3D, 0xE0, 0xEE, 0xCC, 0x60,
+			0x6B, 0x6B, 0xE6, 0xB5, 0x54, 0x8B, 0x32, 0x1F,
+			0x04, 0x1D, 0x0E, 0x9E, 0xFA, 0x6D, 0xB0, 0xE0,
+			0x6D, 0xF9, 0x79, 0xB4, 0xAB, 0x5E, 0xDF, 0x23,
+			0x7F, 0x95, 0xAD, 0x80, 0x17, 0x23, 0x90, 0x1F,
+			0xF0, 0xC3, 0xD9, 0x2D, 0xAC, 0x3F, 0x63, 0xF5,
+			0x77, 0xC5, 0x05, 0xAC, 0x06, 0xB6, 0xA1, 0xB4,
+			0xA2, 0x40, 0xB3, 0x99, 0x34, 0x7D, 0x31, 0xD4,
+			0xB1, 0xD4, 0xC1, 0xBB, 0x71, 0x1E, 0xDA, 0x3F,
+			0xA9, 0x12, 0x68, 0xFA, 0x5B, 0x20, 0x24, 0x6D,
+			0x4D, 0x72, 0x43, 0x18, 0xBF, 0x66, 0x71, 0x69,
+			0x26, 0x7D, 0x77, 0x78, 0xF8, 0xE5, 0x20, 0xAE,
+			0x56, 0x6C, 0x0F, 0x72, 0x94, 0x42, 0x85, 0x4F,
+			0xE4, 0xFB, 0x32, 0x26, 0x1B, 0x1C, 0x6E, 0x0B,
+			0xF0, 0xB8, 0x58, 0x00, 0xD2, 0x36, 0x64, 0xAD,
+			0xA9, 0x00, 0xCE, 0x35, 0x3C, 0x88, 0x79, 0x94,
+			0x0C, 0x0C, 0x9B, 0xF2, 0xDA, 0xBD, 0xCA, 0x93,
+			0x37, 0x26, 0xD3, 0x08, 0x54, 0xD2, 0x0D, 0xBC,
+			0x5D, 0x43, 0x5F, 0xCF, 0x28, 0xB5, 0xAA, 0x15,
+			0x28, 0x46, 0x45, 0x6B, 0xE8, 0xDF, 0xE8, 0xCE,
+			0x8F, 0xC0, 0x1A, 0x53, 0x63, 0x3B, 0x53, 0x75,
+			0xDD, 0x43, 0x1F, 0x07, 0x0A, 0xD5, 0xA1, 0x2A,
+			0x6E, 0x28, 0xE1, 0xD7, 0xD0, 0x09, 0xCF, 0x62,
+			0xC1, 0x5F, 0x21, 0xDB, 0xC5, 0x40, 0x99, 0x48,
+			0x87, 0x6E, 0x11, 0xF5, 0x5A, 0x4E, 0xBC, 0xF9,
+			0xA8, 0x02, 0x7C, 0x47, 0x39, 0xA5, 0xD8, 0x52,
+			0xB1, 0x80, 0xDC, 0xFE, 0x08, 0x4B, 0x5D, 0x09,
+			0xDE, 0x06, 0xF3, 0x2A, 0xAD, 0x14, 0x76, 0x40,
+			0x2F, 0x82, 0x28, 0x6A, 0xB6, 0x43, 0xEF, 0x71,
+			0x63, 0xC2, 0x56, 0xEB, 0x3B, 0x4B, 0x52, 0x2F,
+			0x93, 0xD3, 0x18, 0x3E, 0x18, 0xA8, 0xF7, 0x58,
+			0xFC, 0x8B, 0x3D, 0x4D, 0x4B, 0x72, 0xBD, 0xF7,
+			0x04, 0xC9, 0xB8, 0xD7, 0x6C, 0x8C, 0x67, 0xBB,
+			0x4C, 0x9B, 0x57, 0xF7, 0x22, 0x4E, 0x41, 0xB6,
+			0xFD, 0xD9, 0xF8, 0x41, 0x62, 0x0F, 0xFF, 0xAA,
+			0xC6, 0x87, 0x95, 0xFF, 0xFD, 0x58, 0xD9, 0xB2,
+			0xBA, 0x47, 0x61, 0x24, 0xEA, 0x92, 0x6E, 0x74,
+			0xB3, 0xDA, 0xE5, 0x83, 0x99, 0x24, 0xB1, 0x71,
+			0x2A, 0x33, 0xB2, 0xD5, 0x8F, 0xF0, 0x32, 0xCE,
+			0x37, 0xCF, 0xC7, 0x1C, 0xE8, 0xDE, 0x46, 0x78,
+			0x96, 0x97, 0xF6, 0x73, 0x90, 0xE5, 0x71, 0x05,
+			0xEA, 0x0D, 0xC2, 0x1D, 0x9E, 0x43, 0x34, 0xBC,
+			0x8F, 0x45, 0xE5, 0x08, 0xCA, 0x20, 0x0C, 0x84
+		},
+		.len = 2048
+	},
+	.auth_tag = {
+		.data = {
+			0xD0, 0x62, 0x1F, 0x20, 0x1C, 0xE8, 0xDD, 0x36,
+			0x00, 0x74, 0xF6, 0xD7, 0xFD, 0x2C, 0xA0, 0xAF
+		},
+		.len = 16
+	}
+};
+
 /** GMAC Test Vectors */
 static uint8_t gmac_plaintext[GMAC_LARGE_PLAINTEXT_LENGTH] = {
 			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-- 
1.7.9.5

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

* [PATCH v3 0/5] Chained Mbufs support in SW PMDs
  2016-12-29 17:12 ` [PATCH v2 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
                     ` (4 preceding siblings ...)
  2016-12-29 17:12   ` [PATCH v2 5/5] test: add sgl unit tests for crypto devices Tomasz Kulasek
@ 2017-01-05  9:12   ` Tomasz Kulasek
  2017-01-05  9:12     ` [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
                       ` (6 more replies)
  5 siblings, 7 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05  9:12 UTC (permalink / raw)
  To: dev

This patch set adds support of scattered-gather list for SW PMDs.

As of now, application needs to reserve continuous block of memory for
mbufs which is not always the case. Hence needed to support chaining of
mbufs which are smaller in size but can be used if chained.


Above work involves:
--------------------

 a) Create mbuf functions to coalesce mbuf chains into a single mbuf.
 b) For each software poll mode driver code to detect chained mbufs
    support and coalesce these before preforming crypto.
 c) Add relevant unit tests to test the functionality.


Known limitations for openssl PMD:
----------------------------------

While libcrypto library expects continuous destination buffer for
output of cipher operations, implementation of openssl PMD is limited
the same way, and requires contigous destination mbuf.


Dependencies:
-------------

This patch set shares some unit tests with SGL implementation for QAT
(already merged in dpdk-next-crypto) and should be applied on top of it,
and after applying fix "app/test: fix aad padding size in SGL operation"
by Arek Kusztal.


changes in v3:
 - rebased to dpdk-next-crypto
 - reused tests for AES GCM SGL support in opensll from "app/test: add
   SGL tests to cryptodev QAT suite"

changes in v2:
 - add support for sgl in openssl PMD
 - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
 - extended test vector data for aes gcm from 60 to 2048 bytes

Tomasz Kulasek (5):
  rte_mbuf: add rte_pktmbuf_linearize
  test: add rte_pktmbuf_linearize unit tests
  crypto: add sgl support in sw PMDs
  crypto: add sgl support in openssl PMD
  test: add sgl unit tests for crypto devices

 app/test/test_cryptodev.c                  |  386 ++++++++++++++++++-
 app/test/test_cryptodev.h                  |  139 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   52 +++
 app/test/test_cryptodev_blockcipher.c      |  180 +++++----
 app/test/test_cryptodev_blockcipher.h      |    1 +
 app/test/test_cryptodev_gcm_test_vectors.h |  553 ++++++++++++++++++++++++++++
 app/test/test_mbuf.c                       |  123 +++++++
 doc/guides/cryptodevs/openssl.rst          |    3 +-
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 +
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 +-
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +
 drivers/crypto/null/null_crypto_pmd.c      |    3 +-
 drivers/crypto/openssl/rte_openssl_pmd.c   |  329 +++++++++++++----
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +
 lib/librte_cryptodev/rte_cryptodev.c       |    4 +-
 lib/librte_cryptodev/rte_cryptodev.h       |    2 +
 lib/librte_mbuf/rte_mbuf.h                 |   56 +++
 18 files changed, 1756 insertions(+), 149 deletions(-)

-- 
1.7.9.5

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

* [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize
  2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
@ 2017-01-05  9:12     ` Tomasz Kulasek
  2017-01-05 15:37       ` De Lara Guarch, Pablo
  2017-01-05  9:12     ` [PATCH v3 2/5] test: add rte_pktmbuf_linearize unit tests Tomasz Kulasek
                       ` (5 subsequent siblings)
  6 siblings, 1 reply; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05  9:12 UTC (permalink / raw)
  To: dev

This patch adds function rte_pktmbuf_linearize to let crypto PMD coalesce
chained mbuf before crypto operation and extend their capabilities to
support segmented mbufs when device cannot handle them natively.

Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 lib/librte_mbuf/rte_mbuf.h |   56 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ead7c6e..b11a31d 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -1647,6 +1647,62 @@ static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail
 }
 
 /**
+ * Linearize data in mbuf.
+ *
+ * This function coalesce mbuf merging data in the first segment, unchaining
+ * rest, and then frees them.
+ *
+ * All operations are done in-place, so the structure of incoming mbuf
+ * is changed.
+ *
+ * @param mbuf
+ *   mbuf to linearize
+ * @return
+ *   - 0, on success
+ *   - -1, on error
+ */
+static inline int
+rte_pktmbuf_linearize(struct rte_mbuf *mbuf)
+{
+	int l, n;
+	struct rte_mbuf *m;
+	struct rte_mbuf *m_next;
+	char *buffer;
+
+	if (rte_pktmbuf_is_contiguous(mbuf))
+		return 0;
+
+	/* Extend first segment to the total packet length
+	 */
+	n = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
+
+	if (unlikely(n > rte_pktmbuf_tailroom(mbuf)))
+		return -1;
+
+	buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
+	mbuf->data_len = (uint16_t)(mbuf->pkt_len);
+
+	/* Append data from next segments to the first one
+	 */
+	m = mbuf->next;
+	while (m != NULL) {
+		m_next = m->next;
+
+		l = rte_pktmbuf_data_len(m);
+		rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), l);
+		buffer += l;
+
+		rte_pktmbuf_free_seg(m);
+		m = m_next;
+	}
+
+	mbuf->next = NULL;
+	mbuf->nb_segs = 1;
+
+	return 0;
+}
+
+/**
  * Dump an mbuf structure to a file.
  *
  * Dump all fields for the given packet mbuf and all its associated
-- 
1.7.9.5

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

* [PATCH v3 2/5] test: add rte_pktmbuf_linearize unit tests
  2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2017-01-05  9:12     ` [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
@ 2017-01-05  9:12     ` Tomasz Kulasek
  2017-01-05  9:12     ` [PATCH v3 3/5] crypto: add sgl support in sw PMDs Tomasz Kulasek
                       ` (4 subsequent siblings)
  6 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05  9:12 UTC (permalink / raw)
  To: dev

This patch tests rte_pktmbuf_linearize functionality:

 1) Creates banch of segmented mbufs with different size and number of
    segments.
 2) Generates pkt_len bytes of random data.
 3) Fills noncontigouos mbuf with randomly generated data.
 4) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one
    contiguous.
 5) Verifies data in linearized buffer.

Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_mbuf.c |  123 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 123 insertions(+)

diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c
index c0823ea..39577e7 100644
--- a/app/test/test_mbuf.c
+++ b/app/test/test_mbuf.c
@@ -930,6 +930,124 @@
 	return 0;
 }
 
+static int
+test_mbuf_linearize(int pkt_len, int nb_segs) {
+
+	struct rte_mbuf *m = NULL, *mbuf_src = NULL;
+	uint8_t data[pkt_len], *src, *dst;
+	int data_len = 0;
+	int i, size;
+	int t_len;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return -1;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return -1;
+	}
+
+	/* Setup buffer */
+	for (i = 0; i < pkt_len; i++)
+		data[i] = (uint8_t) rte_rand();
+
+	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+	src = data;
+	size = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (i = 0; size > 0; i++) {
+
+		m = rte_pktmbuf_alloc(pktmbuf_pool);
+		if (i == 0)
+			mbuf_src = m;
+
+		if (!m) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+				rte_pktmbuf_tailroom(m));
+
+		data_len = size > t_len ? t_len : size;
+		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (!dst) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		rte_memcpy(dst, src, data_len);
+		src += data_len;
+
+		if (mbuf_src != m)
+			rte_pktmbuf_chain(mbuf_src, m);
+
+		size -= data_len;
+
+	}
+
+	/* Create destination buffer to store coalesced data */
+	if (rte_pktmbuf_linearize(mbuf_src)) {
+		printf("Mbuf linearization failed\n");
+		goto fail;
+	}
+
+	if (!rte_pktmbuf_is_contiguous(mbuf_src)) {
+		printf("Source buffer should be contiguous after "
+				"linearization\n");
+		goto fail;
+	}
+
+	src = rte_pktmbuf_mtod(mbuf_src, uint8_t *);
+
+	if (memcmp(src, data, rte_pktmbuf_pkt_len(mbuf_src))) {
+		printf("Incorrect data in coalesced mbuf\n");
+		goto fail;
+	}
+
+	if (mbuf_src)
+		rte_pktmbuf_free(mbuf_src);
+	return 0;
+
+fail:
+	if (mbuf_src)
+		rte_pktmbuf_free(mbuf_src);
+	return -1;
+}
+
+static int
+test_mbuf_linearize_check(void)
+{
+	struct test_mbuf_array {
+		int size;
+		int nb_segs;
+	} mbuf_array[5] = {
+			{ 128, 1 },
+			{ 64, 64 },
+			{ 512, 10 },
+			{ 250, 11 },
+			{ 123, 8 },
+	};
+	unsigned int i;
+
+	printf("Test mbuf linearize API\n");
+
+	for (i = 0; i < RTE_DIM(mbuf_array); i++)
+		if (test_mbuf_linearize(mbuf_array[i].size,
+				mbuf_array[i].nb_segs)) {
+			printf("Test failed for %d, %d\n", mbuf_array[i].size,
+					mbuf_array[i].nb_segs);
+			return -1;
+		}
+
+	return 0;
+}
 
 static int
 test_mbuf(void)
@@ -1023,6 +1141,11 @@
 		printf("test_failing_mbuf_sanity_check() failed\n");
 		return -1;
 	}
+
+	if (test_mbuf_linearize_check() < 0) {
+		printf("test_mbuf_linearize_check() failed\n");
+		return -1;
+	}
 	return 0;
 }
 
-- 
1.7.9.5

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

* [PATCH v3 3/5] crypto: add sgl support in sw PMDs
  2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2017-01-05  9:12     ` [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
  2017-01-05  9:12     ` [PATCH v3 2/5] test: add rte_pktmbuf_linearize unit tests Tomasz Kulasek
@ 2017-01-05  9:12     ` Tomasz Kulasek
  2017-01-05  9:12     ` [PATCH v3 4/5] crypto: add sgl support in openssl PMD Tomasz Kulasek
                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05  9:12 UTC (permalink / raw)
  To: dev

This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature flag
informing that selected crypto device supports segmented mbufs natively
and doesn't need to be coalesced before crypto operation.

While using segmented buffers in crypto devices may have unpredictable
results, for PMDs which doesn't support it natively, additional check is
made for debug compilation.

Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 ++++++++++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 ++++++++++++++++---
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +++++++++++++
 drivers/crypto/null/null_crypto_pmd.c      |    3 ++-
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +++++++++++++++
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +++++++++++++
 lib/librte_cryptodev/rte_cryptodev.c       |    4 ++--
 lib/librte_cryptodev/rte_cryptodev.h       |    2 ++
 8 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index dba5e15..1a6120c 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -375,6 +375,20 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_AESNI_GCM_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			GCM_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			qp->qp_stats.enqueue_err_count++;
+			break;
+		}
+#endif
+
 		retval = process_gcm_crypto_op(qp, ops[i]->sym, sess);
 		if (retval < 0) {
 			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 6d27d75..25f681b 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -571,15 +571,28 @@
 	int i, processed_jobs = 0;
 
 	for (i = 0; i < nb_ops; i++) {
-#ifdef RTE_LIBRTE_AESNI_MB_DEBUG
-		if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
+#ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
+		if (unlikely(ops[i]->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
 			MB_LOG_ERR("PMD only supports symmetric crypto "
 				"operation requests, op (%p) is not a "
-				"symmetric operation.", op);
+				"symmetric operation.", ops[i]);
+			qp->stats.enqueue_err_count++;
+			goto flush_jobs;
+		}
+
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			MB_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 			qp->stats.enqueue_err_count++;
 			goto flush_jobs;
 		}
 #endif
+
 		sess = get_session(qp, ops[i]);
 		if (unlikely(sess == NULL)) {
 			qp->stats.enqueue_err_count++;
diff --git a/drivers/crypto/kasumi/rte_kasumi_pmd.c b/drivers/crypto/kasumi/rte_kasumi_pmd.c
index b119da2..4bdd7bb 100644
--- a/drivers/crypto/kasumi/rte_kasumi_pmd.c
+++ b/drivers/crypto/kasumi/rte_kasumi_pmd.c
@@ -455,6 +455,19 @@
 	for (i = 0; i < nb_ops; i++) {
 		curr_c_op = ops[i];
 
+#ifdef RTE_LIBRTE_PMD_KASUMI_DEBUG
+		if (!rte_pktmbuf_is_contiguous(curr_c_op->sym->m_src) ||
+				(curr_c_op->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						curr_c_op->sym->m_dst))) {
+			KASUMI_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", curr_c_op);
+			curr_c_op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		/* Set status as enqueued (not processed yet) by default. */
 		curr_c_op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
 
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index c69606b..c37d3d6 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -216,7 +216,8 @@
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
-			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
 
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 3b4292a..9a6f16d 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -330,6 +330,21 @@
 	unsigned i;
 	unsigned enqueued_ops, processed_ops;
 
+#ifdef RTE_LIBRTE_PMD_SNOW3G_DEBUG
+	for (i = 0; i < num_ops; i++) {
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			SNOW3G_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			return 0;
+		}
+	}
+#endif
+
 	switch (session->op) {
 	case SNOW3G_OP_ONLY_CIPHER:
 		processed_ops = process_snow3g_cipher_op(ops,
diff --git a/drivers/crypto/zuc/rte_zuc_pmd.c b/drivers/crypto/zuc/rte_zuc_pmd.c
index 3849119..bf53f76 100644
--- a/drivers/crypto/zuc/rte_zuc_pmd.c
+++ b/drivers/crypto/zuc/rte_zuc_pmd.c
@@ -211,6 +211,19 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_ZUC_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ZUC_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		src[i] = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
 				(ops[i]->sym->cipher.data.offset >> 3);
 		dst[i] = ops[i]->sym->m_dst ?
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 54e95d5..bbab4b3 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -211,13 +211,13 @@ struct rte_cryptodev_callback {
 		return "CPU_AESNI";
 	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
 		return "HW_ACCELERATED";
-
+	case RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER:
+		return "MBUF_SCATTER_GATHER";
 	default:
 		return NULL;
 	}
 }
 
-
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)
 {
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 29d8eec..fa311a9 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -227,6 +227,8 @@ struct rte_cryptodev_capabilities {
 /**< Operations are off-loaded to an external hardware accelerator */
 #define	RTE_CRYPTODEV_FF_CPU_AVX512		(1ULL << 8)
 /**< Utilises CPU SIMD AVX512 instructions */
+#define	RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER	(1ULL << 9)
+/**< Scatter-gather mbufs are supported */
 
 
 /**
-- 
1.7.9.5

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

* [PATCH v3 4/5] crypto: add sgl support in openssl PMD
  2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
                       ` (2 preceding siblings ...)
  2017-01-05  9:12     ` [PATCH v3 3/5] crypto: add sgl support in sw PMDs Tomasz Kulasek
@ 2017-01-05  9:12     ` Tomasz Kulasek
  2017-01-05  9:12     ` [PATCH v3 5/5] test: add sgl unit tests for crypto devices Tomasz Kulasek
                       ` (2 subsequent siblings)
  6 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05  9:12 UTC (permalink / raw)
  To: dev

Previous implementation uses EVP_EncryptUpdate() on whole source buffer
limiting its usage to the contiguous buffers.

This implementation calls EVP_EncryptUpdate() on each segment for cipher
operations in continuous mode, before finalization allowing to provide
chained mbuf as a source.

However, libcrypto library expects continuous destination buffer for
output of cipher operations and implementation of openssl PMD is limited
the same way, requiring contiguous destination mbuf.


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 doc/guides/cryptodevs/openssl.rst        |    3 +-
 drivers/crypto/openssl/rte_openssl_pmd.c |  329 +++++++++++++++++++++++-------
 2 files changed, 259 insertions(+), 73 deletions(-)

diff --git a/doc/guides/cryptodevs/openssl.rst b/doc/guides/cryptodevs/openssl.rst
index d2b5906..d0b1eeb 100644
--- a/doc/guides/cryptodevs/openssl.rst
+++ b/doc/guides/cryptodevs/openssl.rst
@@ -112,6 +112,7 @@ Limitations
 -----------
 
 * Maximum number of sessions is 2048.
-* Chained mbufs are not supported.
+* Chained mbufs are supported only for source mbuf (destination must be
+  contiguous).
 * Hash only is not supported for GCM and GMAC.
 * Cipher only is not supported for GCM and GMAC.
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 832ea1d..e466c79 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -484,24 +484,112 @@
  * Process Operations
  *------------------------------------------------------------------------------
  */
+static inline int
+process_openssl_encryption_update(struct rte_mbuf *mbuf_src, int offset,
+		uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+	struct rte_mbuf *m;
+	int dstlen;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		return -1;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+			return -1;
+		*dst += l;
+		return 0;
+	}
+
+	if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+		return -1;
+
+	*dst += dstlen;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+			return -1;
+		*dst += dstlen;
+		n -= l;
+	}
+
+	return 0;
+}
+
+static inline int
+process_openssl_decryption_update(struct rte_mbuf *mbuf_src, int offset,
+		uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+	struct rte_mbuf *m;
+	int dstlen;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		return -1;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+			return -1;
+		*dst += l;
+		return 0;
+	}
+
+	if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+		return -1;
+
+	*dst += dstlen;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+			return -1;
+		*dst += dstlen;
+		n -= l;
+	}
+
+	return 0;
+}
 
 /** Process standard openssl cipher encryption */
 static int
-process_openssl_cipher_encrypt(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_encrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
-	int dstlen, totlen;
+	int totlen;
 
 	if (EVP_EncryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
 		goto process_cipher_encrypt_err;
 
 	EVP_CIPHER_CTX_set_padding(ctx, 0);
 
-	if (EVP_EncryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+	if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+			srclen, ctx))
 		goto process_cipher_encrypt_err;
 
-	if (EVP_EncryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+	if (EVP_EncryptFinal_ex(ctx, dst, &totlen) <= 0)
 		goto process_cipher_encrypt_err;
 
 	return 0;
@@ -513,11 +601,11 @@
 
 /** Process standard openssl cipher decryption */
 static int
-process_openssl_cipher_decrypt(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_decrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
-	int dstlen, totlen;
+	int totlen;
 
 	if (EVP_DecryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
 		goto process_cipher_decrypt_err;
@@ -525,12 +613,12 @@
 	if (EVP_CIPHER_CTX_set_padding(ctx, 0) <= 0)
 		goto process_cipher_decrypt_err;
 
-	if (EVP_DecryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+	if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+			srclen, ctx))
 		goto process_cipher_decrypt_err;
 
-	if (EVP_DecryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+	if (EVP_DecryptFinal_ex(ctx, dst, &totlen) <= 0)
 		goto process_cipher_decrypt_err;
-
 	return 0;
 
 process_cipher_decrypt_err:
@@ -540,11 +628,25 @@
 
 /** Process cipher des 3 ctr encryption, decryption algorithm */
 static int
-process_openssl_cipher_des3ctr(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen, EVP_CIPHER_CTX *ctx)
+process_openssl_cipher_des3ctr(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
+		EVP_CIPHER_CTX *ctx)
 {
 	uint8_t ebuf[8], ctr[8];
 	int unused, n;
+	struct rte_mbuf *m;
+	uint8_t *src;
+	int l;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_cipher_des3ctr_err;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+	l = rte_pktmbuf_data_len(m) - offset;
 
 	/* We use 3DES encryption also for decryption.
 	 * IV is not important for 3DES ecb
@@ -553,9 +655,8 @@
 		goto process_cipher_des3ctr_err;
 
 	memcpy(ctr, iv, 8);
-	n = 0;
 
-	while (n < srclen) {
+	for (n = 0; n < srclen; n++) {
 		if (n % 8 == 0) {
 			if (EVP_EncryptUpdate(ctx,
 					(unsigned char *)&ebuf, &unused,
@@ -563,8 +664,16 @@
 				goto process_cipher_des3ctr_err;
 			ctr_inc(ctr);
 		}
-		dst[n] = src[n] ^ ebuf[n % 8];
-		n++;
+		dst[n] = *(src++) ^ ebuf[n % 8];
+
+		l--;
+		if (!l) {
+			m = m->next;
+			if (m) {
+				src = rte_pktmbuf_mtod(m, uint8_t *);
+				l = rte_pktmbuf_data_len(m);
+			}
+		}
 	}
 
 	return 0;
@@ -576,9 +685,9 @@
 
 /** Process auth/encription aes-gcm algorithm */
 static int
-process_openssl_auth_encryption_gcm(uint8_t *src, int srclen,
-		uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
-		uint8_t *key, uint8_t *dst,	uint8_t *tag,
+process_openssl_auth_encryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+		int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+		uint8_t *key, uint8_t *dst, uint8_t *tag,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
 	int len = 0, unused = 0;
@@ -593,20 +702,20 @@
 	if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
 		goto process_auth_encryption_gcm_err;
 
-	if (aadlen > 0) {
+	if (aadlen > 0)
 		if (EVP_EncryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
 			goto process_auth_encryption_gcm_err;
 
-		/* Workaround open ssl bug in version less then 1.0.1f */
-		if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
-			goto process_auth_encryption_gcm_err;
-	}
-
 	if (srclen > 0)
-		if (EVP_EncryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+		if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+				srclen, ctx))
 			goto process_auth_encryption_gcm_err;
 
-	if (EVP_EncryptFinal_ex(ctx, dst + len, &len) <= 0)
+	/* Workaround open ssl bug in version less then 1.0.1f */
+	if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+		goto process_auth_encryption_gcm_err;
+
+	if (EVP_EncryptFinal_ex(ctx, dst, &len) <= 0)
 		goto process_auth_encryption_gcm_err;
 
 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) <= 0)
@@ -620,10 +729,10 @@
 }
 
 static int
-process_openssl_auth_decryption_gcm(uint8_t *src, int srclen,
-		uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
-		uint8_t *key, uint8_t *dst, uint8_t *tag,
-		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
+process_openssl_auth_decryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+		int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+		uint8_t *key, uint8_t *dst, uint8_t *tag, EVP_CIPHER_CTX *ctx,
+		const EVP_CIPHER *algo)
 {
 	int len = 0, unused = 0;
 	uint8_t empty[] = {};
@@ -640,20 +749,20 @@
 	if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
 		goto process_auth_decryption_gcm_err;
 
-	if (aadlen > 0) {
+	if (aadlen > 0)
 		if (EVP_DecryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
 			goto process_auth_decryption_gcm_err;
 
-		/* Workaround open ssl bug in version less then 1.0.1f */
-		if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
-			goto process_auth_decryption_gcm_err;
-	}
-
 	if (srclen > 0)
-		if (EVP_DecryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+		if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+				srclen, ctx))
 			goto process_auth_decryption_gcm_err;
 
-	if (EVP_DecryptFinal_ex(ctx, dst + len, &len) <= 0)
+	/* Workaround open ssl bug in version less then 1.0.1f */
+	if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+		goto process_auth_decryption_gcm_err;
+
+	if (EVP_DecryptFinal_ex(ctx, dst, &len) <= 0)
 		goto process_auth_decryption_gcm_final_err;
 
 	return 0;
@@ -668,21 +777,50 @@
 
 /** Process standard openssl auth algorithms */
 static int
-process_openssl_auth(uint8_t *src, uint8_t *dst,
+process_openssl_auth(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
 		__rte_unused uint8_t *iv, __rte_unused EVP_PKEY * pkey,
 		int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
 {
 	size_t dstlen;
+	struct rte_mbuf *m;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_auth_err;
 
 	if (EVP_DigestInit_ex(ctx, algo, NULL) <= 0)
 		goto process_auth_err;
 
-	if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+			goto process_auth_err;
+		goto process_auth_final;
+	}
+
+	if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
 		goto process_auth_err;
 
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
+			goto process_auth_err;
+		n -= l;
+	}
+
+process_auth_final:
 	if (EVP_DigestFinal_ex(ctx, dst, (unsigned int *)&dstlen) <= 0)
 		goto process_auth_err;
-
 	return 0;
 
 process_auth_err:
@@ -692,18 +830,48 @@
 
 /** Process standard openssl auth algorithms with hmac */
 static int
-process_openssl_auth_hmac(uint8_t *src, uint8_t *dst,
+process_openssl_auth_hmac(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
 		__rte_unused uint8_t *iv, EVP_PKEY *pkey,
-		int srclen,	EVP_MD_CTX *ctx, const EVP_MD *algo)
+		int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
 {
 	size_t dstlen;
+	struct rte_mbuf *m;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_auth_err;
 
 	if (EVP_DigestSignInit(ctx, NULL, algo, NULL, pkey) <= 0)
 		goto process_auth_err;
 
-	if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+			goto process_auth_err;
+		goto process_auth_final;
+	}
+
+	if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
 		goto process_auth_err;
 
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
+			goto process_auth_err;
+		n -= l;
+	}
+
+process_auth_final:
 	if (EVP_DigestSignFinal(ctx, dst, &dstlen) <= 0)
 		goto process_auth_err;
 
@@ -723,9 +891,18 @@
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
 	/* cipher */
-	uint8_t *src = NULL, *dst = NULL, *iv, *tag, *aad;
+	uint8_t *dst = NULL, *iv, *tag, *aad;
 	int srclen, ivlen, aadlen, status = -1;
 
+	/*
+	 * Segmented destination buffer is not supported for
+	 * encryption/decryption
+	 */
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return;
+	}
+
 	iv = op->sym->cipher.iv.data;
 	ivlen = op->sym->cipher.iv.length;
 	aad = op->sym->auth.aad.data;
@@ -741,22 +918,22 @@
 		srclen = 0;
 	else {
 		srclen = op->sym->cipher.data.length;
-		src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-				op->sym->cipher.data.offset);
 		dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
 				op->sym->cipher.data.offset);
 	}
 
 	if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
 		status = process_openssl_auth_encryption_gcm(
-				src, srclen, aad, aadlen, iv, ivlen,
-				sess->cipher.key.data, dst, tag,
-				sess->cipher.ctx, sess->cipher.evp_algo);
+				mbuf_src, op->sym->cipher.data.offset, srclen,
+				aad, aadlen, iv, ivlen, sess->cipher.key.data,
+				dst, tag, sess->cipher.ctx,
+				sess->cipher.evp_algo);
 	else
 		status = process_openssl_auth_decryption_gcm(
-				src, srclen, aad, aadlen, iv, ivlen,
-				sess->cipher.key.data, dst, tag,
-				sess->cipher.ctx, sess->cipher.evp_algo);
+				mbuf_src, op->sym->cipher.data.offset, srclen,
+				aad, aadlen, iv, ivlen, sess->cipher.key.data,
+				dst, tag, sess->cipher.ctx,
+				sess->cipher.evp_algo);
 
 	if (status != 0) {
 		if (status == (-EFAULT) &&
@@ -774,12 +951,19 @@
 		(struct rte_crypto_op *op, struct openssl_session *sess,
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
-	uint8_t *src, *dst, *iv;
+	uint8_t *dst, *iv;
 	int srclen, status;
 
+	/*
+	 * Segmented destination buffer is not supported for
+	 * encryption/decryption
+	 */
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return;
+	}
+
 	srclen = op->sym->cipher.data.length;
-	src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-			op->sym->cipher.data.offset);
 	dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
 			op->sym->cipher.data.offset);
 
@@ -787,17 +971,20 @@
 
 	if (sess->cipher.mode == OPENSSL_CIPHER_LIB)
 		if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
-			status = process_openssl_cipher_encrypt(src, dst, iv,
+			status = process_openssl_cipher_encrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
 					sess->cipher.key.data, srclen,
 					sess->cipher.ctx,
 					sess->cipher.evp_algo);
 		else
-			status = process_openssl_cipher_decrypt(src, dst, iv,
+			status = process_openssl_cipher_decrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
 					sess->cipher.key.data, srclen,
 					sess->cipher.ctx,
 					sess->cipher.evp_algo);
 	else
-		status = process_openssl_cipher_des3ctr(src, dst, iv,
+		status = process_openssl_cipher_des3ctr(mbuf_src, dst,
+				op->sym->cipher.data.offset, iv,
 				sess->cipher.key.data, srclen,
 				sess->cipher.ctx);
 
@@ -811,12 +998,10 @@
 		(struct rte_crypto_op *op, struct openssl_session *sess,
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
-	uint8_t *src, *dst;
+	uint8_t *dst;
 	int srclen, status;
 
 	srclen = op->sym->auth.data.length;
-	src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-			op->sym->auth.data.offset);
 
 	if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY)
 		dst = (uint8_t *)rte_pktmbuf_append(mbuf_src,
@@ -831,13 +1016,14 @@
 
 	switch (sess->auth.mode) {
 	case OPENSSL_AUTH_AS_AUTH:
-		status = process_openssl_auth(src, dst,
-				NULL, NULL,	srclen,
+		status = process_openssl_auth(mbuf_src, dst,
+				op->sym->auth.data.offset, NULL, NULL, srclen,
 				sess->auth.auth.ctx, sess->auth.auth.evp_algo);
 		break;
 	case OPENSSL_AUTH_AS_HMAC:
-		status = process_openssl_auth_hmac(src, dst,
-				NULL, sess->auth.hmac.pkey, srclen,
+		status = process_openssl_auth_hmac(mbuf_src, dst,
+				op->sym->auth.data.offset, NULL,
+				sess->auth.hmac.pkey, srclen,
 				sess->auth.hmac.ctx, sess->auth.hmac.evp_algo);
 		break;
 	default:
@@ -851,8 +1037,7 @@
 			op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
 		}
 		/* Trim area used for digest from mbuf. */
-		rte_pktmbuf_trim(mbuf_src,
-				op->sym->auth.digest.length);
+		rte_pktmbuf_trim(mbuf_src, op->sym->auth.digest.length);
 	}
 
 	if (status != 0)
@@ -903,7 +1088,6 @@
 		op->sym->session = NULL;
 	}
 
-
 	if (op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)
 		op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
 
@@ -997,7 +1181,8 @@
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
-			RTE_CRYPTODEV_FF_CPU_AESNI;
+			RTE_CRYPTODEV_FF_CPU_AESNI |
+			RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
 
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
-- 
1.7.9.5

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

* [PATCH v3 5/5] test: add sgl unit tests for crypto devices
  2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
                       ` (3 preceding siblings ...)
  2017-01-05  9:12     ` [PATCH v3 4/5] crypto: add sgl support in openssl PMD Tomasz Kulasek
@ 2017-01-05  9:12     ` Tomasz Kulasek
  2017-01-05 16:44     ` [PATCH v4] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
  2017-01-05 16:46     ` [PATCH v4 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
  6 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05  9:12 UTC (permalink / raw)
  To: dev; +Cc: Daniel Mrzyglod

This patch provides unit tests for set of cipher/hash combinations covering
currently implemented crypto PMD's and allowing to verify scatter gather
support.

Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_cryptodev.c                  |  386 ++++++++++++++++++-
 app/test/test_cryptodev.h                  |  139 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   52 +++
 app/test/test_cryptodev_blockcipher.c      |  180 +++++----
 app/test/test_cryptodev_blockcipher.h      |    1 +
 app/test/test_cryptodev_gcm_test_vectors.h |  553 ++++++++++++++++++++++++++++
 6 files changed, 1241 insertions(+), 70 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 3eaf1b7..4c9a54f 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -1736,6 +1736,10 @@ struct crypto_unittest_params {
 
 	TEST_ASSERT_NOT_NULL(sym_op->cipher.iv.data, "no room to prepend iv");
 
+	/* For OOP operation both buffers must have the same size */
+	if (ut_params->obuf)
+		rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+
 	memset(sym_op->cipher.iv.data, 0, iv_pad_len);
 	sym_op->cipher.iv.phys_addr = rte_pktmbuf_mtophys(ut_params->ibuf);
 	sym_op->cipher.iv.length = iv_pad_len;
@@ -2557,6 +2561,83 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+		/* Validate obuf */
+		TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+			ciphertext,
+			tdata->ciphertext.data,
+			tdata->validCipherLenInBits.len,
+			"KASUMI Ciphertext data not as expected");
+		return 0;
+}
+
+static int
 test_kasumi_encryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2625,6 +2706,81 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_oop_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+
+	const uint8_t *ciphertext;
+	uint8_t buffer[2048];
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"KASUMI Ciphertext data not as expected");
+	return 0;
+}
+
+
+static int
 test_kasumi_decryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2897,6 +3053,85 @@ struct crypto_unittest_params {
 	return 0;
 }
 
+static int
+test_snow3g_encryption_oop_sgl(const struct snow3g_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create SNOW 3G session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple of */
+	/* the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3);
+
+	TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+			"Failed to allocate input buffer in mempool");
+	TEST_ASSERT_NOT_NULL(ut_params->obuf,
+			"Failed to allocate output buffer in mempool");
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create SNOW 3G operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->validCipherLenInBits.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validDataLenInBits.len,
+		"SNOW 3G Ciphertext data not as expected");
+
+	return 0;
+}
+
 /* Shift right a buffer by "offset" bits, "offset" < 8 */
 static void
 buffer_shift_right(uint8_t *buffer, uint32_t length, uint8_t offset)
@@ -3552,6 +3787,84 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_sgl(const struct zuc_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+	const uint8_t *ciphertext;
+	uint8_t ciphertext_buffer[2048];
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+			tdata->plaintext.data);
+
+	/* Create ZUC session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3,
+			tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	/* Clear mbuf payload */
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create ZUC operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+			tdata->iv.len, tdata->plaintext.len,
+			tdata->validCipherOffsetLenInBits.len,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"ZUC Ciphertext data not as expected");
+
+	return 0;
+}
+
+static int
 test_zuc_authentication(const struct zuc_hash_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -3619,12 +3932,24 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_kasumi_encryption_test_case_1_sgl(void)
+{
+	return test_kasumi_encryption_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_1_oop(void)
 {
 	return test_kasumi_encryption_oop(&kasumi_test_case_1);
 }
 
 static int
+test_kasumi_encryption_test_case_1_oop_sgl(void)
+{
+	return test_kasumi_encryption_oop_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_2(void)
 {
 	return test_kasumi_encryption(&kasumi_test_case_2);
@@ -3696,6 +4021,13 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_snow3g_encryption_test_case_1_oop_sgl(void)
+{
+	return test_snow3g_encryption_oop_sgl(&snow3g_test_case_1);
+}
+
+
+static int
 test_snow3g_encryption_test_case_1_offset_oop(void)
 {
 	return test_snow3g_encryption_offset_oop(&snow3g_test_case_1);
@@ -3815,6 +4147,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_test_case_6_sgl(void)
+{
+	return test_zuc_encryption_sgl(&zuc_test_case_1);
+}
+
+static int
 test_zuc_hash_generate_test_case_1(void)
 {
 	return test_zuc_authentication(&zuc_hash_test_case_1);
@@ -3998,12 +4336,21 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 
 	struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
 
-	sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
-			ut_params->ibuf, auth_tag_len);
-	TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
-			"no room to append digest");
-	sym_op->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
-			ut_params->ibuf, data_pad_len);
+	if (ut_params->obuf) {
+		sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+				ut_params->obuf, auth_tag_len);
+		TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+				"no room to append digest");
+		sym_op->auth.digest.phys_addr = sgl_pktmbuf_mtophys_offset(
+				ut_params->obuf, data_pad_len);
+	} else {
+		sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+				ut_params->ibuf, auth_tag_len);
+		TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+				"no room to append digest");
+		sym_op->auth.digest.phys_addr = sgl_pktmbuf_mtophys_offset(
+				ut_params->ibuf, data_pad_len);
+	}
 	sym_op->auth.digest.length = auth_tag_len;
 
 	if (op == RTE_CRYPTO_CIPHER_OP_DECRYPT) {
@@ -4050,6 +4397,11 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 	TEST_HEXDUMP(stdout, "aad:",
 			sym_op->auth.aad.data, aad_len);
 
+	if (ut_params->obuf) {
+		rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+		rte_pktmbuf_prepend(ut_params->obuf, aad_buffer_len);
+	}
+
 	sym_op->cipher.data.length = data_len;
 	sym_op->cipher.data.offset = aad_buffer_len + iv_pad_len;
 
@@ -6312,6 +6664,14 @@ struct test_crypto_vector {
 }
 
 static int
+test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_1seg(void)
+{
+	return test_AES_GCM_authenticated_encryption_SGL(
+			&gcm_test_case_8, OUT_OF_PLACE, 400,
+			gcm_test_case_8.plaintext.len);
+}
+
+static int
 test_AES_GCM_auth_encrypt_SGL_in_place_1500B(void)
 {
 
@@ -6683,6 +7043,10 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_AES_GMAC_authentication_verify_test_case_4),
 
+		/** Scatter-Gather */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_1seg),
+
 		/** Negative tests */
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			authentication_verify_HMAC_SHA1_fail_data_corrupt),
@@ -6751,6 +7115,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_2),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_3),
@@ -6773,6 +7139,10 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_oop_sgl),
+
+
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_decryption_test_case_1_oop),
 
 		/** KASUMI hash only (UIA1) */
@@ -6825,6 +7195,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_snow3g_encryption_test_case_1_oop_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_decryption_test_case_1_oop),
 
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6902,6 +7274,8 @@ struct test_crypto_vector {
 			test_zuc_hash_generate_test_case_4),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_zuc_hash_generate_test_case_5),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_zuc_encryption_test_case_6_sgl),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
 };
diff --git a/app/test/test_cryptodev.h b/app/test/test_cryptodev.h
index a9089aa..77cd826 100644
--- a/app/test/test_cryptodev.h
+++ b/app/test/test_cryptodev.h
@@ -71,4 +71,143 @@
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA384		(24)
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA512		(32)
 
+/**
+ * Write (spread) data from buffer to mbuf data
+ *
+ * @param mbuf
+ *   Destination mbuf
+ * @param offset
+ *   Start offset in mbuf
+ * @param len
+ *   Number of bytes to copy
+ * @param buffer
+ *   Continuous source buffer
+ */
+static inline void
+pktmbuf_write(struct rte_mbuf *mbuf, int offset, int len, const uint8_t *buffer)
+{
+	int n = len;
+	int l;
+	struct rte_mbuf *m;
+	char *dst;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	l = m->data_len - offset;
+
+	/* copy data from first segment */
+	dst = rte_pktmbuf_mtod_offset(m, char *, offset);
+	if (len <= l) {
+		rte_memcpy(dst, buffer, len);
+		return;
+	}
+
+	rte_memcpy(dst, buffer, l);
+	buffer += l;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		dst = rte_pktmbuf_mtod(m, char *);
+		l = m->data_len;
+		if (n < l) {
+			rte_memcpy(dst, buffer, n);
+			return;
+		}
+		rte_memcpy(dst, buffer, l);
+		buffer += l;
+		n -= l;
+	}
+}
+
+static inline uint8_t *
+sgl_pktmbuf_mtod_offset(struct rte_mbuf *mbuf, int offset) {
+	struct rte_mbuf *m;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	if (!m) {
+		printf("sgl_pktmbuf_mtod_offset: offset out of buffer\n");
+		return NULL;
+	}
+	return rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+}
+
+static inline phys_addr_t
+sgl_pktmbuf_mtophys_offset(struct rte_mbuf *mbuf, int offset) {
+	struct rte_mbuf *m;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	if (!m) {
+		printf("sgl_pktmbuf_mtophys_offset: offset out of buffer\n");
+		return 0;
+	}
+	return rte_pktmbuf_mtophys_offset(m, offset);
+}
+
+static inline struct rte_mbuf *
+create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
+		int nb_segs) {
+
+	struct rte_mbuf *m = NULL, *mbuf = NULL;
+	uint8_t *dst;
+	int data_len = 0;
+	int i, size;
+	int t_len;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return NULL;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return NULL;
+	}
+
+	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+	size = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (i = 0; size > 0; i++) {
+
+		m = rte_pktmbuf_alloc(mbuf_pool);
+		if (i == 0)
+			mbuf = m;
+
+		if (!m) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+				rte_pktmbuf_tailroom(m));
+
+		data_len = size > t_len ? t_len : size;
+		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (!dst) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		if (mbuf != m)
+			rte_pktmbuf_chain(mbuf, m);
+
+		size -= data_len;
+
+	}
+	return mbuf;
+
+fail:
+	if (mbuf)
+		rte_pktmbuf_free(mbuf);
+	return NULL;
+}
+
 #endif /* TEST_CRYPTODEV_H_ */
diff --git a/app/test/test_cryptodev_aes_test_vectors.h b/app/test/test_cryptodev_aes_test_vectors.h
index 898aae1..e566548 100644
--- a/app/test/test_cryptodev_aes_test_vectors.h
+++ b/app/test/test_cryptodev_aes_test_vectors.h
@@ -858,6 +858,16 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-192-CTR XCBC Decryption Digest Verify "
+				"Scatter Gather",
+		.test_data = &aes_test_data_2,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "AES-256-CTR HMAC-SHA1 Encryption Digest",
 		.test_data = &aes_test_data_3,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -883,6 +893,18 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+				"Scatter Gather",
+		.test_data = &aes_test_data_4,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_4,
@@ -926,6 +948,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest "
+				"Scatter Gather Sessionless",
+		.test_data = &aes_test_data_6,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS |
+			BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_6,
@@ -935,6 +968,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
+			"Verify Scatter Gather",
+		.test_data = &aes_test_data_6,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "AES-128-CBC XCBC Encryption Digest",
 		.test_data = &aes_test_data_7,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -1045,6 +1089,14 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_MB
 	},
 	{
+		.test_descr = "AES-192-CBC Encryption Scater gather",
+		.test_data = &aes_test_data_10,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
 		.test_descr = "AES-192-CBC Decryption",
 		.test_data = &aes_test_data_10,
 		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
diff --git a/app/test/test_cryptodev_blockcipher.c b/app/test/test_cryptodev_blockcipher.c
index 03dd073..2290c66 100644
--- a/app/test/test_cryptodev_blockcipher.c
+++ b/app/test/test_cryptodev_blockcipher.c
@@ -41,6 +41,7 @@
 #include <rte_cryptodev_pmd.h>
 
 #include "test.h"
+#include "test_cryptodev.h"
 #include "test_cryptodev_blockcipher.h"
 #include "test_cryptodev_aes_test_vectors.h"
 #include "test_cryptodev_des_test_vectors.h"
@@ -63,6 +64,7 @@
 	struct rte_crypto_sym_op *sym_op = NULL;
 	struct rte_crypto_op *op = NULL;
 	struct rte_cryptodev_sym_session *sess = NULL;
+	struct rte_cryptodev_info dev_info;
 
 	int status = TEST_SUCCESS;
 	const struct blockcipher_test_data *tdata = t->test_data;
@@ -72,6 +74,19 @@
 	uint32_t digest_len = 0;
 	char *buf_p = NULL;
 
+	int nb_segs = 3;
+	int nb_segs_oop = 1;
+
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+		rte_cryptodev_info_get(dev_id, &dev_info);
+		if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+			printf("Device doesn't support scatter-gather. "
+					"Test Skipped.\n");
+			return 0;
+		}
+	}
+
 	if (tdata->cipher_key.len)
 		memcpy(cipher_key, tdata->cipher_key.data,
 			tdata->cipher_key.len);
@@ -96,72 +111,112 @@
 	}
 
 	/* preparing data */
-	ibuf = rte_pktmbuf_alloc(mbuf_pool);
-	if (!ibuf) {
-		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-			"line %u FAILED: %s",
-			__LINE__, "Allocation of rte_mbuf failed");
-		status = TEST_FAILED;
-		goto error_exit;
-	}
 
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
 		buf_len += tdata->iv.len;
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
 		buf_len += digest_len;
 
-	buf_p = rte_pktmbuf_append(ibuf, buf_len);
-	if (!buf_p) {
-		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-			"line %u FAILED: %s",
-			__LINE__, "No room to append mbuf");
-		status = TEST_FAILED;
-		goto error_exit;
-	}
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
 
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
-		buf_p += tdata->iv.len;
-	}
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+			ibuf = create_segmented_mbuf(mbuf_pool,
+					tdata->plaintext.len, nb_segs);
+			pktmbuf_write(ibuf, 0, tdata->plaintext.len,
+					tdata->plaintext.data);
+		} else {
+			ibuf = create_segmented_mbuf(mbuf_pool,
+					tdata->ciphertext.len, nb_segs);
+			pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
+					tdata->ciphertext.data);
+		}
 
-	/* only encryption requires plaintext.data input,
-	 * decryption/(digest gen)/(digest verify) use ciphertext.data
-	 * to be computed
-	 */
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
-		rte_memcpy(buf_p, tdata->plaintext.data,
-			tdata->plaintext.len);
-		buf_p += tdata->plaintext.len;
-	} else {
-		rte_memcpy(buf_p, tdata->ciphertext.data,
-			tdata->ciphertext.len);
-		buf_p += tdata->ciphertext.len;
-	}
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+			rte_memcpy(rte_pktmbuf_prepend(ibuf, tdata->iv.len),
+					tdata->iv.data, tdata->iv.len);
+		}
 
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
-		rte_memcpy(buf_p, tdata->digest.data, digest_len);
-	else
-		memset(buf_p, 0, digest_len);
+		buf_p = rte_pktmbuf_append(ibuf, digest_len);
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+			rte_memcpy(buf_p, tdata->digest.data, digest_len);
+		else
+			memset(buf_p, 0, digest_len);
 
-	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
-		obuf = rte_pktmbuf_alloc(mbuf_pool);
-		if (!obuf) {
-			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-				"FAILED: %s", __LINE__,
-				"Allocation of rte_mbuf failed");
+	} else {
+		ibuf = rte_pktmbuf_alloc(mbuf_pool);
+		if (!ibuf) {
+			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+					"line %u FAILED: %s",
+					__LINE__,
+					"Allocation of rte_mbuf failed");
 			status = TEST_FAILED;
 			goto error_exit;
 		}
 
-		buf_p = rte_pktmbuf_append(obuf, buf_len);
+		buf_p = rte_pktmbuf_append(ibuf, buf_len);
 		if (!buf_p) {
-			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-				"FAILED: %s", __LINE__,
-				"No room to append mbuf");
+			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+					"line %u FAILED: %s",
+					__LINE__, "No room to append mbuf");
 			status = TEST_FAILED;
 			goto error_exit;
 		}
-		memset(buf_p, 0, buf_len);
+
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+			rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
+			buf_p += tdata->iv.len;
+		}
+
+		/* only encryption requires plaintext.data input,
+		 * decryption/(digest gen)/(digest verify) use ciphertext.data
+		 * to be computed
+		 */
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+			rte_memcpy(buf_p, tdata->plaintext.data,
+					tdata->plaintext.len);
+			buf_p += tdata->plaintext.len;
+		} else {
+			rte_memcpy(buf_p, tdata->ciphertext.data,
+					tdata->ciphertext.len);
+			buf_p += tdata->ciphertext.len;
+		}
+
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+			rte_memcpy(buf_p, tdata->digest.data, digest_len);
+		else
+			memset(buf_p, 0, digest_len);
+	}
+
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+			obuf = create_segmented_mbuf(mbuf_pool, buf_len,
+					nb_segs_oop);
+			if (!obuf) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"Allocation of rte_mbuf failed");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+		} else {
+			obuf = rte_pktmbuf_alloc(mbuf_pool);
+			if (!obuf) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"Allocation of rte_mbuf failed");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+			buf_p = rte_pktmbuf_append(obuf, buf_len);
+			if (!buf_p) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"No room to append mbuf");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+			memset(buf_p, 0, buf_len);
+		}
 	}
 
 	/* Generate Crypto op data structure */
@@ -307,17 +362,17 @@
 
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
-			sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
-				(iobuf, uint8_t *, digest_offset);
+			sym_op->auth.digest.data = sgl_pktmbuf_mtod_offset
+				(iobuf, digest_offset);
 			sym_op->auth.digest.phys_addr =
-				rte_pktmbuf_mtophys_offset(iobuf,
+				sgl_pktmbuf_mtophys_offset(iobuf,
 					digest_offset);
 		} else {
 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
-			sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
-				(sym_op->m_src, uint8_t *, digest_offset);
+			sym_op->auth.digest.data = sgl_pktmbuf_mtod_offset
+				(sym_op->m_src, digest_offset);
 			sym_op->auth.digest.phys_addr =
-				rte_pktmbuf_mtophys_offset(sym_op->m_src,
+				sgl_pktmbuf_mtophys_offset(sym_op->m_src,
 					digest_offset);
 		}
 
@@ -386,13 +441,10 @@
 	}
 
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		uint8_t *crypto_res;
+		uint8_t buffer[2048];
 		const uint8_t *compare_ref;
 		uint32_t compare_len;
 
-		crypto_res = rte_pktmbuf_mtod_offset(iobuf, uint8_t *,
-			tdata->iv.len);
-
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
 			compare_ref = tdata->ciphertext.data;
 			compare_len = tdata->ciphertext.len;
@@ -401,7 +453,8 @@
 			compare_len = tdata->plaintext.len;
 		}
 
-		if (memcmp(crypto_res, compare_ref, compare_len)) {
+		if (memcmp(rte_pktmbuf_read(iobuf, tdata->iv.len, compare_len,
+				buffer), compare_ref, compare_len)) {
 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
 				"FAILED: %s", __LINE__,
 				"Crypto data not as expected");
@@ -414,12 +467,11 @@
 		uint8_t *auth_res;
 
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
-			auth_res = rte_pktmbuf_mtod_offset(iobuf,
-				uint8_t *,
-				tdata->iv.len + tdata->ciphertext.len);
+			auth_res = sgl_pktmbuf_mtod_offset(iobuf,
+					tdata->iv.len + tdata->ciphertext.len);
 		else
-			auth_res = rte_pktmbuf_mtod_offset(iobuf,
-				uint8_t *, tdata->ciphertext.len);
+			auth_res = sgl_pktmbuf_mtod_offset(iobuf,
+					tdata->ciphertext.len);
 
 		if (memcmp(auth_res, tdata->digest.data, digest_len)) {
 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
diff --git a/app/test/test_cryptodev_blockcipher.h b/app/test/test_cryptodev_blockcipher.h
index fe97e4c..7256f6b 100644
--- a/app/test/test_cryptodev_blockcipher.h
+++ b/app/test/test_cryptodev_blockcipher.h
@@ -45,6 +45,7 @@
 #define BLOCKCIPHER_TEST_FEATURE_OOP			0x01
 #define BLOCKCIPHER_TEST_FEATURE_SESSIONLESS	0x02
 #define BLOCKCIPHER_TEST_FEATURE_STOPPER	0x04 /* stop upon failing */
+#define BLOCKCIPHER_TEST_FEATURE_SG		0x08 /* Scatter Gather */
 
 #define BLOCKCIPHER_TEST_TARGET_PMD_MB		0x0001 /* Multi-buffer flag */
 #define BLOCKCIPHER_TEST_TARGET_PMD_QAT			0x0002 /* QAT flag */
diff --git a/app/test/test_cryptodev_gcm_test_vectors.h b/app/test/test_cryptodev_gcm_test_vectors.h
index df984fc..45ea3d4 100644
--- a/app/test/test_cryptodev_gcm_test_vectors.h
+++ b/app/test/test_cryptodev_gcm_test_vectors.h
@@ -450,6 +450,559 @@ struct gmac_test_data {
 	}
 };
 
+static const struct gcm_test_data gcm_test_case_8 = {
+	.key = {
+		.data = {
+			0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+			0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+			0xde, 0xca, 0xf8, 0x88
+		},
+		.len = 12
+	},
+	.aad = {
+		.data = {
+			0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+			0xfe, 0xed, 0xfa, 0xce
+		},
+		.len = 12
+	},
+	.plaintext = {
+		.data = {
+			0xC5, 0x34, 0x2E, 0x83, 0xEB, 0x4C, 0x02, 0x03,
+			0xF7, 0xB2, 0x57, 0x35, 0x26, 0x81, 0x63, 0xAE,
+			0x1F, 0xCD, 0x2D, 0x02, 0x91, 0x5A, 0xDB, 0x3A,
+			0xF1, 0x38, 0xD8, 0x75, 0x86, 0x20, 0xCC, 0x1E,
+			0xE6, 0xDC, 0xFF, 0xB5, 0xEA, 0x0E, 0x18, 0x7A,
+			0x86, 0x6C, 0xAB, 0x39, 0x2D, 0x90, 0xAC, 0x77,
+			0x5D, 0xED, 0x65, 0xB3, 0x05, 0x29, 0xBB, 0x09,
+			0xD0, 0x21, 0x74, 0x6A, 0x67, 0x1C, 0x95, 0x42,
+			0x55, 0xAD, 0xC8, 0x91, 0x28, 0xFE, 0x16, 0x9A,
+			0xE1, 0xCB, 0xCD, 0x68, 0x3B, 0xDF, 0x3E, 0x3A,
+			0x34, 0xFE, 0x9B, 0xFB, 0xF5, 0x15, 0x2A, 0x29,
+			0x18, 0x99, 0x24, 0xBF, 0xB6, 0x43, 0xDB, 0xD1,
+			0x69, 0x26, 0x1E, 0x31, 0x2C, 0x8C, 0x3C, 0x6B,
+			0x7F, 0x06, 0xA6, 0x03, 0xE2, 0x1A, 0x50, 0xFE,
+			0x7C, 0x69, 0xE5, 0x5F, 0x35, 0x93, 0xE9, 0x20,
+			0x14, 0xB1, 0xCA, 0x61, 0xE7, 0x9C, 0x89, 0x08,
+			0xD6, 0xB1, 0xC2, 0x63, 0x1B, 0x86, 0x5E, 0xF1,
+			0xF5, 0x23, 0x0E, 0x9B, 0xE5, 0xBD, 0x5D, 0x04,
+			0xF7, 0xEF, 0x8E, 0x46, 0xB0, 0x11, 0x4F, 0x69,
+			0x62, 0x35, 0x51, 0xB7, 0x24, 0xA2, 0x31, 0xD0,
+			0x32, 0x4E, 0xB8, 0x44, 0xC7, 0x59, 0xDE, 0x25,
+			0xEA, 0x2D, 0x00, 0x0E, 0xF1, 0x07, 0xBA, 0xBB,
+			0x9A, 0xBC, 0x4F, 0x57, 0xB7, 0x13, 0x57, 0xEF,
+			0xD9, 0xF6, 0x80, 0x69, 0xEA, 0xE8, 0x47, 0x9C,
+			0x51, 0x71, 0xE6, 0x8F, 0x69, 0x29, 0xB4, 0x60,
+			0xE8, 0x50, 0xE5, 0xD0, 0x9B, 0xD2, 0x62, 0x6F,
+			0x09, 0x5C, 0xD1, 0x4B, 0x85, 0xE2, 0xFD, 0xD3,
+			0xEB, 0x28, 0x55, 0x77, 0x97, 0xCA, 0xD6, 0xA8,
+			0xDC, 0x35, 0x68, 0xF7, 0x6A, 0xCF, 0x48, 0x3F,
+			0x49, 0x31, 0x00, 0x65, 0xB7, 0x31, 0x1A, 0x49,
+			0x75, 0xDE, 0xCE, 0x7F, 0x18, 0xB5, 0x31, 0x9A,
+			0x64, 0x6D, 0xE5, 0x49, 0x1D, 0x6D, 0xF2, 0x21,
+			0x9F, 0xF5, 0xFF, 0x7C, 0x41, 0x30, 0x33, 0x06,
+			0x7B, 0xA4, 0xD8, 0x99, 0xF6, 0xCC, 0xDF, 0xC4,
+			0x3F, 0xF3, 0xCD, 0xE7, 0x74, 0xC4, 0x4A, 0x19,
+			0x5C, 0xCA, 0x42, 0x31, 0xF1, 0x3B, 0x65, 0x1C,
+			0x3D, 0x56, 0x08, 0xBE, 0x15, 0x37, 0x23, 0x50,
+			0xD6, 0xA3, 0x57, 0x64, 0x25, 0xBE, 0xDA, 0xC2,
+			0x4E, 0xF5, 0x1A, 0xAD, 0x6F, 0x43, 0x78, 0x21,
+			0xF9, 0x36, 0x39, 0x1F, 0x5F, 0xF7, 0x1B, 0xA0,
+			0xEE, 0x8B, 0x4F, 0x8A, 0x9D, 0xD8, 0xED, 0x37,
+			0xCE, 0x0D, 0x70, 0xE0, 0x3F, 0xE7, 0x11, 0x30,
+			0x17, 0x1D, 0x03, 0x5E, 0xA0, 0x3D, 0x3F, 0x9E,
+			0xF5, 0xD3, 0x74, 0x2E, 0xC1, 0xD6, 0xFF, 0xF7,
+			0x2E, 0xE7, 0x80, 0x88, 0xCF, 0x0E, 0x7F, 0x12,
+			0x71, 0x62, 0xC7, 0xF1, 0xC4, 0x2B, 0x64, 0x5D,
+			0x1C, 0x9A, 0xB4, 0xCB, 0xB8, 0x24, 0xB3, 0x0B,
+			0x33, 0xF2, 0x8A, 0x8F, 0x76, 0xC8, 0x81, 0xDA,
+			0x1A, 0x10, 0xB5, 0xA9, 0xCD, 0xDC, 0x1A, 0x02,
+			0xC1, 0xAE, 0x4F, 0x02, 0x1B, 0x13, 0x96, 0x5A,
+			0x2E, 0x03, 0xA2, 0x68, 0xB2, 0x29, 0xAC, 0x28,
+			0xB8, 0xDC, 0xD5, 0x27, 0x55, 0xEC, 0x43, 0xDC,
+			0xB7, 0x49, 0x1D, 0xE1, 0x30, 0x25, 0x81, 0xA6,
+			0x90, 0x1F, 0x75, 0xBA, 0x19, 0x1E, 0xF7, 0xC5,
+			0x77, 0x35, 0xEE, 0x68, 0x71, 0x22, 0xA0, 0xB4,
+			0xCC, 0x99, 0x86, 0x1B, 0x1B, 0xC8, 0x27, 0xFC,
+			0x6D, 0x8D, 0xE7, 0x8B, 0xC3, 0x40, 0x3D, 0xA8,
+			0xCB, 0x9B, 0xC4, 0x12, 0x07, 0xDD, 0xA1, 0x92,
+			0xE5, 0x80, 0x7A, 0xF4, 0xDB, 0x4C, 0xE6, 0xEE,
+			0xF9, 0xD5, 0x1C, 0x20, 0x18, 0xD3, 0x8F, 0xDF,
+			0x1C, 0xD3, 0x51, 0x4E, 0x0E, 0xED, 0x06, 0x61,
+			0xF7, 0xBA, 0x81, 0x3A, 0x2F, 0xEA, 0xED, 0x70,
+			0xA9, 0xD9, 0x54, 0x4D, 0xFC, 0x1D, 0x19, 0xEA,
+			0xA6, 0x39, 0x8C, 0x6C, 0x78, 0xA8, 0x05, 0xEB,
+			0xF2, 0xB5, 0xDE, 0x06, 0x9D, 0x8A, 0x78, 0x2A,
+			0xF5, 0x50, 0xA4, 0xBD, 0x9B, 0xDA, 0xCA, 0x66,
+			0xC0, 0x23, 0xAB, 0xE8, 0x95, 0x7E, 0xC9, 0xD2,
+			0x6F, 0x09, 0xF2, 0x9A, 0x17, 0x89, 0xDA, 0x47,
+			0x65, 0x8C, 0x20, 0xFA, 0x4E, 0x86, 0x18, 0xEB,
+			0x7C, 0x08, 0xEC, 0x8A, 0x05, 0x54, 0x96, 0xD2,
+			0x7A, 0x8A, 0x81, 0x58, 0x75, 0x8C, 0x7B, 0x02,
+			0xEE, 0x1F, 0x51, 0x88, 0xD0, 0xD1, 0x90, 0x99,
+			0x0C, 0xAE, 0x51, 0x2E, 0x54, 0x3E, 0xB1, 0x7D,
+			0xBC, 0xE8, 0x54, 0x93, 0x6D, 0x10, 0x3C, 0xC6,
+			0x71, 0xF6, 0xF5, 0x0B, 0x07, 0x0A, 0x6E, 0x59,
+			0x20, 0x45, 0x21, 0x7D, 0x37, 0x64, 0x92, 0x09,
+			0xA7, 0xE2, 0x34, 0x6F, 0xFC, 0xCC, 0x66, 0x0E,
+			0x88, 0x1B, 0x19, 0x86, 0x11, 0xD7, 0x81, 0x25,
+			0xF1, 0x8A, 0x03, 0xB7, 0x7A, 0xF0, 0x98, 0x4A,
+			0x5C, 0xA1, 0x6D, 0x85, 0xA4, 0x8C, 0x4B, 0x65,
+			0x9F, 0x72, 0x64, 0x14, 0xBA, 0x74, 0xEE, 0xA3,
+			0x88, 0xFE, 0x1B, 0xCF, 0x11, 0x4F, 0xD1, 0xAC,
+			0xFA, 0x14, 0xC3, 0xA7, 0xDD, 0x06, 0x85, 0x4E,
+			0x64, 0x06, 0x92, 0x9C, 0xDF, 0x06, 0x09, 0xF1,
+			0x4D, 0xE8, 0xF8, 0x2F, 0x69, 0xB6, 0x8A, 0xAF,
+			0x25, 0x21, 0xB5, 0x48, 0x59, 0xF8, 0x9D, 0x60,
+			0xAE, 0x42, 0x11, 0x7A, 0x68, 0x4D, 0x7E, 0x76,
+			0xB0, 0xD2, 0xE3, 0xD9, 0x24, 0x16, 0x20, 0x0A,
+			0xEB, 0xE0, 0x68, 0xCB, 0xBC, 0xAB, 0x67, 0xE4,
+			0xF3, 0x25, 0x1F, 0xD3, 0x85, 0xA7, 0x1D, 0x7E,
+			0x3C, 0x63, 0xCB, 0xC2, 0x50, 0x90, 0x0F, 0x4B,
+			0x6E, 0x68, 0x06, 0x84, 0x65, 0xF7, 0xD0, 0xD4,
+			0x12, 0xED, 0xFA, 0xC9, 0x40, 0xE2, 0xC0, 0xC9,
+			0x46, 0x22, 0x47, 0x5E, 0x6D, 0xC1, 0x63, 0xDB,
+			0x51, 0x98, 0xDA, 0x1A, 0xC4, 0xB9, 0xED, 0xE9,
+			0x09, 0xB9, 0xCF, 0x91, 0x04, 0x1C, 0x63, 0xD8,
+			0xC5, 0xA5, 0xAE, 0x53, 0x7B, 0xA1, 0x29, 0x83,
+			0x37, 0xFB, 0xBF, 0x96, 0xBB, 0x24, 0x3D, 0x77,
+			0x8C, 0x0F, 0xB3, 0x4B, 0x66, 0x9C, 0x54, 0xBB,
+			0xF6, 0xDD, 0xD1, 0xB4, 0xD2, 0xF6, 0xAA, 0xED,
+			0x18, 0x56, 0x63, 0x3E, 0x0B, 0xCA, 0xAB, 0x70,
+			0xBB, 0x63, 0xEA, 0xB1, 0x00, 0x65, 0x90, 0x18,
+			0xB8, 0x63, 0xA2, 0xF2, 0xB6, 0x1E, 0x61, 0x7B,
+			0xD5, 0x01, 0xD9, 0x4D, 0xC9, 0x9D, 0x99, 0xC1,
+			0x57, 0x9D, 0x6F, 0xAE, 0x64, 0xE4, 0x0C, 0x7E,
+			0xFA, 0x15, 0x5E, 0xB6, 0x43, 0xB8, 0x8B, 0x89,
+			0x87, 0xCD, 0x4F, 0xAD, 0x30, 0x1E, 0xA5, 0x03,
+			0x7A, 0xC2, 0x10, 0x42, 0x14, 0x88, 0xD6, 0x7A,
+			0x6D, 0x56, 0x52, 0x2E, 0x8D, 0x1B, 0x5D, 0x36,
+			0x27, 0xA0, 0x21, 0x4B, 0x64, 0xF0, 0xC5, 0x41,
+			0xAD, 0x05, 0x4A, 0x24, 0xE4, 0x70, 0x88, 0x63,
+			0x12, 0xD0, 0xBC, 0x05, 0x38, 0xD9, 0x41, 0x68,
+			0x9F, 0x16, 0x9A, 0x54, 0x09, 0x21, 0x64, 0x36,
+			0x63, 0x97, 0x3A, 0xB5, 0xE0, 0x25, 0x43, 0x8A,
+			0x6A, 0x59, 0x97, 0xC1, 0x31, 0xA5, 0x66, 0xD2,
+			0xF0, 0x1C, 0xDF, 0x97, 0x51, 0xD0, 0x61, 0xBA,
+			0x55, 0x5F, 0xD7, 0x0D, 0xD4, 0x75, 0x8E, 0x79,
+			0x04, 0x75, 0x00, 0xB9, 0xC0, 0x7A, 0x66, 0x05,
+			0x9F, 0x2B, 0x44, 0x42, 0x75, 0x0F, 0xD5, 0x15,
+			0xD6, 0x16, 0x8F, 0x6C, 0x6E, 0xD4, 0x37, 0xCF,
+			0xB4, 0xDA, 0x93, 0x00, 0x11, 0xFB, 0xBE, 0xEE,
+			0x3B, 0x6D, 0x1D, 0xBA, 0x33, 0xD1, 0x52, 0x8B,
+			0x16, 0x39, 0x42, 0x27, 0xE6, 0x56, 0x4C, 0x41,
+			0x91, 0xB0, 0x98, 0xAE, 0x9B, 0x2D, 0x9B, 0x23,
+			0x80, 0x4C, 0xEA, 0x98, 0x57, 0x95, 0x28, 0x94,
+			0x43, 0xD3, 0x88, 0x12, 0xDF, 0x89, 0x5A, 0x7B,
+			0xC5, 0xCB, 0x36, 0x54, 0x65, 0x74, 0xB8, 0x4E,
+			0xE2, 0x4D, 0x01, 0xD5, 0x9C, 0x82, 0xB9, 0x1A,
+			0x09, 0xD2, 0xCE, 0x04, 0x36, 0xD8, 0x41, 0xAC,
+			0x4C, 0xAD, 0xC6, 0x52, 0x91, 0x1A, 0x06, 0x6D,
+			0xFC, 0xAB, 0x29, 0x93, 0x87, 0x88, 0xB9, 0x8C,
+			0xFA, 0x57, 0x2B, 0x05, 0x03, 0xD0, 0x18, 0xED,
+			0x7A, 0x7B, 0x81, 0x6A, 0x97, 0x65, 0x5B, 0x90,
+			0xDE, 0xA9, 0xFC, 0x8F, 0xFC, 0xBB, 0x98, 0xD8,
+			0xFA, 0x32, 0x3F, 0x3F, 0x7F, 0x74, 0x65, 0x38,
+			0xC4, 0x28, 0xEC, 0x27, 0x1F, 0x28, 0x01, 0xB1,
+			0xAF, 0x2B, 0x8A, 0x05, 0x38, 0x7B, 0x77, 0xC9,
+			0x61, 0x77, 0x34, 0x2C, 0x22, 0xE5, 0xEB, 0xDC,
+			0x9D, 0x18, 0x6E, 0x23, 0x25, 0x52, 0x69, 0xB7,
+			0x05, 0xDB, 0x66, 0x5D, 0xEA, 0x76, 0x83, 0x82,
+			0x97, 0x39, 0xAF, 0xC0, 0x50, 0x81, 0x18, 0x0D,
+			0x22, 0xFA, 0xB7, 0x44, 0x5C, 0x3F, 0x69, 0xF3,
+			0xAC, 0xC5, 0x63, 0x9F, 0xD8, 0x72, 0x7E, 0x9A,
+			0xC2, 0xEB, 0x79, 0xD0, 0x74, 0x65, 0xE8, 0xCA,
+			0xFD, 0xA8, 0x7D, 0x23, 0x07, 0x99, 0x3E, 0xAF,
+			0xDB, 0x67, 0x10, 0xC0, 0xE5, 0x61, 0x77, 0xC6,
+			0x8D, 0xC4, 0x0E, 0xAA, 0x55, 0xE3, 0xC0, 0xC7,
+			0xA5, 0x36, 0x28, 0x61, 0xDB, 0x16, 0x96, 0x5E,
+			0x01, 0x47, 0x82, 0xE3, 0xEB, 0x20, 0x3F, 0x10,
+			0xFA, 0x5A, 0xBC, 0xD3, 0xF9, 0xCE, 0x04, 0x87,
+			0x51, 0x07, 0xF9, 0xD0, 0xE7, 0x6D, 0xCB, 0xCC,
+			0xC4, 0x15, 0x00, 0xE2, 0xDC, 0x8E, 0x7B, 0x5C,
+			0x9A, 0xF2, 0x78, 0x70, 0x4D, 0xA1, 0xAA, 0xB5,
+			0x13, 0xCC, 0x71, 0x66, 0x5A, 0x79, 0x13, 0x3B,
+			0x12, 0xCD, 0x40, 0x30, 0x5A, 0x49, 0xD4, 0x20,
+			0xED, 0xCF, 0x4A, 0x75, 0xE6, 0xD5, 0xDD, 0x0F,
+			0xD4, 0xBE, 0x98, 0x9F, 0xD7, 0x1F, 0xC0, 0x02,
+			0x31, 0xFA, 0x67, 0x37, 0x25, 0x86, 0x56, 0x85,
+			0x2B, 0xA2, 0x57, 0xCD, 0x8E, 0x74, 0xE7, 0x69,
+			0xEE, 0x33, 0x5A, 0x3F, 0xCD, 0x1E, 0xE3, 0xB9,
+			0xAA, 0x52, 0xF5, 0x22, 0x4E, 0xE3, 0xFF, 0xC8,
+			0xE3, 0x13, 0xA3, 0x9A, 0x63, 0x23, 0xC3, 0xD7,
+			0xE5, 0x88, 0x3E, 0x0A, 0x4B, 0xA5, 0x01, 0xE6,
+			0x13, 0xCF, 0xED, 0xEE, 0x2A, 0x58, 0x09, 0x3F,
+			0x2F, 0x28, 0xE7, 0xC4, 0x6B, 0xEC, 0x49, 0x51,
+			0x79, 0x8F, 0xD5, 0x19, 0x5D, 0xA5, 0x10, 0xCE,
+			0x8E, 0xF6, 0x26, 0x78, 0x7A, 0xA8, 0x11, 0x52,
+			0x5F, 0x97, 0x14, 0xC9, 0x29, 0x87, 0xB8, 0xA0,
+			0x2D, 0xE6, 0xA7, 0x2A, 0xD4, 0xFF, 0xEB, 0xBA,
+			0xFD, 0x58, 0x39, 0x33, 0xB1, 0xCE, 0x0E, 0x78,
+			0x67, 0x1E, 0xA1, 0x92, 0x77, 0x63, 0xF8, 0xC0,
+			0x02, 0x49, 0x73, 0xC0, 0xA1, 0x26, 0x83, 0x04,
+			0x9A, 0x5D, 0x85, 0x68, 0x2A, 0x2F, 0xCB, 0x88,
+			0x8D, 0x14, 0xB1, 0x33, 0xFA, 0xFB, 0xE9, 0x05,
+			0xBE, 0x24, 0x1A, 0x6B, 0x29, 0x2B, 0x3F, 0x52,
+			0x8F, 0xFB, 0xE6, 0x02, 0x77, 0x50, 0x71, 0xDB,
+			0xE9, 0x92, 0x3F, 0xE1, 0x20, 0x62, 0x80, 0xAE,
+			0xA4, 0x98, 0xC6, 0xCD, 0xE0, 0xB1, 0xC3, 0x33,
+			0xB1, 0xC5, 0x91, 0x3C, 0x19, 0x34, 0xA8, 0xD9,
+			0xB3, 0x25, 0x69, 0xE3, 0x9C, 0x5F, 0x78, 0xD0,
+			0x83, 0x1F, 0xAB, 0x85, 0x13, 0x56, 0x69, 0xB5,
+			0x06, 0x47, 0x62, 0x37, 0x27, 0x15, 0x14, 0x05,
+			0x4A, 0xF4, 0x6A, 0x68, 0x2A, 0x6A, 0xC3, 0x5A,
+			0xDF, 0xB5, 0xAE, 0x2F, 0x8D, 0x8F, 0x21, 0xDB,
+			0x33, 0x00, 0x9B, 0xD4, 0xC4, 0x08, 0x3B, 0x81,
+			0x63, 0x4C, 0xB0, 0x39, 0x4C, 0x0A, 0xD5, 0x71,
+			0x3E, 0x5A, 0x50, 0x58, 0x9C, 0x07, 0x89, 0x79,
+			0x79, 0x2F, 0x0B, 0xD9, 0x50, 0xBC, 0xCF, 0x46,
+			0x7A, 0x68, 0x5C, 0xBF, 0x1E, 0x49, 0x77, 0x92,
+			0x85, 0x11, 0x39, 0xA6, 0x2F, 0xDA, 0x7B, 0xFA,
+			0x72, 0x87, 0x06, 0xCD, 0x84, 0x41, 0x20, 0x1B,
+			0x66, 0x3F, 0x42, 0x0C, 0x9E, 0x19, 0xD3, 0x18,
+			0x57, 0xA0, 0xEE, 0x16, 0x3A, 0xC7, 0xF9, 0xD3,
+			0x8B, 0xC9, 0x24, 0x70, 0x70, 0x51, 0x7C, 0x06,
+			0x68, 0xD3, 0x29, 0xC9, 0x85, 0x9A, 0x1C, 0xE6,
+			0x8C, 0x17, 0xF4, 0x88, 0xDF, 0xEA, 0xFF, 0x44,
+			0x8D, 0x54, 0xBE, 0x22, 0x07, 0xA5, 0x7C, 0x0C,
+			0xF4, 0x8D, 0xB1, 0x0C, 0x07, 0xED, 0xBD, 0x28,
+			0x19, 0xDA, 0x07, 0x71, 0xA8, 0xA1, 0xE0, 0xDD,
+			0xEE, 0x08, 0x18, 0xA5, 0xBD, 0xDD, 0x32, 0x0B,
+			0x70, 0x1C, 0xD9, 0xEE, 0x19, 0xC2, 0xAE, 0x5C,
+			0xE3, 0x02, 0x74, 0x70, 0x96, 0x61, 0xB1, 0x73,
+			0x3B, 0xD6, 0x74, 0xC0, 0x82, 0xA9, 0x1F, 0xE0,
+			0xF1, 0x22, 0x50, 0xF3, 0x9F, 0xE5, 0x13, 0x92,
+			0xFC, 0x0A, 0x1A, 0x3C, 0xB4, 0x46, 0xFB, 0x81,
+			0x00, 0x84, 0xA4, 0x5E, 0x6B, 0x8C, 0x25, 0x6E,
+			0xD7, 0xB7, 0x3B, 0x01, 0x65, 0xFB, 0x0B, 0x46,
+			0x67, 0x27, 0x2D, 0x51, 0xAD, 0xB5, 0xE0, 0x85,
+			0xC2, 0x95, 0xA3, 0xE3, 0x68, 0x4D, 0x9E, 0x8C,
+			0x11, 0x53, 0xF0, 0xB2, 0x85, 0xFA, 0x52, 0x4E,
+			0xEC, 0xF9, 0xB7, 0x3C, 0x89, 0x2C, 0x4D, 0x32,
+			0x9A, 0xCB, 0x17, 0xF3, 0x16, 0xBF, 0x44, 0x40,
+			0xE9, 0x5E, 0x51, 0x8C, 0x1E, 0x52, 0x0A, 0xC2,
+			0xCD, 0xA5, 0xAA, 0x03, 0x27, 0xB0, 0x8F, 0x64,
+			0xDB, 0xD7, 0x03, 0x01, 0x8A, 0x24, 0x28, 0x7E,
+			0x53, 0x6F, 0x24, 0xFD, 0xAA, 0xE3, 0x78, 0xB6,
+			0xA5, 0x5D, 0x5A, 0x67, 0x20, 0xE2, 0xBE, 0x3A,
+			0x2B, 0xE7, 0x86, 0x11, 0xDD, 0x96, 0xCB, 0x09,
+			0x65, 0xA0, 0x36, 0xF9, 0xB0, 0x20, 0x21, 0x8E,
+			0xDB, 0xC0, 0x73, 0xC7, 0x79, 0xD8, 0xDA, 0xC2,
+			0x66, 0x13, 0x64, 0x34, 0x0C, 0xE1, 0x22, 0x24,
+			0x61, 0x67, 0x08, 0x39, 0x97, 0x3F, 0x33, 0x96,
+			0xF2, 0x44, 0x18, 0x75, 0xBB, 0xF5, 0x6A, 0x5C,
+			0x2C, 0xAE, 0x2A, 0x79, 0x3D, 0x47, 0x19, 0x53,
+			0x50, 0x6C, 0x9F, 0xB3, 0x82, 0x55, 0x09, 0x78,
+			0x7B, 0xAD, 0xBC, 0x05, 0x6F, 0xC8, 0x3D, 0xB6,
+			0x7B, 0x30, 0xE6, 0xBB, 0x8B, 0xD0, 0x2F, 0xA6,
+			0x15, 0xCC, 0x77, 0x8C, 0x21, 0xBA, 0x03, 0xED,
+			0x56, 0x85, 0x82, 0x4F, 0x97, 0x8C, 0x59, 0x4F,
+			0x53, 0x5A, 0xD2, 0x70, 0xD9, 0x07, 0xB3, 0xBD,
+			0x1D, 0x3E, 0x97, 0xD4, 0x7D, 0x93, 0x35, 0xA4,
+			0x82, 0x6E, 0xEA, 0x4B, 0xC8, 0x6C, 0xF5, 0xE6,
+			0xEB, 0xAF, 0x11, 0xB0, 0xB4, 0x71, 0x8F, 0x7B,
+			0xC4, 0x8C, 0xE2, 0x66, 0x51, 0x31, 0x99, 0x01,
+			0x5B, 0xE7, 0x48, 0xF8, 0x4C, 0xE3, 0x9A, 0x77,
+			0xF1, 0xC6, 0x09, 0xDE, 0x76, 0xD4, 0xE3, 0x5C,
+			0xDF, 0xA3, 0xEC, 0x3C, 0x86, 0x7C, 0xA5, 0x3F,
+			0x8D, 0x2A, 0xF3, 0x0B, 0x54, 0xB7, 0x54, 0xA2,
+			0xC1, 0x69, 0xC0, 0x6F, 0x1C, 0x1C, 0x76, 0xD8,
+			0x9F, 0x7A, 0x32, 0xB0, 0xA1, 0xA6, 0x9B, 0xB7,
+			0x21, 0x56, 0x28, 0x2D, 0xB6, 0x97, 0x03, 0x5E,
+			0x65, 0xE3, 0x74, 0x9A, 0x96, 0x7A, 0xF9, 0xF5,
+			0xDD, 0x85, 0xCA, 0x4C, 0xB4, 0x03, 0x6A, 0xCD,
+			0xB6, 0x01, 0xDC, 0x8B, 0xD8, 0x73, 0x8F, 0x4D,
+			0x7F, 0xD6, 0x71, 0xEC, 0xD7, 0xC6, 0x0B, 0x5F,
+			0x09, 0x21, 0xB2, 0x78, 0xA8, 0xAF, 0xAD, 0x2C,
+			0xD4, 0x93, 0x9F, 0x71, 0xF7, 0x05, 0x89, 0x42,
+			0xC9, 0x15, 0x6F, 0x2D, 0xE0, 0xBA, 0xC3, 0xD6,
+			0xBF, 0xAC, 0xF8, 0x24, 0x58, 0x79, 0xA9, 0xC4,
+			0xB4, 0x49, 0x3E, 0x0B, 0x9E, 0x5E, 0xE4, 0xA6,
+			0x8B, 0xE8, 0xDE, 0xFB, 0x4A, 0xF1, 0x69, 0x9D,
+			0x4F, 0x77, 0x83, 0x78, 0x55, 0x19, 0x42, 0x45,
+			0xBF, 0xBD, 0xBD, 0x12, 0x0F, 0xEF, 0x8D, 0x04,
+			0xD8, 0x5C, 0xF2, 0xC9, 0xF1, 0xA6, 0xE0, 0x3E,
+			0x22, 0xA8, 0xA2, 0x5E, 0x66, 0xE9, 0xAB, 0xB4,
+			0x71, 0xBE, 0x4B, 0x3F, 0xBE, 0xC4, 0xBA, 0x4A
+		},
+		.len = 2048
+	},
+	.ciphertext = {
+		.data = {
+			0x5E, 0x86, 0x02, 0x64, 0x32, 0xBF, 0x70, 0xC2,
+			0x19, 0x99, 0x7F, 0x47, 0x0D, 0xA4, 0x91, 0xA8,
+			0x7A, 0xC0, 0xA5, 0x7E, 0xA8, 0x6C, 0x88, 0x00,
+			0xEA, 0xB5, 0x96, 0x6B, 0x25, 0xBD, 0xE7, 0x42,
+			0xDB, 0x35, 0xE7, 0x92, 0x2B, 0x00, 0x82, 0x35,
+			0xD4, 0x2C, 0xCF, 0x47, 0xC8, 0xB2, 0xB3, 0x57,
+			0xF7, 0x24, 0x83, 0x7F, 0xC5, 0x2E, 0xF1, 0xC9,
+			0x57, 0x1A, 0xEF, 0xC2, 0x3A, 0x8C, 0x1E, 0x92,
+			0x88, 0x05, 0xAF, 0x55, 0xE6, 0x0C, 0xA7, 0x6B,
+			0x59, 0x62, 0x32, 0x21, 0xF1, 0xFF, 0xB5, 0x5B,
+			0x22, 0x26, 0x6F, 0x0A, 0x36, 0xDC, 0x0D, 0x16,
+			0x3B, 0x4E, 0x7C, 0xA3, 0x75, 0x30, 0x3F, 0xB0,
+			0x99, 0x38, 0x42, 0x8E, 0x89, 0xA3, 0x7C, 0x99,
+			0x2F, 0x0A, 0xA1, 0xC7, 0xFD, 0x2D, 0x21, 0x8F,
+			0xBD, 0xD4, 0x11, 0xEA, 0x55, 0xF5, 0x6A, 0x50,
+			0x90, 0x3B, 0x60, 0x57, 0xE1, 0x86, 0x1E, 0x50,
+			0x28, 0x67, 0x3F, 0xD2, 0xF3, 0xBD, 0xFA, 0xEE,
+			0xD6, 0x5A, 0x38, 0x30, 0xA3, 0xDD, 0x78, 0xC4,
+			0x37, 0x59, 0x52, 0xC0, 0x92, 0x54, 0xC7, 0x53,
+			0xF0, 0xE6, 0xA9, 0x63, 0x1F, 0x9B, 0x97, 0xFB,
+			0x40, 0x23, 0xFE, 0x52, 0x6A, 0xF0, 0x3A, 0x94,
+			0xEB, 0x6A, 0x9E, 0x8F, 0xC5, 0x05, 0x9C, 0x04,
+			0x1B, 0x00, 0x34, 0x96, 0x12, 0xDA, 0x60, 0xC6,
+			0xAA, 0x1A, 0x3E, 0xEB, 0x70, 0x17, 0x10, 0xBC,
+			0xF5, 0xC2, 0xE2, 0x71, 0xF3, 0xB8, 0x1D, 0xCE,
+			0x47, 0x94, 0x21, 0x71, 0x34, 0x8C, 0xCC, 0xDD,
+			0x27, 0xCE, 0x6F, 0x68, 0xFF, 0x91, 0x4E, 0xC4,
+			0xA0, 0xCA, 0xB0, 0x4F, 0x17, 0x53, 0x73, 0x92,
+			0x6C, 0xA8, 0x16, 0x06, 0xE3, 0xD9, 0x92, 0x99,
+			0xBE, 0xB0, 0x7D, 0x56, 0xF2, 0x72, 0x30, 0xDA,
+			0xC4, 0x4E, 0xF4, 0xA6, 0x8F, 0xD2, 0xC7, 0x8A,
+			0xA2, 0xFC, 0xF5, 0x63, 0x17, 0x48, 0x56, 0x4D,
+			0xBE, 0x94, 0xFE, 0xF5, 0xB1, 0xA9, 0x96, 0xAB,
+			0x3F, 0x2D, 0xD4, 0x15, 0xEE, 0x4F, 0xFA, 0x2C,
+			0xBE, 0x91, 0xB7, 0xBC, 0x18, 0xC8, 0xDB, 0x02,
+			0x20, 0x29, 0xF1, 0xC1, 0x88, 0x8C, 0x8D, 0xD1,
+			0xB3, 0x4E, 0x93, 0x96, 0xDD, 0x22, 0xAB, 0x55,
+			0xB5, 0x9F, 0x8B, 0x20, 0xAE, 0xC6, 0x0E, 0x26,
+			0xC6, 0xFE, 0x2D, 0x5F, 0x95, 0x89, 0x06, 0x15,
+			0x3D, 0x88, 0x16, 0xEC, 0x9B, 0x4A, 0x1B, 0x5D,
+			0x2E, 0xB2, 0x13, 0x56, 0x9F, 0x33, 0xB3, 0x45,
+			0xBF, 0x5F, 0x25, 0x7E, 0x75, 0x22, 0xD2, 0xE6,
+			0x9F, 0xAC, 0x2D, 0xFD, 0x99, 0xC2, 0x9B, 0xFC,
+			0xD7, 0x7A, 0x9B, 0x05, 0x30, 0x0F, 0xB7, 0x4A,
+			0xFE, 0x24, 0xDD, 0x39, 0x9B, 0xBB, 0x2F, 0xDD,
+			0xF9, 0xFB, 0xCA, 0x6C, 0x87, 0xBA, 0x73, 0xD4,
+			0x85, 0x7B, 0xB2, 0x6F, 0x5C, 0xD8, 0xFB, 0xE9,
+			0x41, 0x24, 0x3A, 0x3B, 0x4F, 0x91, 0x77, 0xA2,
+			0x35, 0x78, 0xE5, 0x4C, 0xFE, 0x8B, 0x04, 0x03,
+			0xD3, 0x84, 0xA9, 0x1C, 0xA7, 0x7C, 0x45, 0x13,
+			0x7D, 0xC5, 0x0A, 0x2F, 0x02, 0xF8, 0x56, 0xD5,
+			0x5F, 0x35, 0xED, 0x06, 0xBF, 0x67, 0xBA, 0x51,
+			0x02, 0x95, 0x36, 0xF2, 0x9A, 0xBA, 0x9D, 0xF6,
+			0xD6, 0x77, 0x50, 0xC9, 0xFC, 0x1E, 0x32, 0xB5,
+			0x2F, 0xEA, 0x3C, 0x76, 0xB4, 0xE1, 0xCC, 0x42,
+			0xEB, 0x71, 0x79, 0xD3, 0x7D, 0xB7, 0xC0, 0x88,
+			0x25, 0x81, 0xE8, 0xC0, 0xB8, 0x38, 0x7E, 0x7B,
+			0xFD, 0x18, 0xAB, 0x08, 0xB2, 0x71, 0xA5, 0xAD,
+			0xA7, 0xBE, 0x48, 0x5F, 0x86, 0xE2, 0x41, 0x3D,
+			0x7C, 0x37, 0x7A, 0xAB, 0xDB, 0xE0, 0x3B, 0x3D,
+			0xB6, 0xE8, 0x23, 0x7C, 0xF1, 0x8F, 0xBA, 0xB7,
+			0xE9, 0x78, 0x0B, 0xCA, 0x67, 0xA8, 0x10, 0x36,
+			0xEB, 0x72, 0xED, 0xDD, 0xF0, 0x5C, 0x74, 0x8E,
+			0xE5, 0x2A, 0xAE, 0x6E, 0xC4, 0xF1, 0xFC, 0xD8,
+			0xEE, 0x56, 0x07, 0x88, 0x02, 0xDC, 0x9D, 0xB7,
+			0xF9, 0x13, 0xE1, 0xE1, 0x9D, 0x89, 0x26, 0x0B,
+			0x23, 0x74, 0x4A, 0x43, 0xAA, 0xA0, 0xA8, 0x97,
+			0x85, 0x15, 0x58, 0xAB, 0x2B, 0xB5, 0xDA, 0x1A,
+			0xBA, 0x29, 0x62, 0xCF, 0xDD, 0xA3, 0xBA, 0x9D,
+			0x7D, 0x83, 0xA5, 0x18, 0xD4, 0x03, 0x0F, 0x61,
+			0x9F, 0xB1, 0x7E, 0xEC, 0xD2, 0x6E, 0xAF, 0xCF,
+			0x1E, 0xC1, 0x88, 0x97, 0x99, 0xD6, 0xBF, 0x47,
+			0xB9, 0x0A, 0x69, 0x11, 0x3A, 0x55, 0x8B, 0x1D,
+			0x2D, 0xFF, 0x78, 0xC8, 0xDE, 0x82, 0x29, 0xD6,
+			0x08, 0x3C, 0xC4, 0xCB, 0x2F, 0x01, 0xD0, 0xE8,
+			0xB1, 0x75, 0x5E, 0x23, 0xE0, 0x37, 0x7C, 0x1C,
+			0xB6, 0xD9, 0x47, 0xDE, 0x23, 0x87, 0xD3, 0x68,
+			0x47, 0x46, 0x78, 0xF3, 0xBF, 0x54, 0xA3, 0xB9,
+			0x54, 0xD5, 0xC5, 0x0A, 0x7C, 0x92, 0x2A, 0xC2,
+			0x14, 0x76, 0xA6, 0x5C, 0x6D, 0x0B, 0x94, 0x56,
+			0x00, 0x6B, 0x5C, 0x27, 0xDE, 0x77, 0x9B, 0xF1,
+			0xB1, 0x8C, 0xA7, 0x49, 0x77, 0xFC, 0x4E, 0x29,
+			0x23, 0x8F, 0x2F, 0xF7, 0x83, 0x8D, 0x36, 0xD9,
+			0xAB, 0x0E, 0x78, 0xF5, 0x90, 0x05, 0xB9, 0x79,
+			0x70, 0x88, 0x59, 0x6F, 0xE2, 0xC5, 0xD7, 0x80,
+			0x95, 0x04, 0x29, 0xE0, 0xFA, 0x37, 0xE8, 0x8B,
+			0xC5, 0x21, 0x51, 0x1A, 0x62, 0xCE, 0x93, 0xAF,
+			0x1A, 0xFE, 0xC3, 0x6F, 0x86, 0x94, 0x5E, 0x13,
+			0xA6, 0x9A, 0x26, 0xF0, 0xB5, 0x7C, 0x41, 0x9A,
+			0x80, 0xB8, 0x84, 0x5A, 0x55, 0xA9, 0xB0, 0x6A,
+			0xFA, 0xEB, 0x46, 0x32, 0x0B, 0xE2, 0x9C, 0x65,
+			0x86, 0x11, 0x39, 0x7E, 0xAF, 0x93, 0x19, 0x09,
+			0x70, 0x40, 0x80, 0x14, 0xBA, 0x1D, 0xB3, 0x62,
+			0x5B, 0xF3, 0x9A, 0x21, 0x98, 0x7E, 0x63, 0xB6,
+			0x1A, 0xBD, 0x65, 0x98, 0x35, 0x2A, 0xA9, 0x76,
+			0x29, 0x59, 0x84, 0x25, 0x81, 0xB8, 0xDE, 0x25,
+			0x32, 0x10, 0x50, 0xB7, 0xD3, 0xB3, 0x69, 0xC8,
+			0xE1, 0x33, 0xCB, 0x9E, 0x9C, 0x7A, 0x7C, 0xD2,
+			0x6C, 0x92, 0x97, 0xA9, 0xFA, 0xAF, 0x30, 0xBA,
+			0x9A, 0xB3, 0x3D, 0x9A, 0xE5, 0x0A, 0x9B, 0x8D,
+			0x89, 0xE2, 0x2B, 0xB8, 0xBC, 0xF0, 0x23, 0xFF,
+			0x7B, 0x0D, 0x00, 0x36, 0xEE, 0x79, 0xCB, 0xA5,
+			0x70, 0x4C, 0x66, 0x02, 0x79, 0x2E, 0x5B, 0x83,
+			0xCE, 0x55, 0x8B, 0x89, 0xD6, 0xE3, 0x71, 0x63,
+			0xBC, 0xB1, 0x5F, 0x67, 0xB4, 0x7E, 0x05, 0x0D,
+			0xAC, 0x6D, 0x4E, 0x2C, 0xA5, 0xF4, 0x47, 0x89,
+			0xAC, 0x5E, 0xBE, 0x2F, 0xFC, 0x9B, 0x2F, 0x0B,
+			0xBE, 0x63, 0x54, 0x97, 0xBB, 0x23, 0x27, 0xCD,
+			0xB9, 0xB2, 0x28, 0x0D, 0xA4, 0x78, 0x2C, 0xAB,
+			0xD1, 0xC9, 0x94, 0x40, 0x54, 0xF2, 0x35, 0x61,
+			0x49, 0x01, 0x87, 0x55, 0xA5, 0xB5, 0x1E, 0x84,
+			0x92, 0x9E, 0xC1, 0xA4, 0x0B, 0x66, 0x2B, 0xF8,
+			0xAF, 0xC3, 0x1E, 0xAF, 0x66, 0x3F, 0x6F, 0x5F,
+			0x70, 0xEC, 0x25, 0x29, 0xE4, 0x65, 0xB2, 0x04,
+			0x47, 0xF6, 0x3C, 0xB5, 0x5F, 0x66, 0x9F, 0xA4,
+			0x1B, 0xFC, 0xA2, 0xD5, 0x3E, 0x84, 0xBA, 0x88,
+			0x0D, 0xF1, 0x6A, 0xF2, 0xF6, 0x1D, 0xF1, 0xA3,
+			0x45, 0xB2, 0x51, 0xD8, 0xA2, 0x8F, 0x55, 0xA6,
+			0x89, 0xC4, 0x15, 0xD5, 0x73, 0xA8, 0xB1, 0x31,
+			0x66, 0x9E, 0xC1, 0x43, 0xE1, 0x5D, 0x4E, 0x04,
+			0x84, 0x8F, 0xF2, 0xBC, 0xE1, 0x4E, 0x4D, 0x60,
+			0x81, 0xCA, 0x53, 0x34, 0x95, 0x17, 0x3B, 0xAE,
+			0x8F, 0x95, 0xA7, 0xC6, 0x47, 0xC6, 0xAC, 0x32,
+			0x12, 0x39, 0xCA, 0xEF, 0xE0, 0x07, 0xBF, 0x17,
+			0x4F, 0xDC, 0x1B, 0x4E, 0x3C, 0x84, 0xF1, 0x9F,
+			0x43, 0x70, 0x19, 0xE6, 0xF3, 0x8B, 0x8B, 0x5D,
+			0xDB, 0xD2, 0x9D, 0xD4, 0xB2, 0x30, 0x45, 0x55,
+			0xA2, 0x67, 0xA2, 0x76, 0x4A, 0x74, 0xAD, 0x88,
+			0x71, 0xE6, 0x3E, 0x13, 0x06, 0x30, 0x17, 0xE1,
+			0xEF, 0xAC, 0x71, 0xFB, 0x43, 0xCD, 0xF6, 0xFA,
+			0x0E, 0x4C, 0x4E, 0x16, 0xF6, 0x6A, 0x09, 0x86,
+			0x6B, 0xEA, 0x47, 0x6C, 0x70, 0xE7, 0xAD, 0xA2,
+			0xE0, 0xFD, 0x7F, 0xF0, 0x5C, 0x21, 0x53, 0x0F,
+			0x28, 0xA1, 0x43, 0xE1, 0x06, 0xCA, 0x0B, 0x31,
+			0x88, 0x22, 0xA6, 0xE6, 0x34, 0x5B, 0xE6, 0xCF,
+			0x25, 0x81, 0x63, 0xFF, 0x78, 0x66, 0x85, 0x19,
+			0xE2, 0x0A, 0x7E, 0x81, 0x8A, 0x17, 0x1A, 0x18,
+			0x8A, 0x5F, 0x5D, 0x9E, 0x82, 0x13, 0x10, 0xB9,
+			0xD3, 0xE6, 0x93, 0x1C, 0xE4, 0x2C, 0xCB, 0x49,
+			0x1E, 0xB6, 0x36, 0x13, 0xBF, 0x28, 0xEE, 0xCC,
+			0x49, 0xF5, 0x79, 0xFC, 0x20, 0x65, 0xBD, 0xE8,
+			0xF0, 0x1B, 0x4E, 0xC0, 0x0D, 0x3E, 0x89, 0x91,
+			0xCC, 0x64, 0x10, 0xC0, 0x2A, 0x2B, 0xA3, 0xFA,
+			0x60, 0x3D, 0xC3, 0x52, 0x2F, 0x93, 0xDE, 0xB7,
+			0x6E, 0x8A, 0xDF, 0x6C, 0x08, 0xCC, 0x8B, 0x3B,
+			0xC8, 0x50, 0xEF, 0x58, 0x64, 0x9A, 0x3D, 0x16,
+			0x70, 0x94, 0x11, 0xD8, 0x94, 0x2B, 0x70, 0x91,
+			0x10, 0x70, 0x88, 0xF0, 0x40, 0x75, 0x9A, 0x2B,
+			0x39, 0xA1, 0x27, 0x3F, 0x2E, 0x91, 0xEA, 0xA1,
+			0xCC, 0x12, 0xC1, 0x7F, 0x73, 0x8C, 0x5C, 0x6B,
+			0xFC, 0xC5, 0x6A, 0x1C, 0x05, 0xF1, 0x3D, 0x30,
+			0x82, 0x4A, 0x65, 0x35, 0xCE, 0x80, 0x10, 0xBB,
+			0x41, 0x94, 0xFB, 0x84, 0x80, 0x7B, 0x91, 0xC4,
+			0x4D, 0xA3, 0x5F, 0xB9, 0xFB, 0xF9, 0xC9, 0x1D,
+			0x4F, 0x99, 0x1C, 0x1F, 0x47, 0x44, 0x89, 0x0E,
+			0xED, 0x6D, 0xB5, 0x85, 0x41, 0x94, 0xEF, 0xF9,
+			0x2E, 0xA0, 0xC8, 0xCA, 0xFB, 0x44, 0x02, 0xC6,
+			0xBF, 0x96, 0x87, 0x80, 0x1D, 0xEF, 0x2A, 0x81,
+			0xAB, 0xB2, 0x56, 0xDF, 0x54, 0x8B, 0xAB, 0xAF,
+			0xFE, 0x18, 0x8C, 0xAA, 0xD4, 0x00, 0x17, 0xBE,
+			0xCF, 0x06, 0xE5, 0xA6, 0xBF, 0x5A, 0x52, 0x3B,
+			0x4E, 0xF5, 0x65, 0x60, 0x95, 0xDE, 0x8A, 0x25,
+			0x88, 0xA5, 0x24, 0x96, 0x29, 0x13, 0x0D, 0x19,
+			0x45, 0x95, 0x91, 0x08, 0xD2, 0x9C, 0x4C, 0x34,
+			0x42, 0xF0, 0xA5, 0x72, 0xEB, 0xFB, 0x5E, 0xAA,
+			0x68, 0x80, 0x82, 0xAC, 0x34, 0xAD, 0x89, 0xF6,
+			0xAF, 0x54, 0x82, 0xCF, 0x98, 0x8C, 0x75, 0x63,
+			0x8D, 0xBD, 0x1C, 0x2A, 0xD7, 0x00, 0xA7, 0x8E,
+			0xB9, 0x33, 0xB6, 0x3B, 0x95, 0x9A, 0x59, 0x1D,
+			0x3F, 0x23, 0x6B, 0x18, 0xF8, 0x4F, 0x1A, 0x8D,
+			0xC0, 0x26, 0x9F, 0x87, 0x61, 0xB6, 0xC6, 0x60,
+			0x38, 0x22, 0x73, 0x1C, 0x99, 0x23, 0xEF, 0xD9,
+			0xFD, 0xCB, 0x54, 0x74, 0xBB, 0x77, 0x14, 0xA3,
+			0xA9, 0xE6, 0x7C, 0x7E, 0x03, 0x3A, 0x13, 0x6E,
+			0x1D, 0x6F, 0x64, 0xB3, 0xFA, 0xFB, 0x52, 0xDE,
+			0xDF, 0x08, 0xFB, 0x6F, 0xC5, 0xFA, 0x51, 0x6A,
+			0x69, 0x29, 0x9B, 0x96, 0xE8, 0x16, 0xC8, 0xD1,
+			0xE4, 0x19, 0xBD, 0x14, 0x74, 0x27, 0xE7, 0x10,
+			0xF0, 0xC3, 0xE2, 0xA7, 0x60, 0x48, 0xBF, 0xDD,
+			0xC4, 0x0D, 0xD0, 0xF2, 0xEF, 0xA6, 0xC9, 0xA2,
+			0x73, 0xD1, 0xCF, 0x41, 0xE1, 0x3B, 0xE5, 0x49,
+			0x91, 0x5D, 0x09, 0xFD, 0x1D, 0x95, 0x29, 0xDB,
+			0x52, 0x48, 0xEB, 0xF5, 0x1D, 0xF8, 0x06, 0x67,
+			0x75, 0xF2, 0x57, 0xA4, 0x20, 0x60, 0xEA, 0xB0,
+			0x85, 0x93, 0x7C, 0xDD, 0x52, 0x01, 0xD4, 0x57,
+			0xA8, 0x31, 0x2D, 0xF9, 0x0A, 0xD2, 0x2A, 0xD1,
+			0x34, 0x18, 0x35, 0x16, 0xB6, 0x8B, 0x0F, 0x0B,
+			0xCF, 0x50, 0x80, 0xFE, 0x76, 0xCC, 0x4F, 0x30,
+			0x98, 0x19, 0x16, 0x3D, 0x01, 0xEA, 0x8D, 0x8A,
+			0x3D, 0xDC, 0xFB, 0x1F, 0x77, 0x8D, 0x72, 0x76,
+			0x02, 0x3C, 0x5D, 0xEE, 0x55, 0x13, 0x5B, 0x6E,
+			0x5A, 0x2D, 0xD5, 0x77, 0xD7, 0x01, 0x84, 0x7D,
+			0x21, 0x8C, 0xDD, 0x94, 0x7D, 0x31, 0x3D, 0xF0,
+			0xE7, 0x28, 0xF5, 0x72, 0x36, 0x60, 0xE0, 0x59,
+			0x5F, 0xFE, 0x38, 0xF8, 0x2F, 0xDB, 0x9E, 0x55,
+			0x5A, 0xD6, 0xBA, 0x6C, 0x87, 0xF3, 0xC0, 0x76,
+			0x5F, 0xA3, 0x0A, 0xC3, 0xA3, 0x8D, 0x0E, 0x52,
+			0xA8, 0xDA, 0x26, 0x3A, 0xF9, 0x3E, 0x36, 0xB1,
+			0x06, 0xF8, 0x20, 0x2D, 0x1C, 0x0B, 0x93, 0xBB,
+			0xD3, 0x64, 0x77, 0xCE, 0x11, 0xFC, 0xA2, 0x0E,
+			0x1B, 0x5B, 0x9E, 0x13, 0x9F, 0x20, 0x8B, 0xAA,
+			0xCD, 0x72, 0xD7, 0xA6, 0xF3, 0x1E, 0x4F, 0x72,
+			0xC6, 0x49, 0x0F, 0x7B, 0xF0, 0x4C, 0x61, 0x1F,
+			0x43, 0x0D, 0x4F, 0x0D, 0x33, 0x13, 0xED, 0x63,
+			0xE5, 0xDB, 0x71, 0xAB, 0xA4, 0x83, 0xEF, 0xDC,
+			0x86, 0x9D, 0x4B, 0xBD, 0x1B, 0x8A, 0xFE, 0x39,
+			0xA8, 0x8B, 0xBA, 0x4C, 0x85, 0x28, 0xFC, 0xB3,
+			0x62, 0x85, 0xD2, 0xF0, 0x38, 0xD0, 0x4B, 0xA4,
+			0xD1, 0x3B, 0xD4, 0xD0, 0x2C, 0x78, 0x6C, 0x6A,
+			0xC2, 0x64, 0x2C, 0x31, 0x4A, 0xD8, 0x69, 0x24,
+			0xED, 0x77, 0x7D, 0x68, 0x9A, 0xA1, 0x78, 0x81,
+			0xD9, 0x7E, 0x6C, 0xFE, 0x0A, 0x0D, 0x76, 0xF7,
+			0x4B, 0x58, 0xE7, 0xC9, 0xB5, 0x11, 0x07, 0x87,
+			0x88, 0x6A, 0x9F, 0x3D, 0xE0, 0xEE, 0xCC, 0x60,
+			0x6B, 0x6B, 0xE6, 0xB5, 0x54, 0x8B, 0x32, 0x1F,
+			0x04, 0x1D, 0x0E, 0x9E, 0xFA, 0x6D, 0xB0, 0xE0,
+			0x6D, 0xF9, 0x79, 0xB4, 0xAB, 0x5E, 0xDF, 0x23,
+			0x7F, 0x95, 0xAD, 0x80, 0x17, 0x23, 0x90, 0x1F,
+			0xF0, 0xC3, 0xD9, 0x2D, 0xAC, 0x3F, 0x63, 0xF5,
+			0x77, 0xC5, 0x05, 0xAC, 0x06, 0xB6, 0xA1, 0xB4,
+			0xA2, 0x40, 0xB3, 0x99, 0x34, 0x7D, 0x31, 0xD4,
+			0xB1, 0xD4, 0xC1, 0xBB, 0x71, 0x1E, 0xDA, 0x3F,
+			0xA9, 0x12, 0x68, 0xFA, 0x5B, 0x20, 0x24, 0x6D,
+			0x4D, 0x72, 0x43, 0x18, 0xBF, 0x66, 0x71, 0x69,
+			0x26, 0x7D, 0x77, 0x78, 0xF8, 0xE5, 0x20, 0xAE,
+			0x56, 0x6C, 0x0F, 0x72, 0x94, 0x42, 0x85, 0x4F,
+			0xE4, 0xFB, 0x32, 0x26, 0x1B, 0x1C, 0x6E, 0x0B,
+			0xF0, 0xB8, 0x58, 0x00, 0xD2, 0x36, 0x64, 0xAD,
+			0xA9, 0x00, 0xCE, 0x35, 0x3C, 0x88, 0x79, 0x94,
+			0x0C, 0x0C, 0x9B, 0xF2, 0xDA, 0xBD, 0xCA, 0x93,
+			0x37, 0x26, 0xD3, 0x08, 0x54, 0xD2, 0x0D, 0xBC,
+			0x5D, 0x43, 0x5F, 0xCF, 0x28, 0xB5, 0xAA, 0x15,
+			0x28, 0x46, 0x45, 0x6B, 0xE8, 0xDF, 0xE8, 0xCE,
+			0x8F, 0xC0, 0x1A, 0x53, 0x63, 0x3B, 0x53, 0x75,
+			0xDD, 0x43, 0x1F, 0x07, 0x0A, 0xD5, 0xA1, 0x2A,
+			0x6E, 0x28, 0xE1, 0xD7, 0xD0, 0x09, 0xCF, 0x62,
+			0xC1, 0x5F, 0x21, 0xDB, 0xC5, 0x40, 0x99, 0x48,
+			0x87, 0x6E, 0x11, 0xF5, 0x5A, 0x4E, 0xBC, 0xF9,
+			0xA8, 0x02, 0x7C, 0x47, 0x39, 0xA5, 0xD8, 0x52,
+			0xB1, 0x80, 0xDC, 0xFE, 0x08, 0x4B, 0x5D, 0x09,
+			0xDE, 0x06, 0xF3, 0x2A, 0xAD, 0x14, 0x76, 0x40,
+			0x2F, 0x82, 0x28, 0x6A, 0xB6, 0x43, 0xEF, 0x71,
+			0x63, 0xC2, 0x56, 0xEB, 0x3B, 0x4B, 0x52, 0x2F,
+			0x93, 0xD3, 0x18, 0x3E, 0x18, 0xA8, 0xF7, 0x58,
+			0xFC, 0x8B, 0x3D, 0x4D, 0x4B, 0x72, 0xBD, 0xF7,
+			0x04, 0xC9, 0xB8, 0xD7, 0x6C, 0x8C, 0x67, 0xBB,
+			0x4C, 0x9B, 0x57, 0xF7, 0x22, 0x4E, 0x41, 0xB6,
+			0xFD, 0xD9, 0xF8, 0x41, 0x62, 0x0F, 0xFF, 0xAA,
+			0xC6, 0x87, 0x95, 0xFF, 0xFD, 0x58, 0xD9, 0xB2,
+			0xBA, 0x47, 0x61, 0x24, 0xEA, 0x92, 0x6E, 0x74,
+			0xB3, 0xDA, 0xE5, 0x83, 0x99, 0x24, 0xB1, 0x71,
+			0x2A, 0x33, 0xB2, 0xD5, 0x8F, 0xF0, 0x32, 0xCE,
+			0x37, 0xCF, 0xC7, 0x1C, 0xE8, 0xDE, 0x46, 0x78,
+			0x96, 0x97, 0xF6, 0x73, 0x90, 0xE5, 0x71, 0x05,
+			0xEA, 0x0D, 0xC2, 0x1D, 0x9E, 0x43, 0x34, 0xBC,
+			0x8F, 0x45, 0xE5, 0x08, 0xCA, 0x20, 0x0C, 0x84
+		},
+		.len = 2048
+	},
+	.auth_tag = {
+		.data = {
+			0xD0, 0x62, 0x1F, 0x20, 0x1C, 0xE8, 0xDD, 0x36,
+			0x00, 0x74, 0xF6, 0xD7, 0xFD, 0x2C, 0xA0, 0xAF
+		},
+		.len = 16
+	}
+};
+
 /** GMAC Test Vectors */
 static uint8_t gmac_plaintext[GMAC_LARGE_PLAINTEXT_LENGTH] = {
 			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-- 
1.7.9.5

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

* Re: [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize
  2017-01-05  9:12     ` [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
@ 2017-01-05 15:37       ` De Lara Guarch, Pablo
  2017-01-05 16:52         ` Kulasek, TomaszX
  0 siblings, 1 reply; 41+ messages in thread
From: De Lara Guarch, Pablo @ 2017-01-05 15:37 UTC (permalink / raw)
  To: Kulasek, TomaszX, dev

Hi Tomasz,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Tomasz Kulasek
> Sent: Thursday, January 05, 2017 9:13 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize
> 
> This patch adds function rte_pktmbuf_linearize to let crypto PMD coalesce
> chained mbuf before crypto operation and extend their capabilities to
> support segmented mbufs when device cannot handle them natively.
> 
> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>

Could you separate this patch and patch 2/5 out of this patchset and CC Olivier,
the mbuf maintainer, so it can be better reviewed?
(you can send it as a single patch, both lib and test code)
Then, send another patchset with the other 3 patches,
stating that it depends on that patchset.

Thanks,
Pablo

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

* [PATCH v4] rte_mbuf: add rte_pktmbuf_linearize
  2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
                       ` (4 preceding siblings ...)
  2017-01-05  9:12     ` [PATCH v3 5/5] test: add sgl unit tests for crypto devices Tomasz Kulasek
@ 2017-01-05 16:44     ` Tomasz Kulasek
  2017-01-10 16:50       ` Olivier MATZ
  2017-01-12  9:40       ` [PATCH v5] mbuf: add a function to linearize a packet Tomasz Kulasek
  2017-01-05 16:46     ` [PATCH v4 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
  6 siblings, 2 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05 16:44 UTC (permalink / raw)
  To: dev; +Cc: Pablo de Lara, Olivier Matz

This patch adds function rte_pktmbuf_linearize to let crypto PMD coalesce
chained mbuf before crypto operation and extend their capabilities to
support segmented mbufs when device cannot handle them natively.

Included unit tests for rte_pktmbuf_linearize functionality:

 1) Creates banch of segmented mbufs with different size and number of
    segments.
 2) Generates pkt_len bytes of random data.
 3) Fills noncontigouos mbuf with randomly generated data.
 4) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one
    contiguous.
 5) Verifies data in linearized buffer.

Dependencies:

This patch is rebased to the dpdk-next-crypto and should be applied
before "Chained Mbufs support in SW PMDs" patchset.


changes in v4:
 - separated from "Chained Mbufs support in SW PMDs" patch set for
   better reviewing,
 - merged "rte_pktmbuf_linearize" implementation with unit tests,

changes in v3:
 - rebased to dpdk-next-crypto

changes in v2:
 - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize


Cc: Pablo de Lara <pablo.de.lara.guarch@intel.com>
Cc: Olivier Matz <olivier.matz@6wind.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_mbuf.c       |  123 ++++++++++++++++++++++++++++++++++++++++++++
 lib/librte_mbuf/rte_mbuf.h |   56 ++++++++++++++++++++
 2 files changed, 179 insertions(+)

diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c
index c0823ea..39577e7 100644
--- a/app/test/test_mbuf.c
+++ b/app/test/test_mbuf.c
@@ -930,6 +930,124 @@
 	return 0;
 }
 
+static int
+test_mbuf_linearize(int pkt_len, int nb_segs) {
+
+	struct rte_mbuf *m = NULL, *mbuf_src = NULL;
+	uint8_t data[pkt_len], *src, *dst;
+	int data_len = 0;
+	int i, size;
+	int t_len;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return -1;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return -1;
+	}
+
+	/* Setup buffer */
+	for (i = 0; i < pkt_len; i++)
+		data[i] = (uint8_t) rte_rand();
+
+	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+	src = data;
+	size = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (i = 0; size > 0; i++) {
+
+		m = rte_pktmbuf_alloc(pktmbuf_pool);
+		if (i == 0)
+			mbuf_src = m;
+
+		if (!m) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+				rte_pktmbuf_tailroom(m));
+
+		data_len = size > t_len ? t_len : size;
+		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (!dst) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		rte_memcpy(dst, src, data_len);
+		src += data_len;
+
+		if (mbuf_src != m)
+			rte_pktmbuf_chain(mbuf_src, m);
+
+		size -= data_len;
+
+	}
+
+	/* Create destination buffer to store coalesced data */
+	if (rte_pktmbuf_linearize(mbuf_src)) {
+		printf("Mbuf linearization failed\n");
+		goto fail;
+	}
+
+	if (!rte_pktmbuf_is_contiguous(mbuf_src)) {
+		printf("Source buffer should be contiguous after "
+				"linearization\n");
+		goto fail;
+	}
+
+	src = rte_pktmbuf_mtod(mbuf_src, uint8_t *);
+
+	if (memcmp(src, data, rte_pktmbuf_pkt_len(mbuf_src))) {
+		printf("Incorrect data in coalesced mbuf\n");
+		goto fail;
+	}
+
+	if (mbuf_src)
+		rte_pktmbuf_free(mbuf_src);
+	return 0;
+
+fail:
+	if (mbuf_src)
+		rte_pktmbuf_free(mbuf_src);
+	return -1;
+}
+
+static int
+test_mbuf_linearize_check(void)
+{
+	struct test_mbuf_array {
+		int size;
+		int nb_segs;
+	} mbuf_array[5] = {
+			{ 128, 1 },
+			{ 64, 64 },
+			{ 512, 10 },
+			{ 250, 11 },
+			{ 123, 8 },
+	};
+	unsigned int i;
+
+	printf("Test mbuf linearize API\n");
+
+	for (i = 0; i < RTE_DIM(mbuf_array); i++)
+		if (test_mbuf_linearize(mbuf_array[i].size,
+				mbuf_array[i].nb_segs)) {
+			printf("Test failed for %d, %d\n", mbuf_array[i].size,
+					mbuf_array[i].nb_segs);
+			return -1;
+		}
+
+	return 0;
+}
 
 static int
 test_mbuf(void)
@@ -1023,6 +1141,11 @@
 		printf("test_failing_mbuf_sanity_check() failed\n");
 		return -1;
 	}
+
+	if (test_mbuf_linearize_check() < 0) {
+		printf("test_mbuf_linearize_check() failed\n");
+		return -1;
+	}
 	return 0;
 }
 
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ead7c6e..b11a31d 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -1647,6 +1647,62 @@ static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail
 }
 
 /**
+ * Linearize data in mbuf.
+ *
+ * This function coalesce mbuf merging data in the first segment, unchaining
+ * rest, and then frees them.
+ *
+ * All operations are done in-place, so the structure of incoming mbuf
+ * is changed.
+ *
+ * @param mbuf
+ *   mbuf to linearize
+ * @return
+ *   - 0, on success
+ *   - -1, on error
+ */
+static inline int
+rte_pktmbuf_linearize(struct rte_mbuf *mbuf)
+{
+	int l, n;
+	struct rte_mbuf *m;
+	struct rte_mbuf *m_next;
+	char *buffer;
+
+	if (rte_pktmbuf_is_contiguous(mbuf))
+		return 0;
+
+	/* Extend first segment to the total packet length
+	 */
+	n = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
+
+	if (unlikely(n > rte_pktmbuf_tailroom(mbuf)))
+		return -1;
+
+	buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
+	mbuf->data_len = (uint16_t)(mbuf->pkt_len);
+
+	/* Append data from next segments to the first one
+	 */
+	m = mbuf->next;
+	while (m != NULL) {
+		m_next = m->next;
+
+		l = rte_pktmbuf_data_len(m);
+		rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), l);
+		buffer += l;
+
+		rte_pktmbuf_free_seg(m);
+		m = m_next;
+	}
+
+	mbuf->next = NULL;
+	mbuf->nb_segs = 1;
+
+	return 0;
+}
+
+/**
  * Dump an mbuf structure to a file.
  *
  * Dump all fields for the given packet mbuf and all its associated
-- 
1.7.9.5

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

* [PATCH v4 0/3] Chained Mbufs support in SW PMDs
  2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
                       ` (5 preceding siblings ...)
  2017-01-05 16:44     ` [PATCH v4] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
@ 2017-01-05 16:46     ` Tomasz Kulasek
  2017-01-05 16:46       ` [PATCH v4 1/3] crypto: add sgl support in sw PMDs Tomasz Kulasek
                         ` (3 more replies)
  6 siblings, 4 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05 16:46 UTC (permalink / raw)
  To: dev; +Cc: pablo.de.lara.guarch

This patch set adds support of scattered-gather list for SW PMDs.

As of now, application needs to reserve continuous block of memory for
mbufs which is not always the case. Hence needed to support chaining of
mbufs which are smaller in size but can be used if chained.


Above work involves:
--------------------

 a) Create mbuf functions to coalesce mbuf chains into a single mbuf.
 b) For each software poll mode driver code to detect chained mbufs
    support and coalesce these before preforming crypto.
 c) Add relevant unit tests to test the functionality.


Known limitations for openssl PMD:
----------------------------------

While libcrypto library expects continuous destination buffer for
output of cipher operations, implementation of openssl PMD is limited
the same way, and requires contiguous destination mbuf.


Dependencies:
-------------

While "rte_mbuf: add rte_pktmbuf_linearize" were separated from this
patch set, patch "rte_mbuf: add rte_pktmbuf_linearize" should be
applied before this one.

This patch set shares some unit tests with SGL implementation for QAT
(already merged in dpdk-next-crypto) and should be applied on top of it,
and after applying fix "app/test: fix aad padding size in SGL operation"
by Arek Kusztal.


changes in v4:
 - separated "rte_pktmbuf_linearize" implementation from this patch set
   and sent as new patch for better reviewing,

changes in v3:
 - rebased to dpdk-next-crypto
 - reused tests for AES GCM SGL support in opensll from "app/test: add
   SGL tests to cryptodev QAT suite"

changes in v2:
 - add support for sgl in openssl PMD
 - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
 - extended test vector data for aes gcm from 60 to 2048 bytes

Tomasz Kulasek (3):
  crypto: add sgl support in sw PMDs
  crypto: add sgl support in openssl PMD
  test: add sgl unit tests for crypto devices

 app/test/test_cryptodev.c                  |  386 ++++++++++++++++++-
 app/test/test_cryptodev.h                  |  139 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   52 +++
 app/test/test_cryptodev_blockcipher.c      |  180 +++++----
 app/test/test_cryptodev_blockcipher.h      |    1 +
 app/test/test_cryptodev_gcm_test_vectors.h |  553 ++++++++++++++++++++++++++++
 doc/guides/cryptodevs/openssl.rst          |    3 +-
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 +
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 +-
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +
 drivers/crypto/null/null_crypto_pmd.c      |    3 +-
 drivers/crypto/openssl/rte_openssl_pmd.c   |  329 +++++++++++++----
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +
 lib/librte_cryptodev/rte_cryptodev.c       |    4 +-
 lib/librte_cryptodev/rte_cryptodev.h       |    2 +
 16 files changed, 1577 insertions(+), 149 deletions(-)

-- 
1.7.9.5

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

* [PATCH v4 1/3] crypto: add sgl support in sw PMDs
  2017-01-05 16:46     ` [PATCH v4 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
@ 2017-01-05 16:46       ` Tomasz Kulasek
  2017-01-05 16:46       ` [PATCH v4 2/3] crypto: add sgl support in openssl PMD Tomasz Kulasek
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05 16:46 UTC (permalink / raw)
  To: dev; +Cc: pablo.de.lara.guarch

This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature flag
informing that selected crypto device supports segmented mbufs natively
and doesn't need to be coalesced before crypto operation.

While using segmented buffers in crypto devices may have unpredictable
results, for PMDs which doesn't support it natively, additional check is
made for debug compilation.

Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 ++++++++++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 ++++++++++++++++---
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +++++++++++++
 drivers/crypto/null/null_crypto_pmd.c      |    3 ++-
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +++++++++++++++
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +++++++++++++
 lib/librte_cryptodev/rte_cryptodev.c       |    4 ++--
 lib/librte_cryptodev/rte_cryptodev.h       |    2 ++
 8 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index dba5e15..1a6120c 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -375,6 +375,20 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_AESNI_GCM_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			GCM_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			qp->qp_stats.enqueue_err_count++;
+			break;
+		}
+#endif
+
 		retval = process_gcm_crypto_op(qp, ops[i]->sym, sess);
 		if (retval < 0) {
 			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 6d27d75..25f681b 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -571,15 +571,28 @@
 	int i, processed_jobs = 0;
 
 	for (i = 0; i < nb_ops; i++) {
-#ifdef RTE_LIBRTE_AESNI_MB_DEBUG
-		if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
+#ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
+		if (unlikely(ops[i]->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
 			MB_LOG_ERR("PMD only supports symmetric crypto "
 				"operation requests, op (%p) is not a "
-				"symmetric operation.", op);
+				"symmetric operation.", ops[i]);
+			qp->stats.enqueue_err_count++;
+			goto flush_jobs;
+		}
+
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			MB_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 			qp->stats.enqueue_err_count++;
 			goto flush_jobs;
 		}
 #endif
+
 		sess = get_session(qp, ops[i]);
 		if (unlikely(sess == NULL)) {
 			qp->stats.enqueue_err_count++;
diff --git a/drivers/crypto/kasumi/rte_kasumi_pmd.c b/drivers/crypto/kasumi/rte_kasumi_pmd.c
index b119da2..4bdd7bb 100644
--- a/drivers/crypto/kasumi/rte_kasumi_pmd.c
+++ b/drivers/crypto/kasumi/rte_kasumi_pmd.c
@@ -455,6 +455,19 @@
 	for (i = 0; i < nb_ops; i++) {
 		curr_c_op = ops[i];
 
+#ifdef RTE_LIBRTE_PMD_KASUMI_DEBUG
+		if (!rte_pktmbuf_is_contiguous(curr_c_op->sym->m_src) ||
+				(curr_c_op->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						curr_c_op->sym->m_dst))) {
+			KASUMI_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", curr_c_op);
+			curr_c_op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		/* Set status as enqueued (not processed yet) by default. */
 		curr_c_op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
 
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index c69606b..c37d3d6 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -216,7 +216,8 @@
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
-			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
 
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 3b4292a..9a6f16d 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -330,6 +330,21 @@
 	unsigned i;
 	unsigned enqueued_ops, processed_ops;
 
+#ifdef RTE_LIBRTE_PMD_SNOW3G_DEBUG
+	for (i = 0; i < num_ops; i++) {
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			SNOW3G_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			return 0;
+		}
+	}
+#endif
+
 	switch (session->op) {
 	case SNOW3G_OP_ONLY_CIPHER:
 		processed_ops = process_snow3g_cipher_op(ops,
diff --git a/drivers/crypto/zuc/rte_zuc_pmd.c b/drivers/crypto/zuc/rte_zuc_pmd.c
index 3849119..bf53f76 100644
--- a/drivers/crypto/zuc/rte_zuc_pmd.c
+++ b/drivers/crypto/zuc/rte_zuc_pmd.c
@@ -211,6 +211,19 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_ZUC_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ZUC_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		src[i] = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
 				(ops[i]->sym->cipher.data.offset >> 3);
 		dst[i] = ops[i]->sym->m_dst ?
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 54e95d5..bbab4b3 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -211,13 +211,13 @@ struct rte_cryptodev_callback {
 		return "CPU_AESNI";
 	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
 		return "HW_ACCELERATED";
-
+	case RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER:
+		return "MBUF_SCATTER_GATHER";
 	default:
 		return NULL;
 	}
 }
 
-
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)
 {
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 29d8eec..fa311a9 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -227,6 +227,8 @@ struct rte_cryptodev_capabilities {
 /**< Operations are off-loaded to an external hardware accelerator */
 #define	RTE_CRYPTODEV_FF_CPU_AVX512		(1ULL << 8)
 /**< Utilises CPU SIMD AVX512 instructions */
+#define	RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER	(1ULL << 9)
+/**< Scatter-gather mbufs are supported */
 
 
 /**
-- 
1.7.9.5

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

* [PATCH v4 2/3] crypto: add sgl support in openssl PMD
  2017-01-05 16:46     ` [PATCH v4 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2017-01-05 16:46       ` [PATCH v4 1/3] crypto: add sgl support in sw PMDs Tomasz Kulasek
@ 2017-01-05 16:46       ` Tomasz Kulasek
  2017-01-05 16:46       ` [PATCH v4 3/3] test: add sgl unit tests for crypto devices Tomasz Kulasek
  2017-01-13 15:23       ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
  3 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05 16:46 UTC (permalink / raw)
  To: dev; +Cc: pablo.de.lara.guarch


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 doc/guides/cryptodevs/openssl.rst        |    3 +-
 drivers/crypto/openssl/rte_openssl_pmd.c |  329 +++++++++++++++++++++++-------
 2 files changed, 259 insertions(+), 73 deletions(-)

diff --git a/doc/guides/cryptodevs/openssl.rst b/doc/guides/cryptodevs/openssl.rst
index d2b5906..d0b1eeb 100644
--- a/doc/guides/cryptodevs/openssl.rst
+++ b/doc/guides/cryptodevs/openssl.rst
@@ -112,6 +112,7 @@ Limitations
 -----------
 
 * Maximum number of sessions is 2048.
-* Chained mbufs are not supported.
+* Chained mbufs are supported only for source mbuf (destination must be
+  contiguous).
 * Hash only is not supported for GCM and GMAC.
 * Cipher only is not supported for GCM and GMAC.
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 832ea1d..e466c79 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -484,24 +484,112 @@
  * Process Operations
  *------------------------------------------------------------------------------
  */
+static inline int
+process_openssl_encryption_update(struct rte_mbuf *mbuf_src, int offset,
+		uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+	struct rte_mbuf *m;
+	int dstlen;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		return -1;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+			return -1;
+		*dst += l;
+		return 0;
+	}
+
+	if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+		return -1;
+
+	*dst += dstlen;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+			return -1;
+		*dst += dstlen;
+		n -= l;
+	}
+
+	return 0;
+}
+
+static inline int
+process_openssl_decryption_update(struct rte_mbuf *mbuf_src, int offset,
+		uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+	struct rte_mbuf *m;
+	int dstlen;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		return -1;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+			return -1;
+		*dst += l;
+		return 0;
+	}
+
+	if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+		return -1;
+
+	*dst += dstlen;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+			return -1;
+		*dst += dstlen;
+		n -= l;
+	}
+
+	return 0;
+}
 
 /** Process standard openssl cipher encryption */
 static int
-process_openssl_cipher_encrypt(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_encrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
-	int dstlen, totlen;
+	int totlen;
 
 	if (EVP_EncryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
 		goto process_cipher_encrypt_err;
 
 	EVP_CIPHER_CTX_set_padding(ctx, 0);
 
-	if (EVP_EncryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+	if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+			srclen, ctx))
 		goto process_cipher_encrypt_err;
 
-	if (EVP_EncryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+	if (EVP_EncryptFinal_ex(ctx, dst, &totlen) <= 0)
 		goto process_cipher_encrypt_err;
 
 	return 0;
@@ -513,11 +601,11 @@
 
 /** Process standard openssl cipher decryption */
 static int
-process_openssl_cipher_decrypt(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_decrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
-	int dstlen, totlen;
+	int totlen;
 
 	if (EVP_DecryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
 		goto process_cipher_decrypt_err;
@@ -525,12 +613,12 @@
 	if (EVP_CIPHER_CTX_set_padding(ctx, 0) <= 0)
 		goto process_cipher_decrypt_err;
 
-	if (EVP_DecryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+	if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+			srclen, ctx))
 		goto process_cipher_decrypt_err;
 
-	if (EVP_DecryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+	if (EVP_DecryptFinal_ex(ctx, dst, &totlen) <= 0)
 		goto process_cipher_decrypt_err;
-
 	return 0;
 
 process_cipher_decrypt_err:
@@ -540,11 +628,25 @@
 
 /** Process cipher des 3 ctr encryption, decryption algorithm */
 static int
-process_openssl_cipher_des3ctr(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen, EVP_CIPHER_CTX *ctx)
+process_openssl_cipher_des3ctr(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
+		EVP_CIPHER_CTX *ctx)
 {
 	uint8_t ebuf[8], ctr[8];
 	int unused, n;
+	struct rte_mbuf *m;
+	uint8_t *src;
+	int l;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_cipher_des3ctr_err;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+	l = rte_pktmbuf_data_len(m) - offset;
 
 	/* We use 3DES encryption also for decryption.
 	 * IV is not important for 3DES ecb
@@ -553,9 +655,8 @@
 		goto process_cipher_des3ctr_err;
 
 	memcpy(ctr, iv, 8);
-	n = 0;
 
-	while (n < srclen) {
+	for (n = 0; n < srclen; n++) {
 		if (n % 8 == 0) {
 			if (EVP_EncryptUpdate(ctx,
 					(unsigned char *)&ebuf, &unused,
@@ -563,8 +664,16 @@
 				goto process_cipher_des3ctr_err;
 			ctr_inc(ctr);
 		}
-		dst[n] = src[n] ^ ebuf[n % 8];
-		n++;
+		dst[n] = *(src++) ^ ebuf[n % 8];
+
+		l--;
+		if (!l) {
+			m = m->next;
+			if (m) {
+				src = rte_pktmbuf_mtod(m, uint8_t *);
+				l = rte_pktmbuf_data_len(m);
+			}
+		}
 	}
 
 	return 0;
@@ -576,9 +685,9 @@
 
 /** Process auth/encription aes-gcm algorithm */
 static int
-process_openssl_auth_encryption_gcm(uint8_t *src, int srclen,
-		uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
-		uint8_t *key, uint8_t *dst,	uint8_t *tag,
+process_openssl_auth_encryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+		int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+		uint8_t *key, uint8_t *dst, uint8_t *tag,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
 	int len = 0, unused = 0;
@@ -593,20 +702,20 @@
 	if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
 		goto process_auth_encryption_gcm_err;
 
-	if (aadlen > 0) {
+	if (aadlen > 0)
 		if (EVP_EncryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
 			goto process_auth_encryption_gcm_err;
 
-		/* Workaround open ssl bug in version less then 1.0.1f */
-		if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
-			goto process_auth_encryption_gcm_err;
-	}
-
 	if (srclen > 0)
-		if (EVP_EncryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+		if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+				srclen, ctx))
 			goto process_auth_encryption_gcm_err;
 
-	if (EVP_EncryptFinal_ex(ctx, dst + len, &len) <= 0)
+	/* Workaround open ssl bug in version less then 1.0.1f */
+	if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+		goto process_auth_encryption_gcm_err;
+
+	if (EVP_EncryptFinal_ex(ctx, dst, &len) <= 0)
 		goto process_auth_encryption_gcm_err;
 
 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) <= 0)
@@ -620,10 +729,10 @@
 }
 
 static int
-process_openssl_auth_decryption_gcm(uint8_t *src, int srclen,
-		uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
-		uint8_t *key, uint8_t *dst, uint8_t *tag,
-		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
+process_openssl_auth_decryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+		int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+		uint8_t *key, uint8_t *dst, uint8_t *tag, EVP_CIPHER_CTX *ctx,
+		const EVP_CIPHER *algo)
 {
 	int len = 0, unused = 0;
 	uint8_t empty[] = {};
@@ -640,20 +749,20 @@
 	if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
 		goto process_auth_decryption_gcm_err;
 
-	if (aadlen > 0) {
+	if (aadlen > 0)
 		if (EVP_DecryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
 			goto process_auth_decryption_gcm_err;
 
-		/* Workaround open ssl bug in version less then 1.0.1f */
-		if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
-			goto process_auth_decryption_gcm_err;
-	}
-
 	if (srclen > 0)
-		if (EVP_DecryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+		if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+				srclen, ctx))
 			goto process_auth_decryption_gcm_err;
 
-	if (EVP_DecryptFinal_ex(ctx, dst + len, &len) <= 0)
+	/* Workaround open ssl bug in version less then 1.0.1f */
+	if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+		goto process_auth_decryption_gcm_err;
+
+	if (EVP_DecryptFinal_ex(ctx, dst, &len) <= 0)
 		goto process_auth_decryption_gcm_final_err;
 
 	return 0;
@@ -668,21 +777,50 @@
 
 /** Process standard openssl auth algorithms */
 static int
-process_openssl_auth(uint8_t *src, uint8_t *dst,
+process_openssl_auth(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
 		__rte_unused uint8_t *iv, __rte_unused EVP_PKEY * pkey,
 		int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
 {
 	size_t dstlen;
+	struct rte_mbuf *m;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_auth_err;
 
 	if (EVP_DigestInit_ex(ctx, algo, NULL) <= 0)
 		goto process_auth_err;
 
-	if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+			goto process_auth_err;
+		goto process_auth_final;
+	}
+
+	if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
 		goto process_auth_err;
 
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
+			goto process_auth_err;
+		n -= l;
+	}
+
+process_auth_final:
 	if (EVP_DigestFinal_ex(ctx, dst, (unsigned int *)&dstlen) <= 0)
 		goto process_auth_err;
-
 	return 0;
 
 process_auth_err:
@@ -692,18 +830,48 @@
 
 /** Process standard openssl auth algorithms with hmac */
 static int
-process_openssl_auth_hmac(uint8_t *src, uint8_t *dst,
+process_openssl_auth_hmac(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
 		__rte_unused uint8_t *iv, EVP_PKEY *pkey,
-		int srclen,	EVP_MD_CTX *ctx, const EVP_MD *algo)
+		int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
 {
 	size_t dstlen;
+	struct rte_mbuf *m;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_auth_err;
 
 	if (EVP_DigestSignInit(ctx, NULL, algo, NULL, pkey) <= 0)
 		goto process_auth_err;
 
-	if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+			goto process_auth_err;
+		goto process_auth_final;
+	}
+
+	if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
 		goto process_auth_err;
 
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
+			goto process_auth_err;
+		n -= l;
+	}
+
+process_auth_final:
 	if (EVP_DigestSignFinal(ctx, dst, &dstlen) <= 0)
 		goto process_auth_err;
 
@@ -723,9 +891,18 @@
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
 	/* cipher */
-	uint8_t *src = NULL, *dst = NULL, *iv, *tag, *aad;
+	uint8_t *dst = NULL, *iv, *tag, *aad;
 	int srclen, ivlen, aadlen, status = -1;
 
+	/*
+	 * Segmented destination buffer is not supported for
+	 * encryption/decryption
+	 */
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return;
+	}
+
 	iv = op->sym->cipher.iv.data;
 	ivlen = op->sym->cipher.iv.length;
 	aad = op->sym->auth.aad.data;
@@ -741,22 +918,22 @@
 		srclen = 0;
 	else {
 		srclen = op->sym->cipher.data.length;
-		src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-				op->sym->cipher.data.offset);
 		dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
 				op->sym->cipher.data.offset);
 	}
 
 	if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
 		status = process_openssl_auth_encryption_gcm(
-				src, srclen, aad, aadlen, iv, ivlen,
-				sess->cipher.key.data, dst, tag,
-				sess->cipher.ctx, sess->cipher.evp_algo);
+				mbuf_src, op->sym->cipher.data.offset, srclen,
+				aad, aadlen, iv, ivlen, sess->cipher.key.data,
+				dst, tag, sess->cipher.ctx,
+				sess->cipher.evp_algo);
 	else
 		status = process_openssl_auth_decryption_gcm(
-				src, srclen, aad, aadlen, iv, ivlen,
-				sess->cipher.key.data, dst, tag,
-				sess->cipher.ctx, sess->cipher.evp_algo);
+				mbuf_src, op->sym->cipher.data.offset, srclen,
+				aad, aadlen, iv, ivlen, sess->cipher.key.data,
+				dst, tag, sess->cipher.ctx,
+				sess->cipher.evp_algo);
 
 	if (status != 0) {
 		if (status == (-EFAULT) &&
@@ -774,12 +951,19 @@
 		(struct rte_crypto_op *op, struct openssl_session *sess,
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
-	uint8_t *src, *dst, *iv;
+	uint8_t *dst, *iv;
 	int srclen, status;
 
+	/*
+	 * Segmented destination buffer is not supported for
+	 * encryption/decryption
+	 */
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return;
+	}
+
 	srclen = op->sym->cipher.data.length;
-	src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-			op->sym->cipher.data.offset);
 	dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
 			op->sym->cipher.data.offset);
 
@@ -787,17 +971,20 @@
 
 	if (sess->cipher.mode == OPENSSL_CIPHER_LIB)
 		if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
-			status = process_openssl_cipher_encrypt(src, dst, iv,
+			status = process_openssl_cipher_encrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
 					sess->cipher.key.data, srclen,
 					sess->cipher.ctx,
 					sess->cipher.evp_algo);
 		else
-			status = process_openssl_cipher_decrypt(src, dst, iv,
+			status = process_openssl_cipher_decrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
 					sess->cipher.key.data, srclen,
 					sess->cipher.ctx,
 					sess->cipher.evp_algo);
 	else
-		status = process_openssl_cipher_des3ctr(src, dst, iv,
+		status = process_openssl_cipher_des3ctr(mbuf_src, dst,
+				op->sym->cipher.data.offset, iv,
 				sess->cipher.key.data, srclen,
 				sess->cipher.ctx);
 
@@ -811,12 +998,10 @@
 		(struct rte_crypto_op *op, struct openssl_session *sess,
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
-	uint8_t *src, *dst;
+	uint8_t *dst;
 	int srclen, status;
 
 	srclen = op->sym->auth.data.length;
-	src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-			op->sym->auth.data.offset);
 
 	if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY)
 		dst = (uint8_t *)rte_pktmbuf_append(mbuf_src,
@@ -831,13 +1016,14 @@
 
 	switch (sess->auth.mode) {
 	case OPENSSL_AUTH_AS_AUTH:
-		status = process_openssl_auth(src, dst,
-				NULL, NULL,	srclen,
+		status = process_openssl_auth(mbuf_src, dst,
+				op->sym->auth.data.offset, NULL, NULL, srclen,
 				sess->auth.auth.ctx, sess->auth.auth.evp_algo);
 		break;
 	case OPENSSL_AUTH_AS_HMAC:
-		status = process_openssl_auth_hmac(src, dst,
-				NULL, sess->auth.hmac.pkey, srclen,
+		status = process_openssl_auth_hmac(mbuf_src, dst,
+				op->sym->auth.data.offset, NULL,
+				sess->auth.hmac.pkey, srclen,
 				sess->auth.hmac.ctx, sess->auth.hmac.evp_algo);
 		break;
 	default:
@@ -851,8 +1037,7 @@
 			op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
 		}
 		/* Trim area used for digest from mbuf. */
-		rte_pktmbuf_trim(mbuf_src,
-				op->sym->auth.digest.length);
+		rte_pktmbuf_trim(mbuf_src, op->sym->auth.digest.length);
 	}
 
 	if (status != 0)
@@ -903,7 +1088,6 @@
 		op->sym->session = NULL;
 	}
 
-
 	if (op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)
 		op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
 
@@ -997,7 +1181,8 @@
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
-			RTE_CRYPTODEV_FF_CPU_AESNI;
+			RTE_CRYPTODEV_FF_CPU_AESNI |
+			RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
 
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
-- 
1.7.9.5

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

* [PATCH v4 3/3] test: add sgl unit tests for crypto devices
  2017-01-05 16:46     ` [PATCH v4 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2017-01-05 16:46       ` [PATCH v4 1/3] crypto: add sgl support in sw PMDs Tomasz Kulasek
  2017-01-05 16:46       ` [PATCH v4 2/3] crypto: add sgl support in openssl PMD Tomasz Kulasek
@ 2017-01-05 16:46       ` Tomasz Kulasek
  2017-01-13 15:23       ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
  3 siblings, 0 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-05 16:46 UTC (permalink / raw)
  To: dev; +Cc: pablo.de.lara.guarch, Daniel Mrzyglod

This patch provides unit tests for set of cipher/hash combinations covering
currently implemented crypto PMD's and allowing to verify scatter gather
support.

Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_cryptodev.c                  |  386 ++++++++++++++++++-
 app/test/test_cryptodev.h                  |  139 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   52 +++
 app/test/test_cryptodev_blockcipher.c      |  180 +++++----
 app/test/test_cryptodev_blockcipher.h      |    1 +
 app/test/test_cryptodev_gcm_test_vectors.h |  553 ++++++++++++++++++++++++++++
 6 files changed, 1241 insertions(+), 70 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 3eaf1b7..4c9a54f 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -1736,6 +1736,10 @@ struct crypto_unittest_params {
 
 	TEST_ASSERT_NOT_NULL(sym_op->cipher.iv.data, "no room to prepend iv");
 
+	/* For OOP operation both buffers must have the same size */
+	if (ut_params->obuf)
+		rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+
 	memset(sym_op->cipher.iv.data, 0, iv_pad_len);
 	sym_op->cipher.iv.phys_addr = rte_pktmbuf_mtophys(ut_params->ibuf);
 	sym_op->cipher.iv.length = iv_pad_len;
@@ -2557,6 +2561,83 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+		/* Validate obuf */
+		TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+			ciphertext,
+			tdata->ciphertext.data,
+			tdata->validCipherLenInBits.len,
+			"KASUMI Ciphertext data not as expected");
+		return 0;
+}
+
+static int
 test_kasumi_encryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2625,6 +2706,81 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_oop_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+
+	const uint8_t *ciphertext;
+	uint8_t buffer[2048];
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"KASUMI Ciphertext data not as expected");
+	return 0;
+}
+
+
+static int
 test_kasumi_decryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2897,6 +3053,85 @@ struct crypto_unittest_params {
 	return 0;
 }
 
+static int
+test_snow3g_encryption_oop_sgl(const struct snow3g_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create SNOW 3G session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple of */
+	/* the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3);
+
+	TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+			"Failed to allocate input buffer in mempool");
+	TEST_ASSERT_NOT_NULL(ut_params->obuf,
+			"Failed to allocate output buffer in mempool");
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create SNOW 3G operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->validCipherLenInBits.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validDataLenInBits.len,
+		"SNOW 3G Ciphertext data not as expected");
+
+	return 0;
+}
+
 /* Shift right a buffer by "offset" bits, "offset" < 8 */
 static void
 buffer_shift_right(uint8_t *buffer, uint32_t length, uint8_t offset)
@@ -3552,6 +3787,84 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_sgl(const struct zuc_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+	const uint8_t *ciphertext;
+	uint8_t ciphertext_buffer[2048];
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+			tdata->plaintext.data);
+
+	/* Create ZUC session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3,
+			tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	/* Clear mbuf payload */
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create ZUC operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+			tdata->iv.len, tdata->plaintext.len,
+			tdata->validCipherOffsetLenInBits.len,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"ZUC Ciphertext data not as expected");
+
+	return 0;
+}
+
+static int
 test_zuc_authentication(const struct zuc_hash_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -3619,12 +3932,24 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_kasumi_encryption_test_case_1_sgl(void)
+{
+	return test_kasumi_encryption_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_1_oop(void)
 {
 	return test_kasumi_encryption_oop(&kasumi_test_case_1);
 }
 
 static int
+test_kasumi_encryption_test_case_1_oop_sgl(void)
+{
+	return test_kasumi_encryption_oop_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_2(void)
 {
 	return test_kasumi_encryption(&kasumi_test_case_2);
@@ -3696,6 +4021,13 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_snow3g_encryption_test_case_1_oop_sgl(void)
+{
+	return test_snow3g_encryption_oop_sgl(&snow3g_test_case_1);
+}
+
+
+static int
 test_snow3g_encryption_test_case_1_offset_oop(void)
 {
 	return test_snow3g_encryption_offset_oop(&snow3g_test_case_1);
@@ -3815,6 +4147,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_test_case_6_sgl(void)
+{
+	return test_zuc_encryption_sgl(&zuc_test_case_1);
+}
+
+static int
 test_zuc_hash_generate_test_case_1(void)
 {
 	return test_zuc_authentication(&zuc_hash_test_case_1);
@@ -3998,12 +4336,21 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 
 	struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
 
-	sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
-			ut_params->ibuf, auth_tag_len);
-	TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
-			"no room to append digest");
-	sym_op->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
-			ut_params->ibuf, data_pad_len);
+	if (ut_params->obuf) {
+		sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+				ut_params->obuf, auth_tag_len);
+		TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+				"no room to append digest");
+		sym_op->auth.digest.phys_addr = sgl_pktmbuf_mtophys_offset(
+				ut_params->obuf, data_pad_len);
+	} else {
+		sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+				ut_params->ibuf, auth_tag_len);
+		TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+				"no room to append digest");
+		sym_op->auth.digest.phys_addr = sgl_pktmbuf_mtophys_offset(
+				ut_params->ibuf, data_pad_len);
+	}
 	sym_op->auth.digest.length = auth_tag_len;
 
 	if (op == RTE_CRYPTO_CIPHER_OP_DECRYPT) {
@@ -4050,6 +4397,11 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 	TEST_HEXDUMP(stdout, "aad:",
 			sym_op->auth.aad.data, aad_len);
 
+	if (ut_params->obuf) {
+		rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+		rte_pktmbuf_prepend(ut_params->obuf, aad_buffer_len);
+	}
+
 	sym_op->cipher.data.length = data_len;
 	sym_op->cipher.data.offset = aad_buffer_len + iv_pad_len;
 
@@ -6312,6 +6664,14 @@ struct test_crypto_vector {
 }
 
 static int
+test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_1seg(void)
+{
+	return test_AES_GCM_authenticated_encryption_SGL(
+			&gcm_test_case_8, OUT_OF_PLACE, 400,
+			gcm_test_case_8.plaintext.len);
+}
+
+static int
 test_AES_GCM_auth_encrypt_SGL_in_place_1500B(void)
 {
 
@@ -6683,6 +7043,10 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_AES_GMAC_authentication_verify_test_case_4),
 
+		/** Scatter-Gather */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_1seg),
+
 		/** Negative tests */
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			authentication_verify_HMAC_SHA1_fail_data_corrupt),
@@ -6751,6 +7115,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_2),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_3),
@@ -6773,6 +7139,10 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_oop_sgl),
+
+
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_decryption_test_case_1_oop),
 
 		/** KASUMI hash only (UIA1) */
@@ -6825,6 +7195,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_snow3g_encryption_test_case_1_oop_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_decryption_test_case_1_oop),
 
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6902,6 +7274,8 @@ struct test_crypto_vector {
 			test_zuc_hash_generate_test_case_4),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_zuc_hash_generate_test_case_5),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_zuc_encryption_test_case_6_sgl),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
 };
diff --git a/app/test/test_cryptodev.h b/app/test/test_cryptodev.h
index a9089aa..77cd826 100644
--- a/app/test/test_cryptodev.h
+++ b/app/test/test_cryptodev.h
@@ -71,4 +71,143 @@
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA384		(24)
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA512		(32)
 
+/**
+ * Write (spread) data from buffer to mbuf data
+ *
+ * @param mbuf
+ *   Destination mbuf
+ * @param offset
+ *   Start offset in mbuf
+ * @param len
+ *   Number of bytes to copy
+ * @param buffer
+ *   Continuous source buffer
+ */
+static inline void
+pktmbuf_write(struct rte_mbuf *mbuf, int offset, int len, const uint8_t *buffer)
+{
+	int n = len;
+	int l;
+	struct rte_mbuf *m;
+	char *dst;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	l = m->data_len - offset;
+
+	/* copy data from first segment */
+	dst = rte_pktmbuf_mtod_offset(m, char *, offset);
+	if (len <= l) {
+		rte_memcpy(dst, buffer, len);
+		return;
+	}
+
+	rte_memcpy(dst, buffer, l);
+	buffer += l;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		dst = rte_pktmbuf_mtod(m, char *);
+		l = m->data_len;
+		if (n < l) {
+			rte_memcpy(dst, buffer, n);
+			return;
+		}
+		rte_memcpy(dst, buffer, l);
+		buffer += l;
+		n -= l;
+	}
+}
+
+static inline uint8_t *
+sgl_pktmbuf_mtod_offset(struct rte_mbuf *mbuf, int offset) {
+	struct rte_mbuf *m;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	if (!m) {
+		printf("sgl_pktmbuf_mtod_offset: offset out of buffer\n");
+		return NULL;
+	}
+	return rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+}
+
+static inline phys_addr_t
+sgl_pktmbuf_mtophys_offset(struct rte_mbuf *mbuf, int offset) {
+	struct rte_mbuf *m;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	if (!m) {
+		printf("sgl_pktmbuf_mtophys_offset: offset out of buffer\n");
+		return 0;
+	}
+	return rte_pktmbuf_mtophys_offset(m, offset);
+}
+
+static inline struct rte_mbuf *
+create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
+		int nb_segs) {
+
+	struct rte_mbuf *m = NULL, *mbuf = NULL;
+	uint8_t *dst;
+	int data_len = 0;
+	int i, size;
+	int t_len;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return NULL;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return NULL;
+	}
+
+	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+	size = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (i = 0; size > 0; i++) {
+
+		m = rte_pktmbuf_alloc(mbuf_pool);
+		if (i == 0)
+			mbuf = m;
+
+		if (!m) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+				rte_pktmbuf_tailroom(m));
+
+		data_len = size > t_len ? t_len : size;
+		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (!dst) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		if (mbuf != m)
+			rte_pktmbuf_chain(mbuf, m);
+
+		size -= data_len;
+
+	}
+	return mbuf;
+
+fail:
+	if (mbuf)
+		rte_pktmbuf_free(mbuf);
+	return NULL;
+}
+
 #endif /* TEST_CRYPTODEV_H_ */
diff --git a/app/test/test_cryptodev_aes_test_vectors.h b/app/test/test_cryptodev_aes_test_vectors.h
index 898aae1..e566548 100644
--- a/app/test/test_cryptodev_aes_test_vectors.h
+++ b/app/test/test_cryptodev_aes_test_vectors.h
@@ -858,6 +858,16 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-192-CTR XCBC Decryption Digest Verify "
+				"Scatter Gather",
+		.test_data = &aes_test_data_2,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "AES-256-CTR HMAC-SHA1 Encryption Digest",
 		.test_data = &aes_test_data_3,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -883,6 +893,18 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+				"Scatter Gather",
+		.test_data = &aes_test_data_4,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_4,
@@ -926,6 +948,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest "
+				"Scatter Gather Sessionless",
+		.test_data = &aes_test_data_6,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS |
+			BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_6,
@@ -935,6 +968,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
+			"Verify Scatter Gather",
+		.test_data = &aes_test_data_6,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "AES-128-CBC XCBC Encryption Digest",
 		.test_data = &aes_test_data_7,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -1045,6 +1089,14 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_MB
 	},
 	{
+		.test_descr = "AES-192-CBC Encryption Scater gather",
+		.test_data = &aes_test_data_10,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
 		.test_descr = "AES-192-CBC Decryption",
 		.test_data = &aes_test_data_10,
 		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
diff --git a/app/test/test_cryptodev_blockcipher.c b/app/test/test_cryptodev_blockcipher.c
index 03dd073..2290c66 100644
--- a/app/test/test_cryptodev_blockcipher.c
+++ b/app/test/test_cryptodev_blockcipher.c
@@ -41,6 +41,7 @@
 #include <rte_cryptodev_pmd.h>
 
 #include "test.h"
+#include "test_cryptodev.h"
 #include "test_cryptodev_blockcipher.h"
 #include "test_cryptodev_aes_test_vectors.h"
 #include "test_cryptodev_des_test_vectors.h"
@@ -63,6 +64,7 @@
 	struct rte_crypto_sym_op *sym_op = NULL;
 	struct rte_crypto_op *op = NULL;
 	struct rte_cryptodev_sym_session *sess = NULL;
+	struct rte_cryptodev_info dev_info;
 
 	int status = TEST_SUCCESS;
 	const struct blockcipher_test_data *tdata = t->test_data;
@@ -72,6 +74,19 @@
 	uint32_t digest_len = 0;
 	char *buf_p = NULL;
 
+	int nb_segs = 3;
+	int nb_segs_oop = 1;
+
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+		rte_cryptodev_info_get(dev_id, &dev_info);
+		if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+			printf("Device doesn't support scatter-gather. "
+					"Test Skipped.\n");
+			return 0;
+		}
+	}
+
 	if (tdata->cipher_key.len)
 		memcpy(cipher_key, tdata->cipher_key.data,
 			tdata->cipher_key.len);
@@ -96,72 +111,112 @@
 	}
 
 	/* preparing data */
-	ibuf = rte_pktmbuf_alloc(mbuf_pool);
-	if (!ibuf) {
-		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-			"line %u FAILED: %s",
-			__LINE__, "Allocation of rte_mbuf failed");
-		status = TEST_FAILED;
-		goto error_exit;
-	}
 
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
 		buf_len += tdata->iv.len;
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
 		buf_len += digest_len;
 
-	buf_p = rte_pktmbuf_append(ibuf, buf_len);
-	if (!buf_p) {
-		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-			"line %u FAILED: %s",
-			__LINE__, "No room to append mbuf");
-		status = TEST_FAILED;
-		goto error_exit;
-	}
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
 
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
-		buf_p += tdata->iv.len;
-	}
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+			ibuf = create_segmented_mbuf(mbuf_pool,
+					tdata->plaintext.len, nb_segs);
+			pktmbuf_write(ibuf, 0, tdata->plaintext.len,
+					tdata->plaintext.data);
+		} else {
+			ibuf = create_segmented_mbuf(mbuf_pool,
+					tdata->ciphertext.len, nb_segs);
+			pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
+					tdata->ciphertext.data);
+		}
 
-	/* only encryption requires plaintext.data input,
-	 * decryption/(digest gen)/(digest verify) use ciphertext.data
-	 * to be computed
-	 */
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
-		rte_memcpy(buf_p, tdata->plaintext.data,
-			tdata->plaintext.len);
-		buf_p += tdata->plaintext.len;
-	} else {
-		rte_memcpy(buf_p, tdata->ciphertext.data,
-			tdata->ciphertext.len);
-		buf_p += tdata->ciphertext.len;
-	}
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+			rte_memcpy(rte_pktmbuf_prepend(ibuf, tdata->iv.len),
+					tdata->iv.data, tdata->iv.len);
+		}
 
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
-		rte_memcpy(buf_p, tdata->digest.data, digest_len);
-	else
-		memset(buf_p, 0, digest_len);
+		buf_p = rte_pktmbuf_append(ibuf, digest_len);
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+			rte_memcpy(buf_p, tdata->digest.data, digest_len);
+		else
+			memset(buf_p, 0, digest_len);
 
-	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
-		obuf = rte_pktmbuf_alloc(mbuf_pool);
-		if (!obuf) {
-			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-				"FAILED: %s", __LINE__,
-				"Allocation of rte_mbuf failed");
+	} else {
+		ibuf = rte_pktmbuf_alloc(mbuf_pool);
+		if (!ibuf) {
+			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+					"line %u FAILED: %s",
+					__LINE__,
+					"Allocation of rte_mbuf failed");
 			status = TEST_FAILED;
 			goto error_exit;
 		}
 
-		buf_p = rte_pktmbuf_append(obuf, buf_len);
+		buf_p = rte_pktmbuf_append(ibuf, buf_len);
 		if (!buf_p) {
-			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-				"FAILED: %s", __LINE__,
-				"No room to append mbuf");
+			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+					"line %u FAILED: %s",
+					__LINE__, "No room to append mbuf");
 			status = TEST_FAILED;
 			goto error_exit;
 		}
-		memset(buf_p, 0, buf_len);
+
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+			rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
+			buf_p += tdata->iv.len;
+		}
+
+		/* only encryption requires plaintext.data input,
+		 * decryption/(digest gen)/(digest verify) use ciphertext.data
+		 * to be computed
+		 */
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+			rte_memcpy(buf_p, tdata->plaintext.data,
+					tdata->plaintext.len);
+			buf_p += tdata->plaintext.len;
+		} else {
+			rte_memcpy(buf_p, tdata->ciphertext.data,
+					tdata->ciphertext.len);
+			buf_p += tdata->ciphertext.len;
+		}
+
+		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+			rte_memcpy(buf_p, tdata->digest.data, digest_len);
+		else
+			memset(buf_p, 0, digest_len);
+	}
+
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+			obuf = create_segmented_mbuf(mbuf_pool, buf_len,
+					nb_segs_oop);
+			if (!obuf) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"Allocation of rte_mbuf failed");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+		} else {
+			obuf = rte_pktmbuf_alloc(mbuf_pool);
+			if (!obuf) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"Allocation of rte_mbuf failed");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+			buf_p = rte_pktmbuf_append(obuf, buf_len);
+			if (!buf_p) {
+				snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+						"line %u FAILED: %s", __LINE__,
+						"No room to append mbuf");
+				status = TEST_FAILED;
+				goto error_exit;
+			}
+			memset(buf_p, 0, buf_len);
+		}
 	}
 
 	/* Generate Crypto op data structure */
@@ -307,17 +362,17 @@
 
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
-			sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
-				(iobuf, uint8_t *, digest_offset);
+			sym_op->auth.digest.data = sgl_pktmbuf_mtod_offset
+				(iobuf, digest_offset);
 			sym_op->auth.digest.phys_addr =
-				rte_pktmbuf_mtophys_offset(iobuf,
+				sgl_pktmbuf_mtophys_offset(iobuf,
 					digest_offset);
 		} else {
 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
-			sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
-				(sym_op->m_src, uint8_t *, digest_offset);
+			sym_op->auth.digest.data = sgl_pktmbuf_mtod_offset
+				(sym_op->m_src, digest_offset);
 			sym_op->auth.digest.phys_addr =
-				rte_pktmbuf_mtophys_offset(sym_op->m_src,
+				sgl_pktmbuf_mtophys_offset(sym_op->m_src,
 					digest_offset);
 		}
 
@@ -386,13 +441,10 @@
 	}
 
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		uint8_t *crypto_res;
+		uint8_t buffer[2048];
 		const uint8_t *compare_ref;
 		uint32_t compare_len;
 
-		crypto_res = rte_pktmbuf_mtod_offset(iobuf, uint8_t *,
-			tdata->iv.len);
-
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
 			compare_ref = tdata->ciphertext.data;
 			compare_len = tdata->ciphertext.len;
@@ -401,7 +453,8 @@
 			compare_len = tdata->plaintext.len;
 		}
 
-		if (memcmp(crypto_res, compare_ref, compare_len)) {
+		if (memcmp(rte_pktmbuf_read(iobuf, tdata->iv.len, compare_len,
+				buffer), compare_ref, compare_len)) {
 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
 				"FAILED: %s", __LINE__,
 				"Crypto data not as expected");
@@ -414,12 +467,11 @@
 		uint8_t *auth_res;
 
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
-			auth_res = rte_pktmbuf_mtod_offset(iobuf,
-				uint8_t *,
-				tdata->iv.len + tdata->ciphertext.len);
+			auth_res = sgl_pktmbuf_mtod_offset(iobuf,
+					tdata->iv.len + tdata->ciphertext.len);
 		else
-			auth_res = rte_pktmbuf_mtod_offset(iobuf,
-				uint8_t *, tdata->ciphertext.len);
+			auth_res = sgl_pktmbuf_mtod_offset(iobuf,
+					tdata->ciphertext.len);
 
 		if (memcmp(auth_res, tdata->digest.data, digest_len)) {
 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
diff --git a/app/test/test_cryptodev_blockcipher.h b/app/test/test_cryptodev_blockcipher.h
index fe97e4c..7256f6b 100644
--- a/app/test/test_cryptodev_blockcipher.h
+++ b/app/test/test_cryptodev_blockcipher.h
@@ -45,6 +45,7 @@
 #define BLOCKCIPHER_TEST_FEATURE_OOP			0x01
 #define BLOCKCIPHER_TEST_FEATURE_SESSIONLESS	0x02
 #define BLOCKCIPHER_TEST_FEATURE_STOPPER	0x04 /* stop upon failing */
+#define BLOCKCIPHER_TEST_FEATURE_SG		0x08 /* Scatter Gather */
 
 #define BLOCKCIPHER_TEST_TARGET_PMD_MB		0x0001 /* Multi-buffer flag */
 #define BLOCKCIPHER_TEST_TARGET_PMD_QAT			0x0002 /* QAT flag */
diff --git a/app/test/test_cryptodev_gcm_test_vectors.h b/app/test/test_cryptodev_gcm_test_vectors.h
index df984fc..45ea3d4 100644
--- a/app/test/test_cryptodev_gcm_test_vectors.h
+++ b/app/test/test_cryptodev_gcm_test_vectors.h
@@ -450,6 +450,559 @@ struct gmac_test_data {
 	}
 };
 
+static const struct gcm_test_data gcm_test_case_8 = {
+	.key = {
+		.data = {
+			0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+			0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+			0xde, 0xca, 0xf8, 0x88
+		},
+		.len = 12
+	},
+	.aad = {
+		.data = {
+			0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+			0xfe, 0xed, 0xfa, 0xce
+		},
+		.len = 12
+	},
+	.plaintext = {
+		.data = {
+			0xC5, 0x34, 0x2E, 0x83, 0xEB, 0x4C, 0x02, 0x03,
+			0xF7, 0xB2, 0x57, 0x35, 0x26, 0x81, 0x63, 0xAE,
+			0x1F, 0xCD, 0x2D, 0x02, 0x91, 0x5A, 0xDB, 0x3A,
+			0xF1, 0x38, 0xD8, 0x75, 0x86, 0x20, 0xCC, 0x1E,
+			0xE6, 0xDC, 0xFF, 0xB5, 0xEA, 0x0E, 0x18, 0x7A,
+			0x86, 0x6C, 0xAB, 0x39, 0x2D, 0x90, 0xAC, 0x77,
+			0x5D, 0xED, 0x65, 0xB3, 0x05, 0x29, 0xBB, 0x09,
+			0xD0, 0x21, 0x74, 0x6A, 0x67, 0x1C, 0x95, 0x42,
+			0x55, 0xAD, 0xC8, 0x91, 0x28, 0xFE, 0x16, 0x9A,
+			0xE1, 0xCB, 0xCD, 0x68, 0x3B, 0xDF, 0x3E, 0x3A,
+			0x34, 0xFE, 0x9B, 0xFB, 0xF5, 0x15, 0x2A, 0x29,
+			0x18, 0x99, 0x24, 0xBF, 0xB6, 0x43, 0xDB, 0xD1,
+			0x69, 0x26, 0x1E, 0x31, 0x2C, 0x8C, 0x3C, 0x6B,
+			0x7F, 0x06, 0xA6, 0x03, 0xE2, 0x1A, 0x50, 0xFE,
+			0x7C, 0x69, 0xE5, 0x5F, 0x35, 0x93, 0xE9, 0x20,
+			0x14, 0xB1, 0xCA, 0x61, 0xE7, 0x9C, 0x89, 0x08,
+			0xD6, 0xB1, 0xC2, 0x63, 0x1B, 0x86, 0x5E, 0xF1,
+			0xF5, 0x23, 0x0E, 0x9B, 0xE5, 0xBD, 0x5D, 0x04,
+			0xF7, 0xEF, 0x8E, 0x46, 0xB0, 0x11, 0x4F, 0x69,
+			0x62, 0x35, 0x51, 0xB7, 0x24, 0xA2, 0x31, 0xD0,
+			0x32, 0x4E, 0xB8, 0x44, 0xC7, 0x59, 0xDE, 0x25,
+			0xEA, 0x2D, 0x00, 0x0E, 0xF1, 0x07, 0xBA, 0xBB,
+			0x9A, 0xBC, 0x4F, 0x57, 0xB7, 0x13, 0x57, 0xEF,
+			0xD9, 0xF6, 0x80, 0x69, 0xEA, 0xE8, 0x47, 0x9C,
+			0x51, 0x71, 0xE6, 0x8F, 0x69, 0x29, 0xB4, 0x60,
+			0xE8, 0x50, 0xE5, 0xD0, 0x9B, 0xD2, 0x62, 0x6F,
+			0x09, 0x5C, 0xD1, 0x4B, 0x85, 0xE2, 0xFD, 0xD3,
+			0xEB, 0x28, 0x55, 0x77, 0x97, 0xCA, 0xD6, 0xA8,
+			0xDC, 0x35, 0x68, 0xF7, 0x6A, 0xCF, 0x48, 0x3F,
+			0x49, 0x31, 0x00, 0x65, 0xB7, 0x31, 0x1A, 0x49,
+			0x75, 0xDE, 0xCE, 0x7F, 0x18, 0xB5, 0x31, 0x9A,
+			0x64, 0x6D, 0xE5, 0x49, 0x1D, 0x6D, 0xF2, 0x21,
+			0x9F, 0xF5, 0xFF, 0x7C, 0x41, 0x30, 0x33, 0x06,
+			0x7B, 0xA4, 0xD8, 0x99, 0xF6, 0xCC, 0xDF, 0xC4,
+			0x3F, 0xF3, 0xCD, 0xE7, 0x74, 0xC4, 0x4A, 0x19,
+			0x5C, 0xCA, 0x42, 0x31, 0xF1, 0x3B, 0x65, 0x1C,
+			0x3D, 0x56, 0x08, 0xBE, 0x15, 0x37, 0x23, 0x50,
+			0xD6, 0xA3, 0x57, 0x64, 0x25, 0xBE, 0xDA, 0xC2,
+			0x4E, 0xF5, 0x1A, 0xAD, 0x6F, 0x43, 0x78, 0x21,
+			0xF9, 0x36, 0x39, 0x1F, 0x5F, 0xF7, 0x1B, 0xA0,
+			0xEE, 0x8B, 0x4F, 0x8A, 0x9D, 0xD8, 0xED, 0x37,
+			0xCE, 0x0D, 0x70, 0xE0, 0x3F, 0xE7, 0x11, 0x30,
+			0x17, 0x1D, 0x03, 0x5E, 0xA0, 0x3D, 0x3F, 0x9E,
+			0xF5, 0xD3, 0x74, 0x2E, 0xC1, 0xD6, 0xFF, 0xF7,
+			0x2E, 0xE7, 0x80, 0x88, 0xCF, 0x0E, 0x7F, 0x12,
+			0x71, 0x62, 0xC7, 0xF1, 0xC4, 0x2B, 0x64, 0x5D,
+			0x1C, 0x9A, 0xB4, 0xCB, 0xB8, 0x24, 0xB3, 0x0B,
+			0x33, 0xF2, 0x8A, 0x8F, 0x76, 0xC8, 0x81, 0xDA,
+			0x1A, 0x10, 0xB5, 0xA9, 0xCD, 0xDC, 0x1A, 0x02,
+			0xC1, 0xAE, 0x4F, 0x02, 0x1B, 0x13, 0x96, 0x5A,
+			0x2E, 0x03, 0xA2, 0x68, 0xB2, 0x29, 0xAC, 0x28,
+			0xB8, 0xDC, 0xD5, 0x27, 0x55, 0xEC, 0x43, 0xDC,
+			0xB7, 0x49, 0x1D, 0xE1, 0x30, 0x25, 0x81, 0xA6,
+			0x90, 0x1F, 0x75, 0xBA, 0x19, 0x1E, 0xF7, 0xC5,
+			0x77, 0x35, 0xEE, 0x68, 0x71, 0x22, 0xA0, 0xB4,
+			0xCC, 0x99, 0x86, 0x1B, 0x1B, 0xC8, 0x27, 0xFC,
+			0x6D, 0x8D, 0xE7, 0x8B, 0xC3, 0x40, 0x3D, 0xA8,
+			0xCB, 0x9B, 0xC4, 0x12, 0x07, 0xDD, 0xA1, 0x92,
+			0xE5, 0x80, 0x7A, 0xF4, 0xDB, 0x4C, 0xE6, 0xEE,
+			0xF9, 0xD5, 0x1C, 0x20, 0x18, 0xD3, 0x8F, 0xDF,
+			0x1C, 0xD3, 0x51, 0x4E, 0x0E, 0xED, 0x06, 0x61,
+			0xF7, 0xBA, 0x81, 0x3A, 0x2F, 0xEA, 0xED, 0x70,
+			0xA9, 0xD9, 0x54, 0x4D, 0xFC, 0x1D, 0x19, 0xEA,
+			0xA6, 0x39, 0x8C, 0x6C, 0x78, 0xA8, 0x05, 0xEB,
+			0xF2, 0xB5, 0xDE, 0x06, 0x9D, 0x8A, 0x78, 0x2A,
+			0xF5, 0x50, 0xA4, 0xBD, 0x9B, 0xDA, 0xCA, 0x66,
+			0xC0, 0x23, 0xAB, 0xE8, 0x95, 0x7E, 0xC9, 0xD2,
+			0x6F, 0x09, 0xF2, 0x9A, 0x17, 0x89, 0xDA, 0x47,
+			0x65, 0x8C, 0x20, 0xFA, 0x4E, 0x86, 0x18, 0xEB,
+			0x7C, 0x08, 0xEC, 0x8A, 0x05, 0x54, 0x96, 0xD2,
+			0x7A, 0x8A, 0x81, 0x58, 0x75, 0x8C, 0x7B, 0x02,
+			0xEE, 0x1F, 0x51, 0x88, 0xD0, 0xD1, 0x90, 0x99,
+			0x0C, 0xAE, 0x51, 0x2E, 0x54, 0x3E, 0xB1, 0x7D,
+			0xBC, 0xE8, 0x54, 0x93, 0x6D, 0x10, 0x3C, 0xC6,
+			0x71, 0xF6, 0xF5, 0x0B, 0x07, 0x0A, 0x6E, 0x59,
+			0x20, 0x45, 0x21, 0x7D, 0x37, 0x64, 0x92, 0x09,
+			0xA7, 0xE2, 0x34, 0x6F, 0xFC, 0xCC, 0x66, 0x0E,
+			0x88, 0x1B, 0x19, 0x86, 0x11, 0xD7, 0x81, 0x25,
+			0xF1, 0x8A, 0x03, 0xB7, 0x7A, 0xF0, 0x98, 0x4A,
+			0x5C, 0xA1, 0x6D, 0x85, 0xA4, 0x8C, 0x4B, 0x65,
+			0x9F, 0x72, 0x64, 0x14, 0xBA, 0x74, 0xEE, 0xA3,
+			0x88, 0xFE, 0x1B, 0xCF, 0x11, 0x4F, 0xD1, 0xAC,
+			0xFA, 0x14, 0xC3, 0xA7, 0xDD, 0x06, 0x85, 0x4E,
+			0x64, 0x06, 0x92, 0x9C, 0xDF, 0x06, 0x09, 0xF1,
+			0x4D, 0xE8, 0xF8, 0x2F, 0x69, 0xB6, 0x8A, 0xAF,
+			0x25, 0x21, 0xB5, 0x48, 0x59, 0xF8, 0x9D, 0x60,
+			0xAE, 0x42, 0x11, 0x7A, 0x68, 0x4D, 0x7E, 0x76,
+			0xB0, 0xD2, 0xE3, 0xD9, 0x24, 0x16, 0x20, 0x0A,
+			0xEB, 0xE0, 0x68, 0xCB, 0xBC, 0xAB, 0x67, 0xE4,
+			0xF3, 0x25, 0x1F, 0xD3, 0x85, 0xA7, 0x1D, 0x7E,
+			0x3C, 0x63, 0xCB, 0xC2, 0x50, 0x90, 0x0F, 0x4B,
+			0x6E, 0x68, 0x06, 0x84, 0x65, 0xF7, 0xD0, 0xD4,
+			0x12, 0xED, 0xFA, 0xC9, 0x40, 0xE2, 0xC0, 0xC9,
+			0x46, 0x22, 0x47, 0x5E, 0x6D, 0xC1, 0x63, 0xDB,
+			0x51, 0x98, 0xDA, 0x1A, 0xC4, 0xB9, 0xED, 0xE9,
+			0x09, 0xB9, 0xCF, 0x91, 0x04, 0x1C, 0x63, 0xD8,
+			0xC5, 0xA5, 0xAE, 0x53, 0x7B, 0xA1, 0x29, 0x83,
+			0x37, 0xFB, 0xBF, 0x96, 0xBB, 0x24, 0x3D, 0x77,
+			0x8C, 0x0F, 0xB3, 0x4B, 0x66, 0x9C, 0x54, 0xBB,
+			0xF6, 0xDD, 0xD1, 0xB4, 0xD2, 0xF6, 0xAA, 0xED,
+			0x18, 0x56, 0x63, 0x3E, 0x0B, 0xCA, 0xAB, 0x70,
+			0xBB, 0x63, 0xEA, 0xB1, 0x00, 0x65, 0x90, 0x18,
+			0xB8, 0x63, 0xA2, 0xF2, 0xB6, 0x1E, 0x61, 0x7B,
+			0xD5, 0x01, 0xD9, 0x4D, 0xC9, 0x9D, 0x99, 0xC1,
+			0x57, 0x9D, 0x6F, 0xAE, 0x64, 0xE4, 0x0C, 0x7E,
+			0xFA, 0x15, 0x5E, 0xB6, 0x43, 0xB8, 0x8B, 0x89,
+			0x87, 0xCD, 0x4F, 0xAD, 0x30, 0x1E, 0xA5, 0x03,
+			0x7A, 0xC2, 0x10, 0x42, 0x14, 0x88, 0xD6, 0x7A,
+			0x6D, 0x56, 0x52, 0x2E, 0x8D, 0x1B, 0x5D, 0x36,
+			0x27, 0xA0, 0x21, 0x4B, 0x64, 0xF0, 0xC5, 0x41,
+			0xAD, 0x05, 0x4A, 0x24, 0xE4, 0x70, 0x88, 0x63,
+			0x12, 0xD0, 0xBC, 0x05, 0x38, 0xD9, 0x41, 0x68,
+			0x9F, 0x16, 0x9A, 0x54, 0x09, 0x21, 0x64, 0x36,
+			0x63, 0x97, 0x3A, 0xB5, 0xE0, 0x25, 0x43, 0x8A,
+			0x6A, 0x59, 0x97, 0xC1, 0x31, 0xA5, 0x66, 0xD2,
+			0xF0, 0x1C, 0xDF, 0x97, 0x51, 0xD0, 0x61, 0xBA,
+			0x55, 0x5F, 0xD7, 0x0D, 0xD4, 0x75, 0x8E, 0x79,
+			0x04, 0x75, 0x00, 0xB9, 0xC0, 0x7A, 0x66, 0x05,
+			0x9F, 0x2B, 0x44, 0x42, 0x75, 0x0F, 0xD5, 0x15,
+			0xD6, 0x16, 0x8F, 0x6C, 0x6E, 0xD4, 0x37, 0xCF,
+			0xB4, 0xDA, 0x93, 0x00, 0x11, 0xFB, 0xBE, 0xEE,
+			0x3B, 0x6D, 0x1D, 0xBA, 0x33, 0xD1, 0x52, 0x8B,
+			0x16, 0x39, 0x42, 0x27, 0xE6, 0x56, 0x4C, 0x41,
+			0x91, 0xB0, 0x98, 0xAE, 0x9B, 0x2D, 0x9B, 0x23,
+			0x80, 0x4C, 0xEA, 0x98, 0x57, 0x95, 0x28, 0x94,
+			0x43, 0xD3, 0x88, 0x12, 0xDF, 0x89, 0x5A, 0x7B,
+			0xC5, 0xCB, 0x36, 0x54, 0x65, 0x74, 0xB8, 0x4E,
+			0xE2, 0x4D, 0x01, 0xD5, 0x9C, 0x82, 0xB9, 0x1A,
+			0x09, 0xD2, 0xCE, 0x04, 0x36, 0xD8, 0x41, 0xAC,
+			0x4C, 0xAD, 0xC6, 0x52, 0x91, 0x1A, 0x06, 0x6D,
+			0xFC, 0xAB, 0x29, 0x93, 0x87, 0x88, 0xB9, 0x8C,
+			0xFA, 0x57, 0x2B, 0x05, 0x03, 0xD0, 0x18, 0xED,
+			0x7A, 0x7B, 0x81, 0x6A, 0x97, 0x65, 0x5B, 0x90,
+			0xDE, 0xA9, 0xFC, 0x8F, 0xFC, 0xBB, 0x98, 0xD8,
+			0xFA, 0x32, 0x3F, 0x3F, 0x7F, 0x74, 0x65, 0x38,
+			0xC4, 0x28, 0xEC, 0x27, 0x1F, 0x28, 0x01, 0xB1,
+			0xAF, 0x2B, 0x8A, 0x05, 0x38, 0x7B, 0x77, 0xC9,
+			0x61, 0x77, 0x34, 0x2C, 0x22, 0xE5, 0xEB, 0xDC,
+			0x9D, 0x18, 0x6E, 0x23, 0x25, 0x52, 0x69, 0xB7,
+			0x05, 0xDB, 0x66, 0x5D, 0xEA, 0x76, 0x83, 0x82,
+			0x97, 0x39, 0xAF, 0xC0, 0x50, 0x81, 0x18, 0x0D,
+			0x22, 0xFA, 0xB7, 0x44, 0x5C, 0x3F, 0x69, 0xF3,
+			0xAC, 0xC5, 0x63, 0x9F, 0xD8, 0x72, 0x7E, 0x9A,
+			0xC2, 0xEB, 0x79, 0xD0, 0x74, 0x65, 0xE8, 0xCA,
+			0xFD, 0xA8, 0x7D, 0x23, 0x07, 0x99, 0x3E, 0xAF,
+			0xDB, 0x67, 0x10, 0xC0, 0xE5, 0x61, 0x77, 0xC6,
+			0x8D, 0xC4, 0x0E, 0xAA, 0x55, 0xE3, 0xC0, 0xC7,
+			0xA5, 0x36, 0x28, 0x61, 0xDB, 0x16, 0x96, 0x5E,
+			0x01, 0x47, 0x82, 0xE3, 0xEB, 0x20, 0x3F, 0x10,
+			0xFA, 0x5A, 0xBC, 0xD3, 0xF9, 0xCE, 0x04, 0x87,
+			0x51, 0x07, 0xF9, 0xD0, 0xE7, 0x6D, 0xCB, 0xCC,
+			0xC4, 0x15, 0x00, 0xE2, 0xDC, 0x8E, 0x7B, 0x5C,
+			0x9A, 0xF2, 0x78, 0x70, 0x4D, 0xA1, 0xAA, 0xB5,
+			0x13, 0xCC, 0x71, 0x66, 0x5A, 0x79, 0x13, 0x3B,
+			0x12, 0xCD, 0x40, 0x30, 0x5A, 0x49, 0xD4, 0x20,
+			0xED, 0xCF, 0x4A, 0x75, 0xE6, 0xD5, 0xDD, 0x0F,
+			0xD4, 0xBE, 0x98, 0x9F, 0xD7, 0x1F, 0xC0, 0x02,
+			0x31, 0xFA, 0x67, 0x37, 0x25, 0x86, 0x56, 0x85,
+			0x2B, 0xA2, 0x57, 0xCD, 0x8E, 0x74, 0xE7, 0x69,
+			0xEE, 0x33, 0x5A, 0x3F, 0xCD, 0x1E, 0xE3, 0xB9,
+			0xAA, 0x52, 0xF5, 0x22, 0x4E, 0xE3, 0xFF, 0xC8,
+			0xE3, 0x13, 0xA3, 0x9A, 0x63, 0x23, 0xC3, 0xD7,
+			0xE5, 0x88, 0x3E, 0x0A, 0x4B, 0xA5, 0x01, 0xE6,
+			0x13, 0xCF, 0xED, 0xEE, 0x2A, 0x58, 0x09, 0x3F,
+			0x2F, 0x28, 0xE7, 0xC4, 0x6B, 0xEC, 0x49, 0x51,
+			0x79, 0x8F, 0xD5, 0x19, 0x5D, 0xA5, 0x10, 0xCE,
+			0x8E, 0xF6, 0x26, 0x78, 0x7A, 0xA8, 0x11, 0x52,
+			0x5F, 0x97, 0x14, 0xC9, 0x29, 0x87, 0xB8, 0xA0,
+			0x2D, 0xE6, 0xA7, 0x2A, 0xD4, 0xFF, 0xEB, 0xBA,
+			0xFD, 0x58, 0x39, 0x33, 0xB1, 0xCE, 0x0E, 0x78,
+			0x67, 0x1E, 0xA1, 0x92, 0x77, 0x63, 0xF8, 0xC0,
+			0x02, 0x49, 0x73, 0xC0, 0xA1, 0x26, 0x83, 0x04,
+			0x9A, 0x5D, 0x85, 0x68, 0x2A, 0x2F, 0xCB, 0x88,
+			0x8D, 0x14, 0xB1, 0x33, 0xFA, 0xFB, 0xE9, 0x05,
+			0xBE, 0x24, 0x1A, 0x6B, 0x29, 0x2B, 0x3F, 0x52,
+			0x8F, 0xFB, 0xE6, 0x02, 0x77, 0x50, 0x71, 0xDB,
+			0xE9, 0x92, 0x3F, 0xE1, 0x20, 0x62, 0x80, 0xAE,
+			0xA4, 0x98, 0xC6, 0xCD, 0xE0, 0xB1, 0xC3, 0x33,
+			0xB1, 0xC5, 0x91, 0x3C, 0x19, 0x34, 0xA8, 0xD9,
+			0xB3, 0x25, 0x69, 0xE3, 0x9C, 0x5F, 0x78, 0xD0,
+			0x83, 0x1F, 0xAB, 0x85, 0x13, 0x56, 0x69, 0xB5,
+			0x06, 0x47, 0x62, 0x37, 0x27, 0x15, 0x14, 0x05,
+			0x4A, 0xF4, 0x6A, 0x68, 0x2A, 0x6A, 0xC3, 0x5A,
+			0xDF, 0xB5, 0xAE, 0x2F, 0x8D, 0x8F, 0x21, 0xDB,
+			0x33, 0x00, 0x9B, 0xD4, 0xC4, 0x08, 0x3B, 0x81,
+			0x63, 0x4C, 0xB0, 0x39, 0x4C, 0x0A, 0xD5, 0x71,
+			0x3E, 0x5A, 0x50, 0x58, 0x9C, 0x07, 0x89, 0x79,
+			0x79, 0x2F, 0x0B, 0xD9, 0x50, 0xBC, 0xCF, 0x46,
+			0x7A, 0x68, 0x5C, 0xBF, 0x1E, 0x49, 0x77, 0x92,
+			0x85, 0x11, 0x39, 0xA6, 0x2F, 0xDA, 0x7B, 0xFA,
+			0x72, 0x87, 0x06, 0xCD, 0x84, 0x41, 0x20, 0x1B,
+			0x66, 0x3F, 0x42, 0x0C, 0x9E, 0x19, 0xD3, 0x18,
+			0x57, 0xA0, 0xEE, 0x16, 0x3A, 0xC7, 0xF9, 0xD3,
+			0x8B, 0xC9, 0x24, 0x70, 0x70, 0x51, 0x7C, 0x06,
+			0x68, 0xD3, 0x29, 0xC9, 0x85, 0x9A, 0x1C, 0xE6,
+			0x8C, 0x17, 0xF4, 0x88, 0xDF, 0xEA, 0xFF, 0x44,
+			0x8D, 0x54, 0xBE, 0x22, 0x07, 0xA5, 0x7C, 0x0C,
+			0xF4, 0x8D, 0xB1, 0x0C, 0x07, 0xED, 0xBD, 0x28,
+			0x19, 0xDA, 0x07, 0x71, 0xA8, 0xA1, 0xE0, 0xDD,
+			0xEE, 0x08, 0x18, 0xA5, 0xBD, 0xDD, 0x32, 0x0B,
+			0x70, 0x1C, 0xD9, 0xEE, 0x19, 0xC2, 0xAE, 0x5C,
+			0xE3, 0x02, 0x74, 0x70, 0x96, 0x61, 0xB1, 0x73,
+			0x3B, 0xD6, 0x74, 0xC0, 0x82, 0xA9, 0x1F, 0xE0,
+			0xF1, 0x22, 0x50, 0xF3, 0x9F, 0xE5, 0x13, 0x92,
+			0xFC, 0x0A, 0x1A, 0x3C, 0xB4, 0x46, 0xFB, 0x81,
+			0x00, 0x84, 0xA4, 0x5E, 0x6B, 0x8C, 0x25, 0x6E,
+			0xD7, 0xB7, 0x3B, 0x01, 0x65, 0xFB, 0x0B, 0x46,
+			0x67, 0x27, 0x2D, 0x51, 0xAD, 0xB5, 0xE0, 0x85,
+			0xC2, 0x95, 0xA3, 0xE3, 0x68, 0x4D, 0x9E, 0x8C,
+			0x11, 0x53, 0xF0, 0xB2, 0x85, 0xFA, 0x52, 0x4E,
+			0xEC, 0xF9, 0xB7, 0x3C, 0x89, 0x2C, 0x4D, 0x32,
+			0x9A, 0xCB, 0x17, 0xF3, 0x16, 0xBF, 0x44, 0x40,
+			0xE9, 0x5E, 0x51, 0x8C, 0x1E, 0x52, 0x0A, 0xC2,
+			0xCD, 0xA5, 0xAA, 0x03, 0x27, 0xB0, 0x8F, 0x64,
+			0xDB, 0xD7, 0x03, 0x01, 0x8A, 0x24, 0x28, 0x7E,
+			0x53, 0x6F, 0x24, 0xFD, 0xAA, 0xE3, 0x78, 0xB6,
+			0xA5, 0x5D, 0x5A, 0x67, 0x20, 0xE2, 0xBE, 0x3A,
+			0x2B, 0xE7, 0x86, 0x11, 0xDD, 0x96, 0xCB, 0x09,
+			0x65, 0xA0, 0x36, 0xF9, 0xB0, 0x20, 0x21, 0x8E,
+			0xDB, 0xC0, 0x73, 0xC7, 0x79, 0xD8, 0xDA, 0xC2,
+			0x66, 0x13, 0x64, 0x34, 0x0C, 0xE1, 0x22, 0x24,
+			0x61, 0x67, 0x08, 0x39, 0x97, 0x3F, 0x33, 0x96,
+			0xF2, 0x44, 0x18, 0x75, 0xBB, 0xF5, 0x6A, 0x5C,
+			0x2C, 0xAE, 0x2A, 0x79, 0x3D, 0x47, 0x19, 0x53,
+			0x50, 0x6C, 0x9F, 0xB3, 0x82, 0x55, 0x09, 0x78,
+			0x7B, 0xAD, 0xBC, 0x05, 0x6F, 0xC8, 0x3D, 0xB6,
+			0x7B, 0x30, 0xE6, 0xBB, 0x8B, 0xD0, 0x2F, 0xA6,
+			0x15, 0xCC, 0x77, 0x8C, 0x21, 0xBA, 0x03, 0xED,
+			0x56, 0x85, 0x82, 0x4F, 0x97, 0x8C, 0x59, 0x4F,
+			0x53, 0x5A, 0xD2, 0x70, 0xD9, 0x07, 0xB3, 0xBD,
+			0x1D, 0x3E, 0x97, 0xD4, 0x7D, 0x93, 0x35, 0xA4,
+			0x82, 0x6E, 0xEA, 0x4B, 0xC8, 0x6C, 0xF5, 0xE6,
+			0xEB, 0xAF, 0x11, 0xB0, 0xB4, 0x71, 0x8F, 0x7B,
+			0xC4, 0x8C, 0xE2, 0x66, 0x51, 0x31, 0x99, 0x01,
+			0x5B, 0xE7, 0x48, 0xF8, 0x4C, 0xE3, 0x9A, 0x77,
+			0xF1, 0xC6, 0x09, 0xDE, 0x76, 0xD4, 0xE3, 0x5C,
+			0xDF, 0xA3, 0xEC, 0x3C, 0x86, 0x7C, 0xA5, 0x3F,
+			0x8D, 0x2A, 0xF3, 0x0B, 0x54, 0xB7, 0x54, 0xA2,
+			0xC1, 0x69, 0xC0, 0x6F, 0x1C, 0x1C, 0x76, 0xD8,
+			0x9F, 0x7A, 0x32, 0xB0, 0xA1, 0xA6, 0x9B, 0xB7,
+			0x21, 0x56, 0x28, 0x2D, 0xB6, 0x97, 0x03, 0x5E,
+			0x65, 0xE3, 0x74, 0x9A, 0x96, 0x7A, 0xF9, 0xF5,
+			0xDD, 0x85, 0xCA, 0x4C, 0xB4, 0x03, 0x6A, 0xCD,
+			0xB6, 0x01, 0xDC, 0x8B, 0xD8, 0x73, 0x8F, 0x4D,
+			0x7F, 0xD6, 0x71, 0xEC, 0xD7, 0xC6, 0x0B, 0x5F,
+			0x09, 0x21, 0xB2, 0x78, 0xA8, 0xAF, 0xAD, 0x2C,
+			0xD4, 0x93, 0x9F, 0x71, 0xF7, 0x05, 0x89, 0x42,
+			0xC9, 0x15, 0x6F, 0x2D, 0xE0, 0xBA, 0xC3, 0xD6,
+			0xBF, 0xAC, 0xF8, 0x24, 0x58, 0x79, 0xA9, 0xC4,
+			0xB4, 0x49, 0x3E, 0x0B, 0x9E, 0x5E, 0xE4, 0xA6,
+			0x8B, 0xE8, 0xDE, 0xFB, 0x4A, 0xF1, 0x69, 0x9D,
+			0x4F, 0x77, 0x83, 0x78, 0x55, 0x19, 0x42, 0x45,
+			0xBF, 0xBD, 0xBD, 0x12, 0x0F, 0xEF, 0x8D, 0x04,
+			0xD8, 0x5C, 0xF2, 0xC9, 0xF1, 0xA6, 0xE0, 0x3E,
+			0x22, 0xA8, 0xA2, 0x5E, 0x66, 0xE9, 0xAB, 0xB4,
+			0x71, 0xBE, 0x4B, 0x3F, 0xBE, 0xC4, 0xBA, 0x4A
+		},
+		.len = 2048
+	},
+	.ciphertext = {
+		.data = {
+			0x5E, 0x86, 0x02, 0x64, 0x32, 0xBF, 0x70, 0xC2,
+			0x19, 0x99, 0x7F, 0x47, 0x0D, 0xA4, 0x91, 0xA8,
+			0x7A, 0xC0, 0xA5, 0x7E, 0xA8, 0x6C, 0x88, 0x00,
+			0xEA, 0xB5, 0x96, 0x6B, 0x25, 0xBD, 0xE7, 0x42,
+			0xDB, 0x35, 0xE7, 0x92, 0x2B, 0x00, 0x82, 0x35,
+			0xD4, 0x2C, 0xCF, 0x47, 0xC8, 0xB2, 0xB3, 0x57,
+			0xF7, 0x24, 0x83, 0x7F, 0xC5, 0x2E, 0xF1, 0xC9,
+			0x57, 0x1A, 0xEF, 0xC2, 0x3A, 0x8C, 0x1E, 0x92,
+			0x88, 0x05, 0xAF, 0x55, 0xE6, 0x0C, 0xA7, 0x6B,
+			0x59, 0x62, 0x32, 0x21, 0xF1, 0xFF, 0xB5, 0x5B,
+			0x22, 0x26, 0x6F, 0x0A, 0x36, 0xDC, 0x0D, 0x16,
+			0x3B, 0x4E, 0x7C, 0xA3, 0x75, 0x30, 0x3F, 0xB0,
+			0x99, 0x38, 0x42, 0x8E, 0x89, 0xA3, 0x7C, 0x99,
+			0x2F, 0x0A, 0xA1, 0xC7, 0xFD, 0x2D, 0x21, 0x8F,
+			0xBD, 0xD4, 0x11, 0xEA, 0x55, 0xF5, 0x6A, 0x50,
+			0x90, 0x3B, 0x60, 0x57, 0xE1, 0x86, 0x1E, 0x50,
+			0x28, 0x67, 0x3F, 0xD2, 0xF3, 0xBD, 0xFA, 0xEE,
+			0xD6, 0x5A, 0x38, 0x30, 0xA3, 0xDD, 0x78, 0xC4,
+			0x37, 0x59, 0x52, 0xC0, 0x92, 0x54, 0xC7, 0x53,
+			0xF0, 0xE6, 0xA9, 0x63, 0x1F, 0x9B, 0x97, 0xFB,
+			0x40, 0x23, 0xFE, 0x52, 0x6A, 0xF0, 0x3A, 0x94,
+			0xEB, 0x6A, 0x9E, 0x8F, 0xC5, 0x05, 0x9C, 0x04,
+			0x1B, 0x00, 0x34, 0x96, 0x12, 0xDA, 0x60, 0xC6,
+			0xAA, 0x1A, 0x3E, 0xEB, 0x70, 0x17, 0x10, 0xBC,
+			0xF5, 0xC2, 0xE2, 0x71, 0xF3, 0xB8, 0x1D, 0xCE,
+			0x47, 0x94, 0x21, 0x71, 0x34, 0x8C, 0xCC, 0xDD,
+			0x27, 0xCE, 0x6F, 0x68, 0xFF, 0x91, 0x4E, 0xC4,
+			0xA0, 0xCA, 0xB0, 0x4F, 0x17, 0x53, 0x73, 0x92,
+			0x6C, 0xA8, 0x16, 0x06, 0xE3, 0xD9, 0x92, 0x99,
+			0xBE, 0xB0, 0x7D, 0x56, 0xF2, 0x72, 0x30, 0xDA,
+			0xC4, 0x4E, 0xF4, 0xA6, 0x8F, 0xD2, 0xC7, 0x8A,
+			0xA2, 0xFC, 0xF5, 0x63, 0x17, 0x48, 0x56, 0x4D,
+			0xBE, 0x94, 0xFE, 0xF5, 0xB1, 0xA9, 0x96, 0xAB,
+			0x3F, 0x2D, 0xD4, 0x15, 0xEE, 0x4F, 0xFA, 0x2C,
+			0xBE, 0x91, 0xB7, 0xBC, 0x18, 0xC8, 0xDB, 0x02,
+			0x20, 0x29, 0xF1, 0xC1, 0x88, 0x8C, 0x8D, 0xD1,
+			0xB3, 0x4E, 0x93, 0x96, 0xDD, 0x22, 0xAB, 0x55,
+			0xB5, 0x9F, 0x8B, 0x20, 0xAE, 0xC6, 0x0E, 0x26,
+			0xC6, 0xFE, 0x2D, 0x5F, 0x95, 0x89, 0x06, 0x15,
+			0x3D, 0x88, 0x16, 0xEC, 0x9B, 0x4A, 0x1B, 0x5D,
+			0x2E, 0xB2, 0x13, 0x56, 0x9F, 0x33, 0xB3, 0x45,
+			0xBF, 0x5F, 0x25, 0x7E, 0x75, 0x22, 0xD2, 0xE6,
+			0x9F, 0xAC, 0x2D, 0xFD, 0x99, 0xC2, 0x9B, 0xFC,
+			0xD7, 0x7A, 0x9B, 0x05, 0x30, 0x0F, 0xB7, 0x4A,
+			0xFE, 0x24, 0xDD, 0x39, 0x9B, 0xBB, 0x2F, 0xDD,
+			0xF9, 0xFB, 0xCA, 0x6C, 0x87, 0xBA, 0x73, 0xD4,
+			0x85, 0x7B, 0xB2, 0x6F, 0x5C, 0xD8, 0xFB, 0xE9,
+			0x41, 0x24, 0x3A, 0x3B, 0x4F, 0x91, 0x77, 0xA2,
+			0x35, 0x78, 0xE5, 0x4C, 0xFE, 0x8B, 0x04, 0x03,
+			0xD3, 0x84, 0xA9, 0x1C, 0xA7, 0x7C, 0x45, 0x13,
+			0x7D, 0xC5, 0x0A, 0x2F, 0x02, 0xF8, 0x56, 0xD5,
+			0x5F, 0x35, 0xED, 0x06, 0xBF, 0x67, 0xBA, 0x51,
+			0x02, 0x95, 0x36, 0xF2, 0x9A, 0xBA, 0x9D, 0xF6,
+			0xD6, 0x77, 0x50, 0xC9, 0xFC, 0x1E, 0x32, 0xB5,
+			0x2F, 0xEA, 0x3C, 0x76, 0xB4, 0xE1, 0xCC, 0x42,
+			0xEB, 0x71, 0x79, 0xD3, 0x7D, 0xB7, 0xC0, 0x88,
+			0x25, 0x81, 0xE8, 0xC0, 0xB8, 0x38, 0x7E, 0x7B,
+			0xFD, 0x18, 0xAB, 0x08, 0xB2, 0x71, 0xA5, 0xAD,
+			0xA7, 0xBE, 0x48, 0x5F, 0x86, 0xE2, 0x41, 0x3D,
+			0x7C, 0x37, 0x7A, 0xAB, 0xDB, 0xE0, 0x3B, 0x3D,
+			0xB6, 0xE8, 0x23, 0x7C, 0xF1, 0x8F, 0xBA, 0xB7,
+			0xE9, 0x78, 0x0B, 0xCA, 0x67, 0xA8, 0x10, 0x36,
+			0xEB, 0x72, 0xED, 0xDD, 0xF0, 0x5C, 0x74, 0x8E,
+			0xE5, 0x2A, 0xAE, 0x6E, 0xC4, 0xF1, 0xFC, 0xD8,
+			0xEE, 0x56, 0x07, 0x88, 0x02, 0xDC, 0x9D, 0xB7,
+			0xF9, 0x13, 0xE1, 0xE1, 0x9D, 0x89, 0x26, 0x0B,
+			0x23, 0x74, 0x4A, 0x43, 0xAA, 0xA0, 0xA8, 0x97,
+			0x85, 0x15, 0x58, 0xAB, 0x2B, 0xB5, 0xDA, 0x1A,
+			0xBA, 0x29, 0x62, 0xCF, 0xDD, 0xA3, 0xBA, 0x9D,
+			0x7D, 0x83, 0xA5, 0x18, 0xD4, 0x03, 0x0F, 0x61,
+			0x9F, 0xB1, 0x7E, 0xEC, 0xD2, 0x6E, 0xAF, 0xCF,
+			0x1E, 0xC1, 0x88, 0x97, 0x99, 0xD6, 0xBF, 0x47,
+			0xB9, 0x0A, 0x69, 0x11, 0x3A, 0x55, 0x8B, 0x1D,
+			0x2D, 0xFF, 0x78, 0xC8, 0xDE, 0x82, 0x29, 0xD6,
+			0x08, 0x3C, 0xC4, 0xCB, 0x2F, 0x01, 0xD0, 0xE8,
+			0xB1, 0x75, 0x5E, 0x23, 0xE0, 0x37, 0x7C, 0x1C,
+			0xB6, 0xD9, 0x47, 0xDE, 0x23, 0x87, 0xD3, 0x68,
+			0x47, 0x46, 0x78, 0xF3, 0xBF, 0x54, 0xA3, 0xB9,
+			0x54, 0xD5, 0xC5, 0x0A, 0x7C, 0x92, 0x2A, 0xC2,
+			0x14, 0x76, 0xA6, 0x5C, 0x6D, 0x0B, 0x94, 0x56,
+			0x00, 0x6B, 0x5C, 0x27, 0xDE, 0x77, 0x9B, 0xF1,
+			0xB1, 0x8C, 0xA7, 0x49, 0x77, 0xFC, 0x4E, 0x29,
+			0x23, 0x8F, 0x2F, 0xF7, 0x83, 0x8D, 0x36, 0xD9,
+			0xAB, 0x0E, 0x78, 0xF5, 0x90, 0x05, 0xB9, 0x79,
+			0x70, 0x88, 0x59, 0x6F, 0xE2, 0xC5, 0xD7, 0x80,
+			0x95, 0x04, 0x29, 0xE0, 0xFA, 0x37, 0xE8, 0x8B,
+			0xC5, 0x21, 0x51, 0x1A, 0x62, 0xCE, 0x93, 0xAF,
+			0x1A, 0xFE, 0xC3, 0x6F, 0x86, 0x94, 0x5E, 0x13,
+			0xA6, 0x9A, 0x26, 0xF0, 0xB5, 0x7C, 0x41, 0x9A,
+			0x80, 0xB8, 0x84, 0x5A, 0x55, 0xA9, 0xB0, 0x6A,
+			0xFA, 0xEB, 0x46, 0x32, 0x0B, 0xE2, 0x9C, 0x65,
+			0x86, 0x11, 0x39, 0x7E, 0xAF, 0x93, 0x19, 0x09,
+			0x70, 0x40, 0x80, 0x14, 0xBA, 0x1D, 0xB3, 0x62,
+			0x5B, 0xF3, 0x9A, 0x21, 0x98, 0x7E, 0x63, 0xB6,
+			0x1A, 0xBD, 0x65, 0x98, 0x35, 0x2A, 0xA9, 0x76,
+			0x29, 0x59, 0x84, 0x25, 0x81, 0xB8, 0xDE, 0x25,
+			0x32, 0x10, 0x50, 0xB7, 0xD3, 0xB3, 0x69, 0xC8,
+			0xE1, 0x33, 0xCB, 0x9E, 0x9C, 0x7A, 0x7C, 0xD2,
+			0x6C, 0x92, 0x97, 0xA9, 0xFA, 0xAF, 0x30, 0xBA,
+			0x9A, 0xB3, 0x3D, 0x9A, 0xE5, 0x0A, 0x9B, 0x8D,
+			0x89, 0xE2, 0x2B, 0xB8, 0xBC, 0xF0, 0x23, 0xFF,
+			0x7B, 0x0D, 0x00, 0x36, 0xEE, 0x79, 0xCB, 0xA5,
+			0x70, 0x4C, 0x66, 0x02, 0x79, 0x2E, 0x5B, 0x83,
+			0xCE, 0x55, 0x8B, 0x89, 0xD6, 0xE3, 0x71, 0x63,
+			0xBC, 0xB1, 0x5F, 0x67, 0xB4, 0x7E, 0x05, 0x0D,
+			0xAC, 0x6D, 0x4E, 0x2C, 0xA5, 0xF4, 0x47, 0x89,
+			0xAC, 0x5E, 0xBE, 0x2F, 0xFC, 0x9B, 0x2F, 0x0B,
+			0xBE, 0x63, 0x54, 0x97, 0xBB, 0x23, 0x27, 0xCD,
+			0xB9, 0xB2, 0x28, 0x0D, 0xA4, 0x78, 0x2C, 0xAB,
+			0xD1, 0xC9, 0x94, 0x40, 0x54, 0xF2, 0x35, 0x61,
+			0x49, 0x01, 0x87, 0x55, 0xA5, 0xB5, 0x1E, 0x84,
+			0x92, 0x9E, 0xC1, 0xA4, 0x0B, 0x66, 0x2B, 0xF8,
+			0xAF, 0xC3, 0x1E, 0xAF, 0x66, 0x3F, 0x6F, 0x5F,
+			0x70, 0xEC, 0x25, 0x29, 0xE4, 0x65, 0xB2, 0x04,
+			0x47, 0xF6, 0x3C, 0xB5, 0x5F, 0x66, 0x9F, 0xA4,
+			0x1B, 0xFC, 0xA2, 0xD5, 0x3E, 0x84, 0xBA, 0x88,
+			0x0D, 0xF1, 0x6A, 0xF2, 0xF6, 0x1D, 0xF1, 0xA3,
+			0x45, 0xB2, 0x51, 0xD8, 0xA2, 0x8F, 0x55, 0xA6,
+			0x89, 0xC4, 0x15, 0xD5, 0x73, 0xA8, 0xB1, 0x31,
+			0x66, 0x9E, 0xC1, 0x43, 0xE1, 0x5D, 0x4E, 0x04,
+			0x84, 0x8F, 0xF2, 0xBC, 0xE1, 0x4E, 0x4D, 0x60,
+			0x81, 0xCA, 0x53, 0x34, 0x95, 0x17, 0x3B, 0xAE,
+			0x8F, 0x95, 0xA7, 0xC6, 0x47, 0xC6, 0xAC, 0x32,
+			0x12, 0x39, 0xCA, 0xEF, 0xE0, 0x07, 0xBF, 0x17,
+			0x4F, 0xDC, 0x1B, 0x4E, 0x3C, 0x84, 0xF1, 0x9F,
+			0x43, 0x70, 0x19, 0xE6, 0xF3, 0x8B, 0x8B, 0x5D,
+			0xDB, 0xD2, 0x9D, 0xD4, 0xB2, 0x30, 0x45, 0x55,
+			0xA2, 0x67, 0xA2, 0x76, 0x4A, 0x74, 0xAD, 0x88,
+			0x71, 0xE6, 0x3E, 0x13, 0x06, 0x30, 0x17, 0xE1,
+			0xEF, 0xAC, 0x71, 0xFB, 0x43, 0xCD, 0xF6, 0xFA,
+			0x0E, 0x4C, 0x4E, 0x16, 0xF6, 0x6A, 0x09, 0x86,
+			0x6B, 0xEA, 0x47, 0x6C, 0x70, 0xE7, 0xAD, 0xA2,
+			0xE0, 0xFD, 0x7F, 0xF0, 0x5C, 0x21, 0x53, 0x0F,
+			0x28, 0xA1, 0x43, 0xE1, 0x06, 0xCA, 0x0B, 0x31,
+			0x88, 0x22, 0xA6, 0xE6, 0x34, 0x5B, 0xE6, 0xCF,
+			0x25, 0x81, 0x63, 0xFF, 0x78, 0x66, 0x85, 0x19,
+			0xE2, 0x0A, 0x7E, 0x81, 0x8A, 0x17, 0x1A, 0x18,
+			0x8A, 0x5F, 0x5D, 0x9E, 0x82, 0x13, 0x10, 0xB9,
+			0xD3, 0xE6, 0x93, 0x1C, 0xE4, 0x2C, 0xCB, 0x49,
+			0x1E, 0xB6, 0x36, 0x13, 0xBF, 0x28, 0xEE, 0xCC,
+			0x49, 0xF5, 0x79, 0xFC, 0x20, 0x65, 0xBD, 0xE8,
+			0xF0, 0x1B, 0x4E, 0xC0, 0x0D, 0x3E, 0x89, 0x91,
+			0xCC, 0x64, 0x10, 0xC0, 0x2A, 0x2B, 0xA3, 0xFA,
+			0x60, 0x3D, 0xC3, 0x52, 0x2F, 0x93, 0xDE, 0xB7,
+			0x6E, 0x8A, 0xDF, 0x6C, 0x08, 0xCC, 0x8B, 0x3B,
+			0xC8, 0x50, 0xEF, 0x58, 0x64, 0x9A, 0x3D, 0x16,
+			0x70, 0x94, 0x11, 0xD8, 0x94, 0x2B, 0x70, 0x91,
+			0x10, 0x70, 0x88, 0xF0, 0x40, 0x75, 0x9A, 0x2B,
+			0x39, 0xA1, 0x27, 0x3F, 0x2E, 0x91, 0xEA, 0xA1,
+			0xCC, 0x12, 0xC1, 0x7F, 0x73, 0x8C, 0x5C, 0x6B,
+			0xFC, 0xC5, 0x6A, 0x1C, 0x05, 0xF1, 0x3D, 0x30,
+			0x82, 0x4A, 0x65, 0x35, 0xCE, 0x80, 0x10, 0xBB,
+			0x41, 0x94, 0xFB, 0x84, 0x80, 0x7B, 0x91, 0xC4,
+			0x4D, 0xA3, 0x5F, 0xB9, 0xFB, 0xF9, 0xC9, 0x1D,
+			0x4F, 0x99, 0x1C, 0x1F, 0x47, 0x44, 0x89, 0x0E,
+			0xED, 0x6D, 0xB5, 0x85, 0x41, 0x94, 0xEF, 0xF9,
+			0x2E, 0xA0, 0xC8, 0xCA, 0xFB, 0x44, 0x02, 0xC6,
+			0xBF, 0x96, 0x87, 0x80, 0x1D, 0xEF, 0x2A, 0x81,
+			0xAB, 0xB2, 0x56, 0xDF, 0x54, 0x8B, 0xAB, 0xAF,
+			0xFE, 0x18, 0x8C, 0xAA, 0xD4, 0x00, 0x17, 0xBE,
+			0xCF, 0x06, 0xE5, 0xA6, 0xBF, 0x5A, 0x52, 0x3B,
+			0x4E, 0xF5, 0x65, 0x60, 0x95, 0xDE, 0x8A, 0x25,
+			0x88, 0xA5, 0x24, 0x96, 0x29, 0x13, 0x0D, 0x19,
+			0x45, 0x95, 0x91, 0x08, 0xD2, 0x9C, 0x4C, 0x34,
+			0x42, 0xF0, 0xA5, 0x72, 0xEB, 0xFB, 0x5E, 0xAA,
+			0x68, 0x80, 0x82, 0xAC, 0x34, 0xAD, 0x89, 0xF6,
+			0xAF, 0x54, 0x82, 0xCF, 0x98, 0x8C, 0x75, 0x63,
+			0x8D, 0xBD, 0x1C, 0x2A, 0xD7, 0x00, 0xA7, 0x8E,
+			0xB9, 0x33, 0xB6, 0x3B, 0x95, 0x9A, 0x59, 0x1D,
+			0x3F, 0x23, 0x6B, 0x18, 0xF8, 0x4F, 0x1A, 0x8D,
+			0xC0, 0x26, 0x9F, 0x87, 0x61, 0xB6, 0xC6, 0x60,
+			0x38, 0x22, 0x73, 0x1C, 0x99, 0x23, 0xEF, 0xD9,
+			0xFD, 0xCB, 0x54, 0x74, 0xBB, 0x77, 0x14, 0xA3,
+			0xA9, 0xE6, 0x7C, 0x7E, 0x03, 0x3A, 0x13, 0x6E,
+			0x1D, 0x6F, 0x64, 0xB3, 0xFA, 0xFB, 0x52, 0xDE,
+			0xDF, 0x08, 0xFB, 0x6F, 0xC5, 0xFA, 0x51, 0x6A,
+			0x69, 0x29, 0x9B, 0x96, 0xE8, 0x16, 0xC8, 0xD1,
+			0xE4, 0x19, 0xBD, 0x14, 0x74, 0x27, 0xE7, 0x10,
+			0xF0, 0xC3, 0xE2, 0xA7, 0x60, 0x48, 0xBF, 0xDD,
+			0xC4, 0x0D, 0xD0, 0xF2, 0xEF, 0xA6, 0xC9, 0xA2,
+			0x73, 0xD1, 0xCF, 0x41, 0xE1, 0x3B, 0xE5, 0x49,
+			0x91, 0x5D, 0x09, 0xFD, 0x1D, 0x95, 0x29, 0xDB,
+			0x52, 0x48, 0xEB, 0xF5, 0x1D, 0xF8, 0x06, 0x67,
+			0x75, 0xF2, 0x57, 0xA4, 0x20, 0x60, 0xEA, 0xB0,
+			0x85, 0x93, 0x7C, 0xDD, 0x52, 0x01, 0xD4, 0x57,
+			0xA8, 0x31, 0x2D, 0xF9, 0x0A, 0xD2, 0x2A, 0xD1,
+			0x34, 0x18, 0x35, 0x16, 0xB6, 0x8B, 0x0F, 0x0B,
+			0xCF, 0x50, 0x80, 0xFE, 0x76, 0xCC, 0x4F, 0x30,
+			0x98, 0x19, 0x16, 0x3D, 0x01, 0xEA, 0x8D, 0x8A,
+			0x3D, 0xDC, 0xFB, 0x1F, 0x77, 0x8D, 0x72, 0x76,
+			0x02, 0x3C, 0x5D, 0xEE, 0x55, 0x13, 0x5B, 0x6E,
+			0x5A, 0x2D, 0xD5, 0x77, 0xD7, 0x01, 0x84, 0x7D,
+			0x21, 0x8C, 0xDD, 0x94, 0x7D, 0x31, 0x3D, 0xF0,
+			0xE7, 0x28, 0xF5, 0x72, 0x36, 0x60, 0xE0, 0x59,
+			0x5F, 0xFE, 0x38, 0xF8, 0x2F, 0xDB, 0x9E, 0x55,
+			0x5A, 0xD6, 0xBA, 0x6C, 0x87, 0xF3, 0xC0, 0x76,
+			0x5F, 0xA3, 0x0A, 0xC3, 0xA3, 0x8D, 0x0E, 0x52,
+			0xA8, 0xDA, 0x26, 0x3A, 0xF9, 0x3E, 0x36, 0xB1,
+			0x06, 0xF8, 0x20, 0x2D, 0x1C, 0x0B, 0x93, 0xBB,
+			0xD3, 0x64, 0x77, 0xCE, 0x11, 0xFC, 0xA2, 0x0E,
+			0x1B, 0x5B, 0x9E, 0x13, 0x9F, 0x20, 0x8B, 0xAA,
+			0xCD, 0x72, 0xD7, 0xA6, 0xF3, 0x1E, 0x4F, 0x72,
+			0xC6, 0x49, 0x0F, 0x7B, 0xF0, 0x4C, 0x61, 0x1F,
+			0x43, 0x0D, 0x4F, 0x0D, 0x33, 0x13, 0xED, 0x63,
+			0xE5, 0xDB, 0x71, 0xAB, 0xA4, 0x83, 0xEF, 0xDC,
+			0x86, 0x9D, 0x4B, 0xBD, 0x1B, 0x8A, 0xFE, 0x39,
+			0xA8, 0x8B, 0xBA, 0x4C, 0x85, 0x28, 0xFC, 0xB3,
+			0x62, 0x85, 0xD2, 0xF0, 0x38, 0xD0, 0x4B, 0xA4,
+			0xD1, 0x3B, 0xD4, 0xD0, 0x2C, 0x78, 0x6C, 0x6A,
+			0xC2, 0x64, 0x2C, 0x31, 0x4A, 0xD8, 0x69, 0x24,
+			0xED, 0x77, 0x7D, 0x68, 0x9A, 0xA1, 0x78, 0x81,
+			0xD9, 0x7E, 0x6C, 0xFE, 0x0A, 0x0D, 0x76, 0xF7,
+			0x4B, 0x58, 0xE7, 0xC9, 0xB5, 0x11, 0x07, 0x87,
+			0x88, 0x6A, 0x9F, 0x3D, 0xE0, 0xEE, 0xCC, 0x60,
+			0x6B, 0x6B, 0xE6, 0xB5, 0x54, 0x8B, 0x32, 0x1F,
+			0x04, 0x1D, 0x0E, 0x9E, 0xFA, 0x6D, 0xB0, 0xE0,
+			0x6D, 0xF9, 0x79, 0xB4, 0xAB, 0x5E, 0xDF, 0x23,
+			0x7F, 0x95, 0xAD, 0x80, 0x17, 0x23, 0x90, 0x1F,
+			0xF0, 0xC3, 0xD9, 0x2D, 0xAC, 0x3F, 0x63, 0xF5,
+			0x77, 0xC5, 0x05, 0xAC, 0x06, 0xB6, 0xA1, 0xB4,
+			0xA2, 0x40, 0xB3, 0x99, 0x34, 0x7D, 0x31, 0xD4,
+			0xB1, 0xD4, 0xC1, 0xBB, 0x71, 0x1E, 0xDA, 0x3F,
+			0xA9, 0x12, 0x68, 0xFA, 0x5B, 0x20, 0x24, 0x6D,
+			0x4D, 0x72, 0x43, 0x18, 0xBF, 0x66, 0x71, 0x69,
+			0x26, 0x7D, 0x77, 0x78, 0xF8, 0xE5, 0x20, 0xAE,
+			0x56, 0x6C, 0x0F, 0x72, 0x94, 0x42, 0x85, 0x4F,
+			0xE4, 0xFB, 0x32, 0x26, 0x1B, 0x1C, 0x6E, 0x0B,
+			0xF0, 0xB8, 0x58, 0x00, 0xD2, 0x36, 0x64, 0xAD,
+			0xA9, 0x00, 0xCE, 0x35, 0x3C, 0x88, 0x79, 0x94,
+			0x0C, 0x0C, 0x9B, 0xF2, 0xDA, 0xBD, 0xCA, 0x93,
+			0x37, 0x26, 0xD3, 0x08, 0x54, 0xD2, 0x0D, 0xBC,
+			0x5D, 0x43, 0x5F, 0xCF, 0x28, 0xB5, 0xAA, 0x15,
+			0x28, 0x46, 0x45, 0x6B, 0xE8, 0xDF, 0xE8, 0xCE,
+			0x8F, 0xC0, 0x1A, 0x53, 0x63, 0x3B, 0x53, 0x75,
+			0xDD, 0x43, 0x1F, 0x07, 0x0A, 0xD5, 0xA1, 0x2A,
+			0x6E, 0x28, 0xE1, 0xD7, 0xD0, 0x09, 0xCF, 0x62,
+			0xC1, 0x5F, 0x21, 0xDB, 0xC5, 0x40, 0x99, 0x48,
+			0x87, 0x6E, 0x11, 0xF5, 0x5A, 0x4E, 0xBC, 0xF9,
+			0xA8, 0x02, 0x7C, 0x47, 0x39, 0xA5, 0xD8, 0x52,
+			0xB1, 0x80, 0xDC, 0xFE, 0x08, 0x4B, 0x5D, 0x09,
+			0xDE, 0x06, 0xF3, 0x2A, 0xAD, 0x14, 0x76, 0x40,
+			0x2F, 0x82, 0x28, 0x6A, 0xB6, 0x43, 0xEF, 0x71,
+			0x63, 0xC2, 0x56, 0xEB, 0x3B, 0x4B, 0x52, 0x2F,
+			0x93, 0xD3, 0x18, 0x3E, 0x18, 0xA8, 0xF7, 0x58,
+			0xFC, 0x8B, 0x3D, 0x4D, 0x4B, 0x72, 0xBD, 0xF7,
+			0x04, 0xC9, 0xB8, 0xD7, 0x6C, 0x8C, 0x67, 0xBB,
+			0x4C, 0x9B, 0x57, 0xF7, 0x22, 0x4E, 0x41, 0xB6,
+			0xFD, 0xD9, 0xF8, 0x41, 0x62, 0x0F, 0xFF, 0xAA,
+			0xC6, 0x87, 0x95, 0xFF, 0xFD, 0x58, 0xD9, 0xB2,
+			0xBA, 0x47, 0x61, 0x24, 0xEA, 0x92, 0x6E, 0x74,
+			0xB3, 0xDA, 0xE5, 0x83, 0x99, 0x24, 0xB1, 0x71,
+			0x2A, 0x33, 0xB2, 0xD5, 0x8F, 0xF0, 0x32, 0xCE,
+			0x37, 0xCF, 0xC7, 0x1C, 0xE8, 0xDE, 0x46, 0x78,
+			0x96, 0x97, 0xF6, 0x73, 0x90, 0xE5, 0x71, 0x05,
+			0xEA, 0x0D, 0xC2, 0x1D, 0x9E, 0x43, 0x34, 0xBC,
+			0x8F, 0x45, 0xE5, 0x08, 0xCA, 0x20, 0x0C, 0x84
+		},
+		.len = 2048
+	},
+	.auth_tag = {
+		.data = {
+			0xD0, 0x62, 0x1F, 0x20, 0x1C, 0xE8, 0xDD, 0x36,
+			0x00, 0x74, 0xF6, 0xD7, 0xFD, 0x2C, 0xA0, 0xAF
+		},
+		.len = 16
+	}
+};
+
 /** GMAC Test Vectors */
 static uint8_t gmac_plaintext[GMAC_LARGE_PLAINTEXT_LENGTH] = {
 			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-- 
1.7.9.5

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

* Re: [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize
  2017-01-05 15:37       ` De Lara Guarch, Pablo
@ 2017-01-05 16:52         ` Kulasek, TomaszX
  0 siblings, 0 replies; 41+ messages in thread
From: Kulasek, TomaszX @ 2017-01-05 16:52 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, dev

Hi Pablo

> -----Original Message-----
> From: De Lara Guarch, Pablo
> Sent: Thursday, January 5, 2017 16:37
> To: Kulasek, TomaszX <tomaszx.kulasek@intel.com>; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v3 1/5] rte_mbuf: add
> rte_pktmbuf_linearize
> 
> Hi Tomasz,
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Tomasz Kulasek
> > Sent: Thursday, January 05, 2017 9:13 AM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize
> >
> > This patch adds function rte_pktmbuf_linearize to let crypto PMD
> coalesce
> > chained mbuf before crypto operation and extend their capabilities to
> > support segmented mbufs when device cannot handle them natively.
> >
> > Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
> 
> Could you separate this patch and patch 2/5 out of this patchset and CC
> Olivier,
> the mbuf maintainer, so it can be better reviewed?
> (you can send it as a single patch, both lib and test code)
> Then, send another patchset with the other 3 patches,
> stating that it depends on that patchset.
> 
> Thanks,
> Pablo

Done.

Tomasz

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

* Re: [PATCH v4] rte_mbuf: add rte_pktmbuf_linearize
  2017-01-05 16:44     ` [PATCH v4] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
@ 2017-01-10 16:50       ` Olivier MATZ
  2017-01-12  9:40       ` [PATCH v5] mbuf: add a function to linearize a packet Tomasz Kulasek
  1 sibling, 0 replies; 41+ messages in thread
From: Olivier MATZ @ 2017-01-10 16:50 UTC (permalink / raw)
  To: Tomasz Kulasek; +Cc: dev, Pablo de Lara, Olivier Matz

Hi Tomasz,

On Thu,  5 Jan 2017 17:44:00 +0100, Tomasz Kulasek
<tomaszx.kulasek@intel.com> wrote:
> This patch adds function rte_pktmbuf_linearize to let crypto PMD
> coalesce chained mbuf before crypto operation and extend their
> capabilities to support segmented mbufs when device cannot handle
> them natively.
> 
> Included unit tests for rte_pktmbuf_linearize functionality:
> 
>  1) Creates banch of segmented mbufs with different size and number of
>     segments.
>  2) Generates pkt_len bytes of random data.
>  3) Fills noncontigouos mbuf with randomly generated data.
>  4) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one
>     contiguous.
>  5) Verifies data in linearized buffer.
> 
> Dependencies:
> 
> This patch is rebased to the dpdk-next-crypto and should be applied
> before "Chained Mbufs support in SW PMDs" patchset.
> 
> 
> changes in v4:
>  - separated from "Chained Mbufs support in SW PMDs" patch set for
>    better reviewing,
>  - merged "rte_pktmbuf_linearize" implementation with unit tests,
> 
> changes in v3:
>  - rebased to dpdk-next-crypto
> 
> changes in v2:
>  - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
> 
> 
> Cc: Pablo de Lara <pablo.de.lara.guarch@intel.com>
> Cc: Olivier Matz <olivier.matz@6wind.com>
> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>

The overall idea and code looks good to me. I have some minor
comments, please see below.

To avoid the warning of check-git-log.sh, the title of the commit could
be change to:
  mbuf: add a function to linearize a packet


> diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c
> index c0823ea..39577e7 100644
> --- a/app/test/test_mbuf.c
> +++ b/app/test/test_mbuf.c
> @@ -930,6 +930,124 @@
>  	return 0;
>  }
>  
> +static int
> +test_mbuf_linearize(int pkt_len, int nb_segs) {
> +
> +	struct rte_mbuf *m = NULL, *mbuf_src = NULL;
> +	uint8_t data[pkt_len], *src, *dst;
> +	int data_len = 0;
> +	int i, size;
> +	int t_len;
> +
> +	if (pkt_len < 1) {
> +		printf("Packet size must be 1 or more (is %d)\n",
> pkt_len);
> +		return -1;
> +	}
> +
> +	if (nb_segs < 1) {
> +		printf("Number of segments must be 1 or more (is
> %d)\n",
> +				nb_segs);
> +		return -1;
> +	}
> +
> +	/* Setup buffer */
> +	for (i = 0; i < pkt_len; i++)
> +		data[i] = (uint8_t) rte_rand();

This is maybe a bit overkill.
What about data[i] = i ?

And with this assumption, the local buffer would become useless.

> +
> +	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;

Hmm, I think we could do clearer here. Maybe:

	seg_len = pkt_len / nb_segs;
	if (seg_len == 0)
		seg_len = 1;

> +	src = data;
> +	size = pkt_len;

rename 'size' as 'remain'?

> +
> +	/* Create chained mbuf_src and fill it generated data */
> +	for (i = 0; size > 0; i++) {
> +
> +		m = rte_pktmbuf_alloc(pktmbuf_pool);
> +		if (i == 0)
> +			mbuf_src = m;
> +
> +		if (!m) {

(x == NULL) should be preferred when the variable is a pointer (see
coding_style.rst).

> +			printf("Cannot create segment for source
> mbuf");
> +			goto fail;
> +		}
> +
> +		/* Make sure if tailroom is zeroed */
> +		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
> +				rte_pktmbuf_tailroom(m));
> +
> +		data_len = size > t_len ? t_len : size;

I think the following is easier to read:

	data_len = remain;
	if (data_len > seg_len)
		data_len = seg_len;

But for that one, maybe it's me, I let you decide ;)


> +		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
> +		if (!dst) {

if (dst == NULL)

> +			printf("Cannot append %d bytes to the
> mbuf\n",
> +					data_len);
> +			goto fail;
> +		}
> +
> +		rte_memcpy(dst, src, data_len);
> +		src += data_len;
> +
> +		if (mbuf_src != m)
> +			rte_pktmbuf_chain(mbuf_src, m);
> +
> +		size -= data_len;
> +
> +	}
> +
> +	/* Create destination buffer to store coalesced data */
> +	if (rte_pktmbuf_linearize(mbuf_src)) {
> +		printf("Mbuf linearization failed\n");
> +		goto fail;
> +	}
> +
> +	if (!rte_pktmbuf_is_contiguous(mbuf_src)) {
> +		printf("Source buffer should be contiguous after "
> +				"linearization\n");
> +		goto fail;
> +	}
> +
> +	src = rte_pktmbuf_mtod(mbuf_src, uint8_t *);
> +
> +	if (memcmp(src, data, rte_pktmbuf_pkt_len(mbuf_src))) {
> +		printf("Incorrect data in coalesced mbuf\n");
> +		goto fail;
> +	}
> +
> +	if (mbuf_src)
> +		rte_pktmbuf_free(mbuf_src);

Is it possible that mbuf_src is NULL here?

> +	return 0;
> +
> +fail:
> +	if (mbuf_src)
> +		rte_pktmbuf_free(mbuf_src);
> +	return -1;
> +}
> +
> +static int
> +test_mbuf_linearize_check(void)
> +{
> +	struct test_mbuf_array {
> +		int size;
> +		int nb_segs;
> +	} mbuf_array[5] = {

you could change [5] by []

> +			{ 128, 1 },
> +			{ 64, 64 },
> +			{ 512, 10 },
> +			{ 250, 11 },
> +			{ 123, 8 },
> +	};
> +	unsigned int i;
> +
> +	printf("Test mbuf linearize API\n");
> +
> +	for (i = 0; i < RTE_DIM(mbuf_array); i++)
> +		if (test_mbuf_linearize(mbuf_array[i].size,
> +				mbuf_array[i].nb_segs)) {
> +			printf("Test failed for %d, %d\n",
> mbuf_array[i].size,
> +					mbuf_array[i].nb_segs);
> +			return -1;
> +		}
> +
> +	return 0;
> +}
>  
>  static int
>  test_mbuf(void)
> @@ -1023,6 +1141,11 @@
>  		printf("test_failing_mbuf_sanity_check() failed\n");
>  		return -1;
>  	}
> +
> +	if (test_mbuf_linearize_check() < 0) {
> +		printf("test_mbuf_linearize_check() failed\n");
> +		return -1;
> +	}
>  	return 0;
>  }
>  
> diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
> index ead7c6e..b11a31d 100644
> --- a/lib/librte_mbuf/rte_mbuf.h
> +++ b/lib/librte_mbuf/rte_mbuf.h
> @@ -1647,6 +1647,62 @@ static inline int rte_pktmbuf_chain(struct
> rte_mbuf *head, struct rte_mbuf *tail }
>  
>  /**
> + * Linearize data in mbuf.
> + *
> + * This function coalesce mbuf merging data in the first segment,
> unchaining
> + * rest, and then frees them.

I suggest this description instead:

This function moves the mbuf data in the first segment if there is
enough tailroom. The subsequent segments are unchained and freed.

> + *
> + * All operations are done in-place, so the structure of incoming
> mbuf
> + * is changed.

Not sure what you mean here. Are you talking about pointers to data
that could become invalid?

> + *
> + * @param mbuf
> + *   mbuf to linearize
> + * @return
> + *   - 0, on success
> + *   - -1, on error
> + */
> +static inline int
> +rte_pktmbuf_linearize(struct rte_mbuf *mbuf)
> +{
> +	int l, n;
> +	struct rte_mbuf *m;
> +	struct rte_mbuf *m_next;
> +	char *buffer;
> +
> +	if (rte_pktmbuf_is_contiguous(mbuf))
> +		return 0;
> +
> +	/* Extend first segment to the total packet length
> +	 */

For one-line comments, it can be:
	/* foo bar */

> +	n = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);

rename 'n' as 'copy_len'?

> +
> +	if (unlikely(n > rte_pktmbuf_tailroom(mbuf)))
> +		return -1;
> +
> +	buffer = rte_pktmbuf_mtod_offset(mbuf, char *,
> mbuf->data_len);
> +	mbuf->data_len = (uint16_t)(mbuf->pkt_len);
> +
> +	/* Append data from next segments to the first one
> +	 */

/* foo bar */

> +	m = mbuf->next;
> +	while (m != NULL) {
> +		m_next = m->next;
> +
> +		l = rte_pktmbuf_data_len(m);

rename 'l' as 'seg_len'?

> +		rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), l);
> +		buffer += l;
> +
> +		rte_pktmbuf_free_seg(m);
> +		m = m_next;
> +	}
> +
> +	mbuf->next = NULL;
> +	mbuf->nb_segs = 1;
> +
> +	return 0;
> +}


Thank you Tomasz , I think it could be useful in other scenarii. In the
future it could be extended to memmove() the data of the first segment
if the tailroom is too small.

Regards,
Olivier

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

* [PATCH v5] mbuf: add a function to linearize a packet
  2017-01-05 16:44     ` [PATCH v4] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
  2017-01-10 16:50       ` Olivier MATZ
@ 2017-01-12  9:40       ` Tomasz Kulasek
  2017-01-13 15:32         ` Olivier Matz
  1 sibling, 1 reply; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-12  9:40 UTC (permalink / raw)
  To: dev; +Cc: Pablo de Lara, Olivier Matz

This patch adds function rte_pktmbuf_linearize to let crypto PMD coalesce
chained mbuf before crypto operation and extend their capabilities to
support segmented mbufs when device cannot handle them natively.

Included unit tests for rte_pktmbuf_linearize functionality:

 1) Creates banch of segmented mbufs with different size and number of
    segments.
 2) Fills noncontigouos mbuf with sequential values.
 3) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one
    contiguous.
 4) Verifies data in linearized buffer.

Dependencies:

This patch is rebased to the dpdk-next-crypto and should be applied
before "Chained Mbufs support in SW PMDs" patchset.

changes in v5:
 - name of patch changed,
 - improved coding style,

changes in v4:
 - separated from "Chained Mbufs support in SW PMDs" patch set for
   better reviewing,
 - merged "rte_pktmbuf_linearize" implementation with unit tests,

changes in v3:
 - rebased to dpdk-next-crypto

changes in v2:
 - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize

Cc: Pablo de Lara <pablo.de.lara.guarch@intel.com>
Cc: Olivier Matz <olivier.matz@6wind.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_mbuf.c       |  123 ++++++++++++++++++++++++++++++++++++++++++++
 lib/librte_mbuf/rte_mbuf.h |   51 ++++++++++++++++++
 2 files changed, 174 insertions(+)

diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c
index c0823ea..a2e9bc6 100644
--- a/app/test/test_mbuf.c
+++ b/app/test/test_mbuf.c
@@ -930,6 +930,124 @@
 	return 0;
 }
 
+static int
+test_mbuf_linearize(int pkt_len, int nb_segs) {
+
+	struct rte_mbuf *m = NULL, *mbuf = NULL;
+	uint8_t *data;
+	int data_len = 0;
+	int remain;
+	int seg, seg_len;
+	int i;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return -1;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return -1;
+	}
+
+	seg_len = pkt_len / nb_segs;
+	if (seg_len == 0)
+		seg_len = 1;
+
+	remain = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (seg = 0; remain > 0; seg++) {
+
+		m = rte_pktmbuf_alloc(pktmbuf_pool);
+		if (m == NULL) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+				rte_pktmbuf_tailroom(m));
+
+		data_len = remain;
+		if (data_len > seg_len)
+			data_len = seg_len;
+
+		data = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (data == NULL) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		for (i = 0; i < data_len; i++)
+			data[i] = (seg * seg_len + i) % 0x0ff;
+
+		if (seg == 0)
+			mbuf = m;
+		else
+			rte_pktmbuf_chain(mbuf, m);
+
+		remain -= data_len;
+	}
+
+	/* Create destination buffer to store coalesced data */
+	if (rte_pktmbuf_linearize(mbuf)) {
+		printf("Mbuf linearization failed\n");
+		goto fail;
+	}
+
+	if (!rte_pktmbuf_is_contiguous(mbuf)) {
+		printf("Source buffer should be contiguous after "
+				"linearization\n");
+		goto fail;
+	}
+
+	data = rte_pktmbuf_mtod(mbuf, uint8_t *);
+
+	for (i = 0; i < pkt_len; i++)
+		if (data[i] != (i % 0x0ff)) {
+			printf("Incorrect data in linearized mbuf\n");
+			goto fail;
+		}
+
+	rte_pktmbuf_free(mbuf);
+	return 0;
+
+fail:
+	if (mbuf)
+		rte_pktmbuf_free(mbuf);
+	return -1;
+}
+
+static int
+test_mbuf_linearize_check(void)
+{
+	struct test_mbuf_array {
+		int size;
+		int nb_segs;
+	} mbuf_array[] = {
+			{ 128, 1 },
+			{ 64, 64 },
+			{ 512, 10 },
+			{ 250, 11 },
+			{ 123, 8 },
+	};
+	unsigned int i;
+
+	printf("Test mbuf linearize API\n");
+
+	for (i = 0; i < RTE_DIM(mbuf_array); i++)
+		if (test_mbuf_linearize(mbuf_array[i].size,
+				mbuf_array[i].nb_segs)) {
+			printf("Test failed for %d, %d\n", mbuf_array[i].size,
+					mbuf_array[i].nb_segs);
+			return -1;
+		}
+
+	return 0;
+}
 
 static int
 test_mbuf(void)
@@ -1023,6 +1141,11 @@
 		printf("test_failing_mbuf_sanity_check() failed\n");
 		return -1;
 	}
+
+	if (test_mbuf_linearize_check() < 0) {
+		printf("test_mbuf_linearize_check() failed\n");
+		return -1;
+	}
 	return 0;
 }
 
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ead7c6e..8fd0766 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -1647,6 +1647,57 @@ static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail
 }
 
 /**
+ * Linearize data in mbuf.
+ *
+ * This function moves the mbuf data in the first segment if there is enough
+ * tailroom. The subsequent segments are unchained and freed.
+ *
+ * @param mbuf
+ *   mbuf to linearize
+ * @return
+ *   - 0, on success
+ *   - -1, on error
+ */
+static inline int
+rte_pktmbuf_linearize(struct rte_mbuf *mbuf)
+{
+	int seg_len, copy_len;
+	struct rte_mbuf *m;
+	struct rte_mbuf *m_next;
+	char *buffer;
+
+	if (rte_pktmbuf_is_contiguous(mbuf))
+		return 0;
+
+	/* Extend first segment to the total packet length */
+	copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
+
+	if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf)))
+		return -1;
+
+	buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
+	mbuf->data_len = (uint16_t)(mbuf->pkt_len);
+
+	/* Append data from next segments to the first one */
+	m = mbuf->next;
+	while (m != NULL) {
+		m_next = m->next;
+
+		seg_len = rte_pktmbuf_data_len(m);
+		rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len);
+		buffer += seg_len;
+
+		rte_pktmbuf_free_seg(m);
+		m = m_next;
+	}
+
+	mbuf->next = NULL;
+	mbuf->nb_segs = 1;
+
+	return 0;
+}
+
+/**
  * Dump an mbuf structure to a file.
  *
  * Dump all fields for the given packet mbuf and all its associated
-- 
1.7.9.5

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

* [PATCH v5 0/3] Chained Mbufs support in SW PMDs
  2017-01-05 16:46     ` [PATCH v4 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
                         ` (2 preceding siblings ...)
  2017-01-05 16:46       ` [PATCH v4 3/3] test: add sgl unit tests for crypto devices Tomasz Kulasek
@ 2017-01-13 15:23       ` Tomasz Kulasek
  2017-01-13 15:23         ` [PATCH v5 1/3] crypto: add sgl support in sw PMDs Tomasz Kulasek
                           ` (3 more replies)
  3 siblings, 4 replies; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-13 15:23 UTC (permalink / raw)
  To: dev

This patch set adds support of scattered-gather list for SW PMDs.

As of now, application needs to reserve continuous block of memory for
mbufs which is not always the case. Hence needed to support chaining of
mbufs which are smaller in size but can be used if chained.


Above work involves:
--------------------

 a) Create mbuf functions to coalesce mbuf chains into a single mbuf.
 b) For each software poll mode driver code to detect chained mbufs
    support and coalesce these before preforming crypto.
 c) Add relevant unit tests to test the functionality.


Known limitations for openssl PMD:
----------------------------------

While libcrypto library expects continuous destination buffer for
output of cipher operations, implementation of openssl PMD is limited
the same way, and requires contiguous destination mbuf.


changes in v5:
 - rebased to the master of dpdk-next-crypto

changes in v4:
 - separated "rte_pktmbuf_linearize" implementation from this patch set
   and sent as new patch for better reviewing,

changes in v3:
 - rebased to dpdk-next-crypto
 - reused tests for AES GCM SGL support in opensll from "app/test: add
   SGL tests to cryptodev QAT suite"

changes in v2:
 - add support for sgl in openssl PMD
 - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
 - extended test vector data for aes gcm from 60 to 2048 bytes


Tomasz Kulasek (3):
  crypto: add sgl support in sw PMDs
  crypto: add sgl support in openssl PMD
  test: add sgl unit tests for crypto devices

 app/test/test_cryptodev.c                  |  386 ++++++++++++++++++-
 app/test/test_cryptodev.h                  |  138 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   52 +++
 app/test/test_cryptodev_blockcipher.c      |   90 ++---
 app/test/test_cryptodev_blockcipher.h      |    1 +
 app/test/test_cryptodev_gcm_test_vectors.h |  553 ++++++++++++++++++++++++++++
 doc/guides/cryptodevs/openssl.rst          |    3 +-
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 +
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 +-
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +
 drivers/crypto/null/null_crypto_pmd.c      |    3 +-
 drivers/crypto/openssl/rte_openssl_pmd.c   |  329 +++++++++++++----
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +
 lib/librte_cryptodev/rte_cryptodev.c       |    4 +-
 lib/librte_cryptodev/rte_cryptodev.h       |    2 +
 16 files changed, 1507 insertions(+), 128 deletions(-)

-- 
1.7.9.5

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

* [PATCH v5 1/3] crypto: add sgl support in sw PMDs
  2017-01-13 15:23       ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
@ 2017-01-13 15:23         ` Tomasz Kulasek
  2017-01-16 16:08           ` Declan Doherty
  2017-01-13 15:23         ` [PATCH v5 2/3] crypto: add sgl support in openssl PMD Tomasz Kulasek
                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-13 15:23 UTC (permalink / raw)
  To: dev

This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature flag
informing that selected crypto device supports segmented mbufs natively
and doesn't need to be coalesced before crypto operation.

While using segmented buffers in crypto devices may have unpredictable
results, for PMDs which doesn't support it natively, additional check is
made for debug compilation.

Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 ++++++++++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 ++++++++++++++++---
 drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +++++++++++++
 drivers/crypto/null/null_crypto_pmd.c      |    3 ++-
 drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +++++++++++++++
 drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +++++++++++++
 lib/librte_cryptodev/rte_cryptodev.c       |    4 ++--
 lib/librte_cryptodev/rte_cryptodev.h       |    2 ++
 8 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index af3d60f..5af22f7 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -377,6 +377,20 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_AESNI_GCM_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			GCM_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			qp->qp_stats.enqueue_err_count++;
+			break;
+		}
+#endif
+
 		retval = process_gcm_crypto_op(qp, ops[i]->sym, sess);
 		if (retval < 0) {
 			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 6d27d75..25f681b 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -571,15 +571,28 @@
 	int i, processed_jobs = 0;
 
 	for (i = 0; i < nb_ops; i++) {
-#ifdef RTE_LIBRTE_AESNI_MB_DEBUG
-		if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
+#ifdef RTE_LIBRTE_PMD_AESNI_MB_DEBUG
+		if (unlikely(ops[i]->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
 			MB_LOG_ERR("PMD only supports symmetric crypto "
 				"operation requests, op (%p) is not a "
-				"symmetric operation.", op);
+				"symmetric operation.", ops[i]);
+			qp->stats.enqueue_err_count++;
+			goto flush_jobs;
+		}
+
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			MB_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 			qp->stats.enqueue_err_count++;
 			goto flush_jobs;
 		}
 #endif
+
 		sess = get_session(qp, ops[i]);
 		if (unlikely(sess == NULL)) {
 			qp->stats.enqueue_err_count++;
diff --git a/drivers/crypto/kasumi/rte_kasumi_pmd.c b/drivers/crypto/kasumi/rte_kasumi_pmd.c
index b119da2..4bdd7bb 100644
--- a/drivers/crypto/kasumi/rte_kasumi_pmd.c
+++ b/drivers/crypto/kasumi/rte_kasumi_pmd.c
@@ -455,6 +455,19 @@
 	for (i = 0; i < nb_ops; i++) {
 		curr_c_op = ops[i];
 
+#ifdef RTE_LIBRTE_PMD_KASUMI_DEBUG
+		if (!rte_pktmbuf_is_contiguous(curr_c_op->sym->m_src) ||
+				(curr_c_op->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						curr_c_op->sym->m_dst))) {
+			KASUMI_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", curr_c_op);
+			curr_c_op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		/* Set status as enqueued (not processed yet) by default. */
 		curr_c_op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
 
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index c69606b..c37d3d6 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -216,7 +216,8 @@
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
-			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
 
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 3b4292a..9a6f16d 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -330,6 +330,21 @@
 	unsigned i;
 	unsigned enqueued_ops, processed_ops;
 
+#ifdef RTE_LIBRTE_PMD_SNOW3G_DEBUG
+	for (i = 0; i < num_ops; i++) {
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			SNOW3G_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			return 0;
+		}
+	}
+#endif
+
 	switch (session->op) {
 	case SNOW3G_OP_ONLY_CIPHER:
 		processed_ops = process_snow3g_cipher_op(ops,
diff --git a/drivers/crypto/zuc/rte_zuc_pmd.c b/drivers/crypto/zuc/rte_zuc_pmd.c
index 3849119..bf53f76 100644
--- a/drivers/crypto/zuc/rte_zuc_pmd.c
+++ b/drivers/crypto/zuc/rte_zuc_pmd.c
@@ -211,6 +211,19 @@
 			break;
 		}
 
+#ifdef RTE_LIBRTE_PMD_ZUC_DEBUG
+		if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
+				(ops[i]->sym->m_dst != NULL &&
+				!rte_pktmbuf_is_contiguous(
+						ops[i]->sym->m_dst))) {
+			ZUC_LOG_ERR("PMD supports only contiguous mbufs, "
+				"op (%p) provides noncontiguous mbuf as "
+				"source/destination buffer.\n", ops[i]);
+			ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+			break;
+		}
+#endif
+
 		src[i] = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
 				(ops[i]->sym->cipher.data.offset >> 3);
 		dst[i] = ops[i]->sym->m_dst ?
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 54e95d5..bbab4b3 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -211,13 +211,13 @@ struct rte_cryptodev_callback {
 		return "CPU_AESNI";
 	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
 		return "HW_ACCELERATED";
-
+	case RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER:
+		return "MBUF_SCATTER_GATHER";
 	default:
 		return NULL;
 	}
 }
 
-
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)
 {
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 29d8eec..fa311a9 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -227,6 +227,8 @@ struct rte_cryptodev_capabilities {
 /**< Operations are off-loaded to an external hardware accelerator */
 #define	RTE_CRYPTODEV_FF_CPU_AVX512		(1ULL << 8)
 /**< Utilises CPU SIMD AVX512 instructions */
+#define	RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER	(1ULL << 9)
+/**< Scatter-gather mbufs are supported */
 
 
 /**
-- 
1.7.9.5

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

* [PATCH v5 2/3] crypto: add sgl support in openssl PMD
  2017-01-13 15:23       ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2017-01-13 15:23         ` [PATCH v5 1/3] crypto: add sgl support in sw PMDs Tomasz Kulasek
@ 2017-01-13 15:23         ` Tomasz Kulasek
  2017-01-16 16:10           ` Declan Doherty
  2017-01-13 15:23         ` [PATCH v5 3/3] test: add sgl unit tests for crypto devices Tomasz Kulasek
  2017-01-16 19:00         ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs De Lara Guarch, Pablo
  3 siblings, 1 reply; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-13 15:23 UTC (permalink / raw)
  To: dev


Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 doc/guides/cryptodevs/openssl.rst        |    3 +-
 drivers/crypto/openssl/rte_openssl_pmd.c |  329 +++++++++++++++++++++++-------
 2 files changed, 259 insertions(+), 73 deletions(-)

diff --git a/doc/guides/cryptodevs/openssl.rst b/doc/guides/cryptodevs/openssl.rst
index f1c39ba..f6ed6ea 100644
--- a/doc/guides/cryptodevs/openssl.rst
+++ b/doc/guides/cryptodevs/openssl.rst
@@ -112,6 +112,7 @@ Limitations
 -----------
 
 * Maximum number of sessions is 2048.
-* Chained mbufs are not supported.
+* Chained mbufs are supported only for source mbuf (destination must be
+  contiguous).
 * Hash only is not supported for GCM and GMAC.
 * Cipher only is not supported for GCM and GMAC.
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index 312154a..426e407 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -484,24 +484,112 @@
  * Process Operations
  *------------------------------------------------------------------------------
  */
+static inline int
+process_openssl_encryption_update(struct rte_mbuf *mbuf_src, int offset,
+		uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+	struct rte_mbuf *m;
+	int dstlen;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		return -1;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+			return -1;
+		*dst += l;
+		return 0;
+	}
+
+	if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+		return -1;
+
+	*dst += dstlen;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_EncryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+			return -1;
+		*dst += dstlen;
+		n -= l;
+	}
+
+	return 0;
+}
+
+static inline int
+process_openssl_decryption_update(struct rte_mbuf *mbuf_src, int offset,
+		uint8_t **dst, int srclen, EVP_CIPHER_CTX *ctx)
+{
+	struct rte_mbuf *m;
+	int dstlen;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		return -1;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, srclen) <= 0)
+			return -1;
+		*dst += l;
+		return 0;
+	}
+
+	if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+		return -1;
+
+	*dst += dstlen;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DecryptUpdate(ctx, *dst, &dstlen, src, l) <= 0)
+			return -1;
+		*dst += dstlen;
+		n -= l;
+	}
+
+	return 0;
+}
 
 /** Process standard openssl cipher encryption */
 static int
-process_openssl_cipher_encrypt(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_encrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
-	int dstlen, totlen;
+	int totlen;
 
 	if (EVP_EncryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
 		goto process_cipher_encrypt_err;
 
 	EVP_CIPHER_CTX_set_padding(ctx, 0);
 
-	if (EVP_EncryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+	if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+			srclen, ctx))
 		goto process_cipher_encrypt_err;
 
-	if (EVP_EncryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+	if (EVP_EncryptFinal_ex(ctx, dst, &totlen) <= 0)
 		goto process_cipher_encrypt_err;
 
 	return 0;
@@ -513,23 +601,23 @@
 
 /** Process standard openssl cipher decryption */
 static int
-process_openssl_cipher_decrypt(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen,
+process_openssl_cipher_decrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
-	int dstlen, totlen;
+	int totlen;
 
 	if (EVP_DecryptInit_ex(ctx, algo, NULL, key, iv) <= 0)
 		goto process_cipher_decrypt_err;
 
 	EVP_CIPHER_CTX_set_padding(ctx, 0);
 
-	if (EVP_DecryptUpdate(ctx, dst, &dstlen, src, srclen) <= 0)
+	if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+			srclen, ctx))
 		goto process_cipher_decrypt_err;
 
-	if (EVP_DecryptFinal_ex(ctx, dst + dstlen, &totlen) <= 0)
+	if (EVP_DecryptFinal_ex(ctx, dst, &totlen) <= 0)
 		goto process_cipher_decrypt_err;
-
 	return 0;
 
 process_cipher_decrypt_err:
@@ -539,11 +627,25 @@
 
 /** Process cipher des 3 ctr encryption, decryption algorithm */
 static int
-process_openssl_cipher_des3ctr(uint8_t *src, uint8_t *dst,
-		uint8_t *iv, uint8_t *key, int srclen, EVP_CIPHER_CTX *ctx)
+process_openssl_cipher_des3ctr(struct rte_mbuf *mbuf_src, uint8_t *dst,
+		int offset, uint8_t *iv, uint8_t *key, int srclen,
+		EVP_CIPHER_CTX *ctx)
 {
 	uint8_t ebuf[8], ctr[8];
 	int unused, n;
+	struct rte_mbuf *m;
+	uint8_t *src;
+	int l;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_cipher_des3ctr_err;
+
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+	l = rte_pktmbuf_data_len(m) - offset;
 
 	/* We use 3DES encryption also for decryption.
 	 * IV is not important for 3DES ecb
@@ -552,9 +654,8 @@
 		goto process_cipher_des3ctr_err;
 
 	memcpy(ctr, iv, 8);
-	n = 0;
 
-	while (n < srclen) {
+	for (n = 0; n < srclen; n++) {
 		if (n % 8 == 0) {
 			if (EVP_EncryptUpdate(ctx,
 					(unsigned char *)&ebuf, &unused,
@@ -562,8 +663,16 @@
 				goto process_cipher_des3ctr_err;
 			ctr_inc(ctr);
 		}
-		dst[n] = src[n] ^ ebuf[n % 8];
-		n++;
+		dst[n] = *(src++) ^ ebuf[n % 8];
+
+		l--;
+		if (!l) {
+			m = m->next;
+			if (m) {
+				src = rte_pktmbuf_mtod(m, uint8_t *);
+				l = rte_pktmbuf_data_len(m);
+			}
+		}
 	}
 
 	return 0;
@@ -575,9 +684,9 @@
 
 /** Process auth/encription aes-gcm algorithm */
 static int
-process_openssl_auth_encryption_gcm(uint8_t *src, int srclen,
-		uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
-		uint8_t *key, uint8_t *dst,	uint8_t *tag,
+process_openssl_auth_encryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+		int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+		uint8_t *key, uint8_t *dst, uint8_t *tag,
 		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
 {
 	int len = 0, unused = 0;
@@ -592,20 +701,20 @@
 	if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
 		goto process_auth_encryption_gcm_err;
 
-	if (aadlen > 0) {
+	if (aadlen > 0)
 		if (EVP_EncryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
 			goto process_auth_encryption_gcm_err;
 
-		/* Workaround open ssl bug in version less then 1.0.1f */
-		if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
-			goto process_auth_encryption_gcm_err;
-	}
-
 	if (srclen > 0)
-		if (EVP_EncryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+		if (process_openssl_encryption_update(mbuf_src, offset, &dst,
+				srclen, ctx))
 			goto process_auth_encryption_gcm_err;
 
-	if (EVP_EncryptFinal_ex(ctx, dst + len, &len) <= 0)
+	/* Workaround open ssl bug in version less then 1.0.1f */
+	if (EVP_EncryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+		goto process_auth_encryption_gcm_err;
+
+	if (EVP_EncryptFinal_ex(ctx, dst, &len) <= 0)
 		goto process_auth_encryption_gcm_err;
 
 	if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) <= 0)
@@ -619,10 +728,10 @@
 }
 
 static int
-process_openssl_auth_decryption_gcm(uint8_t *src, int srclen,
-		uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
-		uint8_t *key, uint8_t *dst, uint8_t *tag,
-		EVP_CIPHER_CTX *ctx, const EVP_CIPHER *algo)
+process_openssl_auth_decryption_gcm(struct rte_mbuf *mbuf_src, int offset,
+		int srclen, uint8_t *aad, int aadlen, uint8_t *iv, int ivlen,
+		uint8_t *key, uint8_t *dst, uint8_t *tag, EVP_CIPHER_CTX *ctx,
+		const EVP_CIPHER *algo)
 {
 	int len = 0, unused = 0;
 	uint8_t empty[] = {};
@@ -639,20 +748,20 @@
 	if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) <= 0)
 		goto process_auth_decryption_gcm_err;
 
-	if (aadlen > 0) {
+	if (aadlen > 0)
 		if (EVP_DecryptUpdate(ctx, NULL, &len, aad, aadlen) <= 0)
 			goto process_auth_decryption_gcm_err;
 
-		/* Workaround open ssl bug in version less then 1.0.1f */
-		if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
-			goto process_auth_decryption_gcm_err;
-	}
-
 	if (srclen > 0)
-		if (EVP_DecryptUpdate(ctx, dst, &len, src, srclen) <= 0)
+		if (process_openssl_decryption_update(mbuf_src, offset, &dst,
+				srclen, ctx))
 			goto process_auth_decryption_gcm_err;
 
-	if (EVP_DecryptFinal_ex(ctx, dst + len, &len) <= 0)
+	/* Workaround open ssl bug in version less then 1.0.1f */
+	if (EVP_DecryptUpdate(ctx, empty, &unused, empty, 0) <= 0)
+		goto process_auth_decryption_gcm_err;
+
+	if (EVP_DecryptFinal_ex(ctx, dst, &len) <= 0)
 		goto process_auth_decryption_gcm_final_err;
 
 	return 0;
@@ -667,21 +776,50 @@
 
 /** Process standard openssl auth algorithms */
 static int
-process_openssl_auth(uint8_t *src, uint8_t *dst,
+process_openssl_auth(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
 		__rte_unused uint8_t *iv, __rte_unused EVP_PKEY * pkey,
 		int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
 {
 	size_t dstlen;
+	struct rte_mbuf *m;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_auth_err;
 
 	if (EVP_DigestInit_ex(ctx, algo, NULL) <= 0)
 		goto process_auth_err;
 
-	if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DigestUpdate(ctx, (char *)src, srclen) <= 0)
+			goto process_auth_err;
+		goto process_auth_final;
+	}
+
+	if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
 		goto process_auth_err;
 
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DigestUpdate(ctx, (char *)src, l) <= 0)
+			goto process_auth_err;
+		n -= l;
+	}
+
+process_auth_final:
 	if (EVP_DigestFinal_ex(ctx, dst, (unsigned int *)&dstlen) <= 0)
 		goto process_auth_err;
-
 	return 0;
 
 process_auth_err:
@@ -691,18 +829,48 @@
 
 /** Process standard openssl auth algorithms with hmac */
 static int
-process_openssl_auth_hmac(uint8_t *src, uint8_t *dst,
+process_openssl_auth_hmac(struct rte_mbuf *mbuf_src, uint8_t *dst, int offset,
 		__rte_unused uint8_t *iv, EVP_PKEY *pkey,
-		int srclen,	EVP_MD_CTX *ctx, const EVP_MD *algo)
+		int srclen, EVP_MD_CTX *ctx, const EVP_MD *algo)
 {
 	size_t dstlen;
+	struct rte_mbuf *m;
+	int l, n = srclen;
+	uint8_t *src;
+
+	for (m = mbuf_src; m != NULL && offset > rte_pktmbuf_data_len(m);
+			m = m->next)
+		offset -= rte_pktmbuf_data_len(m);
+
+	if (m == 0)
+		goto process_auth_err;
 
 	if (EVP_DigestSignInit(ctx, NULL, algo, NULL, pkey) <= 0)
 		goto process_auth_err;
 
-	if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+	src = rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+
+	l = rte_pktmbuf_data_len(m) - offset;
+	if (srclen <= l) {
+		if (EVP_DigestSignUpdate(ctx, (char *)src, srclen) <= 0)
+			goto process_auth_err;
+		goto process_auth_final;
+	}
+
+	if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
 		goto process_auth_err;
 
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		src = rte_pktmbuf_mtod(m, uint8_t *);
+		l = rte_pktmbuf_data_len(m) < n ? rte_pktmbuf_data_len(m) : n;
+		if (EVP_DigestSignUpdate(ctx, (char *)src, l) <= 0)
+			goto process_auth_err;
+		n -= l;
+	}
+
+process_auth_final:
 	if (EVP_DigestSignFinal(ctx, dst, &dstlen) <= 0)
 		goto process_auth_err;
 
@@ -722,9 +890,18 @@
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
 	/* cipher */
-	uint8_t *src = NULL, *dst = NULL, *iv, *tag, *aad;
+	uint8_t *dst = NULL, *iv, *tag, *aad;
 	int srclen, ivlen, aadlen, status = -1;
 
+	/*
+	 * Segmented destination buffer is not supported for
+	 * encryption/decryption
+	 */
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return;
+	}
+
 	iv = op->sym->cipher.iv.data;
 	ivlen = op->sym->cipher.iv.length;
 	aad = op->sym->auth.aad.data;
@@ -740,22 +917,22 @@
 		srclen = 0;
 	else {
 		srclen = op->sym->cipher.data.length;
-		src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-				op->sym->cipher.data.offset);
 		dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
 				op->sym->cipher.data.offset);
 	}
 
 	if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
 		status = process_openssl_auth_encryption_gcm(
-				src, srclen, aad, aadlen, iv, ivlen,
-				sess->cipher.key.data, dst, tag,
-				sess->cipher.ctx, sess->cipher.evp_algo);
+				mbuf_src, op->sym->cipher.data.offset, srclen,
+				aad, aadlen, iv, ivlen, sess->cipher.key.data,
+				dst, tag, sess->cipher.ctx,
+				sess->cipher.evp_algo);
 	else
 		status = process_openssl_auth_decryption_gcm(
-				src, srclen, aad, aadlen, iv, ivlen,
-				sess->cipher.key.data, dst, tag,
-				sess->cipher.ctx, sess->cipher.evp_algo);
+				mbuf_src, op->sym->cipher.data.offset, srclen,
+				aad, aadlen, iv, ivlen, sess->cipher.key.data,
+				dst, tag, sess->cipher.ctx,
+				sess->cipher.evp_algo);
 
 	if (status != 0) {
 		if (status == (-EFAULT) &&
@@ -773,12 +950,19 @@
 		(struct rte_crypto_op *op, struct openssl_session *sess,
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
-	uint8_t *src, *dst, *iv;
+	uint8_t *dst, *iv;
 	int srclen, status;
 
+	/*
+	 * Segmented destination buffer is not supported for
+	 * encryption/decryption
+	 */
+	if (!rte_pktmbuf_is_contiguous(mbuf_dst)) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return;
+	}
+
 	srclen = op->sym->cipher.data.length;
-	src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-			op->sym->cipher.data.offset);
 	dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
 			op->sym->cipher.data.offset);
 
@@ -786,17 +970,20 @@
 
 	if (sess->cipher.mode == OPENSSL_CIPHER_LIB)
 		if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
-			status = process_openssl_cipher_encrypt(src, dst, iv,
+			status = process_openssl_cipher_encrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
 					sess->cipher.key.data, srclen,
 					sess->cipher.ctx,
 					sess->cipher.evp_algo);
 		else
-			status = process_openssl_cipher_decrypt(src, dst, iv,
+			status = process_openssl_cipher_decrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
 					sess->cipher.key.data, srclen,
 					sess->cipher.ctx,
 					sess->cipher.evp_algo);
 	else
-		status = process_openssl_cipher_des3ctr(src, dst, iv,
+		status = process_openssl_cipher_des3ctr(mbuf_src, dst,
+				op->sym->cipher.data.offset, iv,
 				sess->cipher.key.data, srclen,
 				sess->cipher.ctx);
 
@@ -810,12 +997,10 @@
 		(struct rte_crypto_op *op, struct openssl_session *sess,
 		struct rte_mbuf *mbuf_src, struct rte_mbuf *mbuf_dst)
 {
-	uint8_t *src, *dst;
+	uint8_t *dst;
 	int srclen, status;
 
 	srclen = op->sym->auth.data.length;
-	src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
-			op->sym->auth.data.offset);
 
 	if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY)
 		dst = (uint8_t *)rte_pktmbuf_append(mbuf_src,
@@ -830,13 +1015,14 @@
 
 	switch (sess->auth.mode) {
 	case OPENSSL_AUTH_AS_AUTH:
-		status = process_openssl_auth(src, dst,
-				NULL, NULL,	srclen,
+		status = process_openssl_auth(mbuf_src, dst,
+				op->sym->auth.data.offset, NULL, NULL, srclen,
 				sess->auth.auth.ctx, sess->auth.auth.evp_algo);
 		break;
 	case OPENSSL_AUTH_AS_HMAC:
-		status = process_openssl_auth_hmac(src, dst,
-				NULL, sess->auth.hmac.pkey, srclen,
+		status = process_openssl_auth_hmac(mbuf_src, dst,
+				op->sym->auth.data.offset, NULL,
+				sess->auth.hmac.pkey, srclen,
 				sess->auth.hmac.ctx, sess->auth.hmac.evp_algo);
 		break;
 	default:
@@ -850,8 +1036,7 @@
 			op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
 		}
 		/* Trim area used for digest from mbuf. */
-		rte_pktmbuf_trim(mbuf_src,
-				op->sym->auth.digest.length);
+		rte_pktmbuf_trim(mbuf_src, op->sym->auth.digest.length);
 	}
 
 	if (status != 0)
@@ -902,7 +1087,6 @@
 		op->sym->session = NULL;
 	}
 
-
 	if (op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)
 		op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
 
@@ -996,7 +1180,8 @@
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
-			RTE_CRYPTODEV_FF_CPU_AESNI;
+			RTE_CRYPTODEV_FF_CPU_AESNI |
+			RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER;
 
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
-- 
1.7.9.5

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

* [PATCH v5 3/3] test: add sgl unit tests for crypto devices
  2017-01-13 15:23       ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
  2017-01-13 15:23         ` [PATCH v5 1/3] crypto: add sgl support in sw PMDs Tomasz Kulasek
  2017-01-13 15:23         ` [PATCH v5 2/3] crypto: add sgl support in openssl PMD Tomasz Kulasek
@ 2017-01-13 15:23         ` Tomasz Kulasek
  2017-01-16 16:11           ` Declan Doherty
  2017-01-16 19:00         ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs De Lara Guarch, Pablo
  3 siblings, 1 reply; 41+ messages in thread
From: Tomasz Kulasek @ 2017-01-13 15:23 UTC (permalink / raw)
  To: dev; +Cc: Daniel Mrzyglod

This patch provides unit tests for set of cipher/hash combinations covering
currently implemented crypto PMD's and allowing to verify scatter gather
support.

Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
---
 app/test/test_cryptodev.c                  |  386 ++++++++++++++++++-
 app/test/test_cryptodev.h                  |  138 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   52 +++
 app/test/test_cryptodev_blockcipher.c      |   87 ++---
 app/test/test_cryptodev_blockcipher.h      |    1 +
 app/test/test_cryptodev_gcm_test_vectors.h |  553 ++++++++++++++++++++++++++++
 6 files changed, 1168 insertions(+), 49 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 3eaf1b7..5786fde 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -1736,6 +1736,10 @@ struct crypto_unittest_params {
 
 	TEST_ASSERT_NOT_NULL(sym_op->cipher.iv.data, "no room to prepend iv");
 
+	/* For OOP operation both buffers must have the same size */
+	if (ut_params->obuf)
+		rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+
 	memset(sym_op->cipher.iv.data, 0, iv_pad_len);
 	sym_op->cipher.iv.phys_addr = rte_pktmbuf_mtophys(ut_params->ibuf);
 	sym_op->cipher.iv.length = iv_pad_len;
@@ -2557,6 +2561,83 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10, 0);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+		/* Validate obuf */
+		TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+			ciphertext,
+			tdata->ciphertext.data,
+			tdata->validCipherLenInBits.len,
+			"KASUMI Ciphertext data not as expected");
+		return 0;
+}
+
+static int
 test_kasumi_encryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2625,6 +2706,81 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_oop_sgl(const struct kasumi_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+
+	const uint8_t *ciphertext;
+	uint8_t buffer[2048];
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create KASUMI session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_KASUMI_F8,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10, 0);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3, 0);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create KASUMI operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->plaintext.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_KASUMI_F8);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_pad_len, buffer);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"KASUMI Ciphertext data not as expected");
+	return 0;
+}
+
+
+static int
 test_kasumi_decryption_oop(const struct kasumi_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2897,6 +3053,85 @@ struct crypto_unittest_params {
 	return 0;
 }
 
+static int
+test_snow3g_encryption_oop_sgl(const struct snow3g_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+	uint8_t buffer[10000];
+	const uint8_t *ciphertext;
+
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	/* Create SNOW 3G session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+					RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+					tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+	/* Append data which is padded to a multiple of */
+	/* the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10, 0);
+	ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 3, 0);
+
+	TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+			"Failed to allocate input buffer in mempool");
+	TEST_ASSERT_NOT_NULL(ut_params->obuf,
+			"Failed to allocate output buffer in mempool");
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create SNOW 3G operation */
+	retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+					tdata->iv.len,
+					tdata->validCipherLenInBits.len,
+					tdata->validCipherOffsetLenInBits.len,
+					RTE_CRYPTO_CIPHER_SNOW3G_UEA2);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+				plaintext_len, buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+				plaintext_len, buffer);
+
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validDataLenInBits.len,
+		"SNOW 3G Ciphertext data not as expected");
+
+	return 0;
+}
+
 /* Shift right a buffer by "offset" bits, "offset" < 8 */
 static void
 buffer_shift_right(uint8_t *buffer, uint32_t length, uint8_t offset)
@@ -3552,6 +3787,84 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_sgl(const struct zuc_test_data *tdata)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	int retval;
+
+	unsigned int plaintext_pad_len;
+	unsigned int plaintext_len;
+	const uint8_t *ciphertext;
+	uint8_t ciphertext_buffer[2048];
+	struct rte_cryptodev_info dev_info;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+		printf("Device doesn't support scatter-gather. "
+				"Test Skipped.\n");
+		return 0;
+	}
+
+	plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+	/* Append data which is padded to a multiple */
+	/* of the algorithms block size */
+	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+			plaintext_pad_len, 10, 0);
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+			tdata->plaintext.data);
+
+	/* Create ZUC session */
+	retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+			RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3,
+			tdata->key.data, tdata->key.len);
+	if (retval < 0)
+		return retval;
+
+	/* Clear mbuf payload */
+
+	pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+	/* Create ZUC operation */
+	retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+			tdata->iv.len, tdata->plaintext.len,
+			tdata->validCipherOffsetLenInBits.len,
+			RTE_CRYPTO_CIPHER_ZUC_EEA3);
+	if (retval < 0)
+		return retval;
+
+	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+						ut_params->op);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+	ut_params->obuf = ut_params->op->sym->m_dst;
+	if (ut_params->obuf)
+		ciphertext = rte_pktmbuf_read(ut_params->obuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+	else
+		ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+			tdata->iv.len, plaintext_len, ciphertext_buffer);
+
+	/* Validate obuf */
+	TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+		ciphertext,
+		tdata->ciphertext.data,
+		tdata->validCipherLenInBits.len,
+		"ZUC Ciphertext data not as expected");
+
+	return 0;
+}
+
+static int
 test_zuc_authentication(const struct zuc_hash_test_data *tdata)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -3619,12 +3932,24 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_kasumi_encryption_test_case_1_sgl(void)
+{
+	return test_kasumi_encryption_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_1_oop(void)
 {
 	return test_kasumi_encryption_oop(&kasumi_test_case_1);
 }
 
 static int
+test_kasumi_encryption_test_case_1_oop_sgl(void)
+{
+	return test_kasumi_encryption_oop_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_2(void)
 {
 	return test_kasumi_encryption(&kasumi_test_case_2);
@@ -3696,6 +4021,13 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_snow3g_encryption_test_case_1_oop_sgl(void)
+{
+	return test_snow3g_encryption_oop_sgl(&snow3g_test_case_1);
+}
+
+
+static int
 test_snow3g_encryption_test_case_1_offset_oop(void)
 {
 	return test_snow3g_encryption_offset_oop(&snow3g_test_case_1);
@@ -3815,6 +4147,12 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_test_case_6_sgl(void)
+{
+	return test_zuc_encryption_sgl(&zuc_test_case_1);
+}
+
+static int
 test_zuc_hash_generate_test_case_1(void)
 {
 	return test_zuc_authentication(&zuc_hash_test_case_1);
@@ -3998,12 +4336,21 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 
 	struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
 
-	sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
-			ut_params->ibuf, auth_tag_len);
-	TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
-			"no room to append digest");
-	sym_op->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(
-			ut_params->ibuf, data_pad_len);
+	if (ut_params->obuf) {
+		sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+				ut_params->obuf, auth_tag_len);
+		TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+				"no room to append digest");
+		sym_op->auth.digest.phys_addr = pktmbuf_mtophys_offset(
+				ut_params->obuf, data_pad_len);
+	} else {
+		sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+				ut_params->ibuf, auth_tag_len);
+		TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+				"no room to append digest");
+		sym_op->auth.digest.phys_addr = pktmbuf_mtophys_offset(
+				ut_params->ibuf, data_pad_len);
+	}
 	sym_op->auth.digest.length = auth_tag_len;
 
 	if (op == RTE_CRYPTO_CIPHER_OP_DECRYPT) {
@@ -4050,6 +4397,11 @@ static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
 	TEST_HEXDUMP(stdout, "aad:",
 			sym_op->auth.aad.data, aad_len);
 
+	if (ut_params->obuf) {
+		rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+		rte_pktmbuf_prepend(ut_params->obuf, aad_buffer_len);
+	}
+
 	sym_op->cipher.data.length = data_len;
 	sym_op->cipher.data.offset = aad_buffer_len + iv_pad_len;
 
@@ -6312,6 +6664,14 @@ struct test_crypto_vector {
 }
 
 static int
+test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_1seg(void)
+{
+	return test_AES_GCM_authenticated_encryption_SGL(
+			&gcm_test_case_8, OUT_OF_PLACE, 400,
+			gcm_test_case_8.plaintext.len);
+}
+
+static int
 test_AES_GCM_auth_encrypt_SGL_in_place_1500B(void)
 {
 
@@ -6683,6 +7043,10 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_AES_GMAC_authentication_verify_test_case_4),
 
+		/** Scatter-Gather */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_1seg),
+
 		/** Negative tests */
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			authentication_verify_HMAC_SHA1_fail_data_corrupt),
@@ -6751,6 +7115,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_2),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_3),
@@ -6773,6 +7139,10 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_kasumi_encryption_test_case_1_oop_sgl),
+
+
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_kasumi_decryption_test_case_1_oop),
 
 		/** KASUMI hash only (UIA1) */
@@ -6825,6 +7195,8 @@ struct test_crypto_vector {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_encryption_test_case_1_oop),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_snow3g_encryption_test_case_1_oop_sgl),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_snow3g_decryption_test_case_1_oop),
 
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6902,6 +7274,8 @@ struct test_crypto_vector {
 			test_zuc_hash_generate_test_case_4),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_zuc_hash_generate_test_case_5),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_zuc_encryption_test_case_6_sgl),
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
 };
diff --git a/app/test/test_cryptodev.h b/app/test/test_cryptodev.h
index a9089aa..67354a9 100644
--- a/app/test/test_cryptodev.h
+++ b/app/test/test_cryptodev.h
@@ -71,4 +71,142 @@
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA384		(24)
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA512		(32)
 
+/**
+ * Write (spread) data from buffer to mbuf data
+ *
+ * @param mbuf
+ *   Destination mbuf
+ * @param offset
+ *   Start offset in mbuf
+ * @param len
+ *   Number of bytes to copy
+ * @param buffer
+ *   Continuous source buffer
+ */
+static inline void
+pktmbuf_write(struct rte_mbuf *mbuf, int offset, int len, const uint8_t *buffer)
+{
+	int n = len;
+	int l;
+	struct rte_mbuf *m;
+	char *dst;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	l = m->data_len - offset;
+
+	/* copy data from first segment */
+	dst = rte_pktmbuf_mtod_offset(m, char *, offset);
+	if (len <= l) {
+		rte_memcpy(dst, buffer, len);
+		return;
+	}
+
+	rte_memcpy(dst, buffer, l);
+	buffer += l;
+	n -= l;
+
+	for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+		dst = rte_pktmbuf_mtod(m, char *);
+		l = m->data_len;
+		if (n < l) {
+			rte_memcpy(dst, buffer, n);
+			return;
+		}
+		rte_memcpy(dst, buffer, l);
+		buffer += l;
+		n -= l;
+	}
+}
+
+static inline uint8_t *
+pktmbuf_mtod_offset(struct rte_mbuf *mbuf, int offset) {
+	struct rte_mbuf *m;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	if (m == NULL) {
+		printf("pktmbuf_mtod_offset: offset out of buffer\n");
+		return NULL;
+	}
+	return rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+}
+
+static inline phys_addr_t
+pktmbuf_mtophys_offset(struct rte_mbuf *mbuf, int offset) {
+	struct rte_mbuf *m;
+
+	for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+		offset -= m->data_len;
+
+	if (m == NULL) {
+		printf("pktmbuf_mtophys_offset: offset out of buffer\n");
+		return 0;
+	}
+	return rte_pktmbuf_mtophys_offset(m, offset);
+}
+
+static inline struct rte_mbuf *
+create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
+		int nb_segs, uint8_t pattern) {
+
+	struct rte_mbuf *m = NULL, *mbuf = NULL;
+	uint8_t *dst;
+	int data_len = 0;
+	int i, size;
+	int t_len;
+
+	if (pkt_len < 1) {
+		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+		return NULL;
+	}
+
+	if (nb_segs < 1) {
+		printf("Number of segments must be 1 or more (is %d)\n",
+				nb_segs);
+		return NULL;
+	}
+
+	t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+	size = pkt_len;
+
+	/* Create chained mbuf_src and fill it generated data */
+	for (i = 0; size > 0; i++) {
+
+		m = rte_pktmbuf_alloc(mbuf_pool);
+		if (i == 0)
+			mbuf = m;
+
+		if (m == NULL) {
+			printf("Cannot create segment for source mbuf");
+			goto fail;
+		}
+
+		/* Make sure if tailroom is zeroed */
+		memset(m->buf_addr, pattern, m->buf_len);
+
+		data_len = size > t_len ? t_len : size;
+		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+		if (dst == NULL) {
+			printf("Cannot append %d bytes to the mbuf\n",
+					data_len);
+			goto fail;
+		}
+
+		if (mbuf != m)
+			rte_pktmbuf_chain(mbuf, m);
+
+		size -= data_len;
+
+	}
+	return mbuf;
+
+fail:
+	if (mbuf)
+		rte_pktmbuf_free(mbuf);
+	return NULL;
+}
+
 #endif /* TEST_CRYPTODEV_H_ */
diff --git a/app/test/test_cryptodev_aes_test_vectors.h b/app/test/test_cryptodev_aes_test_vectors.h
index 898aae1..e566548 100644
--- a/app/test/test_cryptodev_aes_test_vectors.h
+++ b/app/test/test_cryptodev_aes_test_vectors.h
@@ -858,6 +858,16 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-192-CTR XCBC Decryption Digest Verify "
+				"Scatter Gather",
+		.test_data = &aes_test_data_2,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "AES-256-CTR HMAC-SHA1 Encryption Digest",
 		.test_data = &aes_test_data_3,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -883,6 +893,18 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+				"Scatter Gather",
+		.test_data = &aes_test_data_4,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_4,
@@ -926,6 +948,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest "
+				"Scatter Gather Sessionless",
+		.test_data = &aes_test_data_6,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS |
+			BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
 		.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
 			"Verify",
 		.test_data = &aes_test_data_6,
@@ -935,6 +968,17 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT
 	},
 	{
+		.test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
+			"Verify Scatter Gather",
+		.test_data = &aes_test_data_6,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+			BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			BLOCKCIPHER_TEST_TARGET_PMD_QAT
+	},
+	{
 		.test_descr = "AES-128-CBC XCBC Encryption Digest",
 		.test_data = &aes_test_data_7,
 		.op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
@@ -1045,6 +1089,14 @@
 			BLOCKCIPHER_TEST_TARGET_PMD_MB
 	},
 	{
+		.test_descr = "AES-192-CBC Encryption Scater gather",
+		.test_data = &aes_test_data_10,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+			BLOCKCIPHER_TEST_FEATURE_OOP,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
 		.test_descr = "AES-192-CBC Decryption",
 		.test_data = &aes_test_data_10,
 		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
diff --git a/app/test/test_cryptodev_blockcipher.c b/app/test/test_cryptodev_blockcipher.c
index f1fe624..01aef3b 100644
--- a/app/test/test_cryptodev_blockcipher.c
+++ b/app/test/test_cryptodev_blockcipher.c
@@ -41,6 +41,7 @@
 #include <rte_cryptodev_pmd.h>
 
 #include "test.h"
+#include "test_cryptodev.h"
 #include "test_cryptodev_blockcipher.h"
 #include "test_cryptodev_aes_test_vectors.h"
 #include "test_cryptodev_des_test_vectors.h"
@@ -64,6 +65,7 @@
 	struct rte_crypto_sym_op *sym_op = NULL;
 	struct rte_crypto_op *op = NULL;
 	struct rte_cryptodev_sym_session *sess = NULL;
+	struct rte_cryptodev_info dev_info;
 
 	int status = TEST_SUCCESS;
 	const struct blockcipher_test_data *tdata = t->test_data;
@@ -77,6 +79,19 @@
 	uint8_t tmp_src_buf[MBUF_SIZE];
 	uint8_t tmp_dst_buf[MBUF_SIZE];
 
+	int nb_segs = 1;
+
+	if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+		rte_cryptodev_info_get(dev_id, &dev_info);
+		if (!(dev_info.feature_flags &
+				RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+			printf("Device doesn't support scatter-gather. "
+					"Test Skipped.\n");
+			return 0;
+		}
+		nb_segs = 3;
+	}
+
 	if (tdata->cipher_key.len)
 		memcpy(cipher_key, tdata->cipher_key.data,
 			tdata->cipher_key.len);
@@ -101,49 +116,38 @@
 	}
 
 	/* preparing data */
-	ibuf = rte_pktmbuf_alloc(mbuf_pool);
-	if (!ibuf) {
-		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-			"line %u FAILED: %s",
-			__LINE__, "Allocation of rte_mbuf failed");
-		status = TEST_FAILED;
-		goto error_exit;
-	}
-	memset(ibuf->buf_addr, src_pattern, ibuf->buf_len);
-
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
 		buf_len += tdata->iv.len;
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
 		buf_len += digest_len;
 
-	buf_p = rte_pktmbuf_append(ibuf, buf_len);
-	if (!buf_p) {
+	/* for contiguous mbuf, nb_segs is 1 */
+	ibuf = create_segmented_mbuf(mbuf_pool,
+			tdata->ciphertext.len, nb_segs, src_pattern);
+	if (ibuf == NULL) {
 		snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
 			"line %u FAILED: %s",
-			__LINE__, "No room to append mbuf");
+			__LINE__, "Cannot create source mbuf");
 		status = TEST_FAILED;
 		goto error_exit;
 	}
 
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
-		buf_p += tdata->iv.len;
-	}
-
 	/* only encryption requires plaintext.data input,
 	 * decryption/(digest gen)/(digest verify) use ciphertext.data
 	 * to be computed
 	 */
-	if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
-		rte_memcpy(buf_p, tdata->plaintext.data,
-			tdata->plaintext.len);
-		buf_p += tdata->plaintext.len;
-	} else {
-		rte_memcpy(buf_p, tdata->ciphertext.data,
-			tdata->ciphertext.len);
-		buf_p += tdata->ciphertext.len;
-	}
+	if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
+		pktmbuf_write(ibuf, 0, tdata->plaintext.len,
+				tdata->plaintext.data);
+	else
+		pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
+				tdata->ciphertext.data);
 
+	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+		rte_memcpy(rte_pktmbuf_prepend(ibuf, tdata->iv.len),
+				tdata->iv.data, tdata->iv.len);
+	}
+	buf_p = rte_pktmbuf_append(ibuf, digest_len);
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
 		rte_memcpy(buf_p, tdata->digest.data, digest_len);
 	else
@@ -314,17 +318,17 @@
 
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
-			sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
-				(iobuf, uint8_t *, digest_offset);
+			sym_op->auth.digest.data = pktmbuf_mtod_offset
+				(iobuf, digest_offset);
 			sym_op->auth.digest.phys_addr =
-				rte_pktmbuf_mtophys_offset(iobuf,
+				pktmbuf_mtophys_offset(iobuf,
 					digest_offset);
 		} else {
 			auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
-			sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
-				(sym_op->m_src, uint8_t *, digest_offset);
+			sym_op->auth.digest.data = pktmbuf_mtod_offset
+				(sym_op->m_src, digest_offset);
 			sym_op->auth.digest.phys_addr =
-				rte_pktmbuf_mtophys_offset(sym_op->m_src,
+				pktmbuf_mtophys_offset(sym_op->m_src,
 					digest_offset);
 		}
 
@@ -403,13 +407,10 @@
 	}
 
 	if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-		uint8_t *crypto_res;
+		uint8_t buffer[2048];
 		const uint8_t *compare_ref;
 		uint32_t compare_len;
 
-		crypto_res = rte_pktmbuf_mtod_offset(iobuf, uint8_t *,
-			tdata->iv.len);
-
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
 			compare_ref = tdata->ciphertext.data;
 			compare_len = tdata->ciphertext.len;
@@ -418,7 +419,8 @@
 			compare_len = tdata->plaintext.len;
 		}
 
-		if (memcmp(crypto_res, compare_ref, compare_len)) {
+		if (memcmp(rte_pktmbuf_read(iobuf, tdata->iv.len, compare_len,
+				buffer), compare_ref, compare_len)) {
 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
 				"FAILED: %s", __LINE__,
 				"Crypto data not as expected");
@@ -431,12 +433,11 @@
 		uint8_t *auth_res;
 
 		if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
-			auth_res = rte_pktmbuf_mtod_offset(iobuf,
-				uint8_t *,
-				tdata->iv.len + tdata->ciphertext.len);
+			auth_res = pktmbuf_mtod_offset(iobuf,
+					tdata->iv.len + tdata->ciphertext.len);
 		else
-			auth_res = rte_pktmbuf_mtod_offset(iobuf,
-				uint8_t *, tdata->ciphertext.len);
+			auth_res = pktmbuf_mtod_offset(iobuf,
+					tdata->ciphertext.len);
 
 		if (memcmp(auth_res, tdata->digest.data, digest_len)) {
 			snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
diff --git a/app/test/test_cryptodev_blockcipher.h b/app/test/test_cryptodev_blockcipher.h
index fe97e4c..7256f6b 100644
--- a/app/test/test_cryptodev_blockcipher.h
+++ b/app/test/test_cryptodev_blockcipher.h
@@ -45,6 +45,7 @@
 #define BLOCKCIPHER_TEST_FEATURE_OOP			0x01
 #define BLOCKCIPHER_TEST_FEATURE_SESSIONLESS	0x02
 #define BLOCKCIPHER_TEST_FEATURE_STOPPER	0x04 /* stop upon failing */
+#define BLOCKCIPHER_TEST_FEATURE_SG		0x08 /* Scatter Gather */
 
 #define BLOCKCIPHER_TEST_TARGET_PMD_MB		0x0001 /* Multi-buffer flag */
 #define BLOCKCIPHER_TEST_TARGET_PMD_QAT			0x0002 /* QAT flag */
diff --git a/app/test/test_cryptodev_gcm_test_vectors.h b/app/test/test_cryptodev_gcm_test_vectors.h
index df984fc..45ea3d4 100644
--- a/app/test/test_cryptodev_gcm_test_vectors.h
+++ b/app/test/test_cryptodev_gcm_test_vectors.h
@@ -450,6 +450,559 @@ struct gmac_test_data {
 	}
 };
 
+static const struct gcm_test_data gcm_test_case_8 = {
+	.key = {
+		.data = {
+			0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+			0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+			0xde, 0xca, 0xf8, 0x88
+		},
+		.len = 12
+	},
+	.aad = {
+		.data = {
+			0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+			0xfe, 0xed, 0xfa, 0xce
+		},
+		.len = 12
+	},
+	.plaintext = {
+		.data = {
+			0xC5, 0x34, 0x2E, 0x83, 0xEB, 0x4C, 0x02, 0x03,
+			0xF7, 0xB2, 0x57, 0x35, 0x26, 0x81, 0x63, 0xAE,
+			0x1F, 0xCD, 0x2D, 0x02, 0x91, 0x5A, 0xDB, 0x3A,
+			0xF1, 0x38, 0xD8, 0x75, 0x86, 0x20, 0xCC, 0x1E,
+			0xE6, 0xDC, 0xFF, 0xB5, 0xEA, 0x0E, 0x18, 0x7A,
+			0x86, 0x6C, 0xAB, 0x39, 0x2D, 0x90, 0xAC, 0x77,
+			0x5D, 0xED, 0x65, 0xB3, 0x05, 0x29, 0xBB, 0x09,
+			0xD0, 0x21, 0x74, 0x6A, 0x67, 0x1C, 0x95, 0x42,
+			0x55, 0xAD, 0xC8, 0x91, 0x28, 0xFE, 0x16, 0x9A,
+			0xE1, 0xCB, 0xCD, 0x68, 0x3B, 0xDF, 0x3E, 0x3A,
+			0x34, 0xFE, 0x9B, 0xFB, 0xF5, 0x15, 0x2A, 0x29,
+			0x18, 0x99, 0x24, 0xBF, 0xB6, 0x43, 0xDB, 0xD1,
+			0x69, 0x26, 0x1E, 0x31, 0x2C, 0x8C, 0x3C, 0x6B,
+			0x7F, 0x06, 0xA6, 0x03, 0xE2, 0x1A, 0x50, 0xFE,
+			0x7C, 0x69, 0xE5, 0x5F, 0x35, 0x93, 0xE9, 0x20,
+			0x14, 0xB1, 0xCA, 0x61, 0xE7, 0x9C, 0x89, 0x08,
+			0xD6, 0xB1, 0xC2, 0x63, 0x1B, 0x86, 0x5E, 0xF1,
+			0xF5, 0x23, 0x0E, 0x9B, 0xE5, 0xBD, 0x5D, 0x04,
+			0xF7, 0xEF, 0x8E, 0x46, 0xB0, 0x11, 0x4F, 0x69,
+			0x62, 0x35, 0x51, 0xB7, 0x24, 0xA2, 0x31, 0xD0,
+			0x32, 0x4E, 0xB8, 0x44, 0xC7, 0x59, 0xDE, 0x25,
+			0xEA, 0x2D, 0x00, 0x0E, 0xF1, 0x07, 0xBA, 0xBB,
+			0x9A, 0xBC, 0x4F, 0x57, 0xB7, 0x13, 0x57, 0xEF,
+			0xD9, 0xF6, 0x80, 0x69, 0xEA, 0xE8, 0x47, 0x9C,
+			0x51, 0x71, 0xE6, 0x8F, 0x69, 0x29, 0xB4, 0x60,
+			0xE8, 0x50, 0xE5, 0xD0, 0x9B, 0xD2, 0x62, 0x6F,
+			0x09, 0x5C, 0xD1, 0x4B, 0x85, 0xE2, 0xFD, 0xD3,
+			0xEB, 0x28, 0x55, 0x77, 0x97, 0xCA, 0xD6, 0xA8,
+			0xDC, 0x35, 0x68, 0xF7, 0x6A, 0xCF, 0x48, 0x3F,
+			0x49, 0x31, 0x00, 0x65, 0xB7, 0x31, 0x1A, 0x49,
+			0x75, 0xDE, 0xCE, 0x7F, 0x18, 0xB5, 0x31, 0x9A,
+			0x64, 0x6D, 0xE5, 0x49, 0x1D, 0x6D, 0xF2, 0x21,
+			0x9F, 0xF5, 0xFF, 0x7C, 0x41, 0x30, 0x33, 0x06,
+			0x7B, 0xA4, 0xD8, 0x99, 0xF6, 0xCC, 0xDF, 0xC4,
+			0x3F, 0xF3, 0xCD, 0xE7, 0x74, 0xC4, 0x4A, 0x19,
+			0x5C, 0xCA, 0x42, 0x31, 0xF1, 0x3B, 0x65, 0x1C,
+			0x3D, 0x56, 0x08, 0xBE, 0x15, 0x37, 0x23, 0x50,
+			0xD6, 0xA3, 0x57, 0x64, 0x25, 0xBE, 0xDA, 0xC2,
+			0x4E, 0xF5, 0x1A, 0xAD, 0x6F, 0x43, 0x78, 0x21,
+			0xF9, 0x36, 0x39, 0x1F, 0x5F, 0xF7, 0x1B, 0xA0,
+			0xEE, 0x8B, 0x4F, 0x8A, 0x9D, 0xD8, 0xED, 0x37,
+			0xCE, 0x0D, 0x70, 0xE0, 0x3F, 0xE7, 0x11, 0x30,
+			0x17, 0x1D, 0x03, 0x5E, 0xA0, 0x3D, 0x3F, 0x9E,
+			0xF5, 0xD3, 0x74, 0x2E, 0xC1, 0xD6, 0xFF, 0xF7,
+			0x2E, 0xE7, 0x80, 0x88, 0xCF, 0x0E, 0x7F, 0x12,
+			0x71, 0x62, 0xC7, 0xF1, 0xC4, 0x2B, 0x64, 0x5D,
+			0x1C, 0x9A, 0xB4, 0xCB, 0xB8, 0x24, 0xB3, 0x0B,
+			0x33, 0xF2, 0x8A, 0x8F, 0x76, 0xC8, 0x81, 0xDA,
+			0x1A, 0x10, 0xB5, 0xA9, 0xCD, 0xDC, 0x1A, 0x02,
+			0xC1, 0xAE, 0x4F, 0x02, 0x1B, 0x13, 0x96, 0x5A,
+			0x2E, 0x03, 0xA2, 0x68, 0xB2, 0x29, 0xAC, 0x28,
+			0xB8, 0xDC, 0xD5, 0x27, 0x55, 0xEC, 0x43, 0xDC,
+			0xB7, 0x49, 0x1D, 0xE1, 0x30, 0x25, 0x81, 0xA6,
+			0x90, 0x1F, 0x75, 0xBA, 0x19, 0x1E, 0xF7, 0xC5,
+			0x77, 0x35, 0xEE, 0x68, 0x71, 0x22, 0xA0, 0xB4,
+			0xCC, 0x99, 0x86, 0x1B, 0x1B, 0xC8, 0x27, 0xFC,
+			0x6D, 0x8D, 0xE7, 0x8B, 0xC3, 0x40, 0x3D, 0xA8,
+			0xCB, 0x9B, 0xC4, 0x12, 0x07, 0xDD, 0xA1, 0x92,
+			0xE5, 0x80, 0x7A, 0xF4, 0xDB, 0x4C, 0xE6, 0xEE,
+			0xF9, 0xD5, 0x1C, 0x20, 0x18, 0xD3, 0x8F, 0xDF,
+			0x1C, 0xD3, 0x51, 0x4E, 0x0E, 0xED, 0x06, 0x61,
+			0xF7, 0xBA, 0x81, 0x3A, 0x2F, 0xEA, 0xED, 0x70,
+			0xA9, 0xD9, 0x54, 0x4D, 0xFC, 0x1D, 0x19, 0xEA,
+			0xA6, 0x39, 0x8C, 0x6C, 0x78, 0xA8, 0x05, 0xEB,
+			0xF2, 0xB5, 0xDE, 0x06, 0x9D, 0x8A, 0x78, 0x2A,
+			0xF5, 0x50, 0xA4, 0xBD, 0x9B, 0xDA, 0xCA, 0x66,
+			0xC0, 0x23, 0xAB, 0xE8, 0x95, 0x7E, 0xC9, 0xD2,
+			0x6F, 0x09, 0xF2, 0x9A, 0x17, 0x89, 0xDA, 0x47,
+			0x65, 0x8C, 0x20, 0xFA, 0x4E, 0x86, 0x18, 0xEB,
+			0x7C, 0x08, 0xEC, 0x8A, 0x05, 0x54, 0x96, 0xD2,
+			0x7A, 0x8A, 0x81, 0x58, 0x75, 0x8C, 0x7B, 0x02,
+			0xEE, 0x1F, 0x51, 0x88, 0xD0, 0xD1, 0x90, 0x99,
+			0x0C, 0xAE, 0x51, 0x2E, 0x54, 0x3E, 0xB1, 0x7D,
+			0xBC, 0xE8, 0x54, 0x93, 0x6D, 0x10, 0x3C, 0xC6,
+			0x71, 0xF6, 0xF5, 0x0B, 0x07, 0x0A, 0x6E, 0x59,
+			0x20, 0x45, 0x21, 0x7D, 0x37, 0x64, 0x92, 0x09,
+			0xA7, 0xE2, 0x34, 0x6F, 0xFC, 0xCC, 0x66, 0x0E,
+			0x88, 0x1B, 0x19, 0x86, 0x11, 0xD7, 0x81, 0x25,
+			0xF1, 0x8A, 0x03, 0xB7, 0x7A, 0xF0, 0x98, 0x4A,
+			0x5C, 0xA1, 0x6D, 0x85, 0xA4, 0x8C, 0x4B, 0x65,
+			0x9F, 0x72, 0x64, 0x14, 0xBA, 0x74, 0xEE, 0xA3,
+			0x88, 0xFE, 0x1B, 0xCF, 0x11, 0x4F, 0xD1, 0xAC,
+			0xFA, 0x14, 0xC3, 0xA7, 0xDD, 0x06, 0x85, 0x4E,
+			0x64, 0x06, 0x92, 0x9C, 0xDF, 0x06, 0x09, 0xF1,
+			0x4D, 0xE8, 0xF8, 0x2F, 0x69, 0xB6, 0x8A, 0xAF,
+			0x25, 0x21, 0xB5, 0x48, 0x59, 0xF8, 0x9D, 0x60,
+			0xAE, 0x42, 0x11, 0x7A, 0x68, 0x4D, 0x7E, 0x76,
+			0xB0, 0xD2, 0xE3, 0xD9, 0x24, 0x16, 0x20, 0x0A,
+			0xEB, 0xE0, 0x68, 0xCB, 0xBC, 0xAB, 0x67, 0xE4,
+			0xF3, 0x25, 0x1F, 0xD3, 0x85, 0xA7, 0x1D, 0x7E,
+			0x3C, 0x63, 0xCB, 0xC2, 0x50, 0x90, 0x0F, 0x4B,
+			0x6E, 0x68, 0x06, 0x84, 0x65, 0xF7, 0xD0, 0xD4,
+			0x12, 0xED, 0xFA, 0xC9, 0x40, 0xE2, 0xC0, 0xC9,
+			0x46, 0x22, 0x47, 0x5E, 0x6D, 0xC1, 0x63, 0xDB,
+			0x51, 0x98, 0xDA, 0x1A, 0xC4, 0xB9, 0xED, 0xE9,
+			0x09, 0xB9, 0xCF, 0x91, 0x04, 0x1C, 0x63, 0xD8,
+			0xC5, 0xA5, 0xAE, 0x53, 0x7B, 0xA1, 0x29, 0x83,
+			0x37, 0xFB, 0xBF, 0x96, 0xBB, 0x24, 0x3D, 0x77,
+			0x8C, 0x0F, 0xB3, 0x4B, 0x66, 0x9C, 0x54, 0xBB,
+			0xF6, 0xDD, 0xD1, 0xB4, 0xD2, 0xF6, 0xAA, 0xED,
+			0x18, 0x56, 0x63, 0x3E, 0x0B, 0xCA, 0xAB, 0x70,
+			0xBB, 0x63, 0xEA, 0xB1, 0x00, 0x65, 0x90, 0x18,
+			0xB8, 0x63, 0xA2, 0xF2, 0xB6, 0x1E, 0x61, 0x7B,
+			0xD5, 0x01, 0xD9, 0x4D, 0xC9, 0x9D, 0x99, 0xC1,
+			0x57, 0x9D, 0x6F, 0xAE, 0x64, 0xE4, 0x0C, 0x7E,
+			0xFA, 0x15, 0x5E, 0xB6, 0x43, 0xB8, 0x8B, 0x89,
+			0x87, 0xCD, 0x4F, 0xAD, 0x30, 0x1E, 0xA5, 0x03,
+			0x7A, 0xC2, 0x10, 0x42, 0x14, 0x88, 0xD6, 0x7A,
+			0x6D, 0x56, 0x52, 0x2E, 0x8D, 0x1B, 0x5D, 0x36,
+			0x27, 0xA0, 0x21, 0x4B, 0x64, 0xF0, 0xC5, 0x41,
+			0xAD, 0x05, 0x4A, 0x24, 0xE4, 0x70, 0x88, 0x63,
+			0x12, 0xD0, 0xBC, 0x05, 0x38, 0xD9, 0x41, 0x68,
+			0x9F, 0x16, 0x9A, 0x54, 0x09, 0x21, 0x64, 0x36,
+			0x63, 0x97, 0x3A, 0xB5, 0xE0, 0x25, 0x43, 0x8A,
+			0x6A, 0x59, 0x97, 0xC1, 0x31, 0xA5, 0x66, 0xD2,
+			0xF0, 0x1C, 0xDF, 0x97, 0x51, 0xD0, 0x61, 0xBA,
+			0x55, 0x5F, 0xD7, 0x0D, 0xD4, 0x75, 0x8E, 0x79,
+			0x04, 0x75, 0x00, 0xB9, 0xC0, 0x7A, 0x66, 0x05,
+			0x9F, 0x2B, 0x44, 0x42, 0x75, 0x0F, 0xD5, 0x15,
+			0xD6, 0x16, 0x8F, 0x6C, 0x6E, 0xD4, 0x37, 0xCF,
+			0xB4, 0xDA, 0x93, 0x00, 0x11, 0xFB, 0xBE, 0xEE,
+			0x3B, 0x6D, 0x1D, 0xBA, 0x33, 0xD1, 0x52, 0x8B,
+			0x16, 0x39, 0x42, 0x27, 0xE6, 0x56, 0x4C, 0x41,
+			0x91, 0xB0, 0x98, 0xAE, 0x9B, 0x2D, 0x9B, 0x23,
+			0x80, 0x4C, 0xEA, 0x98, 0x57, 0x95, 0x28, 0x94,
+			0x43, 0xD3, 0x88, 0x12, 0xDF, 0x89, 0x5A, 0x7B,
+			0xC5, 0xCB, 0x36, 0x54, 0x65, 0x74, 0xB8, 0x4E,
+			0xE2, 0x4D, 0x01, 0xD5, 0x9C, 0x82, 0xB9, 0x1A,
+			0x09, 0xD2, 0xCE, 0x04, 0x36, 0xD8, 0x41, 0xAC,
+			0x4C, 0xAD, 0xC6, 0x52, 0x91, 0x1A, 0x06, 0x6D,
+			0xFC, 0xAB, 0x29, 0x93, 0x87, 0x88, 0xB9, 0x8C,
+			0xFA, 0x57, 0x2B, 0x05, 0x03, 0xD0, 0x18, 0xED,
+			0x7A, 0x7B, 0x81, 0x6A, 0x97, 0x65, 0x5B, 0x90,
+			0xDE, 0xA9, 0xFC, 0x8F, 0xFC, 0xBB, 0x98, 0xD8,
+			0xFA, 0x32, 0x3F, 0x3F, 0x7F, 0x74, 0x65, 0x38,
+			0xC4, 0x28, 0xEC, 0x27, 0x1F, 0x28, 0x01, 0xB1,
+			0xAF, 0x2B, 0x8A, 0x05, 0x38, 0x7B, 0x77, 0xC9,
+			0x61, 0x77, 0x34, 0x2C, 0x22, 0xE5, 0xEB, 0xDC,
+			0x9D, 0x18, 0x6E, 0x23, 0x25, 0x52, 0x69, 0xB7,
+			0x05, 0xDB, 0x66, 0x5D, 0xEA, 0x76, 0x83, 0x82,
+			0x97, 0x39, 0xAF, 0xC0, 0x50, 0x81, 0x18, 0x0D,
+			0x22, 0xFA, 0xB7, 0x44, 0x5C, 0x3F, 0x69, 0xF3,
+			0xAC, 0xC5, 0x63, 0x9F, 0xD8, 0x72, 0x7E, 0x9A,
+			0xC2, 0xEB, 0x79, 0xD0, 0x74, 0x65, 0xE8, 0xCA,
+			0xFD, 0xA8, 0x7D, 0x23, 0x07, 0x99, 0x3E, 0xAF,
+			0xDB, 0x67, 0x10, 0xC0, 0xE5, 0x61, 0x77, 0xC6,
+			0x8D, 0xC4, 0x0E, 0xAA, 0x55, 0xE3, 0xC0, 0xC7,
+			0xA5, 0x36, 0x28, 0x61, 0xDB, 0x16, 0x96, 0x5E,
+			0x01, 0x47, 0x82, 0xE3, 0xEB, 0x20, 0x3F, 0x10,
+			0xFA, 0x5A, 0xBC, 0xD3, 0xF9, 0xCE, 0x04, 0x87,
+			0x51, 0x07, 0xF9, 0xD0, 0xE7, 0x6D, 0xCB, 0xCC,
+			0xC4, 0x15, 0x00, 0xE2, 0xDC, 0x8E, 0x7B, 0x5C,
+			0x9A, 0xF2, 0x78, 0x70, 0x4D, 0xA1, 0xAA, 0xB5,
+			0x13, 0xCC, 0x71, 0x66, 0x5A, 0x79, 0x13, 0x3B,
+			0x12, 0xCD, 0x40, 0x30, 0x5A, 0x49, 0xD4, 0x20,
+			0xED, 0xCF, 0x4A, 0x75, 0xE6, 0xD5, 0xDD, 0x0F,
+			0xD4, 0xBE, 0x98, 0x9F, 0xD7, 0x1F, 0xC0, 0x02,
+			0x31, 0xFA, 0x67, 0x37, 0x25, 0x86, 0x56, 0x85,
+			0x2B, 0xA2, 0x57, 0xCD, 0x8E, 0x74, 0xE7, 0x69,
+			0xEE, 0x33, 0x5A, 0x3F, 0xCD, 0x1E, 0xE3, 0xB9,
+			0xAA, 0x52, 0xF5, 0x22, 0x4E, 0xE3, 0xFF, 0xC8,
+			0xE3, 0x13, 0xA3, 0x9A, 0x63, 0x23, 0xC3, 0xD7,
+			0xE5, 0x88, 0x3E, 0x0A, 0x4B, 0xA5, 0x01, 0xE6,
+			0x13, 0xCF, 0xED, 0xEE, 0x2A, 0x58, 0x09, 0x3F,
+			0x2F, 0x28, 0xE7, 0xC4, 0x6B, 0xEC, 0x49, 0x51,
+			0x79, 0x8F, 0xD5, 0x19, 0x5D, 0xA5, 0x10, 0xCE,
+			0x8E, 0xF6, 0x26, 0x78, 0x7A, 0xA8, 0x11, 0x52,
+			0x5F, 0x97, 0x14, 0xC9, 0x29, 0x87, 0xB8, 0xA0,
+			0x2D, 0xE6, 0xA7, 0x2A, 0xD4, 0xFF, 0xEB, 0xBA,
+			0xFD, 0x58, 0x39, 0x33, 0xB1, 0xCE, 0x0E, 0x78,
+			0x67, 0x1E, 0xA1, 0x92, 0x77, 0x63, 0xF8, 0xC0,
+			0x02, 0x49, 0x73, 0xC0, 0xA1, 0x26, 0x83, 0x04,
+			0x9A, 0x5D, 0x85, 0x68, 0x2A, 0x2F, 0xCB, 0x88,
+			0x8D, 0x14, 0xB1, 0x33, 0xFA, 0xFB, 0xE9, 0x05,
+			0xBE, 0x24, 0x1A, 0x6B, 0x29, 0x2B, 0x3F, 0x52,
+			0x8F, 0xFB, 0xE6, 0x02, 0x77, 0x50, 0x71, 0xDB,
+			0xE9, 0x92, 0x3F, 0xE1, 0x20, 0x62, 0x80, 0xAE,
+			0xA4, 0x98, 0xC6, 0xCD, 0xE0, 0xB1, 0xC3, 0x33,
+			0xB1, 0xC5, 0x91, 0x3C, 0x19, 0x34, 0xA8, 0xD9,
+			0xB3, 0x25, 0x69, 0xE3, 0x9C, 0x5F, 0x78, 0xD0,
+			0x83, 0x1F, 0xAB, 0x85, 0x13, 0x56, 0x69, 0xB5,
+			0x06, 0x47, 0x62, 0x37, 0x27, 0x15, 0x14, 0x05,
+			0x4A, 0xF4, 0x6A, 0x68, 0x2A, 0x6A, 0xC3, 0x5A,
+			0xDF, 0xB5, 0xAE, 0x2F, 0x8D, 0x8F, 0x21, 0xDB,
+			0x33, 0x00, 0x9B, 0xD4, 0xC4, 0x08, 0x3B, 0x81,
+			0x63, 0x4C, 0xB0, 0x39, 0x4C, 0x0A, 0xD5, 0x71,
+			0x3E, 0x5A, 0x50, 0x58, 0x9C, 0x07, 0x89, 0x79,
+			0x79, 0x2F, 0x0B, 0xD9, 0x50, 0xBC, 0xCF, 0x46,
+			0x7A, 0x68, 0x5C, 0xBF, 0x1E, 0x49, 0x77, 0x92,
+			0x85, 0x11, 0x39, 0xA6, 0x2F, 0xDA, 0x7B, 0xFA,
+			0x72, 0x87, 0x06, 0xCD, 0x84, 0x41, 0x20, 0x1B,
+			0x66, 0x3F, 0x42, 0x0C, 0x9E, 0x19, 0xD3, 0x18,
+			0x57, 0xA0, 0xEE, 0x16, 0x3A, 0xC7, 0xF9, 0xD3,
+			0x8B, 0xC9, 0x24, 0x70, 0x70, 0x51, 0x7C, 0x06,
+			0x68, 0xD3, 0x29, 0xC9, 0x85, 0x9A, 0x1C, 0xE6,
+			0x8C, 0x17, 0xF4, 0x88, 0xDF, 0xEA, 0xFF, 0x44,
+			0x8D, 0x54, 0xBE, 0x22, 0x07, 0xA5, 0x7C, 0x0C,
+			0xF4, 0x8D, 0xB1, 0x0C, 0x07, 0xED, 0xBD, 0x28,
+			0x19, 0xDA, 0x07, 0x71, 0xA8, 0xA1, 0xE0, 0xDD,
+			0xEE, 0x08, 0x18, 0xA5, 0xBD, 0xDD, 0x32, 0x0B,
+			0x70, 0x1C, 0xD9, 0xEE, 0x19, 0xC2, 0xAE, 0x5C,
+			0xE3, 0x02, 0x74, 0x70, 0x96, 0x61, 0xB1, 0x73,
+			0x3B, 0xD6, 0x74, 0xC0, 0x82, 0xA9, 0x1F, 0xE0,
+			0xF1, 0x22, 0x50, 0xF3, 0x9F, 0xE5, 0x13, 0x92,
+			0xFC, 0x0A, 0x1A, 0x3C, 0xB4, 0x46, 0xFB, 0x81,
+			0x00, 0x84, 0xA4, 0x5E, 0x6B, 0x8C, 0x25, 0x6E,
+			0xD7, 0xB7, 0x3B, 0x01, 0x65, 0xFB, 0x0B, 0x46,
+			0x67, 0x27, 0x2D, 0x51, 0xAD, 0xB5, 0xE0, 0x85,
+			0xC2, 0x95, 0xA3, 0xE3, 0x68, 0x4D, 0x9E, 0x8C,
+			0x11, 0x53, 0xF0, 0xB2, 0x85, 0xFA, 0x52, 0x4E,
+			0xEC, 0xF9, 0xB7, 0x3C, 0x89, 0x2C, 0x4D, 0x32,
+			0x9A, 0xCB, 0x17, 0xF3, 0x16, 0xBF, 0x44, 0x40,
+			0xE9, 0x5E, 0x51, 0x8C, 0x1E, 0x52, 0x0A, 0xC2,
+			0xCD, 0xA5, 0xAA, 0x03, 0x27, 0xB0, 0x8F, 0x64,
+			0xDB, 0xD7, 0x03, 0x01, 0x8A, 0x24, 0x28, 0x7E,
+			0x53, 0x6F, 0x24, 0xFD, 0xAA, 0xE3, 0x78, 0xB6,
+			0xA5, 0x5D, 0x5A, 0x67, 0x20, 0xE2, 0xBE, 0x3A,
+			0x2B, 0xE7, 0x86, 0x11, 0xDD, 0x96, 0xCB, 0x09,
+			0x65, 0xA0, 0x36, 0xF9, 0xB0, 0x20, 0x21, 0x8E,
+			0xDB, 0xC0, 0x73, 0xC7, 0x79, 0xD8, 0xDA, 0xC2,
+			0x66, 0x13, 0x64, 0x34, 0x0C, 0xE1, 0x22, 0x24,
+			0x61, 0x67, 0x08, 0x39, 0x97, 0x3F, 0x33, 0x96,
+			0xF2, 0x44, 0x18, 0x75, 0xBB, 0xF5, 0x6A, 0x5C,
+			0x2C, 0xAE, 0x2A, 0x79, 0x3D, 0x47, 0x19, 0x53,
+			0x50, 0x6C, 0x9F, 0xB3, 0x82, 0x55, 0x09, 0x78,
+			0x7B, 0xAD, 0xBC, 0x05, 0x6F, 0xC8, 0x3D, 0xB6,
+			0x7B, 0x30, 0xE6, 0xBB, 0x8B, 0xD0, 0x2F, 0xA6,
+			0x15, 0xCC, 0x77, 0x8C, 0x21, 0xBA, 0x03, 0xED,
+			0x56, 0x85, 0x82, 0x4F, 0x97, 0x8C, 0x59, 0x4F,
+			0x53, 0x5A, 0xD2, 0x70, 0xD9, 0x07, 0xB3, 0xBD,
+			0x1D, 0x3E, 0x97, 0xD4, 0x7D, 0x93, 0x35, 0xA4,
+			0x82, 0x6E, 0xEA, 0x4B, 0xC8, 0x6C, 0xF5, 0xE6,
+			0xEB, 0xAF, 0x11, 0xB0, 0xB4, 0x71, 0x8F, 0x7B,
+			0xC4, 0x8C, 0xE2, 0x66, 0x51, 0x31, 0x99, 0x01,
+			0x5B, 0xE7, 0x48, 0xF8, 0x4C, 0xE3, 0x9A, 0x77,
+			0xF1, 0xC6, 0x09, 0xDE, 0x76, 0xD4, 0xE3, 0x5C,
+			0xDF, 0xA3, 0xEC, 0x3C, 0x86, 0x7C, 0xA5, 0x3F,
+			0x8D, 0x2A, 0xF3, 0x0B, 0x54, 0xB7, 0x54, 0xA2,
+			0xC1, 0x69, 0xC0, 0x6F, 0x1C, 0x1C, 0x76, 0xD8,
+			0x9F, 0x7A, 0x32, 0xB0, 0xA1, 0xA6, 0x9B, 0xB7,
+			0x21, 0x56, 0x28, 0x2D, 0xB6, 0x97, 0x03, 0x5E,
+			0x65, 0xE3, 0x74, 0x9A, 0x96, 0x7A, 0xF9, 0xF5,
+			0xDD, 0x85, 0xCA, 0x4C, 0xB4, 0x03, 0x6A, 0xCD,
+			0xB6, 0x01, 0xDC, 0x8B, 0xD8, 0x73, 0x8F, 0x4D,
+			0x7F, 0xD6, 0x71, 0xEC, 0xD7, 0xC6, 0x0B, 0x5F,
+			0x09, 0x21, 0xB2, 0x78, 0xA8, 0xAF, 0xAD, 0x2C,
+			0xD4, 0x93, 0x9F, 0x71, 0xF7, 0x05, 0x89, 0x42,
+			0xC9, 0x15, 0x6F, 0x2D, 0xE0, 0xBA, 0xC3, 0xD6,
+			0xBF, 0xAC, 0xF8, 0x24, 0x58, 0x79, 0xA9, 0xC4,
+			0xB4, 0x49, 0x3E, 0x0B, 0x9E, 0x5E, 0xE4, 0xA6,
+			0x8B, 0xE8, 0xDE, 0xFB, 0x4A, 0xF1, 0x69, 0x9D,
+			0x4F, 0x77, 0x83, 0x78, 0x55, 0x19, 0x42, 0x45,
+			0xBF, 0xBD, 0xBD, 0x12, 0x0F, 0xEF, 0x8D, 0x04,
+			0xD8, 0x5C, 0xF2, 0xC9, 0xF1, 0xA6, 0xE0, 0x3E,
+			0x22, 0xA8, 0xA2, 0x5E, 0x66, 0xE9, 0xAB, 0xB4,
+			0x71, 0xBE, 0x4B, 0x3F, 0xBE, 0xC4, 0xBA, 0x4A
+		},
+		.len = 2048
+	},
+	.ciphertext = {
+		.data = {
+			0x5E, 0x86, 0x02, 0x64, 0x32, 0xBF, 0x70, 0xC2,
+			0x19, 0x99, 0x7F, 0x47, 0x0D, 0xA4, 0x91, 0xA8,
+			0x7A, 0xC0, 0xA5, 0x7E, 0xA8, 0x6C, 0x88, 0x00,
+			0xEA, 0xB5, 0x96, 0x6B, 0x25, 0xBD, 0xE7, 0x42,
+			0xDB, 0x35, 0xE7, 0x92, 0x2B, 0x00, 0x82, 0x35,
+			0xD4, 0x2C, 0xCF, 0x47, 0xC8, 0xB2, 0xB3, 0x57,
+			0xF7, 0x24, 0x83, 0x7F, 0xC5, 0x2E, 0xF1, 0xC9,
+			0x57, 0x1A, 0xEF, 0xC2, 0x3A, 0x8C, 0x1E, 0x92,
+			0x88, 0x05, 0xAF, 0x55, 0xE6, 0x0C, 0xA7, 0x6B,
+			0x59, 0x62, 0x32, 0x21, 0xF1, 0xFF, 0xB5, 0x5B,
+			0x22, 0x26, 0x6F, 0x0A, 0x36, 0xDC, 0x0D, 0x16,
+			0x3B, 0x4E, 0x7C, 0xA3, 0x75, 0x30, 0x3F, 0xB0,
+			0x99, 0x38, 0x42, 0x8E, 0x89, 0xA3, 0x7C, 0x99,
+			0x2F, 0x0A, 0xA1, 0xC7, 0xFD, 0x2D, 0x21, 0x8F,
+			0xBD, 0xD4, 0x11, 0xEA, 0x55, 0xF5, 0x6A, 0x50,
+			0x90, 0x3B, 0x60, 0x57, 0xE1, 0x86, 0x1E, 0x50,
+			0x28, 0x67, 0x3F, 0xD2, 0xF3, 0xBD, 0xFA, 0xEE,
+			0xD6, 0x5A, 0x38, 0x30, 0xA3, 0xDD, 0x78, 0xC4,
+			0x37, 0x59, 0x52, 0xC0, 0x92, 0x54, 0xC7, 0x53,
+			0xF0, 0xE6, 0xA9, 0x63, 0x1F, 0x9B, 0x97, 0xFB,
+			0x40, 0x23, 0xFE, 0x52, 0x6A, 0xF0, 0x3A, 0x94,
+			0xEB, 0x6A, 0x9E, 0x8F, 0xC5, 0x05, 0x9C, 0x04,
+			0x1B, 0x00, 0x34, 0x96, 0x12, 0xDA, 0x60, 0xC6,
+			0xAA, 0x1A, 0x3E, 0xEB, 0x70, 0x17, 0x10, 0xBC,
+			0xF5, 0xC2, 0xE2, 0x71, 0xF3, 0xB8, 0x1D, 0xCE,
+			0x47, 0x94, 0x21, 0x71, 0x34, 0x8C, 0xCC, 0xDD,
+			0x27, 0xCE, 0x6F, 0x68, 0xFF, 0x91, 0x4E, 0xC4,
+			0xA0, 0xCA, 0xB0, 0x4F, 0x17, 0x53, 0x73, 0x92,
+			0x6C, 0xA8, 0x16, 0x06, 0xE3, 0xD9, 0x92, 0x99,
+			0xBE, 0xB0, 0x7D, 0x56, 0xF2, 0x72, 0x30, 0xDA,
+			0xC4, 0x4E, 0xF4, 0xA6, 0x8F, 0xD2, 0xC7, 0x8A,
+			0xA2, 0xFC, 0xF5, 0x63, 0x17, 0x48, 0x56, 0x4D,
+			0xBE, 0x94, 0xFE, 0xF5, 0xB1, 0xA9, 0x96, 0xAB,
+			0x3F, 0x2D, 0xD4, 0x15, 0xEE, 0x4F, 0xFA, 0x2C,
+			0xBE, 0x91, 0xB7, 0xBC, 0x18, 0xC8, 0xDB, 0x02,
+			0x20, 0x29, 0xF1, 0xC1, 0x88, 0x8C, 0x8D, 0xD1,
+			0xB3, 0x4E, 0x93, 0x96, 0xDD, 0x22, 0xAB, 0x55,
+			0xB5, 0x9F, 0x8B, 0x20, 0xAE, 0xC6, 0x0E, 0x26,
+			0xC6, 0xFE, 0x2D, 0x5F, 0x95, 0x89, 0x06, 0x15,
+			0x3D, 0x88, 0x16, 0xEC, 0x9B, 0x4A, 0x1B, 0x5D,
+			0x2E, 0xB2, 0x13, 0x56, 0x9F, 0x33, 0xB3, 0x45,
+			0xBF, 0x5F, 0x25, 0x7E, 0x75, 0x22, 0xD2, 0xE6,
+			0x9F, 0xAC, 0x2D, 0xFD, 0x99, 0xC2, 0x9B, 0xFC,
+			0xD7, 0x7A, 0x9B, 0x05, 0x30, 0x0F, 0xB7, 0x4A,
+			0xFE, 0x24, 0xDD, 0x39, 0x9B, 0xBB, 0x2F, 0xDD,
+			0xF9, 0xFB, 0xCA, 0x6C, 0x87, 0xBA, 0x73, 0xD4,
+			0x85, 0x7B, 0xB2, 0x6F, 0x5C, 0xD8, 0xFB, 0xE9,
+			0x41, 0x24, 0x3A, 0x3B, 0x4F, 0x91, 0x77, 0xA2,
+			0x35, 0x78, 0xE5, 0x4C, 0xFE, 0x8B, 0x04, 0x03,
+			0xD3, 0x84, 0xA9, 0x1C, 0xA7, 0x7C, 0x45, 0x13,
+			0x7D, 0xC5, 0x0A, 0x2F, 0x02, 0xF8, 0x56, 0xD5,
+			0x5F, 0x35, 0xED, 0x06, 0xBF, 0x67, 0xBA, 0x51,
+			0x02, 0x95, 0x36, 0xF2, 0x9A, 0xBA, 0x9D, 0xF6,
+			0xD6, 0x77, 0x50, 0xC9, 0xFC, 0x1E, 0x32, 0xB5,
+			0x2F, 0xEA, 0x3C, 0x76, 0xB4, 0xE1, 0xCC, 0x42,
+			0xEB, 0x71, 0x79, 0xD3, 0x7D, 0xB7, 0xC0, 0x88,
+			0x25, 0x81, 0xE8, 0xC0, 0xB8, 0x38, 0x7E, 0x7B,
+			0xFD, 0x18, 0xAB, 0x08, 0xB2, 0x71, 0xA5, 0xAD,
+			0xA7, 0xBE, 0x48, 0x5F, 0x86, 0xE2, 0x41, 0x3D,
+			0x7C, 0x37, 0x7A, 0xAB, 0xDB, 0xE0, 0x3B, 0x3D,
+			0xB6, 0xE8, 0x23, 0x7C, 0xF1, 0x8F, 0xBA, 0xB7,
+			0xE9, 0x78, 0x0B, 0xCA, 0x67, 0xA8, 0x10, 0x36,
+			0xEB, 0x72, 0xED, 0xDD, 0xF0, 0x5C, 0x74, 0x8E,
+			0xE5, 0x2A, 0xAE, 0x6E, 0xC4, 0xF1, 0xFC, 0xD8,
+			0xEE, 0x56, 0x07, 0x88, 0x02, 0xDC, 0x9D, 0xB7,
+			0xF9, 0x13, 0xE1, 0xE1, 0x9D, 0x89, 0x26, 0x0B,
+			0x23, 0x74, 0x4A, 0x43, 0xAA, 0xA0, 0xA8, 0x97,
+			0x85, 0x15, 0x58, 0xAB, 0x2B, 0xB5, 0xDA, 0x1A,
+			0xBA, 0x29, 0x62, 0xCF, 0xDD, 0xA3, 0xBA, 0x9D,
+			0x7D, 0x83, 0xA5, 0x18, 0xD4, 0x03, 0x0F, 0x61,
+			0x9F, 0xB1, 0x7E, 0xEC, 0xD2, 0x6E, 0xAF, 0xCF,
+			0x1E, 0xC1, 0x88, 0x97, 0x99, 0xD6, 0xBF, 0x47,
+			0xB9, 0x0A, 0x69, 0x11, 0x3A, 0x55, 0x8B, 0x1D,
+			0x2D, 0xFF, 0x78, 0xC8, 0xDE, 0x82, 0x29, 0xD6,
+			0x08, 0x3C, 0xC4, 0xCB, 0x2F, 0x01, 0xD0, 0xE8,
+			0xB1, 0x75, 0x5E, 0x23, 0xE0, 0x37, 0x7C, 0x1C,
+			0xB6, 0xD9, 0x47, 0xDE, 0x23, 0x87, 0xD3, 0x68,
+			0x47, 0x46, 0x78, 0xF3, 0xBF, 0x54, 0xA3, 0xB9,
+			0x54, 0xD5, 0xC5, 0x0A, 0x7C, 0x92, 0x2A, 0xC2,
+			0x14, 0x76, 0xA6, 0x5C, 0x6D, 0x0B, 0x94, 0x56,
+			0x00, 0x6B, 0x5C, 0x27, 0xDE, 0x77, 0x9B, 0xF1,
+			0xB1, 0x8C, 0xA7, 0x49, 0x77, 0xFC, 0x4E, 0x29,
+			0x23, 0x8F, 0x2F, 0xF7, 0x83, 0x8D, 0x36, 0xD9,
+			0xAB, 0x0E, 0x78, 0xF5, 0x90, 0x05, 0xB9, 0x79,
+			0x70, 0x88, 0x59, 0x6F, 0xE2, 0xC5, 0xD7, 0x80,
+			0x95, 0x04, 0x29, 0xE0, 0xFA, 0x37, 0xE8, 0x8B,
+			0xC5, 0x21, 0x51, 0x1A, 0x62, 0xCE, 0x93, 0xAF,
+			0x1A, 0xFE, 0xC3, 0x6F, 0x86, 0x94, 0x5E, 0x13,
+			0xA6, 0x9A, 0x26, 0xF0, 0xB5, 0x7C, 0x41, 0x9A,
+			0x80, 0xB8, 0x84, 0x5A, 0x55, 0xA9, 0xB0, 0x6A,
+			0xFA, 0xEB, 0x46, 0x32, 0x0B, 0xE2, 0x9C, 0x65,
+			0x86, 0x11, 0x39, 0x7E, 0xAF, 0x93, 0x19, 0x09,
+			0x70, 0x40, 0x80, 0x14, 0xBA, 0x1D, 0xB3, 0x62,
+			0x5B, 0xF3, 0x9A, 0x21, 0x98, 0x7E, 0x63, 0xB6,
+			0x1A, 0xBD, 0x65, 0x98, 0x35, 0x2A, 0xA9, 0x76,
+			0x29, 0x59, 0x84, 0x25, 0x81, 0xB8, 0xDE, 0x25,
+			0x32, 0x10, 0x50, 0xB7, 0xD3, 0xB3, 0x69, 0xC8,
+			0xE1, 0x33, 0xCB, 0x9E, 0x9C, 0x7A, 0x7C, 0xD2,
+			0x6C, 0x92, 0x97, 0xA9, 0xFA, 0xAF, 0x30, 0xBA,
+			0x9A, 0xB3, 0x3D, 0x9A, 0xE5, 0x0A, 0x9B, 0x8D,
+			0x89, 0xE2, 0x2B, 0xB8, 0xBC, 0xF0, 0x23, 0xFF,
+			0x7B, 0x0D, 0x00, 0x36, 0xEE, 0x79, 0xCB, 0xA5,
+			0x70, 0x4C, 0x66, 0x02, 0x79, 0x2E, 0x5B, 0x83,
+			0xCE, 0x55, 0x8B, 0x89, 0xD6, 0xE3, 0x71, 0x63,
+			0xBC, 0xB1, 0x5F, 0x67, 0xB4, 0x7E, 0x05, 0x0D,
+			0xAC, 0x6D, 0x4E, 0x2C, 0xA5, 0xF4, 0x47, 0x89,
+			0xAC, 0x5E, 0xBE, 0x2F, 0xFC, 0x9B, 0x2F, 0x0B,
+			0xBE, 0x63, 0x54, 0x97, 0xBB, 0x23, 0x27, 0xCD,
+			0xB9, 0xB2, 0x28, 0x0D, 0xA4, 0x78, 0x2C, 0xAB,
+			0xD1, 0xC9, 0x94, 0x40, 0x54, 0xF2, 0x35, 0x61,
+			0x49, 0x01, 0x87, 0x55, 0xA5, 0xB5, 0x1E, 0x84,
+			0x92, 0x9E, 0xC1, 0xA4, 0x0B, 0x66, 0x2B, 0xF8,
+			0xAF, 0xC3, 0x1E, 0xAF, 0x66, 0x3F, 0x6F, 0x5F,
+			0x70, 0xEC, 0x25, 0x29, 0xE4, 0x65, 0xB2, 0x04,
+			0x47, 0xF6, 0x3C, 0xB5, 0x5F, 0x66, 0x9F, 0xA4,
+			0x1B, 0xFC, 0xA2, 0xD5, 0x3E, 0x84, 0xBA, 0x88,
+			0x0D, 0xF1, 0x6A, 0xF2, 0xF6, 0x1D, 0xF1, 0xA3,
+			0x45, 0xB2, 0x51, 0xD8, 0xA2, 0x8F, 0x55, 0xA6,
+			0x89, 0xC4, 0x15, 0xD5, 0x73, 0xA8, 0xB1, 0x31,
+			0x66, 0x9E, 0xC1, 0x43, 0xE1, 0x5D, 0x4E, 0x04,
+			0x84, 0x8F, 0xF2, 0xBC, 0xE1, 0x4E, 0x4D, 0x60,
+			0x81, 0xCA, 0x53, 0x34, 0x95, 0x17, 0x3B, 0xAE,
+			0x8F, 0x95, 0xA7, 0xC6, 0x47, 0xC6, 0xAC, 0x32,
+			0x12, 0x39, 0xCA, 0xEF, 0xE0, 0x07, 0xBF, 0x17,
+			0x4F, 0xDC, 0x1B, 0x4E, 0x3C, 0x84, 0xF1, 0x9F,
+			0x43, 0x70, 0x19, 0xE6, 0xF3, 0x8B, 0x8B, 0x5D,
+			0xDB, 0xD2, 0x9D, 0xD4, 0xB2, 0x30, 0x45, 0x55,
+			0xA2, 0x67, 0xA2, 0x76, 0x4A, 0x74, 0xAD, 0x88,
+			0x71, 0xE6, 0x3E, 0x13, 0x06, 0x30, 0x17, 0xE1,
+			0xEF, 0xAC, 0x71, 0xFB, 0x43, 0xCD, 0xF6, 0xFA,
+			0x0E, 0x4C, 0x4E, 0x16, 0xF6, 0x6A, 0x09, 0x86,
+			0x6B, 0xEA, 0x47, 0x6C, 0x70, 0xE7, 0xAD, 0xA2,
+			0xE0, 0xFD, 0x7F, 0xF0, 0x5C, 0x21, 0x53, 0x0F,
+			0x28, 0xA1, 0x43, 0xE1, 0x06, 0xCA, 0x0B, 0x31,
+			0x88, 0x22, 0xA6, 0xE6, 0x34, 0x5B, 0xE6, 0xCF,
+			0x25, 0x81, 0x63, 0xFF, 0x78, 0x66, 0x85, 0x19,
+			0xE2, 0x0A, 0x7E, 0x81, 0x8A, 0x17, 0x1A, 0x18,
+			0x8A, 0x5F, 0x5D, 0x9E, 0x82, 0x13, 0x10, 0xB9,
+			0xD3, 0xE6, 0x93, 0x1C, 0xE4, 0x2C, 0xCB, 0x49,
+			0x1E, 0xB6, 0x36, 0x13, 0xBF, 0x28, 0xEE, 0xCC,
+			0x49, 0xF5, 0x79, 0xFC, 0x20, 0x65, 0xBD, 0xE8,
+			0xF0, 0x1B, 0x4E, 0xC0, 0x0D, 0x3E, 0x89, 0x91,
+			0xCC, 0x64, 0x10, 0xC0, 0x2A, 0x2B, 0xA3, 0xFA,
+			0x60, 0x3D, 0xC3, 0x52, 0x2F, 0x93, 0xDE, 0xB7,
+			0x6E, 0x8A, 0xDF, 0x6C, 0x08, 0xCC, 0x8B, 0x3B,
+			0xC8, 0x50, 0xEF, 0x58, 0x64, 0x9A, 0x3D, 0x16,
+			0x70, 0x94, 0x11, 0xD8, 0x94, 0x2B, 0x70, 0x91,
+			0x10, 0x70, 0x88, 0xF0, 0x40, 0x75, 0x9A, 0x2B,
+			0x39, 0xA1, 0x27, 0x3F, 0x2E, 0x91, 0xEA, 0xA1,
+			0xCC, 0x12, 0xC1, 0x7F, 0x73, 0x8C, 0x5C, 0x6B,
+			0xFC, 0xC5, 0x6A, 0x1C, 0x05, 0xF1, 0x3D, 0x30,
+			0x82, 0x4A, 0x65, 0x35, 0xCE, 0x80, 0x10, 0xBB,
+			0x41, 0x94, 0xFB, 0x84, 0x80, 0x7B, 0x91, 0xC4,
+			0x4D, 0xA3, 0x5F, 0xB9, 0xFB, 0xF9, 0xC9, 0x1D,
+			0x4F, 0x99, 0x1C, 0x1F, 0x47, 0x44, 0x89, 0x0E,
+			0xED, 0x6D, 0xB5, 0x85, 0x41, 0x94, 0xEF, 0xF9,
+			0x2E, 0xA0, 0xC8, 0xCA, 0xFB, 0x44, 0x02, 0xC6,
+			0xBF, 0x96, 0x87, 0x80, 0x1D, 0xEF, 0x2A, 0x81,
+			0xAB, 0xB2, 0x56, 0xDF, 0x54, 0x8B, 0xAB, 0xAF,
+			0xFE, 0x18, 0x8C, 0xAA, 0xD4, 0x00, 0x17, 0xBE,
+			0xCF, 0x06, 0xE5, 0xA6, 0xBF, 0x5A, 0x52, 0x3B,
+			0x4E, 0xF5, 0x65, 0x60, 0x95, 0xDE, 0x8A, 0x25,
+			0x88, 0xA5, 0x24, 0x96, 0x29, 0x13, 0x0D, 0x19,
+			0x45, 0x95, 0x91, 0x08, 0xD2, 0x9C, 0x4C, 0x34,
+			0x42, 0xF0, 0xA5, 0x72, 0xEB, 0xFB, 0x5E, 0xAA,
+			0x68, 0x80, 0x82, 0xAC, 0x34, 0xAD, 0x89, 0xF6,
+			0xAF, 0x54, 0x82, 0xCF, 0x98, 0x8C, 0x75, 0x63,
+			0x8D, 0xBD, 0x1C, 0x2A, 0xD7, 0x00, 0xA7, 0x8E,
+			0xB9, 0x33, 0xB6, 0x3B, 0x95, 0x9A, 0x59, 0x1D,
+			0x3F, 0x23, 0x6B, 0x18, 0xF8, 0x4F, 0x1A, 0x8D,
+			0xC0, 0x26, 0x9F, 0x87, 0x61, 0xB6, 0xC6, 0x60,
+			0x38, 0x22, 0x73, 0x1C, 0x99, 0x23, 0xEF, 0xD9,
+			0xFD, 0xCB, 0x54, 0x74, 0xBB, 0x77, 0x14, 0xA3,
+			0xA9, 0xE6, 0x7C, 0x7E, 0x03, 0x3A, 0x13, 0x6E,
+			0x1D, 0x6F, 0x64, 0xB3, 0xFA, 0xFB, 0x52, 0xDE,
+			0xDF, 0x08, 0xFB, 0x6F, 0xC5, 0xFA, 0x51, 0x6A,
+			0x69, 0x29, 0x9B, 0x96, 0xE8, 0x16, 0xC8, 0xD1,
+			0xE4, 0x19, 0xBD, 0x14, 0x74, 0x27, 0xE7, 0x10,
+			0xF0, 0xC3, 0xE2, 0xA7, 0x60, 0x48, 0xBF, 0xDD,
+			0xC4, 0x0D, 0xD0, 0xF2, 0xEF, 0xA6, 0xC9, 0xA2,
+			0x73, 0xD1, 0xCF, 0x41, 0xE1, 0x3B, 0xE5, 0x49,
+			0x91, 0x5D, 0x09, 0xFD, 0x1D, 0x95, 0x29, 0xDB,
+			0x52, 0x48, 0xEB, 0xF5, 0x1D, 0xF8, 0x06, 0x67,
+			0x75, 0xF2, 0x57, 0xA4, 0x20, 0x60, 0xEA, 0xB0,
+			0x85, 0x93, 0x7C, 0xDD, 0x52, 0x01, 0xD4, 0x57,
+			0xA8, 0x31, 0x2D, 0xF9, 0x0A, 0xD2, 0x2A, 0xD1,
+			0x34, 0x18, 0x35, 0x16, 0xB6, 0x8B, 0x0F, 0x0B,
+			0xCF, 0x50, 0x80, 0xFE, 0x76, 0xCC, 0x4F, 0x30,
+			0x98, 0x19, 0x16, 0x3D, 0x01, 0xEA, 0x8D, 0x8A,
+			0x3D, 0xDC, 0xFB, 0x1F, 0x77, 0x8D, 0x72, 0x76,
+			0x02, 0x3C, 0x5D, 0xEE, 0x55, 0x13, 0x5B, 0x6E,
+			0x5A, 0x2D, 0xD5, 0x77, 0xD7, 0x01, 0x84, 0x7D,
+			0x21, 0x8C, 0xDD, 0x94, 0x7D, 0x31, 0x3D, 0xF0,
+			0xE7, 0x28, 0xF5, 0x72, 0x36, 0x60, 0xE0, 0x59,
+			0x5F, 0xFE, 0x38, 0xF8, 0x2F, 0xDB, 0x9E, 0x55,
+			0x5A, 0xD6, 0xBA, 0x6C, 0x87, 0xF3, 0xC0, 0x76,
+			0x5F, 0xA3, 0x0A, 0xC3, 0xA3, 0x8D, 0x0E, 0x52,
+			0xA8, 0xDA, 0x26, 0x3A, 0xF9, 0x3E, 0x36, 0xB1,
+			0x06, 0xF8, 0x20, 0x2D, 0x1C, 0x0B, 0x93, 0xBB,
+			0xD3, 0x64, 0x77, 0xCE, 0x11, 0xFC, 0xA2, 0x0E,
+			0x1B, 0x5B, 0x9E, 0x13, 0x9F, 0x20, 0x8B, 0xAA,
+			0xCD, 0x72, 0xD7, 0xA6, 0xF3, 0x1E, 0x4F, 0x72,
+			0xC6, 0x49, 0x0F, 0x7B, 0xF0, 0x4C, 0x61, 0x1F,
+			0x43, 0x0D, 0x4F, 0x0D, 0x33, 0x13, 0xED, 0x63,
+			0xE5, 0xDB, 0x71, 0xAB, 0xA4, 0x83, 0xEF, 0xDC,
+			0x86, 0x9D, 0x4B, 0xBD, 0x1B, 0x8A, 0xFE, 0x39,
+			0xA8, 0x8B, 0xBA, 0x4C, 0x85, 0x28, 0xFC, 0xB3,
+			0x62, 0x85, 0xD2, 0xF0, 0x38, 0xD0, 0x4B, 0xA4,
+			0xD1, 0x3B, 0xD4, 0xD0, 0x2C, 0x78, 0x6C, 0x6A,
+			0xC2, 0x64, 0x2C, 0x31, 0x4A, 0xD8, 0x69, 0x24,
+			0xED, 0x77, 0x7D, 0x68, 0x9A, 0xA1, 0x78, 0x81,
+			0xD9, 0x7E, 0x6C, 0xFE, 0x0A, 0x0D, 0x76, 0xF7,
+			0x4B, 0x58, 0xE7, 0xC9, 0xB5, 0x11, 0x07, 0x87,
+			0x88, 0x6A, 0x9F, 0x3D, 0xE0, 0xEE, 0xCC, 0x60,
+			0x6B, 0x6B, 0xE6, 0xB5, 0x54, 0x8B, 0x32, 0x1F,
+			0x04, 0x1D, 0x0E, 0x9E, 0xFA, 0x6D, 0xB0, 0xE0,
+			0x6D, 0xF9, 0x79, 0xB4, 0xAB, 0x5E, 0xDF, 0x23,
+			0x7F, 0x95, 0xAD, 0x80, 0x17, 0x23, 0x90, 0x1F,
+			0xF0, 0xC3, 0xD9, 0x2D, 0xAC, 0x3F, 0x63, 0xF5,
+			0x77, 0xC5, 0x05, 0xAC, 0x06, 0xB6, 0xA1, 0xB4,
+			0xA2, 0x40, 0xB3, 0x99, 0x34, 0x7D, 0x31, 0xD4,
+			0xB1, 0xD4, 0xC1, 0xBB, 0x71, 0x1E, 0xDA, 0x3F,
+			0xA9, 0x12, 0x68, 0xFA, 0x5B, 0x20, 0x24, 0x6D,
+			0x4D, 0x72, 0x43, 0x18, 0xBF, 0x66, 0x71, 0x69,
+			0x26, 0x7D, 0x77, 0x78, 0xF8, 0xE5, 0x20, 0xAE,
+			0x56, 0x6C, 0x0F, 0x72, 0x94, 0x42, 0x85, 0x4F,
+			0xE4, 0xFB, 0x32, 0x26, 0x1B, 0x1C, 0x6E, 0x0B,
+			0xF0, 0xB8, 0x58, 0x00, 0xD2, 0x36, 0x64, 0xAD,
+			0xA9, 0x00, 0xCE, 0x35, 0x3C, 0x88, 0x79, 0x94,
+			0x0C, 0x0C, 0x9B, 0xF2, 0xDA, 0xBD, 0xCA, 0x93,
+			0x37, 0x26, 0xD3, 0x08, 0x54, 0xD2, 0x0D, 0xBC,
+			0x5D, 0x43, 0x5F, 0xCF, 0x28, 0xB5, 0xAA, 0x15,
+			0x28, 0x46, 0x45, 0x6B, 0xE8, 0xDF, 0xE8, 0xCE,
+			0x8F, 0xC0, 0x1A, 0x53, 0x63, 0x3B, 0x53, 0x75,
+			0xDD, 0x43, 0x1F, 0x07, 0x0A, 0xD5, 0xA1, 0x2A,
+			0x6E, 0x28, 0xE1, 0xD7, 0xD0, 0x09, 0xCF, 0x62,
+			0xC1, 0x5F, 0x21, 0xDB, 0xC5, 0x40, 0x99, 0x48,
+			0x87, 0x6E, 0x11, 0xF5, 0x5A, 0x4E, 0xBC, 0xF9,
+			0xA8, 0x02, 0x7C, 0x47, 0x39, 0xA5, 0xD8, 0x52,
+			0xB1, 0x80, 0xDC, 0xFE, 0x08, 0x4B, 0x5D, 0x09,
+			0xDE, 0x06, 0xF3, 0x2A, 0xAD, 0x14, 0x76, 0x40,
+			0x2F, 0x82, 0x28, 0x6A, 0xB6, 0x43, 0xEF, 0x71,
+			0x63, 0xC2, 0x56, 0xEB, 0x3B, 0x4B, 0x52, 0x2F,
+			0x93, 0xD3, 0x18, 0x3E, 0x18, 0xA8, 0xF7, 0x58,
+			0xFC, 0x8B, 0x3D, 0x4D, 0x4B, 0x72, 0xBD, 0xF7,
+			0x04, 0xC9, 0xB8, 0xD7, 0x6C, 0x8C, 0x67, 0xBB,
+			0x4C, 0x9B, 0x57, 0xF7, 0x22, 0x4E, 0x41, 0xB6,
+			0xFD, 0xD9, 0xF8, 0x41, 0x62, 0x0F, 0xFF, 0xAA,
+			0xC6, 0x87, 0x95, 0xFF, 0xFD, 0x58, 0xD9, 0xB2,
+			0xBA, 0x47, 0x61, 0x24, 0xEA, 0x92, 0x6E, 0x74,
+			0xB3, 0xDA, 0xE5, 0x83, 0x99, 0x24, 0xB1, 0x71,
+			0x2A, 0x33, 0xB2, 0xD5, 0x8F, 0xF0, 0x32, 0xCE,
+			0x37, 0xCF, 0xC7, 0x1C, 0xE8, 0xDE, 0x46, 0x78,
+			0x96, 0x97, 0xF6, 0x73, 0x90, 0xE5, 0x71, 0x05,
+			0xEA, 0x0D, 0xC2, 0x1D, 0x9E, 0x43, 0x34, 0xBC,
+			0x8F, 0x45, 0xE5, 0x08, 0xCA, 0x20, 0x0C, 0x84
+		},
+		.len = 2048
+	},
+	.auth_tag = {
+		.data = {
+			0xD0, 0x62, 0x1F, 0x20, 0x1C, 0xE8, 0xDD, 0x36,
+			0x00, 0x74, 0xF6, 0xD7, 0xFD, 0x2C, 0xA0, 0xAF
+		},
+		.len = 16
+	}
+};
+
 /** GMAC Test Vectors */
 static uint8_t gmac_plaintext[GMAC_LARGE_PLAINTEXT_LENGTH] = {
 			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-- 
1.7.9.5

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

* Re: [PATCH v5] mbuf: add a function to linearize a packet
  2017-01-12  9:40       ` [PATCH v5] mbuf: add a function to linearize a packet Tomasz Kulasek
@ 2017-01-13 15:32         ` Olivier Matz
  2017-01-13 15:40           ` Kulasek, TomaszX
  2017-01-15 18:32           ` Thomas Monjalon
  0 siblings, 2 replies; 41+ messages in thread
From: Olivier Matz @ 2017-01-13 15:32 UTC (permalink / raw)
  To: Tomasz Kulasek; +Cc: dev, Pablo de Lara

On Thu, 12 Jan 2017 10:40:44 +0100, Tomasz Kulasek
<tomaszx.kulasek@intel.com> wrote:
> This patch adds function rte_pktmbuf_linearize to let crypto PMD
> coalesce chained mbuf before crypto operation and extend their
> capabilities to support segmented mbufs when device cannot handle
> them natively.
> 
> Included unit tests for rte_pktmbuf_linearize functionality:
> 
>  1) Creates banch of segmented mbufs with different size and number of
>     segments.
>  2) Fills noncontigouos mbuf with sequential values.
>  3) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one
>     contiguous.
>  4) Verifies data in linearized buffer.
> 
> Dependencies:
> 
> This patch is rebased to the dpdk-next-crypto and should be applied
> before "Chained Mbufs support in SW PMDs" patchset.
> 
> changes in v5:
>  - name of patch changed,
>  - improved coding style,
> 
> changes in v4:
>  - separated from "Chained Mbufs support in SW PMDs" patch set for
>    better reviewing,
>  - merged "rte_pktmbuf_linearize" implementation with unit tests,
> 
> changes in v3:
>  - rebased to dpdk-next-crypto
> 
> changes in v2:
>  - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
> 
> Cc: Pablo de Lara <pablo.de.lara.guarch@intel.com>
> Cc: Olivier Matz <olivier.matz@6wind.com>
> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>

Acked-by: Olivier Matz <olivier.matz@6wind.com>

Just one comment about the changelog for next time: as it's not
something we need to keep in the git history, you can put it after the
'---', so it will be dropped when applying the patch with 'git am'.

Thanks,
Olivier

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

* Re: [PATCH v5] mbuf: add a function to linearize a packet
  2017-01-13 15:32         ` Olivier Matz
@ 2017-01-13 15:40           ` Kulasek, TomaszX
  2017-01-15 18:32           ` Thomas Monjalon
  1 sibling, 0 replies; 41+ messages in thread
From: Kulasek, TomaszX @ 2017-01-13 15:40 UTC (permalink / raw)
  To: Olivier Matz; +Cc: dev, De Lara Guarch, Pablo



> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Friday, January 13, 2017 16:33
> To: Kulasek, TomaszX <tomaszx.kulasek@intel.com>
> Cc: dev@dpdk.org; De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>
> Subject: Re: [PATCH v5] mbuf: add a function to linearize a packet
> 
> On Thu, 12 Jan 2017 10:40:44 +0100, Tomasz Kulasek
> <tomaszx.kulasek@intel.com> wrote:
> > This patch adds function rte_pktmbuf_linearize to let crypto PMD
> > coalesce chained mbuf before crypto operation and extend their
> > capabilities to support segmented mbufs when device cannot handle
> > them natively.
> >
> > Included unit tests for rte_pktmbuf_linearize functionality:
> >
> >  1) Creates banch of segmented mbufs with different size and number of
> >     segments.
> >  2) Fills noncontigouos mbuf with sequential values.
> >  3) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one
> >     contiguous.
> >  4) Verifies data in linearized buffer.
> >
> > Dependencies:
> >
> > This patch is rebased to the dpdk-next-crypto and should be applied
> > before "Chained Mbufs support in SW PMDs" patchset.
> >
> > changes in v5:
> >  - name of patch changed,
> >  - improved coding style,
> >
> > changes in v4:
> >  - separated from "Chained Mbufs support in SW PMDs" patch set for
> >    better reviewing,
> >  - merged "rte_pktmbuf_linearize" implementation with unit tests,
> >
> > changes in v3:
> >  - rebased to dpdk-next-crypto
> >
> > changes in v2:
> >  - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
> >
> > Cc: Pablo de Lara <pablo.de.lara.guarch@intel.com>
> > Cc: Olivier Matz <olivier.matz@6wind.com>
> > Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
> 
> Acked-by: Olivier Matz <olivier.matz@6wind.com>
> 
> Just one comment about the changelog for next time: as it's not
> something we need to keep in the git history, you can put it after the
> '---', so it will be dropped when applying the patch with 'git am'.
> 
> Thanks,
> Olivier

Ok, thanks.
Tomasz

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

* Re: [PATCH v5] mbuf: add a function to linearize a packet
  2017-01-13 15:32         ` Olivier Matz
  2017-01-13 15:40           ` Kulasek, TomaszX
@ 2017-01-15 18:32           ` Thomas Monjalon
  1 sibling, 0 replies; 41+ messages in thread
From: Thomas Monjalon @ 2017-01-15 18:32 UTC (permalink / raw)
  To: Tomasz Kulasek; +Cc: dev, Olivier Matz, Pablo de Lara

2017-01-13 16:32, Olivier Matz:
> On Thu, 12 Jan 2017 10:40:44 +0100, Tomasz Kulasek
> <tomaszx.kulasek@intel.com> wrote:
> > This patch adds function rte_pktmbuf_linearize to let crypto PMD
> > coalesce chained mbuf before crypto operation and extend their
> > capabilities to support segmented mbufs when device cannot handle
> > them natively.
> > 
> > Included unit tests for rte_pktmbuf_linearize functionality:
> > 
> >  1) Creates banch of segmented mbufs with different size and number of
> >     segments.
> >  2) Fills noncontigouos mbuf with sequential values.
> >  3) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one
> >     contiguous.
> >  4) Verifies data in linearized buffer.
> > 
> > Dependencies:
> > 
> > This patch is rebased to the dpdk-next-crypto and should be applied
> > before "Chained Mbufs support in SW PMDs" patchset.
> > 
> > changes in v5:
> >  - name of patch changed,
> >  - improved coding style,
> > 
> > changes in v4:
> >  - separated from "Chained Mbufs support in SW PMDs" patch set for
> >    better reviewing,
> >  - merged "rte_pktmbuf_linearize" implementation with unit tests,
> > 
> > changes in v3:
> >  - rebased to dpdk-next-crypto
> > 
> > changes in v2:
> >  - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
> > 
> > Cc: Pablo de Lara <pablo.de.lara.guarch@intel.com>
> > Cc: Olivier Matz <olivier.matz@6wind.com>
> > Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
> 
> Acked-by: Olivier Matz <olivier.matz@6wind.com>

Applied, thanks

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

* Re: [PATCH v5 1/3] crypto: add sgl support in sw PMDs
  2017-01-13 15:23         ` [PATCH v5 1/3] crypto: add sgl support in sw PMDs Tomasz Kulasek
@ 2017-01-16 16:08           ` Declan Doherty
  0 siblings, 0 replies; 41+ messages in thread
From: Declan Doherty @ 2017-01-16 16:08 UTC (permalink / raw)
  To: Tomasz Kulasek, dev

On 13/01/17 15:23, Tomasz Kulasek wrote:
> This patch introduces RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER feature flag
> informing that selected crypto device supports segmented mbufs natively
> and doesn't need to be coalesced before crypto operation.
>
> While using segmented buffers in crypto devices may have unpredictable
> results, for PMDs which doesn't support it natively, additional check is
> made for debug compilation.
>
> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
> ---
...
>

Acked-by: Declan Doherty <declan.doherty@intel.com>

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

* Re: [PATCH v5 2/3] crypto: add sgl support in openssl PMD
  2017-01-13 15:23         ` [PATCH v5 2/3] crypto: add sgl support in openssl PMD Tomasz Kulasek
@ 2017-01-16 16:10           ` Declan Doherty
  0 siblings, 0 replies; 41+ messages in thread
From: Declan Doherty @ 2017-01-16 16:10 UTC (permalink / raw)
  To: Tomasz Kulasek, dev

On 13/01/17 15:23, Tomasz Kulasek wrote:
>
> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
> ---
>  doc/guides/cryptodevs/openssl.rst        |    3 +-
>  drivers/crypto/openssl/rte_openssl_pmd.c |  329 +++++++++++++++++++++++-------
>  2 files changed, 259 insertions(+), 73 deletions(-)
>
> diff --git a/doc/guides/cryptodevs/openssl.rst b/doc/guides/cryptodevs/openssl.rst
> index f1c39ba..f6ed6ea 100644
> --- a/doc/guides/cryptodevs/openssl.rst
> +++ b/doc/guides/cryptodevs/openssl.rst
> @@ -112,6 +112,7 @@ Limitations
>  -----------
...
>

Acked-by: Declan Doherty <declan.doherty@intel.com>

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

* Re: [PATCH v5 3/3] test: add sgl unit tests for crypto devices
  2017-01-13 15:23         ` [PATCH v5 3/3] test: add sgl unit tests for crypto devices Tomasz Kulasek
@ 2017-01-16 16:11           ` Declan Doherty
  0 siblings, 0 replies; 41+ messages in thread
From: Declan Doherty @ 2017-01-16 16:11 UTC (permalink / raw)
  To: Tomasz Kulasek, dev; +Cc: Daniel Mrzyglod

On 13/01/17 15:23, Tomasz Kulasek wrote:
> This patch provides unit tests for set of cipher/hash combinations covering
> currently implemented crypto PMD's and allowing to verify scatter gather
> support.
>
> Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
> Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
> ---
...
>

Acked-by: Declan Doherty <declan.doherty@intel.com>

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

* Re: [PATCH v5 0/3] Chained Mbufs support in SW PMDs
  2017-01-13 15:23       ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
                           ` (2 preceding siblings ...)
  2017-01-13 15:23         ` [PATCH v5 3/3] test: add sgl unit tests for crypto devices Tomasz Kulasek
@ 2017-01-16 19:00         ` De Lara Guarch, Pablo
  3 siblings, 0 replies; 41+ messages in thread
From: De Lara Guarch, Pablo @ 2017-01-16 19:00 UTC (permalink / raw)
  To: Kulasek, TomaszX, dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Tomasz Kulasek
> Sent: Friday, January 13, 2017 3:23 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v5 0/3] Chained Mbufs support in SW PMDs
> 
> This patch set adds support of scattered-gather list for SW PMDs.
> 
> As of now, application needs to reserve continuous block of memory for
> mbufs which is not always the case. Hence needed to support chaining of
> mbufs which are smaller in size but can be used if chained.
> 
> 
> Above work involves:
> --------------------
> 
>  a) Create mbuf functions to coalesce mbuf chains into a single mbuf.
>  b) For each software poll mode driver code to detect chained mbufs
>     support and coalesce these before preforming crypto.
>  c) Add relevant unit tests to test the functionality.
> 
> 
> Known limitations for openssl PMD:
> ----------------------------------
> 
> While libcrypto library expects continuous destination buffer for
> output of cipher operations, implementation of openssl PMD is limited
> the same way, and requires contiguous destination mbuf.
> 
> 
> changes in v5:
>  - rebased to the master of dpdk-next-crypto
> 
> changes in v4:
>  - separated "rte_pktmbuf_linearize" implementation from this patch set
>    and sent as new patch for better reviewing,
> 
> changes in v3:
>  - rebased to dpdk-next-crypto
>  - reused tests for AES GCM SGL support in opensll from "app/test: add
>    SGL tests to cryptodev QAT suite"
> 
> changes in v2:
>  - add support for sgl in openssl PMD
>  - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize
>  - extended test vector data for aes gcm from 60 to 2048 bytes
> 
> 
> Tomasz Kulasek (3):
>   crypto: add sgl support in sw PMDs
>   crypto: add sgl support in openssl PMD
>   test: add sgl unit tests for crypto devices
> 
>  app/test/test_cryptodev.c                  |  386 ++++++++++++++++++-
>  app/test/test_cryptodev.h                  |  138 +++++++
>  app/test/test_cryptodev_aes_test_vectors.h |   52 +++
>  app/test/test_cryptodev_blockcipher.c      |   90 ++---
>  app/test/test_cryptodev_blockcipher.h      |    1 +
>  app/test/test_cryptodev_gcm_test_vectors.h |  553
> ++++++++++++++++++++++++++++
>  doc/guides/cryptodevs/openssl.rst          |    3 +-
>  drivers/crypto/aesni_gcm/aesni_gcm_pmd.c   |   14 +
>  drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c |   19 +-
>  drivers/crypto/kasumi/rte_kasumi_pmd.c     |   13 +
>  drivers/crypto/null/null_crypto_pmd.c      |    3 +-
>  drivers/crypto/openssl/rte_openssl_pmd.c   |  329 +++++++++++++----
>  drivers/crypto/snow3g/rte_snow3g_pmd.c     |   15 +
>  drivers/crypto/zuc/rte_zuc_pmd.c           |   13 +
>  lib/librte_cryptodev/rte_cryptodev.c       |    4 +-
>  lib/librte_cryptodev/rte_cryptodev.h       |    2 +
>  16 files changed, 1507 insertions(+), 128 deletions(-)
> 
> --
> 1.7.9.5

Applied to dpdk-next-crypto.
Thanks,

Pablo

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

end of thread, other threads:[~2017-01-16 19:00 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-02 17:07 [PATCH 0/4] Chained Mbufs support in SW PMDs Tomasz Kulasek
2016-12-02 17:07 ` [PATCH 1/4] rte_mbuf: add rte_pktmbuf_coalesce Tomasz Kulasek
2016-12-16 10:06   ` Olivier Matz
2016-12-29 15:58     ` Kulasek, TomaszX
2016-12-02 17:07 ` [PATCH 2/4] test: add rte_pktmbuf_coalesce unit tests Tomasz Kulasek
2016-12-02 17:07 ` [PATCH 3/4] crypto: add sgl support for sw PMDs Tomasz Kulasek
2016-12-03  8:28   ` Michał Mirosław
2016-12-12 10:01     ` Kulasek, TomaszX
2016-12-02 17:07 ` [PATCH 4/4] test: add sgl unit tests for crypto devices Tomasz Kulasek
2016-12-29 17:12 ` [PATCH v2 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
2016-12-29 17:12   ` [PATCH v2 1/5] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
2016-12-29 17:12   ` [PATCH v2 2/5] test: add rte_pktmbuf_linearize unit tests Tomasz Kulasek
2016-12-29 17:12   ` [PATCH v2 3/5] crypto: add sgl support in sw PMDs Tomasz Kulasek
2016-12-29 17:12   ` [PATCH v2 4/5] crypto: add sgl support in openssl PMD Tomasz Kulasek
2016-12-29 17:12   ` [PATCH v2 5/5] test: add sgl unit tests for crypto devices Tomasz Kulasek
2017-01-05  9:12   ` [PATCH v3 0/5] Chained Mbufs support in SW PMDs Tomasz Kulasek
2017-01-05  9:12     ` [PATCH v3 1/5] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
2017-01-05 15:37       ` De Lara Guarch, Pablo
2017-01-05 16:52         ` Kulasek, TomaszX
2017-01-05  9:12     ` [PATCH v3 2/5] test: add rte_pktmbuf_linearize unit tests Tomasz Kulasek
2017-01-05  9:12     ` [PATCH v3 3/5] crypto: add sgl support in sw PMDs Tomasz Kulasek
2017-01-05  9:12     ` [PATCH v3 4/5] crypto: add sgl support in openssl PMD Tomasz Kulasek
2017-01-05  9:12     ` [PATCH v3 5/5] test: add sgl unit tests for crypto devices Tomasz Kulasek
2017-01-05 16:44     ` [PATCH v4] rte_mbuf: add rte_pktmbuf_linearize Tomasz Kulasek
2017-01-10 16:50       ` Olivier MATZ
2017-01-12  9:40       ` [PATCH v5] mbuf: add a function to linearize a packet Tomasz Kulasek
2017-01-13 15:32         ` Olivier Matz
2017-01-13 15:40           ` Kulasek, TomaszX
2017-01-15 18:32           ` Thomas Monjalon
2017-01-05 16:46     ` [PATCH v4 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
2017-01-05 16:46       ` [PATCH v4 1/3] crypto: add sgl support in sw PMDs Tomasz Kulasek
2017-01-05 16:46       ` [PATCH v4 2/3] crypto: add sgl support in openssl PMD Tomasz Kulasek
2017-01-05 16:46       ` [PATCH v4 3/3] test: add sgl unit tests for crypto devices Tomasz Kulasek
2017-01-13 15:23       ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs Tomasz Kulasek
2017-01-13 15:23         ` [PATCH v5 1/3] crypto: add sgl support in sw PMDs Tomasz Kulasek
2017-01-16 16:08           ` Declan Doherty
2017-01-13 15:23         ` [PATCH v5 2/3] crypto: add sgl support in openssl PMD Tomasz Kulasek
2017-01-16 16:10           ` Declan Doherty
2017-01-13 15:23         ` [PATCH v5 3/3] test: add sgl unit tests for crypto devices Tomasz Kulasek
2017-01-16 16:11           ` Declan Doherty
2017-01-16 19:00         ` [PATCH v5 0/3] Chained Mbufs support in SW PMDs De Lara Guarch, Pablo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.