test/compress: add stateless overflow recovery case
[dpdk.git] / app / test / test_compressdev.c
index 9a79896..283c649 100644 (file)
@@ -30,6 +30,7 @@
  * due to the compress block headers
  */
 #define COMPRESS_BUF_SIZE_RATIO 1.3
+#define COMPRESS_BUF_SIZE_RATIO_OVERFLOW 0.2
 #define NUM_LARGE_MBUFS 16
 #define SMALL_SEG_SIZE 256
 #define MAX_SEGS 16
@@ -72,6 +73,11 @@ enum varied_buff {
        LB_TO_SGL       /* output buffer is chained */
 };
 
+enum overflow_test {
+       OVERFLOW_DISABLED,
+       OVERFLOW_ENABLED
+};
+
 struct priv_op_data {
        uint16_t orig_idx;
 };
@@ -104,6 +110,14 @@ struct test_data_params {
        /* stateful decompression specific parameters */
        unsigned int decompress_output_block_size;
        unsigned int decompress_steps_max;
+       /* external mbufs specific parameters */
+       unsigned int use_external_mbufs;
+       unsigned int inbuf_data_size;
+       const struct rte_memzone *inbuf_memzone;
+       const struct rte_memzone *compbuf_memzone;
+       const struct rte_memzone *uncompbuf_memzone;
+       /* overflow test activation */
+       enum overflow_test overflow;
 };
 
 static struct comp_testsuite_params testsuite_params = { 0 };
@@ -714,6 +728,54 @@ prepare_sgl_bufs(const char *test_buf, struct rte_mbuf *head_buf,
        return 0;
 }
 
+static void
+extbuf_free_callback(void *addr __rte_unused, void *opaque __rte_unused)
+{
+}
+
+static int
+test_run_enqueue_dequeue(struct rte_comp_op **ops, unsigned int num_bufs,
+                 struct rte_comp_op **ops_processed)
+{
+       uint16_t num_enqd, num_deqd, num_total_deqd;
+       unsigned int deqd_retries = 0;
+
+       /* Enqueue and dequeue all operations */
+       num_enqd = rte_compressdev_enqueue_burst(0, 0, ops, num_bufs);
+       if (num_enqd < num_bufs) {
+               RTE_LOG(ERR, USER1,
+                       "Some operations could not be enqueued\n");
+               return -1;
+       }
+
+       num_total_deqd = 0;
+       do {
+               /*
+                * If retrying a dequeue call, wait for 10 ms to allow
+                * enough time to the driver to process the operations
+                */
+               if (deqd_retries != 0) {
+                       /*
+                        * Avoid infinite loop if not all the
+                        * operations get out of the device
+                        */
+                       if (deqd_retries == MAX_DEQD_RETRIES) {
+                               RTE_LOG(ERR, USER1,
+                                       "Not all operations could be dequeued\n");
+                               return -1;
+                       }
+                       usleep(DEQUEUE_WAIT_TIME);
+               }
+               num_deqd = rte_compressdev_dequeue_burst(0, 0,
+                               &ops_processed[num_total_deqd], num_bufs);
+               num_total_deqd += num_deqd;
+               deqd_retries++;
+
+       } while (num_total_deqd < num_enqd);
+
+       return 0;
+}
+
 /*
  * Compresses and decompresses buffer with compressdev API and Zlib API
  */
@@ -734,7 +796,11 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
        unsigned int out_of_space = test_data->out_of_space;
        unsigned int big_data = test_data->big_data;
        enum zlib_direction zlib_dir = test_data->zlib_dir;
+       enum overflow_test overflow_tst = test_data->overflow;
        int ret_status = TEST_FAILED;
+       struct rte_mbuf_ext_shared_info inbuf_info;
+       struct rte_mbuf_ext_shared_info compbuf_info;
+       struct rte_mbuf_ext_shared_info decompbuf_info;
        int ret;
        struct rte_mbuf *uncomp_bufs[num_bufs];
        struct rte_mbuf *comp_bufs[num_bufs];
@@ -759,6 +825,7 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
        char *contig_buf = NULL;
        uint64_t compress_checksum[num_bufs];
+       uint32_t compressed_data_size[num_bufs];
        void *stream = NULL;
        char *all_decomp_data = NULL;
        unsigned int decomp_produced_data_size = 0;
@@ -779,6 +846,7 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
        memset(ops, 0, sizeof(struct rte_comp_op *) * num_bufs);
        memset(ops_processed, 0, sizeof(struct rte_comp_op *) * num_bufs);
        memset(priv_xforms, 0, sizeof(void *) * num_bufs);
