diff --git a/app/test-crypto-perf/cperf_ops.c b/app/test-crypto-perf/cperf_ops.c
index 5be20d9..ad32065 100644
--- a/app/test-crypto-perf/cperf_ops.c
+++ b/app/test-crypto-perf/cperf_ops.c
@@ -175,6 +175,14 @@ cperf_set_ops_auth(struct rte_crypto_op **ops,
 					offset -= tbuf->data_len;
 					tbuf = tbuf->next;
 				}
+				/*
+				 * If there is not enough room in segment,
+				 * place the digest in the next segment
+				 */
+				if ((tbuf->data_len - offset) < options->digest_sz) {
+					tbuf = tbuf->next;
+					offset = 0;
+				}
 				buf = tbuf;
 			}
 
@@ -256,6 +264,14 @@ cperf_set_ops_cipher_auth(struct rte_crypto_op **ops,
 					offset -= tbuf->data_len;
 					tbuf = tbuf->next;
 				}
+				/*
+				 * If there is not enough room in segment,
+				 * place the digest in the next segment
+				 */
+				if ((tbuf->data_len - offset) < options->digest_sz) {
+					tbuf = tbuf->next;
+					offset = 0;
+				}
 				buf = tbuf;
 			}
 
@@ -346,6 +362,14 @@ cperf_set_ops_aead(struct rte_crypto_op **ops,
 					offset -= tbuf->data_len;
 					tbuf = tbuf->next;
 				}
+				/*
+				 * If there is not enough room in segment,
+				 * place the digest in the next segment
+				 */
+				if ((tbuf->data_len - offset) < options->digest_sz) {
+					tbuf = tbuf->next;
+					offset = 0;
+				}
 				buf = tbuf;
 			}
 
diff --git a/app/test-crypto-perf/cperf_options.h b/app/test-crypto-perf/cperf_options.h
index 2f42cb6..6d339f4 100644
--- a/app/test-crypto-perf/cperf_options.h
+++ b/app/test-crypto-perf/cperf_options.h
@@ -11,7 +11,7 @@
 #define CPERF_TOTAL_OPS		("total-ops")
 #define CPERF_BURST_SIZE	("burst-sz")
 #define CPERF_BUFFER_SIZE	("buffer-sz")
-#define CPERF_SEGMENTS_NB	("segments-nb")
+#define CPERF_SEGMENT_SIZE	("segment-sz")
 #define CPERF_DESC_NB		("desc-nb")
 
 #define CPERF_DEVTYPE		("devtype")
@@ -71,7 +71,7 @@ struct cperf_options {
 
 	uint32_t pool_sz;
 	uint32_t total_ops;
-	uint32_t segments_nb;
+	uint32_t segment_sz;
 	uint32_t test_buffer_size;
 	uint32_t nb_descriptors;
 
diff --git a/app/test-crypto-perf/cperf_options_parsing.c b/app/test-crypto-perf/cperf_options_parsing.c
index f3508a4..d372691 100644
--- a/app/test-crypto-perf/cperf_options_parsing.c
+++ b/app/test-crypto-perf/cperf_options_parsing.c
@@ -328,17 +328,17 @@ parse_buffer_sz(struct cperf_options *opts, const char *arg)
 }
 
 static int
