From: "Daly, Lee" <lee.daly@intel.com>
To: pablo.de.lara.guarch@intel.com
Cc: dev@dpdk.org, "Daly, Lee" <lee.daly@intel.com>
Subject: [PATCH v3] compress/isal: add chained mbuf support
Date: Mon, 23 Jul 2018 19:02:25 +0100 [thread overview]
Message-ID: <1532368945-23909-1-git-send-email-lee.daly@intel.com> (raw)
In-Reply-To: <1531312811-177746-1-git-send-email-lee.daly@intel.com>
This patch adds chained mbuf support for input or output buffers
during compression/decompression operations.
Signed-off-by: Lee Daly <lee.daly@intel.com>
---
doc/guides/compressdevs/features/isal.ini | 17 +-
doc/guides/compressdevs/isal.rst | 2 -
drivers/compress/isal/isal_compress_pmd.c | 397 ++++++++++++++++++++------
drivers/compress/isal/isal_compress_pmd_ops.c | 5 +-
4 files changed, 323 insertions(+), 98 deletions(-)
diff --git a/doc/guides/compressdevs/features/isal.ini b/doc/guides/compressdevs/features/isal.ini
index 7183d10..919cf70 100644
--- a/doc/guides/compressdevs/features/isal.ini
+++ b/doc/guides/compressdevs/features/isal.ini
@@ -4,10 +4,13 @@
; Supported features of 'ISA-L' compression driver.
;
[Features]
-CPU SSE = Y
-CPU AVX = Y
-CPU AVX2 = Y
-CPU AVX512 = Y
-Deflate = Y
-Fixed = Y
-Dynamic = Y
+CPU SSE = Y
+CPU AVX = Y
+CPU AVX2 = Y
+CPU AVX512 = Y
+OOP SGL In SGL Out = Y
+OOP SGL In LB Out = Y
+OOP LB In SGL Out = Y
+Deflate = Y
+Fixed = Y
+Dynamic = Y
diff --git a/doc/guides/compressdevs/isal.rst b/doc/guides/compressdevs/isal.rst
index 276ff06..3bc3022 100644
--- a/doc/guides/compressdevs/isal.rst
+++ b/doc/guides/compressdevs/isal.rst
@@ -78,8 +78,6 @@ As a result the level mappings from the API to the PMD are shown below.
Limitations
-----------
-* Chained mbufs will not be supported until a future release, meaning max data size being passed to PMD through a single mbuf is 64K - 1. If data is larger than this it will need to be split up and sent as multiple operations.
-
* Compressdev level 0, no compression, is not supported.
* Checksums will not be supported until future release.
diff --git a/drivers/compress/isal/isal_compress_pmd.c b/drivers/compress/isal/isal_compress_pmd.c
index 5966cc3..a776019 100644
--- a/drivers/compress/isal/isal_compress_pmd.c
+++ b/drivers/compress/isal/isal_compress_pmd.c
@@ -188,6 +188,206 @@ isal_comp_set_priv_xform_parameters(struct isal_priv_xform *priv_xform,
return 0;
}
+/* Compression using chained mbufs for input/output data */
+static int
+chained_mbuf_compression(struct rte_comp_op *op, struct isal_comp_qp *qp)
+{
+ int ret;
+ uint32_t remaining_offset;
+ uint32_t remaining_data = op->src.length;
+ struct rte_mbuf *src = op->m_src;
+ struct rte_mbuf *dst = op->m_dst;
+
+ /* check for offset passing multiple segments
+ * and point compression stream to input/output buffer
+ */
+ if (op->src.offset > src->data_len) {
+ remaining_offset = op->src.offset;
+ while (remaining_offset > src->data_len) {
+ remaining_offset -= src->data_len;
+ src = src->next;
+ }
+
+
+ qp->stream->avail_in = src->data_len - remaining_offset;
+ qp->stream->next_in = rte_pktmbuf_mtod_offset(src, uint8_t *,
+ (op->src.offset % src->data_len));
+ } else {
+ qp->stream->avail_in = src->data_len - op->src.offset;
+ qp->stream->next_in = rte_pktmbuf_mtod_offset(src, uint8_t *,
+ op->src.offset);
+ }
+
+ if (op->dst.offset > dst->data_len) {
+ remaining_offset = op->dst.offset;
+ while (remaining_offset > dst->data_len) {
+ remaining_offset -= dst->data_len;
+ dst = dst->next;
+ }
+
+ qp->stream->avail_out = dst->data_len - remaining_offset;
+ qp->stream->next_out = rte_pktmbuf_mtod_offset(dst, uint8_t *,
+ (op->dst.offset % dst->data_len));
+ } else {
+ qp->stream->avail_out = dst->data_len - op->dst.offset;
+ qp->stream->next_out = rte_pktmbuf_mtod_offset(dst, uint8_t *,
+ op->dst.offset);
+ }
+
+ if (unlikely(!qp->stream->next_in || !qp->stream->next_out)) {
+ ISAL_PMD_LOG(ERR, "Invalid source or destination buffer\n");
+ op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
+ return -1;
+ }
+
+ while (qp->stream->internal_state.state != ZSTATE_END) {
+ /* Last segment of data */
+ if (remaining_data <= src->data_len)
+ qp->stream->end_of_stream = 1;
+
+ /* Execute compression operation */
+ ret = isal_deflate(qp->stream);
+
+ remaining_data = op->src.length - qp->stream->total_in;
+
+ if (ret != COMP_OK) {
+ ISAL_PMD_LOG(ERR, "Compression operation failed\n");
+ op->status = RTE_COMP_OP_STATUS_ERROR;
+ return ret;
+ }
+
+ if (qp->stream->avail_in == 0 &&
+ qp->stream->total_in != op->src.length) {
+ if (src->next != NULL) {
+ src = src->next;
+ qp->stream->next_in =
+ rte_pktmbuf_mtod(src, uint8_t *);
+ qp->stream->avail_in =
+ RTE_MIN(remaining_data, src->data_len);
+ } else {
+ ISAL_PMD_LOG(ERR,
+ "Not enough input buffer segments\n");
+ op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
+ return -1;
+ }
+ }
+
+ if (qp->stream->avail_out == 0 &&
+ qp->stream->internal_state.state != ZSTATE_END) {
+ if (dst->next != NULL) {
+ dst = dst->next;
+ qp->stream->next_out =
+ rte_pktmbuf_mtod(dst, uint8_t *);
+ qp->stream->avail_out = dst->data_len;
+ } else {
+ ISAL_PMD_LOG(ERR,
+ "Not enough output buffer segments\n");
+ op->status =
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
+ return -1;
+ }
+ }
+ }
+ op->consumed = qp->stream->total_in;
+ op->produced = qp->stream->total_out;
+
+ return 0;
+}
+
+/* Decompression using chained mbufs for input/output data */
+static int
+chained_mbuf_decompression(struct rte_comp_op *op, struct isal_comp_qp *qp)
+{
+ int ret;
+ uint32_t consumed_data, remaining_offset;
+ uint32_t remaining_data = op->src.length;
+ struct rte_mbuf *src = op->m_src;
+ struct rte_mbuf *dst = op->m_dst;
+
+ /* check for offset passing multiple segments
+ * and point decompression state to input/output buffer
+ */
+ if (op->src.offset > src->data_len) {
+ remaining_offset = op->src.offset;
+ while (remaining_offset > src->data_len) {
+ remaining_offset -= src->data_len;
+ src = src->next;
+ }
+
+ qp->state->avail_in = src->data_len - remaining_offset;
+ qp->state->next_in = rte_pktmbuf_mtod_offset(src,
+ uint8_t *, (op->src.offset % src->data_len));
+ } else {
+ qp->state->avail_in = src->data_len - op->src.offset;
+ qp->state->next_in = rte_pktmbuf_mtod_offset(src, uint8_t *,
+ op->src.offset);
+ }
+ if (op->dst.offset > dst->data_len) {
+ remaining_offset = op->dst.offset;
+ while (remaining_offset > dst->data_len) {
+ remaining_offset -= dst->data_len;
+ dst = dst->next;
+ }
+
+ qp->state->avail_out = dst->data_len - remaining_offset;
+ qp->state->next_out = rte_pktmbuf_mtod_offset(dst, uint8_t *,
+ (op->dst.offset % dst->data_len));
+ } else {
+ qp->state->avail_out = dst->data_len - op->dst.offset;
+ qp->state->next_out = rte_pktmbuf_mtod_offset(dst, uint8_t *,
+ op->dst.offset);
+ }
+ while (qp->state->block_state != ISAL_BLOCK_FINISH) {
+
+ ret = isal_inflate(qp->state);
+
+ if (remaining_data == op->src.length) {
+ consumed_data = src->data_len - qp->state->avail_in -
+ (op->src.offset % src->data_len);
+ } else
+ consumed_data = src->data_len - qp->state->avail_in;
+
+ op->consumed += consumed_data;
+ remaining_data -= consumed_data;
+
+ if (ret != ISAL_DECOMP_OK) {
+ ISAL_PMD_LOG(ERR, "Decompression operation failed\n");
+ op->status = RTE_COMP_OP_STATUS_ERROR;
+ return ret;
+ }
+
+ if (qp->state->avail_in == 0
+ && op->consumed != op->src.length) {
+ if (src->next != NULL) {
+ src = src->next;
+ qp->state->next_in =
+ rte_pktmbuf_mtod(src, uint8_t *);
+ qp->state->avail_in =
+ RTE_MIN(remaining_data, src->data_len);
+ }
+ }
+
+ if (qp->state->avail_out == 0 &&
+ qp->state->block_state != ISAL_BLOCK_FINISH) {
+ if (dst->next != NULL) {
+ dst = dst->next;
+ qp->state->next_out =
+ rte_pktmbuf_mtod(dst, uint8_t *);
+ qp->state->avail_out = dst->data_len;
+ } else {
+ ISAL_PMD_LOG(ERR,
+ "Not enough output buffer segments\n");
+ op->status =
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
+ return -1;
+ }
+ }
+ }
+ op->produced = qp->state->total_out;
+
+ return 0;
+}
+
/* Stateless Compression Function */
static int
process_isal_deflate(struct rte_comp_op *op, struct isal_comp_qp *qp,
@@ -207,7 +407,7 @@ process_isal_deflate(struct rte_comp_op *op, struct isal_comp_qp *qp,
/* Stateless operation, input will be consumed in one go */
qp->stream->flush = NO_FLUSH;
- /* set op level & intermediate level buffer */
+ /* set compression level & intermediate level buffer size */
qp->stream->level = priv_xform->compress.level;
qp->stream->level_buf_size = priv_xform->level_buffer_size;
@@ -225,59 +425,70 @@ process_isal_deflate(struct rte_comp_op *op, struct isal_comp_qp *qp,
isal_deflate_set_hufftables(qp->stream, NULL,
IGZIP_HUFFTABLE_DEFAULT);
- qp->stream->end_of_stream = 1; /* All input consumed in one go */
- if ((op->src.length + op->src.offset) > op->m_src->data_len) {
- ISAL_PMD_LOG(ERR, "Input mbuf not big enough for the length and"
- " offset provided.\n");
- op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
- return -1;
- }
- /* Point compression stream to input buffer */
- qp->stream->avail_in = op->src.length;
- qp->stream->next_in = rte_pktmbuf_mtod_offset(op->m_src, uint8_t *,
- op->src.offset);
-
- if (op->dst.offset > op->m_dst->data_len) {
- ISAL_PMD_LOG(ERR, "Output mbuf not big enough for the length"
- " and offset provided.\n");
+ if (op->m_src->pkt_len < (op->src.length + op->src.offset)) {
+ ISAL_PMD_LOG(ERR, "Input mbuf(s) not big enough.\n");
op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
return -1;
}
- /* Point compression stream to output buffer */
- qp->stream->avail_out = op->m_dst->data_len - op->dst.offset;
- qp->stream->next_out = rte_pktmbuf_mtod_offset(op->m_dst, uint8_t *,
- op->dst.offset);
- if (unlikely(!qp->stream->next_in || !qp->stream->next_out)) {
- ISAL_PMD_LOG(ERR, "Invalid source or destination buffers\n");
- op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
- return -1;
- }
+ /* Chained mbufs */
+ if (op->m_src->nb_segs > 1 || op->m_dst->nb_segs > 1) {
+ ret = chained_mbuf_compression(op, qp);
+ if (ret < 0)
+ return ret;
+ } else {
+ /* Linear buffer */
+ qp->stream->end_of_stream = 1; /* All input consumed in one */
+ /* Point compression stream to input buffer */
+ qp->stream->avail_in = op->src.length;
+ qp->stream->next_in = rte_pktmbuf_mtod_offset(op->m_src,
+ uint8_t *, op->src.offset);
+
+ if (op->dst.offset > op->m_dst->data_len) {
+ ISAL_PMD_LOG(ERR, "Output mbuf not big enough for "
+ "length and offset provided.\n");
+ op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
+ return -1;
+ }
+ /* Point compression stream to output buffer */
+ qp->stream->avail_out = op->m_dst->data_len - op->dst.offset;
+ qp->stream->next_out = rte_pktmbuf_mtod_offset(op->m_dst,
+ uint8_t *, op->dst.offset);
+
+ if (unlikely(!qp->stream->next_in || !qp->stream->next_out)) {
+ ISAL_PMD_LOG(ERR, "Invalid source or destination"
+ " buffers\n");
+ op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
+ return -1;
+ }
- /* Execute compression operation */
- ret = isal_deflate_stateless(qp->stream);
+ /* Execute compression operation */
+ ret = isal_deflate_stateless(qp->stream);
- /* Check that output buffer did not run out of space */
- if (ret == STATELESS_OVERFLOW) {
- ISAL_PMD_LOG(ERR, "Output buffer not big enough\n");
- op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
- return ret;
- }
+ /* Check that output buffer did not run out of space */
+ if (ret == STATELESS_OVERFLOW) {
+ ISAL_PMD_LOG(ERR, "Output buffer not big enough\n");
+ op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
+ return ret;
+ }
- /* Check that input buffer has been fully consumed */
- if (qp->stream->avail_in != (uint32_t)0) {
- ISAL_PMD_LOG(ERR, "Input buffer could not be read entirely\n");
- op->status = RTE_COMP_OP_STATUS_ERROR;
- return -1;
- }
+ /* Check that input buffer has been fully consumed */
+ if (qp->stream->avail_in != (uint32_t)0) {
+ ISAL_PMD_LOG(ERR, "Input buffer could not be read"
+ " entirely\n");
+ op->status = RTE_COMP_OP_STATUS_ERROR;
+ return -1;
+ }
- if (ret != COMP_OK) {
- op->status = RTE_COMP_OP_STATUS_ERROR;
- return ret;
- }
+ if (ret != COMP_OK) {
+ ISAL_PMD_LOG(ERR, "Compression operation failed\n");
+ op->status = RTE_COMP_OP_STATUS_ERROR;
+ return ret;
+ }
- op->consumed = qp->stream->total_in;
- op->produced = qp->stream->total_out;
+ op->consumed = qp->stream->total_in;
+ op->produced = qp->stream->total_out;
+ }
return ret;
}
@@ -293,59 +504,69 @@ process_isal_inflate(struct rte_comp_op *op, struct isal_comp_qp *qp)
/* Initialize decompression state */
isal_inflate_init(qp->state);
- if ((op->src.length + op->src.offset) > op->m_src->data_len) {
- ISAL_PMD_LOG(ERR, "Input mbuf not big enough for the length and"
- " offset provided.\n");
- op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
- return -1;
- }
- /* Point decompression state to input buffer */
- qp->state->avail_in = op->src.length;
- qp->state->next_in = rte_pktmbuf_mtod_offset(op->m_src, uint8_t *,
- op->src.offset);
-
- if (op->dst.offset > op->m_dst->data_len) {
- ISAL_PMD_LOG(ERR, "Output mbuf not big enough for the length "
- "and offset provided.\n");
+ if (op->m_src->pkt_len < (op->src.length + op->src.offset)) {
+ ISAL_PMD_LOG(ERR, "Input mbuf(s) not big enough.\n");
op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
return -1;
}
- /* Point decompression state to output buffer */
- qp->state->avail_out = op->m_dst->data_len - op->dst.offset;
- qp->state->next_out = rte_pktmbuf_mtod_offset(op->m_dst, uint8_t *,
- op->dst.offset);
- if (unlikely(!qp->state->next_in || !qp->state->next_out)) {
- ISAL_PMD_LOG(ERR, "Invalid source or destination buffers\n");
- op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
- return -1;
- }
+ /* Chained mbufs */
+ if (op->m_src->nb_segs > 1 || op->m_dst->nb_segs > 1) {
+ ret = chained_mbuf_decompression(op, qp);
+ if (ret != 0)
+ return ret;
+ } else {
+ /* Linear buffer */
+ /* Point decompression state to input buffer */
+ qp->state->avail_in = op->src.length;
+ qp->state->next_in = rte_pktmbuf_mtod_offset(op->m_src,
+ uint8_t *, op->src.offset);
+
+ if (op->dst.offset > op->m_dst->data_len) {
+ ISAL_PMD_LOG(ERR, "Output mbuf not big enough for "
+ "length and offset provided.\n");
+ op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
+ return -1;
+ }
+ /* Point decompression state to output buffer */
+ qp->state->avail_out = op->m_dst->data_len - op->dst.offset;
+ qp->state->next_out = rte_pktmbuf_mtod_offset(op->m_dst,
+ uint8_t *, op->dst.offset);
+
+ if (unlikely(!qp->state->next_in || !qp->state->next_out)) {
+ ISAL_PMD_LOG(ERR, "Invalid source or destination"
+ " buffers\n");
+ op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
+ return -1;
+ }
- /* Execute decompression operation */
- ret = isal_inflate_stateless(qp->state);
+ /* Execute decompression operation */
+ ret = isal_inflate_stateless(qp->state);
- if (ret == ISAL_OUT_OVERFLOW) {
- ISAL_PMD_LOG(ERR, "Output buffer not big enough\n");
- op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
- return ret;
- }
+ if (ret == ISAL_OUT_OVERFLOW) {
+ ISAL_PMD_LOG(ERR, "Output buffer not big enough\n");
+ op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
+ return ret;
+ }
- /* Check that input buffer has been fully consumed */
- if (qp->state->avail_in != (uint32_t)0) {
- ISAL_PMD_LOG(ERR, "Input buffer could not be read entirely\n");
- op->status = RTE_COMP_OP_STATUS_ERROR;
- return -1;
- }
+ /* Check that input buffer has been fully consumed */
+ if (qp->state->avail_in != (uint32_t)0) {
+ ISAL_PMD_LOG(ERR, "Input buffer could not be read"
+ " entirely\n");
+ op->status = RTE_COMP_OP_STATUS_ERROR;
+ return -1;
+ }
- if (ret != ISAL_DECOMP_OK) {
- op->status = RTE_COMP_OP_STATUS_ERROR;
- return ret;
- }
+ if (ret != ISAL_DECOMP_OK) {
+ op->status = RTE_COMP_OP_STATUS_ERROR;
+ return ret;
+ }
- op->consumed = op->src.length - qp->state->avail_in;
- op->produced = qp->state->total_out;
+ op->consumed = op->src.length - qp->state->avail_in;
+ op->produced = qp->state->total_out;
+ }
-return ret;
+ return ret;
}
/* Process compression/decompression operation */
diff --git a/drivers/compress/isal/isal_compress_pmd_ops.c b/drivers/compress/isal/isal_compress_pmd_ops.c
index c61acd4..41cade8 100644
--- a/drivers/compress/isal/isal_compress_pmd_ops.c
+++ b/drivers/compress/isal/isal_compress_pmd_ops.c
@@ -12,7 +12,10 @@
static const struct rte_compressdev_capabilities isal_pmd_capabilities[] = {
{
.algo = RTE_COMP_ALGO_DEFLATE,
- .comp_feature_flags = RTE_COMP_FF_SHAREABLE_PRIV_XFORM |
+ .comp_feature_flags = RTE_COMP_FF_OOP_SGL_IN_SGL_OUT |
+ RTE_COMP_FF_OOP_SGL_IN_LB_OUT |
+ RTE_COMP_FF_OOP_LB_IN_SGL_OUT |
+ RTE_COMP_FF_SHAREABLE_PRIV_XFORM |
RTE_COMP_FF_HUFFMAN_FIXED |
RTE_COMP_FF_HUFFMAN_DYNAMIC,
.window_size = {
--
2.7.4
next prev parent reply other threads:[~2018-07-23 18:03 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-05 11:03 [PATCH] compress/isal: add chained mbuf support Lee Daly
2018-07-11 12:40 ` [PATCH v2] " Lee, Daly
2018-07-20 10:38 ` De Lara Guarch, Pablo
2018-07-23 18:02 ` Daly, Lee [this message]
2018-07-23 21:14 ` [PATCH v3] " De Lara Guarch, Pablo
2018-07-24 11:19 ` [PATCH v4] " Daly, Lee
2018-07-24 13:27 ` De Lara Guarch, Pablo
2018-07-24 13:36 ` De Lara Guarch, Pablo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1532368945-23909-1-git-send-email-lee.daly@intel.com \
--to=lee.daly@intel.com \
--cc=dev@dpdk.org \
--cc=pablo.de.lara.guarch@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.