+       memset(compressed_data_size, 0, sizeof(uint32_t) * num_bufs);
 
        if (decompress_state == RTE_COMP_OP_STATEFUL) {
                data_size = strlen(test_bufs[0]) + 1;
@@ -803,7 +871,20 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                goto exit;
        }
 
-       if (buff_type == SGL_BOTH || buff_type == SGL_TO_LB) {
+       if (test_data->use_external_mbufs) {
+               inbuf_info.free_cb = extbuf_free_callback;
+               inbuf_info.fcb_opaque = NULL;
+               rte_mbuf_ext_refcnt_set(&inbuf_info, 1);
+               for (i = 0; i < num_bufs; i++) {
+                       rte_pktmbuf_attach_extbuf(uncomp_bufs[i],
+                                       test_data->inbuf_memzone->addr,
+                                       test_data->inbuf_memzone->iova,
+                                       test_data->inbuf_data_size,
+                                       &inbuf_info);
+                       rte_pktmbuf_append(uncomp_bufs[i],
+                                       test_data->inbuf_data_size);
+               }
+       } else if (buff_type == SGL_BOTH || buff_type == SGL_TO_LB) {
                for (i = 0; i < num_bufs; i++) {
                        data_size = strlen(test_bufs[i]) + 1;
                        if (prepare_sgl_bufs(test_bufs[i], uncomp_bufs[i],
@@ -818,6 +899,11 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                for (i = 0; i < num_bufs; i++) {
                        data_size = strlen(test_bufs[i]) + 1;
                        buf_ptr = rte_pktmbuf_append(uncomp_bufs[i], data_size);
+                       if (buf_ptr == NULL) {
+                               RTE_LOG(ERR, USER1,
+                                       "Append extra bytes to the source mbuf failed\n");
+                               goto exit;
+                       }
                        strlcpy(buf_ptr, test_bufs[i], data_size);
                }
        }
@@ -831,7 +917,20 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                goto exit;
        }
 
-       if (buff_type == SGL_BOTH || buff_type == LB_TO_SGL) {
+       if (test_data->use_external_mbufs) {
+               compbuf_info.free_cb = extbuf_free_callback;
+               compbuf_info.fcb_opaque = NULL;
+               rte_mbuf_ext_refcnt_set(&compbuf_info, 1);
+               for (i = 0; i < num_bufs; i++) {
+                       rte_pktmbuf_attach_extbuf(comp_bufs[i],
+                                       test_data->compbuf_memzone->addr,
+                                       test_data->compbuf_memzone->iova,
+                                       test_data->compbuf_memzone->len,
+                                       &compbuf_info);
+                       rte_pktmbuf_append(comp_bufs[i],
+                                       test_data->compbuf_memzone->len);
+               }
+       } else if (buff_type == SGL_BOTH || buff_type == LB_TO_SGL) {
                for (i = 0; i < num_bufs; i++) {
                        if (out_of_space == 1 && oos_zlib_decompress)
                                data_size = OUT_OF_SPACE_BUF;
@@ -853,11 +952,22 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                for (i = 0; i < num_bufs; i++) {
                        if (out_of_space == 1 && oos_zlib_decompress)
                                data_size = OUT_OF_SPACE_BUF;
-                       else
-                               (data_size = strlen(test_bufs[i]) *
-                                       COMPRESS_BUF_SIZE_RATIO);
-
-                       rte_pktmbuf_append(comp_bufs[i], data_size);
+                       else {
+                               float ratio =
+                               ((test_data->zlib_dir == ZLIB_DECOMPRESS ||
+                                  test_data->zlib_dir == ZLIB_NONE) &&
+                                 overflow_tst == OVERFLOW_ENABLED) ?
+                                        COMPRESS_BUF_SIZE_RATIO_OVERFLOW :
+                                        COMPRESS_BUF_SIZE_RATIO;
+
+                               data_size = strlen(test_bufs[i]) * ratio;
+                       }
+                       buf_ptr = rte_pktmbuf_append(comp_bufs[i], data_size);
+                       if (buf_ptr == NULL) {
+                               RTE_LOG(ERR, USER1,
+                                       "Append extra bytes to the destination mbuf failed\n");
+                               goto exit;
+                       }
                }
        }
 
@@ -923,7 +1033,8 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                        num_priv_xforms++;
                }
 
-               if (capa->comp_feature_flags & RTE_COMP_FF_SHAREABLE_PRIV_XFORM) {
+               if (capa->comp_feature_flags &
+                               RTE_COMP_FF_SHAREABLE_PRIV_XFORM) {
                        /* Attach shareable private xform data to ops */
                        for (i = 0; i < num_bufs; i++)
                                ops[i]->private_xform = priv_xforms[i % num_xforms];
@@ -947,40 +1058,41 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                                ops[i]->private_xform = priv_xforms[i];
                }
 
-               /* Enqueue and dequeue all operations */
-               num_enqd = rte_compressdev_enqueue_burst(0, 0, ops, num_bufs);
-               if (num_enqd < num_bufs) {
+recovery_lb:
+               ret = test_run_enqueue_dequeue(ops, num_bufs, ops_processed);
+               if (ret < 0) {
                        RTE_LOG(ERR, USER1,
-                               "The operations could not be enqueued\n");
+                               "Enqueue/dequeue operation failed\n");
                        goto exit;
                }
 
-               num_total_deqd = 0;
-               do {
-                       /*
-                        * If retrying a dequeue call, wait for 10 ms to allow
-                        * enough time to the driver to process the operations
-                        */
-                       if (deqd_retries != 0) {
-                               /*
-                                * Avoid infinite loop if not all the
-                                * operations get out of the device
-                                */
-                               if (deqd_retries == MAX_DEQD_RETRIES) {
+               for (i = 0; i < num_bufs; i++) {
+                       compressed_data_size[i] += ops_processed[i]->produced;
+
+                       if (ops_processed[i]->status ==
+                               RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE) {
+
+                               ops[i]->status =
+                                       RTE_COMP_OP_STATUS_NOT_PROCESSED;
+                               ops[i]->src.offset +=
+                                       ops_processed[i]->consumed;
+                               ops[i]->src.length -=
+                                       ops_processed[i]->consumed;
+                               ops[i]->dst.offset +=
+                                       ops_processed[i]->produced;
+
+                               buf_ptr = rte_pktmbuf_append(
+                                       ops[i]->m_dst,
+                                       ops_processed[i]->produced);
+
+                               if (buf_ptr == NULL) {
                                        RTE_LOG(ERR, USER1,
-                                               "Not all operations could be "
-                                               "dequeued\n");
+                                               "Data recovery: append extra bytes to the current mbuf failed\n");
                                        goto exit;
                                }
-                               usleep(DEQUEUE_WAIT_TIME);
+                               goto recovery_lb;
                        }
-                       num_deqd = rte_compressdev_dequeue_burst(0, 0,
-                                       &ops_processed[num_total_deqd], num_bufs);
-                       num_total_deqd += num_deqd;
-                       deqd_retries++;
-
-               } while (num_total_deqd < num_enqd);
-
+               }
                deqd_retries = 0;
 
                /* Free compress private xforms */
@@ -1024,7 +1136,7 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
        for (i = 0; i < num_bufs; i++) {
                if (out_of_space && oos_zlib_decompress) {
                        if (ops_processed[i]->status !=
-                                       RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED) {
+                               RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED) {
                                ret_status = TEST_FAILED;
                                RTE_LOG(ERR, USER1,
                                        "Operation without expected out of "
@@ -1035,6 +1147,16 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                }
 
                if (ops_processed[i]->status != RTE_COMP_OP_STATUS_SUCCESS) {
+                       if (overflow_tst == OVERFLOW_ENABLED) {
+                               if (ops_processed[i]->status ==
+                               RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED) {
+                                       ret_status = 1;
+                                       RTE_LOG(INFO, USER1,
+                                       "Out-of-space-recoverable functionality"
+                                       " is not supported on this device\n");
+                                       goto exit;
+                               }
+                       }
                        RTE_LOG(ERR, USER1,
                                "Some operations were not successful\n");
                        goto exit;
@@ -1058,7 +1180,20 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                goto exit;
        }
 
-       if (buff_type == SGL_BOTH || buff_type == LB_TO_SGL) {
+       if (test_data->use_external_mbufs) {
+               decompbuf_info.free_cb = extbuf_free_callback;
+               decompbuf_info.fcb_opaque = NULL;
+               rte_mbuf_ext_refcnt_set(&decompbuf_info, 1);
+               for (i = 0; i < num_bufs; i++) {
+                       rte_pktmbuf_attach_extbuf(uncomp_bufs[i],
+                                       test_data->uncompbuf_memzone->addr,
+                                       test_data->uncompbuf_memzone->iova,
+                                       test_data->uncompbuf_memzone->len,
+                                       &decompbuf_info);
+                       rte_pktmbuf_append(uncomp_bufs[i],
+                                       test_data->uncompbuf_memzone->len);
+               }
+       } else if (buff_type == SGL_BOTH || buff_type == LB_TO_SGL) {
                for (i = 0; i < num_bufs; i++) {
                        priv_data = (struct priv_op_data *)
                                        (ops_processed[i] + 1);
@@ -1094,7 +1229,12 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                                data_size =
                                strlen(test_bufs[priv_data->orig_idx]) + 1;
 
-                       rte_pktmbuf_append(uncomp_bufs[i], data_size);
+                       buf_ptr = rte_pktmbuf_append(uncomp_bufs[i], data_size);
+                       if (buf_ptr == NULL) {
+                               RTE_LOG(ERR, USER1,
+                                       "Append extra bytes to the decompressed mbuf failed\n");
+                               goto exit;
+                       }
                }
        }
 
@@ -1116,7 +1256,10 @@ test_deflate_comp_decomp(const struct interim_data_params *int_data,
                 * Set the length of the compressed data to the
                 * number of bytes that were produced in the previous stage
                 */
-               ops[i]->src.length = ops_processed[i]->produced;
+               if (compressed_data_size[i])
+                       ops[i]->src.length = compressed_data_size[i];
+               else
+                       ops[i]->src.length = ops_processed[i]->produced;
 
                ops[i]->dst.offset = 0;
                if (decompress_state == RTE_COMP_OP_STATELESS) {
@@ -1386,8 +1529,13 @@ next_step:
         */
        for (i = 0; i < num_bufs; i++) {
                priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
-               const char *buf1 = test_bufs[priv_data->orig_idx];
+               const char *buf1 = test_data->use_external_mbufs ?
+                               test_data->inbuf_memzone->addr :
+                               test_bufs[priv_data->orig_idx];
                const char *buf2;
+               data_size = test_data->use_external_mbufs ?
+                               test_data->inbuf_data_size :
+                               strlen(buf1) + 1;
                contig_buf = rte_malloc(NULL, ops_processed[i]->produced, 0);
                if (contig_buf == NULL) {
                        RTE_LOG(ERR, USER1, "Contiguous buffer could not "
@@ -1397,7 +1545,7 @@ next_step:
 
                buf2 = rte_pktmbuf_read(ops_processed[i]->m_dst, 0,
                                ops_processed[i]->produced, contig_buf);
-               if (compare_buffers(buf1, strlen(buf1) + 1,
+               if (compare_buffers(buf1, data_size,
                                buf2, ops_processed[i]->produced) < 0)
                        goto exit;
 
@@ -1478,14 +1626,13 @@ test_compressdev_deflate_stateless_fixed(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATELESS,
-               LB_BOTH,
-               ZLIB_DECOMPRESS,
-               0,
-               0,
-               0,
-               0
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .overflow = OVERFLOW_DISABLED
        };
 
        for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
@@ -1550,14 +1697,13 @@ test_compressdev_deflate_stateless_dynamic(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATELESS,
-               LB_BOTH,
-               ZLIB_DECOMPRESS,
-               0,
-               0,
-               0,
-               0
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .overflow = OVERFLOW_DISABLED
        };
 
        for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
@@ -1606,14 +1752,13 @@ test_compressdev_deflate_stateless_multi_op(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATELESS,
-               LB_BOTH,
-               ZLIB_DECOMPRESS,
-               0,
-               0,
-               0,
-               0
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .overflow = OVERFLOW_DISABLED
        };
 
        /* Compress with compressdev, decompress with Zlib */
@@ -1661,14 +1806,13 @@ test_compressdev_deflate_stateless_multi_level(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATELESS,
-               LB_BOTH,
-               ZLIB_DECOMPRESS,
-               0,
-               0,
-               0,
-               0
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .overflow = OVERFLOW_DISABLED
        };
 
        for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
@@ -1752,14 +1896,13 @@ test_compressdev_deflate_stateless_multi_xform(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATELESS,
-               LB_BOTH,
-               ZLIB_DECOMPRESS,
-               0,
-               0,
-               0,
-               0
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .overflow = OVERFLOW_DISABLED
        };
 
        /* Compress with compressdev, decompress with Zlib */
@@ -1802,14 +1945,13 @@ test_compressdev_deflate_stateless_sgl(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATELESS,
-               SGL_BOTH,
-               ZLIB_DECOMPRESS,
-               0,
-               0,
-               0,
-               0
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = SGL_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .overflow = OVERFLOW_DISABLED
        };
 
        for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
@@ -1914,14 +2056,13 @@ test_compressdev_deflate_stateless_checksum(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATELESS,
-               LB_BOTH,
-               ZLIB_DECOMPRESS,
-               0,
-               0,
-               0,
-               0
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .overflow = OVERFLOW_DISABLED
        };
 
        /* Check if driver supports crc32 checksum and test */
@@ -2033,14 +2174,13 @@ test_compressdev_out_of_space_buffer(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATELESS,
-               LB_BOTH,
-               ZLIB_DECOMPRESS,
-               1,  /* run out-of-space test */
-               0,
-               0,
-               0
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 1,  /* run out-of-space test */
+               .big_data = 0,
+               .overflow = OVERFLOW_DISABLED
        };
        /* Compress with compressdev, decompress with Zlib */
        test_data.zlib_dir = ZLIB_DECOMPRESS;
@@ -2112,14 +2252,13 @@ test_compressdev_deflate_stateless_dynamic_big(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATELESS,
-               SGL_BOTH,
-               ZLIB_DECOMPRESS,
-               0,
-               1,
-               0,
-               0
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = SGL_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 1,
+               .overflow = OVERFLOW_DISABLED
        };
 
        ts_params->def_comp_xform->compress.deflate.huffman =
@@ -2176,14 +2315,15 @@ test_compressdev_deflate_stateful_decomp(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATEFUL,
-               LB_BOTH,
-               ZLIB_COMPRESS,
-               0,
-               0,
-               2000,
-               4
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATEFUL,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_COMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .decompress_output_block_size = 2000,
+               .decompress_steps_max = 4,
+               .overflow = OVERFLOW_DISABLED
        };
 
        /* Compress with Zlib, decompress with compressdev */
@@ -2258,14 +2398,15 @@ test_compressdev_deflate_stateful_decomp_checksum(void)
        };
 
        struct test_data_params test_data = {
-               RTE_COMP_OP_STATELESS,
-               RTE_COMP_OP_STATEFUL,
-               LB_BOTH,
-               ZLIB_COMPRESS,
-               0,
-               0,
-               2000,
-               4
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATEFUL,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_COMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .decompress_output_block_size = 2000,
+               .decompress_steps_max = 4,
+               .overflow = OVERFLOW_DISABLED
        };
 
        /* Check if driver supports crc32 checksum and test */
@@ -2346,6 +2487,175 @@ exit:
        return ret;
 }
 
+static const struct rte_memzone *
+make_memzone(const char *name, size_t size)
+{
+       unsigned int socket_id = rte_socket_id();
+       char mz_name[RTE_MEMZONE_NAMESIZE];
+       const struct rte_memzone *memzone;
+
+       snprintf(mz_name, RTE_MEMZONE_NAMESIZE, "%s_%u", name, socket_id);
+       memzone = rte_memzone_lookup(mz_name);
+       if (memzone != NULL && memzone->len != size) {
+               rte_memzone_free(memzone);
+               memzone = NULL;
+       }
+       if (memzone == NULL) {
+               memzone = rte_memzone_reserve_aligned(mz_name, size, socket_id,
+                               RTE_MEMZONE_IOVA_CONTIG, RTE_CACHE_LINE_SIZE);
+               if (memzone == NULL)
+                       RTE_LOG(ERR, USER1, "Can't allocate memory zone %s",
+                               mz_name);
+       }
+       return memzone;
+}
+
+static int
+test_compressdev_external_mbufs(void)
+{
+       struct comp_testsuite_params *ts_params = &testsuite_params;
+       size_t data_len = 0;
+       uint16_t i;
+       int ret = TEST_FAILED;
+
+       for (i = 0; i < RTE_DIM(compress_test_bufs); i++)
+               data_len = RTE_MAX(data_len, strlen(compress_test_bufs[i]) + 1);
+
+       struct interim_data_params int_data = {
+               NULL,
+               1,
+               NULL,
+               &ts_params->def_comp_xform,
+               &ts_params->def_decomp_xform,
+               1
+       };
+
+       struct test_data_params test_data = {
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .use_external_mbufs = 1,
+               .inbuf_data_size = data_len,
+               .inbuf_memzone = make_memzone("inbuf", data_len),
+               .compbuf_memzone = make_memzone("compbuf", data_len *
+                                               COMPRESS_BUF_SIZE_RATIO),
+               .uncompbuf_memzone = make_memzone("decompbuf", data_len),
+               .overflow = OVERFLOW_DISABLED
+       };
+
+       for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+               /* prepare input data */
+               data_len = strlen(compress_test_bufs[i]) + 1;
+               rte_memcpy(test_data.inbuf_memzone->addr, compress_test_bufs[i],
+                          data_len);
+               test_data.inbuf_data_size = data_len;
+               int_data.buf_idx = &i;
+
+               /* Compress with compressdev, decompress with Zlib */
+               test_data.zlib_dir = ZLIB_DECOMPRESS;
+               if (test_deflate_comp_decomp(&int_data, &test_data) < 0)
+                       goto exit;
+
+               /* Compress with Zlib, decompress with compressdev */
+               test_data.zlib_dir = ZLIB_COMPRESS;
+               if (test_deflate_comp_decomp(&int_data, &test_data) < 0)
+                       goto exit;
+       }
+
+       ret = TEST_SUCCESS;
+
+exit:
+       rte_memzone_free(test_data.inbuf_memzone);
+       rte_memzone_free(test_data.compbuf_memzone);
+       rte_memzone_free(test_data.uncompbuf_memzone);
+       return ret;
+}
+
+static int
+test_compressdev_deflate_stateless_fixed_oos_recoverable(void)
+{
+       struct comp_testsuite_params *ts_params = &testsuite_params;
+       uint16_t i;
+       int ret;
+       int comp_result;
+       const struct rte_compressdev_capabilities *capab;
+
+       capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+       TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+       if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_FIXED) == 0)
+               return -ENOTSUP;
+
+       struct rte_comp_xform *compress_xform =
+                       rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+
+       if (compress_xform == NULL) {
+               RTE_LOG(ERR, USER1,
+                       "Compress xform could not be created\n");
+               ret = TEST_FAILED;
+               goto exit;
+       }
+
+       memcpy(compress_xform, ts_params->def_comp_xform,
+                       sizeof(struct rte_comp_xform));
+       compress_xform->compress.deflate.huffman = RTE_COMP_HUFFMAN_FIXED;
+
+       struct interim_data_params int_data = {
+               NULL,
+               1,
+               NULL,
+               &compress_xform,
+               &ts_params->def_decomp_xform,
+               1
+       };
+
+       struct test_data_params test_data = {
+               .compress_state = RTE_COMP_OP_STATELESS,
+               .decompress_state = RTE_COMP_OP_STATELESS,
+               .buff_type = LB_BOTH,
+               .zlib_dir = ZLIB_DECOMPRESS,
+               .out_of_space = 0,
+               .big_data = 0,
+               .overflow = OVERFLOW_ENABLED
+       };
+
+       for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+               int_data.test_bufs = &compress_test_bufs[i];
+               int_data.buf_idx = &i;
+
+               /* Compress with compressdev, decompress with Zlib */
+               test_data.zlib_dir = ZLIB_DECOMPRESS;
+               comp_result = test_deflate_comp_decomp(&int_data, &test_data);
+               if (comp_result < 0) {
+                       ret = TEST_FAILED;
+                       goto exit;
+               } else if (comp_result > 0) {
+                       ret = -ENOTSUP;
+                       goto exit;
+               }
+
+               /* Compress with Zlib, decompress with compressdev */
+               test_data.zlib_dir = ZLIB_COMPRESS;
+               comp_result = test_deflate_comp_decomp(&int_data, &test_data);
+               if (comp_result < 0) {
+                       ret = TEST_FAILED;
+                       goto exit;
+               } else if (comp_result > 0) {
+                       ret = -ENOTSUP;
+                       goto exit;
+               }
+       }
+
+       ret = TEST_SUCCESS;
+
+exit:
+       rte_free(compress_xform);
+       return ret;
+}
+
 static struct unit_test_suite compressdev_testsuite  = {
        .suite_name = "compressdev unit test suite",
        .setup = testsuite_setup,
@@ -2375,6 +2685,10 @@ static struct unit_test_suite compressdev_testsuite  = {
                        test_compressdev_deflate_stateful_decomp),
                TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
                        test_compressdev_deflate_stateful_decomp_checksum),
+               TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+                       test_compressdev_external_mbufs),
+               TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+               test_compressdev_deflate_stateless_fixed_oos_recoverable),
                TEST_CASES_END() /**< NULL terminate unit test array */
        }
 };