-parse_segments_nb(struct cperf_options *opts, const char *arg)
+parse_segment_sz(struct cperf_options *opts, const char *arg)
 {
-	int ret = parse_uint32_t(&opts->segments_nb, arg);
+	int ret = parse_uint32_t(&opts->segment_sz, arg);
 
 	if (ret) {
-		RTE_LOG(ERR, USER1, "failed to parse segments number\n");
+		RTE_LOG(ERR, USER1, "failed to parse segment size\n");
 		return -1;
 	}
 
-	if ((opts->segments_nb == 0) || (opts->segments_nb > 255)) {
-		RTE_LOG(ERR, USER1, "invalid segments number specified\n");
+	if (opts->segment_sz == 0) {
+		RTE_LOG(ERR, USER1, "Segment size has to be bigger than 0\n");
 		return -1;
 	}
 
@@ -678,7 +678,7 @@ static struct option lgopts[] = {
 	{ CPERF_TOTAL_OPS, required_argument, 0, 0 },
 	{ CPERF_BURST_SIZE, required_argument, 0, 0 },
 	{ CPERF_BUFFER_SIZE, required_argument, 0, 0 },
-	{ CPERF_SEGMENTS_NB, required_argument, 0, 0 },
+	{ CPERF_SEGMENT_SIZE, required_argument, 0, 0 },
 	{ CPERF_DESC_NB, required_argument, 0, 0 },
 
 	{ CPERF_DEVTYPE, required_argument, 0, 0 },
@@ -739,7 +739,11 @@ cperf_options_default(struct cperf_options *opts)
 	opts->min_burst_size = 32;
 	opts->inc_burst_size = 0;
 
-	opts->segments_nb = 1;
+	/*
+	 * Will be parsed from command line or set to
+	 * maximum buffer size + digest, later
+	 */
+	opts->segment_sz = 0;
 
 	strncpy(opts->device_type, "crypto_aesni_mb",
 			sizeof(opts->device_type));
@@ -783,7 +787,7 @@ cperf_opts_parse_long(int opt_idx, struct cperf_options *opts)
 		{ CPERF_TOTAL_OPS,	parse_total_ops },
 		{ CPERF_BURST_SIZE,	parse_burst_sz },
 		{ CPERF_BUFFER_SIZE,	parse_buffer_sz },
-		{ CPERF_SEGMENTS_NB,	parse_segments_nb },
+		{ CPERF_SEGMENT_SIZE,	parse_segment_sz },
 		{ CPERF_DESC_NB,	parse_desc_nb },
 		{ CPERF_DEVTYPE,	parse_device_type },
 		{ CPERF_OPTYPE,		parse_op_type },
@@ -893,9 +897,21 @@ check_cipher_buffer_length(struct cperf_options *options)
 int
 cperf_options_check(struct cperf_options *options)
 {
-	if (options->segments_nb > options->min_buffer_size) {
+	if (options->op_type == CPERF_CIPHER_ONLY)
+		options->digest_sz = 0;
+
+	/*
+	 * If segment size is not set, assume only one segment,
+	 * big enough to contain the largest buffer and the digest
+	 */
+	if (options->segment_sz == 0)
+		options->segment_sz = options->max_buffer_size +
+				options->digest_sz;
+
+	if (options->segment_sz < options->digest_sz) {
 		RTE_LOG(ERR, USER1,
-				"Segments number greater than buffer size.\n");
+				"Segment size should be at least "
+				"the size of the digest\n");
 		return -EINVAL;
 	}
 
@@ -1019,7 +1035,7 @@ cperf_options_dump(struct cperf_options *opts)
 			printf("%u ", opts->burst_size_list[size_idx]);
 		printf("\n");
 	}
-	printf("\n# segments per buffer: %u\n", opts->segments_nb);
+	printf("\n# segment size: %u\n", opts->segment_sz);
 	printf("#\n");
 	printf("# cryptodev type: %s\n", opts->device_type);
 	printf("#\n");
diff --git a/app/test-crypto-perf/cperf_test_latency.c b/app/test-crypto-perf/cperf_test_latency.c
index 2a46af9..7b9dc9f 100644
--- a/app/test-crypto-perf/cperf_test_latency.c
+++ b/app/test-crypto-perf/cperf_test_latency.c
@@ -116,18 +116,18 @@ cperf_latency_test_free(struct cperf_latency_ctx *ctx, uint32_t mbuf_nb)
 
 static struct rte_mbuf *
 cperf_mbuf_create(struct rte_mempool *mempool,
-		uint32_t segments_nb,
+		uint32_t segment_sz,
+		uint16_t segments_nb,
 		const struct cperf_options *options,
 		const struct cperf_test_vector *test_vector)
 {
 	struct rte_mbuf *mbuf;
-	uint32_t segment_sz = options->max_buffer_size / segments_nb;
-	uint32_t last_sz = options->max_buffer_size % segments_nb;
 	uint8_t *mbuf_data;
 	uint8_t *test_data =
 			(options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) ?
 					test_vector->plaintext.data :
 					test_vector->ciphertext.data;
+	uint32_t remaining_bytes = options->max_buffer_size;
 
 	mbuf = rte_pktmbuf_alloc(mempool);
 	if (mbuf == NULL)
@@ -137,11 +137,18 @@ cperf_mbuf_create(struct rte_mempool *mempool,
 	if (mbuf_data == NULL)
 		goto error;
 
-	memcpy(mbuf_data, test_data, segment_sz);
-	test_data += segment_sz;
+	if (options->max_buffer_size <= segment_sz) {
+		memcpy(mbuf_data, test_data, options->max_buffer_size);
+		test_data += options->max_buffer_size;
+		remaining_bytes = 0;
+	} else {
+		memcpy(mbuf_data, test_data, segment_sz);
+		test_data += segment_sz;
+		remaining_bytes -= segment_sz;
+	}
 	segments_nb--;
 
-	while (segments_nb) {
+	while (remaining_bytes) {
 		struct rte_mbuf *m;
 
 		m = rte_pktmbuf_alloc(mempool);
@@ -154,22 +161,32 @@ cperf_mbuf_create(struct rte_mempool *mempool,
 		if (mbuf_data == NULL)
 			goto error;
 
-		memcpy(mbuf_data, test_data, segment_sz);
-		test_data += segment_sz;
+		if (remaining_bytes <= segment_sz) {
+			memcpy(mbuf_data, test_data, remaining_bytes);
+			remaining_bytes = 0;
+			test_data += remaining_bytes;
+		} else {
+			memcpy(mbuf_data, test_data, segment_sz);
+			remaining_bytes -= segment_sz;
+			test_data += segment_sz;
+		}
 		segments_nb--;
 	}
 
-	if (last_sz) {
-		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, last_sz);
-		if (mbuf_data == NULL)
-			goto error;
+	/*
+	 * If there was not enough room for the digest at the end
+	 * of the last segment, allocate a new one
+	 */
+	if (segments_nb != 0) {
+		struct rte_mbuf *m;
 
-		memcpy(mbuf_data, test_data, last_sz);
-	}
+		m = rte_pktmbuf_alloc(mempool);
+
+		if (m == NULL)
+			goto error;
 
-	if (options->op_type != CPERF_CIPHER_ONLY) {
-		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,
-			options->digest_sz);
+		rte_pktmbuf_chain(mbuf, m);
+		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,	segment_sz);
 		if (mbuf_data == NULL)
 			goto error;
 	}
@@ -217,13 +234,14 @@ cperf_latency_test_constructor(struct rte_mempool *sess_mp,
 	snprintf(pool_name, sizeof(pool_name), "cperf_pool_in_cdev_%d",
 				dev_id);
 
+	uint32_t max_size = options->max_buffer_size + options->digest_sz;
+	uint16_t segments_nb = (max_size % options->segment_sz) ?
+			(max_size / options->segment_sz) + 1 :
+			max_size / options->segment_sz;
+
 	ctx->pkt_mbuf_pool_in = rte_pktmbuf_pool_create(pool_name,
-			options->pool_sz * options->segments_nb, 0, 0,
-			RTE_PKTMBUF_HEADROOM +
-			RTE_CACHE_LINE_ROUNDUP(
-				(options->max_buffer_size / options->segments_nb) +
-				(options->max_buffer_size % options->segments_nb) +
-					options->digest_sz),
+			options->pool_sz * segments_nb, 0, 0,
+			RTE_PKTMBUF_HEADROOM + options->segment_sz,
 			rte_socket_id());
 
 	if (ctx->pkt_mbuf_pool_in == NULL)
@@ -236,7 +254,9 @@ cperf_latency_test_constructor(struct rte_mempool *sess_mp,
 
 	for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
 		ctx->mbufs_in[mbuf_idx] = cperf_mbuf_create(
-				ctx->pkt_mbuf_pool_in, options->segments_nb,
+				ctx->pkt_mbuf_pool_in,
+				options->segment_sz,
+				segments_nb,
 				options, test_vector);
 		if (ctx->mbufs_in[mbuf_idx] == NULL)
 			goto err;
@@ -251,9 +271,7 @@ cperf_latency_test_constructor(struct rte_mempool *sess_mp,
 		ctx->pkt_mbuf_pool_out = rte_pktmbuf_pool_create(
 				pool_name, options->pool_sz, 0, 0,
 				RTE_PKTMBUF_HEADROOM +
-				RTE_CACHE_LINE_ROUNDUP(
-					options->max_buffer_size +
-					options->digest_sz),
+				max_size,
 				rte_socket_id());
 
 		if (ctx->pkt_mbuf_pool_out == NULL)
@@ -267,8 +285,8 @@ cperf_latency_test_constructor(struct rte_mempool *sess_mp,
 	for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
 		if (options->out_of_place == 1)	{
 			ctx->mbufs_out[mbuf_idx] = cperf_mbuf_create(
-					ctx->pkt_mbuf_pool_out, 1,
-					options, test_vector);
+					ctx->pkt_mbuf_pool_out, max_size,
+					1, options, test_vector);
 			if (ctx->mbufs_out[mbuf_idx] == NULL)
 				goto err;
 		} else {
@@ -339,7 +357,7 @@ cperf_latency_test_runner(void *arg)
 	int linearize = 0;
 
 	/* Check if source mbufs require coalescing */
-	if (ctx->options->segments_nb > 1) {
+	if (ctx->options->segment_sz < ctx->options->max_buffer_size) {
 		rte_cryptodev_info_get(ctx->dev_id, &dev_info);
 		if ((dev_info.feature_flags &
 				RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
diff --git a/app/test-crypto-perf/cperf_test_pmd_cyclecount.c b/app/test-crypto-perf/cperf_test_pmd_cyclecount.c
index ef1aa7e..872124f 100644
--- a/app/test-crypto-perf/cperf_test_pmd_cyclecount.c
+++ b/app/test-crypto-perf/cperf_test_pmd_cyclecount.c
@@ -133,18 +133,18 @@ cperf_pmd_cyclecount_test_free(struct cperf_pmd_cyclecount_ctx *ctx,
 }
 
 static struct rte_mbuf *
-cperf_mbuf_create(struct rte_mempool *mempool, uint32_t segments_nb,
+cperf_mbuf_create(struct rte_mempool *mempool,
+		uint32_t segment_sz, uint16_t segments_nb,
 		const struct cperf_options *options,
 		const struct cperf_test_vector *test_vector)
 {
 	struct rte_mbuf *mbuf;
-	uint32_t segment_sz = options->max_buffer_size / segments_nb;
-	uint32_t last_sz = options->max_buffer_size % segments_nb;
 	uint8_t *mbuf_data;
 	uint8_t *test_data =
 			(options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) ?
 			test_vector->plaintext.data :
 			test_vector->ciphertext.data;
+	uint32_t remaining_bytes = options->max_buffer_size;
 
 	mbuf = rte_pktmbuf_alloc(mempool);
 	if (mbuf == NULL)
@@ -154,11 +154,18 @@ cperf_mbuf_create(struct rte_mempool *mempool, uint32_t segments_nb,
 	if (mbuf_data == NULL)
 		goto error;
 
-	memcpy(mbuf_data, test_data, segment_sz);
-	test_data += segment_sz;
+	if (options->max_buffer_size <= segment_sz) {
+		memcpy(mbuf_data, test_data, options->max_buffer_size);
+		test_data += options->max_buffer_size;
+		remaining_bytes = 0;
+	} else {
+		memcpy(mbuf_data, test_data, segment_sz);
+		test_data += segment_sz;
+		remaining_bytes -= segment_sz;
+	}
 	segments_nb--;
 
-	while (segments_nb) {
+	while (remaining_bytes) {
 		struct rte_mbuf *m;
 
 		m = rte_pktmbuf_alloc(mempool);
@@ -171,22 +178,32 @@ cperf_mbuf_create(struct rte_mempool *mempool, uint32_t segments_nb,
 		if (mbuf_data == NULL)
 			goto error;
 
-		memcpy(mbuf_data, test_data, segment_sz);
-		test_data += segment_sz;
+		if (remaining_bytes <= segment_sz) {
+			memcpy(mbuf_data, test_data, remaining_bytes);
+			remaining_bytes = 0;
+			test_data += remaining_bytes;
+		} else {
+			memcpy(mbuf_data, test_data, segment_sz);
+			remaining_bytes -= segment_sz;
+			test_data += segment_sz;
+		}
 		segments_nb--;
 	}
 
-	if (last_sz) {
-		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, last_sz);
-		if (mbuf_data == NULL)
-			goto error;
+	/*
+	 * If there was not enough room for the digest at the end
+	 * of the last segment, allocate a new one
+	 */
+	if (segments_nb != 0) {
+		struct rte_mbuf *m;
 
-		memcpy(mbuf_data, test_data, last_sz);
-	}
+		m = rte_pktmbuf_alloc(mempool);
 
-	if (options->op_type != CPERF_CIPHER_ONLY) {
-		mbuf_data = (uint8_t *)rte_pktmbuf_append(
-				mbuf, options->digest_sz);
+		if (m == NULL)
+			goto error;
+
+		rte_pktmbuf_chain(mbuf, m);
+		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,	segment_sz);
 		if (mbuf_data == NULL)
 			goto error;
 	}
@@ -209,13 +226,7 @@ cperf_pmd_cyclecount_test_constructor(struct rte_mempool *sess_mp,
 	struct cperf_pmd_cyclecount_ctx *ctx = NULL;
 	unsigned int mbuf_idx = 0;
 	char pool_name[32] = "";
-	uint16_t dataroom_sz = RTE_PKTMBUF_HEADROOM +
-			RTE_CACHE_LINE_ROUNDUP(
-					(options->max_buffer_size /
-							options->segments_nb) +
-					(options->max_buffer_size %
-							options->segments_nb) +
-					options->digest_sz);
+	uint32_t dataroom_sz = RTE_PKTMBUF_HEADROOM + options->segment_sz;
 
 	/* preallocate buffers for crypto ops as they can get quite big */
 	size_t alloc_sz = sizeof(struct rte_crypto_op *) *
@@ -243,8 +254,12 @@ cperf_pmd_cyclecount_test_constructor(struct rte_mempool *sess_mp,
 
 	snprintf(pool_name, sizeof(pool_name), "cperf_pool_in_cdev_%d", dev_id);
 
+	uint32_t max_size = options->max_buffer_size + options->digest_sz;
+	uint16_t segments_nb = (max_size % options->segment_sz) ?
+			(max_size / options->segment_sz) + 1 :
+			max_size / options->segment_sz;
 	ctx->pkt_mbuf_pool_in = rte_pktmbuf_pool_create(pool_name,
-			options->pool_sz * options->segments_nb, 0, 0,
+			options->pool_sz * segments_nb, 0, 0,
 			dataroom_sz, rte_socket_id());
 
 	if (ctx->pkt_mbuf_pool_in == NULL)
@@ -256,7 +271,9 @@ cperf_pmd_cyclecount_test_constructor(struct rte_mempool *sess_mp,
 
 	for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
 		ctx->mbufs_in[mbuf_idx] = cperf_mbuf_create(
-				ctx->pkt_mbuf_pool_in, options->segments_nb,
+				ctx->pkt_mbuf_pool_in,
+				options->segment_sz,
+				segments_nb,
 				options, test_vector);
 		if (ctx->mbufs_in[mbuf_idx] == NULL)
 			goto err;
@@ -267,7 +284,8 @@ cperf_pmd_cyclecount_test_constructor(struct rte_mempool *sess_mp,
 				dev_id);
 
 		ctx->pkt_mbuf_pool_out = rte_pktmbuf_pool_create(pool_name,
-				options->pool_sz, 0, 0, dataroom_sz,
+				options->pool_sz, 0, 0,
+				RTE_PKTMBUF_HEADROOM + max_size,
 				rte_socket_id());
 
 		if (ctx->pkt_mbuf_pool_out == NULL)
@@ -280,8 +298,8 @@ cperf_pmd_cyclecount_test_constructor(struct rte_mempool *sess_mp,
 	for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
 		if (options->out_of_place == 1) {
 			ctx->mbufs_out[mbuf_idx] = cperf_mbuf_create(
-					ctx->pkt_mbuf_pool_out, 1, options,
-					test_vector);
+					ctx->pkt_mbuf_pool_out, max_size,
+					1, options, test_vector);
 			if (ctx->mbufs_out[mbuf_idx] == NULL)
 				goto err;
 		} else {
@@ -573,7 +591,7 @@ cperf_pmd_cyclecount_test_runner(void *test_ctx)
 	struct rte_cryptodev_info dev_info;
 
 	/* Check if source mbufs require coalescing */
-	if (opts->segments_nb > 1) {
+	if (opts->segments_sz < ctx->options->max_buffer_size) {
 		rte_cryptodev_info_get(state.ctx->dev_id, &dev_info);
 		if ((dev_info.feature_flags &
 				    RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) ==
diff --git a/app/test-crypto-perf/cperf_test_throughput.c b/app/test-crypto-perf/cperf_test_throughput.c
index 07aea6a..fcb82a8 100644
--- a/app/test-crypto-perf/cperf_test_throughput.c
+++ b/app/test-crypto-perf/cperf_test_throughput.c
@@ -100,18 +100,18 @@ cperf_throughput_test_free(struct cperf_throughput_ctx *ctx, uint32_t mbuf_nb)
 
 static struct rte_mbuf *
 cperf_mbuf_create(struct rte_mempool *mempool,
-		uint32_t segments_nb,
+		uint32_t segment_sz,
+		uint16_t segments_nb,
 		const struct cperf_options *options,
 		const struct cperf_test_vector *test_vector)
 {
 	struct rte_mbuf *mbuf;
-	uint32_t segment_sz = options->max_buffer_size / segments_nb;
-	uint32_t last_sz = options->max_buffer_size % segments_nb;
 	uint8_t *mbuf_data;
 	uint8_t *test_data =
 			(options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) ?
 					test_vector->plaintext.data :
 					test_vector->ciphertext.data;
+	uint32_t remaining_bytes = options->max_buffer_size;
 
 	mbuf = rte_pktmbuf_alloc(mempool);
 	if (mbuf == NULL)
@@ -121,11 +121,18 @@ cperf_mbuf_create(struct rte_mempool *mempool,
 	if (mbuf_data == NULL)
 		goto error;
 
-	memcpy(mbuf_data, test_data, segment_sz);
-	test_data += segment_sz;
+	if (options->max_buffer_size <= segment_sz) {
+		memcpy(mbuf_data, test_data, options->max_buffer_size);
+		test_data += options->max_buffer_size;
+		remaining_bytes = 0;
+	} else {
+		memcpy(mbuf_data, test_data, segment_sz);
+		test_data += segment_sz;
+		remaining_bytes -= segment_sz;
+	}
 	segments_nb--;
 
-	while (segments_nb) {
+	while (remaining_bytes) {
 		struct rte_mbuf *m;
 
 		m = rte_pktmbuf_alloc(mempool);
@@ -138,22 +145,32 @@ cperf_mbuf_create(struct rte_mempool *mempool,
 		if (mbuf_data == NULL)
 			goto error;
 
-		memcpy(mbuf_data, test_data, segment_sz);
-		test_data += segment_sz;
+		if (remaining_bytes <= segment_sz) {
+			memcpy(mbuf_data, test_data, remaining_bytes);
+			remaining_bytes = 0;
+			test_data += remaining_bytes;
+		} else {
+			memcpy(mbuf_data, test_data, segment_sz);
+			remaining_bytes -= segment_sz;
+			test_data += segment_sz;
+		}
 		segments_nb--;
 	}
 
-	if (last_sz) {
-		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, last_sz);
-		if (mbuf_data == NULL)
-			goto error;
+	/*
+	 * If there was not enough room for the digest at the end
+	 * of the last segment, allocate a new one
+	 */
+	if (segments_nb != 0) {
+		struct rte_mbuf *m;
 
-		memcpy(mbuf_data, test_data, last_sz);
-	}
+		m = rte_pktmbuf_alloc(mempool);
+
+		if (m == NULL)
+			goto error;
 
-	if (options->op_type != CPERF_CIPHER_ONLY) {
-		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,
-				options->digest_sz);
+		rte_pktmbuf_chain(mbuf, m);
+		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,	segment_sz);
 		if (mbuf_data == NULL)
 			goto error;
 	}
@@ -200,13 +217,14 @@ cperf_throughput_test_constructor(struct rte_mempool *sess_mp,
 	snprintf(pool_name, sizeof(pool_name), "cperf_pool_in_cdev_%d",
 			dev_id);
 
+	uint32_t max_size = options->max_buffer_size + options->digest_sz;
+	uint16_t segments_nb = (max_size % options->segment_sz) ?
+			(max_size / options->segment_sz) + 1 :
+			max_size / options->segment_sz;
+
 	ctx->pkt_mbuf_pool_in = rte_pktmbuf_pool_create(pool_name,
-			options->pool_sz * options->segments_nb, 0, 0,
-			RTE_PKTMBUF_HEADROOM +
-			RTE_CACHE_LINE_ROUNDUP(
-				(options->max_buffer_size / options->segments_nb) +
-				(options->max_buffer_size % options->segments_nb) +
-					options->digest_sz),
+			options->pool_sz * segments_nb, 0, 0,
+			RTE_PKTMBUF_HEADROOM + options->segment_sz,
 			rte_socket_id());
 
 	if (ctx->pkt_mbuf_pool_in == NULL)
@@ -218,7 +236,9 @@ cperf_throughput_test_constructor(struct rte_mempool *sess_mp,
 
 	for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
 		ctx->mbufs_in[mbuf_idx] = cperf_mbuf_create(
-				ctx->pkt_mbuf_pool_in, options->segments_nb,
+				ctx->pkt_mbuf_pool_in,
+				options->segment_sz,
+				segments_nb,
 				options, test_vector);
 		if (ctx->mbufs_in[mbuf_idx] == NULL)
 			goto err;
@@ -232,9 +252,7 @@ cperf_throughput_test_constructor(struct rte_mempool *sess_mp,
 		ctx->pkt_mbuf_pool_out = rte_pktmbuf_pool_create(
 				pool_name, options->pool_sz, 0, 0,
 				RTE_PKTMBUF_HEADROOM +
-				RTE_CACHE_LINE_ROUNDUP(
-					options->max_buffer_size +
-					options->digest_sz),
+				max_size,
 				rte_socket_id());
 
 		if (ctx->pkt_mbuf_pool_out == NULL)
@@ -248,8 +266,8 @@ cperf_throughput_test_constructor(struct rte_mempool *sess_mp,
 	for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
 		if (options->out_of_place == 1)	{
 			ctx->mbufs_out[mbuf_idx] = cperf_mbuf_create(
-					ctx->pkt_mbuf_pool_out, 1,
-					options, test_vector);
+					ctx->pkt_mbuf_pool_out, max_size,
+					1, options, test_vector);
 			if (ctx->mbufs_out[mbuf_idx] == NULL)
 				goto err;
 		} else {
@@ -297,7 +315,7 @@ cperf_throughput_test_runner(void *test_ctx)
 	int linearize = 0;
 
 	/* Check if source mbufs require coalescing */
-	if (ctx->options->segments_nb > 1) {
+	if (ctx->options->segment_sz < ctx->options->max_buffer_size) {
 		rte_cryptodev_info_get(ctx->dev_id, &dev_info);
 		if ((dev_info.feature_flags &
 				RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
diff --git a/app/test-crypto-perf/cperf_test_verify.c b/app/test-crypto-perf/cperf_test_verify.c
index bc07eb6..ba9621b 100644
--- a/app/test-crypto-perf/cperf_test_verify.c
+++ b/app/test-crypto-perf/cperf_test_verify.c
@@ -104,18 +104,18 @@ cperf_verify_test_free(struct cperf_verify_ctx *ctx, uint32_t mbuf_nb)
 
 static struct rte_mbuf *
 cperf_mbuf_create(struct rte_mempool *mempool,
-		uint32_t segments_nb,
+		uint32_t segment_sz,
+		uint16_t segments_nb,
 		const struct cperf_options *options,
 		const struct cperf_test_vector *test_vector)
 {
 	struct rte_mbuf *mbuf;
-	uint32_t segment_sz = options->max_buffer_size / segments_nb;
-	uint32_t last_sz = options->max_buffer_size % segments_nb;
 	uint8_t *mbuf_data;
 	uint8_t *test_data =
 			(options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) ?
 					test_vector->plaintext.data :
 					test_vector->ciphertext.data;
+	uint32_t remaining_bytes = options->max_buffer_size;
 
 	mbuf = rte_pktmbuf_alloc(mempool);
 	if (mbuf == NULL)
@@ -125,11 +125,18 @@ cperf_mbuf_create(struct rte_mempool *mempool,
 	if (mbuf_data == NULL)
 		goto error;
 
-	memcpy(mbuf_data, test_data, segment_sz);
-	test_data += segment_sz;
+	if (options->max_buffer_size <= segment_sz) {
+		memcpy(mbuf_data, test_data, options->max_buffer_size);
+		test_data += options->max_buffer_size;
+		remaining_bytes = 0;
+	} else {
+		memcpy(mbuf_data, test_data, segment_sz);
+		test_data += segment_sz;
+		remaining_bytes -= segment_sz;
+	}
 	segments_nb--;
 
-	while (segments_nb) {
+	while (remaining_bytes) {
 		struct rte_mbuf *m;
 
 		m = rte_pktmbuf_alloc(mempool);
@@ -142,22 +149,32 @@ cperf_mbuf_create(struct rte_mempool *mempool,
 		if (mbuf_data == NULL)
 			goto error;
 
-		memcpy(mbuf_data, test_data, segment_sz);
-		test_data += segment_sz;
+		if (remaining_bytes <= segment_sz) {
+			memcpy(mbuf_data, test_data, remaining_bytes);
+			remaining_bytes = 0;
+			test_data += remaining_bytes;
+		} else {
+			memcpy(mbuf_data, test_data, segment_sz);
+			remaining_bytes -= segment_sz;
+			test_data += segment_sz;
+		}
 		segments_nb--;
 	}
 
-	if (last_sz) {
-		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf, last_sz);
-		if (mbuf_data == NULL)
-			goto error;
+	/*
+	 * If there was not enough room for the digest at the end
+	 * of the last segment, allocate a new one
+	 */
+	if (segments_nb != 0) {
+		struct rte_mbuf *m;
 
-		memcpy(mbuf_data, test_data, last_sz);
-	}
+		m = rte_pktmbuf_alloc(mempool);
 
-	if (options->op_type != CPERF_CIPHER_ONLY) {
-		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,
-				options->digest_sz);
+		if (m == NULL)
+			goto error;
+
+		rte_pktmbuf_chain(mbuf, m);
+		mbuf_data = (uint8_t *)rte_pktmbuf_append(mbuf,	segment_sz);
 		if (mbuf_data == NULL)
 			goto error;
 	}
@@ -204,13 +221,14 @@ cperf_verify_test_constructor(struct rte_mempool *sess_mp,
 	snprintf(pool_name, sizeof(pool_name), "cperf_pool_in_cdev_%d",
 			dev_id);
 
+	uint32_t max_size = options->max_buffer_size + options->digest_sz;
+	uint16_t segments_nb = (max_size % options->segment_sz) ?
+			(max_size / options->segment_sz) + 1 :
+			max_size / options->segment_sz;
+
 	ctx->pkt_mbuf_pool_in = rte_pktmbuf_pool_create(pool_name,
-			options->pool_sz * options->segments_nb, 0, 0,
-			RTE_PKTMBUF_HEADROOM +
-			RTE_CACHE_LINE_ROUNDUP(
-				(options->max_buffer_size / options->segments_nb) +
-				(options->max_buffer_size % options->segments_nb) +
-					options->digest_sz),
+			options->pool_sz * segments_nb, 0, 0,
+			RTE_PKTMBUF_HEADROOM + options->segment_sz,
 			rte_socket_id());
 
 	if (ctx->pkt_mbuf_pool_in == NULL)
@@ -222,7 +240,9 @@ cperf_verify_test_constructor(struct rte_mempool *sess_mp,
 
 	for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
 		ctx->mbufs_in[mbuf_idx] = cperf_mbuf_create(
-				ctx->pkt_mbuf_pool_in, options->segments_nb,
+				ctx->pkt_mbuf_pool_in,
+				options->segment_sz,
+				segments_nb,
 				options, test_vector);
 		if (ctx->mbufs_in[mbuf_idx] == NULL)
 			goto err;
@@ -236,9 +256,7 @@ cperf_verify_test_constructor(struct rte_mempool *sess_mp,
 		ctx->pkt_mbuf_pool_out = rte_pktmbuf_pool_create(
 				pool_name, options->pool_sz, 0, 0,
 				RTE_PKTMBUF_HEADROOM +
-				RTE_CACHE_LINE_ROUNDUP(
-					options->max_buffer_size +
-					options->digest_sz),
+				max_size,
 				rte_socket_id());
 
 		if (ctx->pkt_mbuf_pool_out == NULL)
@@ -252,8 +270,8 @@ cperf_verify_test_constructor(struct rte_mempool *sess_mp,
 	for (mbuf_idx = 0; mbuf_idx < options->pool_sz; mbuf_idx++) {
 		if (options->out_of_place == 1)	{
 			ctx->mbufs_out[mbuf_idx] = cperf_mbuf_create(
-					ctx->pkt_mbuf_pool_out, 1,
-					options, test_vector);
+					ctx->pkt_mbuf_pool_out, max_size,
+					1, options, test_vector);
 			if (ctx->mbufs_out[mbuf_idx] == NULL)
 				goto err;
 		} else {
@@ -405,7 +423,7 @@ cperf_verify_test_runner(void *test_ctx)
 	int linearize = 0;
 
 	/* Check if source mbufs require coalescing */
-	if (ctx->options->segments_nb > 1) {
+	if (ctx->options->segment_sz < ctx->options->max_buffer_size) {
 		rte_cryptodev_info_get(ctx->dev_id, &dev_info);
 		if ((dev_info.feature_flags &
 				RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
diff --git a/doc/guides/tools/cryptoperf.rst b/doc/guides/tools/cryptoperf.rst
index 2f526c6..d587c20 100644
--- a/doc/guides/tools/cryptoperf.rst
+++ b/doc/guides/tools/cryptoperf.rst
@@ -172,9 +172,11 @@ The following are the appication command-line options:
           * List of values, up to 32 values, separated in commas (i.e. ``--buffer-sz 32,64,128``)
 
 
-* ``--segments-nb <n>``
+* ``--segment-sz <n>``
 
-        Set the number of segments per packet.
+        Set the size of the segment to use, for Scatter Gather List testing.
+        By default, it is set to the size of the maximum buffer size, including the digest size,
+        so a single segment is created.
 
 * ``--devtype <name>``
 
