1aa7d8aeeeb0cfb6d8f1cd9ffc2a8ebe6c178ecc
[dpdk.git] / test / test / test_compressdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4 #include <string.h>
5 #include <zlib.h>
6 #include <math.h>
7
8 #include <rte_cycles.h>
9 #include <rte_malloc.h>
10 #include <rte_mempool.h>
11 #include <rte_mbuf.h>
12 #include <rte_compressdev.h>
13
14 #include "test_compressdev_test_buffer.h"
15 #include "test.h"
16
17 #define DEFAULT_WINDOW_SIZE 15
18 #define DEFAULT_MEM_LEVEL 8
19 #define MAX_DEQD_RETRIES 10
20 #define DEQUEUE_WAIT_TIME 10000
21
22 /*
23  * 30% extra size for compressed data compared to original data,
24  * in case data size cannot be reduced and it is actually bigger
25  * due to the compress block headers
26  */
27 #define COMPRESS_BUF_SIZE_RATIO 1.3
28 #define NUM_MBUFS 16
29 #define NUM_OPS 16
30 #define NUM_MAX_XFORMS 1
31 #define NUM_MAX_INFLIGHT_OPS 128
32 #define CACHE_SIZE 0
33
34 const char *
35 huffman_type_strings[] = {
36         [RTE_COMP_HUFFMAN_DEFAULT]      = "PMD default",
37         [RTE_COMP_HUFFMAN_FIXED]        = "Fixed",
38         [RTE_COMP_HUFFMAN_DYNAMIC]      = "Dynamic"
39 };
40
41 enum zlib_direction {
42         ZLIB_NONE,
43         ZLIB_COMPRESS,
44         ZLIB_DECOMPRESS,
45         ZLIB_ALL
46 };
47
48 struct priv_op_data {
49         uint16_t orig_idx;
50 };
51
52 struct comp_testsuite_params {
53         struct rte_mempool *mbuf_pool;
54         struct rte_mempool *op_pool;
55         struct rte_comp_xform def_comp_xform;
56         struct rte_comp_xform def_decomp_xform;
57 };
58
59 static struct comp_testsuite_params testsuite_params = { 0 };
60
61 static void
62 testsuite_teardown(void)
63 {
64         struct comp_testsuite_params *ts_params = &testsuite_params;
65
66         rte_mempool_free(ts_params->mbuf_pool);
67         rte_mempool_free(ts_params->op_pool);
68 }
69
70 static int
71 testsuite_setup(void)
72 {
73         struct comp_testsuite_params *ts_params = &testsuite_params;
74         unsigned int i;
75
76         if (rte_compressdev_count() == 0) {
77                 RTE_LOG(ERR, USER1, "Need at least one compress device\n");
78                 return TEST_FAILED;
79         }
80
81         uint32_t max_buf_size = 0;
82         for (i = 0; i < RTE_DIM(compress_test_bufs); i++)
83                 max_buf_size = RTE_MAX(max_buf_size,
84                                 strlen(compress_test_bufs[i]) + 1);
85
86         max_buf_size *= COMPRESS_BUF_SIZE_RATIO;
87         /*
88          * Buffers to be used in compression and decompression.
89          * Since decompressed data might be larger than
90          * compressed data (due to block header),
91          * buffers should be big enough for both cases.
92          */
93         ts_params->mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool",
94                         NUM_MBUFS,
95                         CACHE_SIZE, 0,
96                         max_buf_size + RTE_PKTMBUF_HEADROOM,
97                         rte_socket_id());
98         if (ts_params->mbuf_pool == NULL) {
99                 RTE_LOG(ERR, USER1, "Large mbuf pool could not be created\n");
100                 return TEST_FAILED;
101         }
102
103         ts_params->op_pool = rte_comp_op_pool_create("op_pool", NUM_OPS,
104                                 0, sizeof(struct priv_op_data),
105                                 rte_socket_id());
106         if (ts_params->op_pool == NULL) {
107                 RTE_LOG(ERR, USER1, "Operation pool could not be created\n");
108                 goto exit;
109         }
110
111         /* Initializes default values for compress/decompress xforms */
112         ts_params->def_comp_xform.type = RTE_COMP_COMPRESS;
113         ts_params->def_comp_xform.compress.algo = RTE_COMP_ALGO_DEFLATE,
114         ts_params->def_comp_xform.compress.deflate.huffman =
115                                                 RTE_COMP_HUFFMAN_DEFAULT;
116         ts_params->def_comp_xform.compress.level = RTE_COMP_LEVEL_PMD_DEFAULT;
117         ts_params->def_comp_xform.compress.chksum = RTE_COMP_CHECKSUM_NONE;
118         ts_params->def_comp_xform.compress.window_size = DEFAULT_WINDOW_SIZE;
119
120         ts_params->def_decomp_xform.type = RTE_COMP_DECOMPRESS;
121         ts_params->def_decomp_xform.decompress.algo = RTE_COMP_ALGO_DEFLATE,
122         ts_params->def_decomp_xform.decompress.chksum = RTE_COMP_CHECKSUM_NONE;
123         ts_params->def_decomp_xform.decompress.window_size = DEFAULT_WINDOW_SIZE;
124
125         return TEST_SUCCESS;
126
127 exit:
128         testsuite_teardown();
129
130         return TEST_FAILED;
131 }
132
133 static int
134 generic_ut_setup(void)
135 {
136         /* Configure compressdev (one device, one queue pair) */
137         struct rte_compressdev_config config = {
138                 .socket_id = rte_socket_id(),
139                 .nb_queue_pairs = 1,
140                 .max_nb_priv_xforms = NUM_MAX_XFORMS,
141                 .max_nb_streams = 0
142         };
143
144         if (rte_compressdev_configure(0, &config) < 0) {
145                 RTE_LOG(ERR, USER1, "Device configuration failed\n");
146                 return -1;
147         }
148
149         if (rte_compressdev_queue_pair_setup(0, 0, NUM_MAX_INFLIGHT_OPS,
150                         rte_socket_id()) < 0) {
151                 RTE_LOG(ERR, USER1, "Queue pair setup failed\n");
152                 return -1;
153         }
154
155         if (rte_compressdev_start(0) < 0) {
156                 RTE_LOG(ERR, USER1, "Device could not be started\n");
157                 return -1;
158         }
159
160         return 0;
161 }
162
163 static void
164 generic_ut_teardown(void)
165 {
166         rte_compressdev_stop(0);
167         if (rte_compressdev_close(0) < 0)
168                 RTE_LOG(ERR, USER1, "Device could not be closed\n");
169 }
170
171 static int
172 compare_buffers(const char *buffer1, uint32_t buffer1_len,
173                 const char *buffer2, uint32_t buffer2_len)
174 {
175         if (buffer1_len != buffer2_len) {
176                 RTE_LOG(ERR, USER1, "Buffer lengths are different\n");
177                 return -1;
178         }
179
180         if (memcmp(buffer1, buffer2, buffer1_len) != 0) {
181                 RTE_LOG(ERR, USER1, "Buffers are different\n");
182                 return -1;
183         }
184
185         return 0;
186 }
187
188 /*
189  * Maps compressdev and Zlib flush flags
190  */
191 static int
192 map_zlib_flush_flag(enum rte_comp_flush_flag flag)
193 {
194         switch (flag) {
195         case RTE_COMP_FLUSH_NONE:
196                 return Z_NO_FLUSH;
197         case RTE_COMP_FLUSH_SYNC:
198                 return Z_SYNC_FLUSH;
199         case RTE_COMP_FLUSH_FULL:
200                 return Z_FULL_FLUSH;
201         case RTE_COMP_FLUSH_FINAL:
202                 return Z_FINISH;
203         /*
204          * There should be only the values above,
205          * so this should never happen
206          */
207         default:
208                 return -1;
209         }
210 }
211
212 static int
213 compress_zlib(struct rte_comp_op *op,
214                 const struct rte_comp_xform *xform, int mem_level)
215 {
216         z_stream stream;
217         int zlib_flush;
218         int strategy, window_bits, comp_level;
219         int ret = -1;
220
221         /* initialize zlib stream */
222         stream.zalloc = Z_NULL;
223         stream.zfree = Z_NULL;
224         stream.opaque = Z_NULL;
225
226         if (xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_FIXED)
227                 strategy = Z_FIXED;
228         else
229                 strategy = Z_DEFAULT_STRATEGY;
230
231         /*
232          * Window bits is the base two logarithm of the window size (in bytes).
233          * When doing raw DEFLATE, this number will be negative.
234          */
235         window_bits = -(xform->compress.window_size);
236
237         comp_level = xform->compress.level;
238
239         if (comp_level != RTE_COMP_LEVEL_NONE)
240                 ret = deflateInit2(&stream, comp_level, Z_DEFLATED,
241                         window_bits, mem_level, strategy);
242         else
243                 ret = deflateInit(&stream, Z_NO_COMPRESSION);
244
245         if (ret != Z_OK) {
246                 printf("Zlib deflate could not be initialized\n");
247                 goto exit;
248         }
249
250         /* Assuming stateless operation */
251         stream.avail_in = op->src.length;
252         stream.next_in = rte_pktmbuf_mtod(op->m_src, uint8_t *);
253         stream.avail_out = op->m_dst->data_len;
254         stream.next_out = rte_pktmbuf_mtod(op->m_dst, uint8_t *);
255
256         /* Stateless operation, all buffer will be compressed in one go */
257         zlib_flush = map_zlib_flush_flag(op->flush_flag);
258         ret = deflate(&stream, zlib_flush);
259
260         if (stream.avail_in != 0) {
261                 RTE_LOG(ERR, USER1, "Buffer could not be read entirely\n");
262                 goto exit;
263         }
264
265         if (ret != Z_STREAM_END)
266                 goto exit;
267
268         op->consumed = op->src.length - stream.avail_in;
269         op->produced = op->m_dst->data_len - stream.avail_out;
270         op->status = RTE_COMP_OP_STATUS_SUCCESS;
271
272         deflateReset(&stream);
273
274         ret = 0;
275 exit:
276         deflateEnd(&stream);
277
278         return ret;
279 }
280
281 static int
282 decompress_zlib(struct rte_comp_op *op,
283                 const struct rte_comp_xform *xform)
284 {
285         z_stream stream;
286         int window_bits;
287         int zlib_flush;
288         int ret = TEST_FAILED;
289
290         /* initialize zlib stream */
291         stream.zalloc = Z_NULL;
292         stream.zfree = Z_NULL;
293         stream.opaque = Z_NULL;
294
295         /*
296          * Window bits is the base two logarithm of the window size (in bytes).
297          * When doing raw DEFLATE, this number will be negative.
298          */
299         window_bits = -(xform->decompress.window_size);
300
301         ret = inflateInit2(&stream, window_bits);
302
303         if (ret != Z_OK) {
304                 printf("Zlib deflate could not be initialized\n");
305                 goto exit;
306         }
307
308         /* Assuming stateless operation */
309         stream.avail_in = op->src.length;
310         stream.next_in = rte_pktmbuf_mtod(op->m_src, uint8_t *);
311         stream.avail_out = op->m_dst->data_len;
312         stream.next_out = rte_pktmbuf_mtod(op->m_dst, uint8_t *);
313
314         /* Stateless operation, all buffer will be compressed in one go */
315         zlib_flush = map_zlib_flush_flag(op->flush_flag);
316         ret = inflate(&stream, zlib_flush);
317
318         if (stream.avail_in != 0) {
319                 RTE_LOG(ERR, USER1, "Buffer could not be read entirely\n");
320                 goto exit;
321         }
322
323         if (ret != Z_STREAM_END)
324                 goto exit;
325
326         op->consumed = op->src.length - stream.avail_in;
327         op->produced = op->m_dst->data_len - stream.avail_out;
328         op->status = RTE_COMP_OP_STATUS_SUCCESS;
329
330         inflateReset(&stream);
331
332         ret = 0;
333 exit:
334         inflateEnd(&stream);
335
336         return ret;
337 }
338
339 /*
340  * Compresses and decompresses buffer with compressdev API and Zlib API
341  */
342 static int
343 test_deflate_comp_decomp(const char * const test_bufs[],
344                 unsigned int num_bufs,
345                 uint16_t buf_idx[],
346                 struct rte_comp_xform *compress_xform,
347                 struct rte_comp_xform *decompress_xform,
348                 enum rte_comp_op_type state,
349                 enum zlib_direction zlib_dir)
350 {
351         struct comp_testsuite_params *ts_params = &testsuite_params;
352         int ret_status = -1;
353         int ret;
354         struct rte_mbuf *uncomp_bufs[num_bufs];
355         struct rte_mbuf *comp_bufs[num_bufs];
356         struct rte_comp_op *ops[num_bufs];
357         struct rte_comp_op *ops_processed[num_bufs];
358         void *priv_xforms[num_bufs];
359         uint16_t num_enqd, num_deqd, num_total_deqd;
360         uint16_t num_priv_xforms = 0;
361         unsigned int deqd_retries = 0;
362         struct priv_op_data *priv_data;
363         char *data_ptr;
364         unsigned int i;
365         const struct rte_compressdev_capabilities *capa =
366                 rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
367
368         /* Initialize all arrays to NULL */
369         memset(uncomp_bufs, 0, sizeof(struct rte_mbuf *) * num_bufs);
370         memset(comp_bufs, 0, sizeof(struct rte_mbuf *) * num_bufs);
371         memset(ops, 0, sizeof(struct rte_comp_op *) * num_bufs);
372         memset(ops_processed, 0, sizeof(struct rte_comp_op *) * num_bufs);
373         memset(priv_xforms, 0, sizeof(void *) * num_bufs);
374
375         /* Prepare the source mbufs with the data */
376         ret = rte_pktmbuf_alloc_bulk(ts_params->mbuf_pool, uncomp_bufs, num_bufs);
377         if (ret < 0) {
378                 RTE_LOG(ERR, USER1,
379                         "Source mbufs could not be allocated "
380                         "from the mempool\n");
381                 goto exit;
382         }
383
384         for (i = 0; i < num_bufs; i++) {
385                 data_ptr = rte_pktmbuf_append(uncomp_bufs[i],
386                                         strlen(test_bufs[i]) + 1);
387                 snprintf(data_ptr, strlen(test_bufs[i]) + 1, "%s",
388                                         test_bufs[i]);
389         }
390
391         /* Prepare the destination mbufs */
392         ret = rte_pktmbuf_alloc_bulk(ts_params->mbuf_pool, comp_bufs, num_bufs);
393         if (ret < 0) {
394                 RTE_LOG(ERR, USER1,
395                         "Destination mbufs could not be allocated "
396                         "from the mempool\n");
397                 goto exit;
398         }
399
400         for (i = 0; i < num_bufs; i++)
401                 rte_pktmbuf_append(comp_bufs[i],
402                         strlen(test_bufs[i]) * COMPRESS_BUF_SIZE_RATIO);
403
404         /* Build the compression operations */
405         ret = rte_comp_op_bulk_alloc(ts_params->op_pool, ops, num_bufs);
406         if (ret < 0) {
407                 RTE_LOG(ERR, USER1,
408                         "Compress operations could not be allocated "
409                         "from the mempool\n");
410                 goto exit;
411         }
412
413         for (i = 0; i < num_bufs; i++) {
414                 ops[i]->m_src = uncomp_bufs[i];
415                 ops[i]->m_dst = comp_bufs[i];
416                 ops[i]->src.offset = 0;
417                 ops[i]->src.length = rte_pktmbuf_pkt_len(uncomp_bufs[i]);
418                 ops[i]->dst.offset = 0;
419                 if (state == RTE_COMP_OP_STATELESS) {
420                         ops[i]->flush_flag = RTE_COMP_FLUSH_FINAL;
421                 } else {
422                         RTE_LOG(ERR, USER1,
423                                 "Stateful operations are not supported "
424                                 "in these tests yet\n");
425                         goto exit;
426                 }
427                 ops[i]->input_chksum = 0;
428                 /*
429                  * Store original operation index in private data,
430                  * since ordering does not have to be maintained,
431                  * when dequeueing from compressdev, so a comparison
432                  * at the end of the test can be done.
433                  */
434                 priv_data = (struct priv_op_data *) (ops[i] + 1);
435                 priv_data->orig_idx = i;
436         }
437
438         /* Compress data (either with Zlib API or compressdev API */
439         if (zlib_dir == ZLIB_COMPRESS || zlib_dir == ZLIB_ALL) {
440                 for (i = 0; i < num_bufs; i++) {
441                         ret = compress_zlib(ops[i],
442                                 (const struct rte_comp_xform *)compress_xform,
443                                         DEFAULT_MEM_LEVEL);
444                         if (ret < 0)
445                                 goto exit;
446
447                         ops_processed[i] = ops[i];
448                 }
449         } else {
450                 if (capa->comp_feature_flags & RTE_COMP_FF_SHAREABLE_PRIV_XFORM) {
451                         /* Create single compress private xform data */
452                         ret = rte_compressdev_private_xform_create(0,
453                                 (const struct rte_comp_xform *)compress_xform,
454                                 &priv_xforms[0]);
455                         if (ret < 0) {
456                                 RTE_LOG(ERR, USER1,
457                                         "Compression private xform "
458                                         "could not be created\n");
459                                 goto exit;
460                         }
461                         num_priv_xforms++;
462                         /* Attach shareable private xform data to ops */
463                         for (i = 0; i < num_bufs; i++)
464                                 ops[i]->private_xform = priv_xforms[0];
465                 } else {
466                         /* Create compress private xform data per op */
467                         for (i = 0; i < num_bufs; i++) {
468                                 ret = rte_compressdev_private_xform_create(0,
469                                         compress_xform, &priv_xforms[i]);
470                                 if (ret < 0) {
471                                         RTE_LOG(ERR, USER1,
472                                                 "Compression private xform "
473                                                 "could not be created\n");
474                                         goto exit;
475                                 }
476                                 num_priv_xforms++;
477                         }
478
479                         /* Attach non shareable private xform data to ops */
480                         for (i = 0; i < num_bufs; i++)
481                                 ops[i]->private_xform = priv_xforms[i];
482                 }
483
484                 /* Enqueue and dequeue all operations */
485                 num_enqd = rte_compressdev_enqueue_burst(0, 0, ops, num_bufs);
486                 if (num_enqd < num_bufs) {
487                         RTE_LOG(ERR, USER1,
488                                 "The operations could not be enqueued\n");
489                         goto exit;
490                 }
491
492                 num_total_deqd = 0;
493                 do {
494                         /*
495                          * If retrying a dequeue call, wait for 10 ms to allow
496                          * enough time to the driver to process the operations
497                          */
498                         if (deqd_retries != 0) {
499                                 /*
500                                  * Avoid infinite loop if not all the
501                                  * operations get out of the device
502                                  */
503                                 if (deqd_retries == MAX_DEQD_RETRIES) {
504                                         RTE_LOG(ERR, USER1,
505                                                 "Not all operations could be "
506                                                 "dequeued\n");
507                                         goto exit;
508                                 }
509                                 usleep(DEQUEUE_WAIT_TIME);
510                         }
511                         num_deqd = rte_compressdev_dequeue_burst(0, 0,
512                                         &ops_processed[num_total_deqd], num_bufs);
513                         num_total_deqd += num_deqd;
514                         deqd_retries++;
515                 } while (num_total_deqd < num_enqd);
516
517                 deqd_retries = 0;
518
519                 /* Free compress private xforms */
520                 for (i = 0; i < num_priv_xforms; i++) {
521                         rte_compressdev_private_xform_free(0, priv_xforms[i]);
522                         priv_xforms[i] = NULL;
523                 }
524                 num_priv_xforms = 0;
525         }
526
527         enum rte_comp_huffman huffman_type =
528                 compress_xform->compress.deflate.huffman;
529         for (i = 0; i < num_bufs; i++) {
530                 priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
531                 RTE_LOG(DEBUG, USER1, "Buffer %u compressed from %u to %u bytes "
532                         "(level = %u, huffman = %s)\n",
533                         buf_idx[priv_data->orig_idx],
534                         ops_processed[i]->consumed, ops_processed[i]->produced,
535                         compress_xform->compress.level,
536                         huffman_type_strings[huffman_type]);
537                 RTE_LOG(DEBUG, USER1, "Compression ratio = %.2f",
538                         (float)ops_processed[i]->produced /
539                         ops_processed[i]->consumed * 100);
540                 ops[i] = NULL;
541         }
542
543         /*
544          * Check operation status and free source mbufs (destination mbuf and
545          * compress operation information is needed for the decompression stage)
546          */
547         for (i = 0; i < num_bufs; i++) {
548                 if (ops_processed[i]->status != RTE_COMP_OP_STATUS_SUCCESS) {
549                         RTE_LOG(ERR, USER1,
550                                 "Some operations were not successful\n");
551                         goto exit;
552                 }
553                 priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
554                 rte_pktmbuf_free(uncomp_bufs[priv_data->orig_idx]);
555                 uncomp_bufs[priv_data->orig_idx] = NULL;
556         }
557
558         /* Allocate buffers for decompressed data */
559         ret = rte_pktmbuf_alloc_bulk(ts_params->mbuf_pool, uncomp_bufs, num_bufs);
560         if (ret < 0) {
561                 RTE_LOG(ERR, USER1,
562                         "Destination mbufs could not be allocated "
563                         "from the mempool\n");
564                 goto exit;
565         }
566
567         for (i = 0; i < num_bufs; i++) {
568                 priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
569                 rte_pktmbuf_append(uncomp_bufs[i],
570                                 strlen(test_bufs[priv_data->orig_idx]) + 1);
571         }
572
573         /* Build the decompression operations */
574         ret = rte_comp_op_bulk_alloc(ts_params->op_pool, ops, num_bufs);
575         if (ret < 0) {
576                 RTE_LOG(ERR, USER1,
577                         "Decompress operations could not be allocated "
578                         "from the mempool\n");
579                 goto exit;
580         }
581
582         /* Source buffer is the compressed data from the previous operations */
583         for (i = 0; i < num_bufs; i++) {
584                 ops[i]->m_src = ops_processed[i]->m_dst;
585                 ops[i]->m_dst = uncomp_bufs[i];
586                 ops[i]->src.offset = 0;
587                 /*
588                  * Set the length of the compressed data to the
589                  * number of bytes that were produced in the previous stage
590                  */
591                 ops[i]->src.length = ops_processed[i]->produced;
592                 ops[i]->dst.offset = 0;
593                 if (state == RTE_COMP_OP_STATELESS) {
594                         ops[i]->flush_flag = RTE_COMP_FLUSH_FINAL;
595                 } else {
596                         RTE_LOG(ERR, USER1,
597                                 "Stateful operations are not supported "
598                                 "in these tests yet\n");
599                         goto exit;
600                 }
601                 ops[i]->input_chksum = 0;
602                 /*
603                  * Copy private data from previous operations,
604                  * to keep the pointer to the original buffer
605                  */
606                 memcpy(ops[i] + 1, ops_processed[i] + 1,
607                                 sizeof(struct priv_op_data));
608         }
609
610         /*
611          * Free the previous compress operations,
612          * as it is not needed anymore
613          */
614         for (i = 0; i < num_bufs; i++) {
615                 rte_comp_op_free(ops_processed[i]);
616                 ops_processed[i] = NULL;
617         }
618
619         /* Decompress data (either with Zlib API or compressdev API */
620         if (zlib_dir == ZLIB_DECOMPRESS || zlib_dir == ZLIB_ALL) {
621                 for (i = 0; i < num_bufs; i++) {
622                         ret = decompress_zlib(ops[i],
623                                 (const struct rte_comp_xform *)decompress_xform);
624                         if (ret < 0)
625                                 goto exit;
626
627                         ops_processed[i] = ops[i];
628                 }
629         } else {
630                 if (capa->comp_feature_flags & RTE_COMP_FF_SHAREABLE_PRIV_XFORM) {
631                         /* Create single decompress private xform data */
632                         ret = rte_compressdev_private_xform_create(0,
633                                 (const struct rte_comp_xform *)decompress_xform,
634                                 &priv_xforms[0]);
635                         if (ret < 0) {
636                                 RTE_LOG(ERR, USER1,
637                                         "Decompression private xform "
638                                         "could not be created\n");
639                                 goto exit;
640                         }
641                         num_priv_xforms++;
642                         /* Attach shareable private xform data to ops */
643                         for (i = 0; i < num_bufs; i++)
644                                 ops[i]->private_xform = priv_xforms[0];
645                 } else {
646                         /* Create decompress private xform data per op */
647                         for (i = 0; i < num_bufs; i++) {
648                                 ret = rte_compressdev_private_xform_create(0,
649                                         decompress_xform, &priv_xforms[i]);
650                                 if (ret < 0) {
651                                         RTE_LOG(ERR, USER1,
652                                                 "Deompression private xform "
653                                                 "could not be created\n");
654                                         goto exit;
655                                 }
656                                 num_priv_xforms++;
657                         }
658
659                         /* Attach non shareable private xform data to ops */
660                         for (i = 0; i < num_bufs; i++)
661                                 ops[i]->private_xform = priv_xforms[i];
662                 }
663
664                 /* Enqueue and dequeue all operations */
665                 num_enqd = rte_compressdev_enqueue_burst(0, 0, ops, num_bufs);
666                 if (num_enqd < num_bufs) {
667                         RTE_LOG(ERR, USER1,
668                                 "The operations could not be enqueued\n");
669                         goto exit;
670                 }
671
672                 num_total_deqd = 0;
673                 do {
674                         /*
675                          * If retrying a dequeue call, wait for 10 ms to allow
676                          * enough time to the driver to process the operations
677                          */
678                         if (deqd_retries != 0) {
679                                 /*
680                                  * Avoid infinite loop if not all the
681                                  * operations get out of the device
682                                  */
683                                 if (deqd_retries == MAX_DEQD_RETRIES) {
684                                         RTE_LOG(ERR, USER1,
685                                                 "Not all operations could be "
686                                                 "dequeued\n");
687                                         goto exit;
688                                 }
689                                 usleep(DEQUEUE_WAIT_TIME);
690                         }
691                         num_deqd = rte_compressdev_dequeue_burst(0, 0,
692                                         &ops_processed[num_total_deqd], num_bufs);
693                         num_total_deqd += num_deqd;
694                         deqd_retries++;
695                 } while (num_total_deqd < num_enqd);
696
697                 deqd_retries = 0;
698         }
699
700         for (i = 0; i < num_bufs; i++) {
701                 priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
702                 RTE_LOG(DEBUG, USER1, "Buffer %u decompressed from %u to %u bytes\n",
703                         buf_idx[priv_data->orig_idx],
704                         ops_processed[i]->consumed, ops_processed[i]->produced);
705                 ops[i] = NULL;
706         }
707
708         /*
709          * Check operation status and free source mbuf (destination mbuf and
710          * compress operation information is still needed)
711          */
712         for (i = 0; i < num_bufs; i++) {
713                 if (ops_processed[i]->status != RTE_COMP_OP_STATUS_SUCCESS) {
714                         RTE_LOG(ERR, USER1,
715                                 "Some operations were not successful\n");
716                         goto exit;
717                 }
718                 priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
719                 rte_pktmbuf_free(comp_bufs[priv_data->orig_idx]);
720                 comp_bufs[priv_data->orig_idx] = NULL;
721         }
722
723         /*
724          * Compare the original stream with the decompressed stream
725          * (in size and the data)
726          */
727         for (i = 0; i < num_bufs; i++) {
728                 priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
729                 const char *buf1 = test_bufs[priv_data->orig_idx];
730                 const char *buf2 = rte_pktmbuf_mtod(ops_processed[i]->m_dst,
731                                 const char *);
732
733                 if (compare_buffers(buf1, strlen(buf1) + 1,
734                                 buf2, ops_processed[i]->produced) < 0)
735                         goto exit;
736         }
737
738         ret_status = 0;
739
740 exit:
741         /* Free resources */
742         for (i = 0; i < num_bufs; i++) {
743                 rte_pktmbuf_free(uncomp_bufs[i]);
744                 rte_pktmbuf_free(comp_bufs[i]);
745                 rte_comp_op_free(ops[i]);
746                 rte_comp_op_free(ops_processed[i]);
747         }
748         for (i = 0; i < num_priv_xforms; i++) {
749                 if (priv_xforms[i] != NULL)
750                         rte_compressdev_private_xform_free(0, priv_xforms[i]);
751         }
752
753         return ret_status;
754 }
755
756 static int
757 test_compressdev_deflate_stateless_fixed(void)
758 {
759         struct comp_testsuite_params *ts_params = &testsuite_params;
760         const char *test_buffer;
761         uint16_t i;
762         struct rte_comp_xform compress_xform;
763
764         memcpy(&compress_xform, &ts_params->def_comp_xform,
765                         sizeof(struct rte_comp_xform));
766         compress_xform.compress.deflate.huffman = RTE_COMP_HUFFMAN_FIXED;
767
768         for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
769                 test_buffer = compress_test_bufs[i];
770
771                 /* Compress with compressdev, decompress with Zlib */
772                 if (test_deflate_comp_decomp(&test_buffer, 1,
773                                 &i,
774                                 &compress_xform,
775                                 &ts_params->def_decomp_xform,
776                                 RTE_COMP_OP_STATELESS,
777                                 ZLIB_DECOMPRESS) < 0)
778                         return TEST_FAILED;
779
780                 /* Compress with Zlib, decompress with compressdev */
781                 if (test_deflate_comp_decomp(&test_buffer, 1,
782                                 &i,
783                                 &compress_xform,
784                                 &ts_params->def_decomp_xform,
785                                 RTE_COMP_OP_STATELESS,
786                                 ZLIB_COMPRESS) < 0)
787                         return TEST_FAILED;
788         }
789
790         return TEST_SUCCESS;
791 }
792
793 static int
794 test_compressdev_deflate_stateless_dynamic(void)
795 {
796         struct comp_testsuite_params *ts_params = &testsuite_params;
797         const char *test_buffer;
798         uint16_t i;
799         struct rte_comp_xform compress_xform;
800
801         memcpy(&compress_xform, &ts_params->def_comp_xform,
802                         sizeof(struct rte_comp_xform));
803         compress_xform.compress.deflate.huffman = RTE_COMP_HUFFMAN_DYNAMIC;
804
805         for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
806                 test_buffer = compress_test_bufs[i];
807
808                 /* Compress with compressdev, decompress with Zlib */
809                 if (test_deflate_comp_decomp(&test_buffer, 1,
810                                 &i,
811                                 &compress_xform,
812                                 &ts_params->def_decomp_xform,
813                                 RTE_COMP_OP_STATELESS,
814                                 ZLIB_DECOMPRESS) < 0)
815                         return TEST_FAILED;
816
817                 /* Compress with Zlib, decompress with compressdev */
818                 if (test_deflate_comp_decomp(&test_buffer, 1,
819                                 &i,
820                                 &compress_xform,
821                                 &ts_params->def_decomp_xform,
822                                 RTE_COMP_OP_STATELESS,
823                                 ZLIB_COMPRESS) < 0)
824                         return TEST_FAILED;
825         }
826
827         return TEST_SUCCESS;
828 }
829
830 static int
831 test_compressdev_deflate_stateless_multi_op(void)
832 {
833         struct comp_testsuite_params *ts_params = &testsuite_params;
834         uint16_t num_bufs = RTE_DIM(compress_test_bufs);
835         uint16_t buf_idx[num_bufs];
836         uint16_t i;
837
838         for (i = 0; i < num_bufs; i++)
839                 buf_idx[i] = i;
840
841         /* Compress with compressdev, decompress with Zlib */
842         if (test_deflate_comp_decomp(compress_test_bufs, num_bufs,
843                         buf_idx,
844                         &ts_params->def_comp_xform,
845                         &ts_params->def_decomp_xform,
846                         RTE_COMP_OP_STATELESS,
847                         ZLIB_DECOMPRESS) < 0)
848                 return TEST_FAILED;
849
850         /* Compress with Zlib, decompress with compressdev */
851         if (test_deflate_comp_decomp(compress_test_bufs, num_bufs,
852                         buf_idx,
853                         &ts_params->def_comp_xform,
854                         &ts_params->def_decomp_xform,
855                         RTE_COMP_OP_STATELESS,
856                         ZLIB_COMPRESS) < 0)
857                 return TEST_FAILED;
858
859         return TEST_SUCCESS;
860 }
861
862
863 static int
864 test_compressdev_deflate_stateless_multi_level(void)
865 {
866         struct comp_testsuite_params *ts_params = &testsuite_params;
867         const char *test_buffer;
868         unsigned int level;
869         uint16_t i;
870         struct rte_comp_xform compress_xform;
871
872         memcpy(&compress_xform, &ts_params->def_comp_xform,
873                         sizeof(struct rte_comp_xform));
874
875         for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
876                 test_buffer = compress_test_bufs[i];
877                 for (level = RTE_COMP_LEVEL_MIN; level <= RTE_COMP_LEVEL_MAX;
878                                 level++) {
879                         compress_xform.compress.level = level;
880                         /* Compress with compressdev, decompress with Zlib */
881                         if (test_deflate_comp_decomp(&test_buffer, 1,
882                                         &i,
883                                         &compress_xform,
884                                         &ts_params->def_decomp_xform,
885                                         RTE_COMP_OP_STATELESS,
886                                         ZLIB_DECOMPRESS) < 0)
887                                 return TEST_FAILED;
888                 }
889         }
890
891         return TEST_SUCCESS;
892 }
893 static struct unit_test_suite compressdev_testsuite  = {
894         .suite_name = "compressdev unit test suite",
895         .setup = testsuite_setup,
896         .teardown = testsuite_teardown,
897         .unit_test_cases = {
898                 TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
899                         test_compressdev_deflate_stateless_fixed),
900                 TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
901                         test_compressdev_deflate_stateless_dynamic),
902                 TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
903                         test_compressdev_deflate_stateless_multi_op),
904                 TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
905                         test_compressdev_deflate_stateless_multi_level),
906                 TEST_CASES_END() /**< NULL terminate unit test array */
907         }
908 };
909
910 static int
911 test_compressdev(void)
912 {
913         return unit_test_suite_runner(&compressdev_testsuite);
914 }
915
916 REGISTER_TEST_COMMAND(compressdev_autotest, test_compressdev);