1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Cavium Networks
5 #include <rte_bus_vdev.h>
6 #include <rte_common.h>
8 #include "zlib_pmd_private.h"
10 /** Compute next mbuf in the list, assign data buffer and length,
11 * returns 0 if mbuf is NULL
13 #define COMPUTE_BUF(mbuf, data, len) \
14 ((mbuf = mbuf->next) ? \
15 (data = rte_pktmbuf_mtod(mbuf, uint8_t *)), \
16 (len = rte_pktmbuf_data_len(mbuf)) : 0)
19 process_zlib_deflate(struct rte_comp_op
*op
, z_stream
*strm
)
21 int ret
, flush
, fin_flush
;
22 struct rte_mbuf
*mbuf_src
= op
->m_src
;
23 struct rte_mbuf
*mbuf_dst
= op
->m_dst
;
25 switch (op
->flush_flag
) {
26 case RTE_COMP_FLUSH_FULL
:
27 case RTE_COMP_FLUSH_FINAL
:
31 op
->status
= RTE_COMP_OP_STATUS_INVALID_ARGS
;
32 ZLIB_PMD_ERR("Invalid flush value\n");
35 if (unlikely(!strm
)) {
36 op
->status
= RTE_COMP_OP_STATUS_INVALID_ARGS
;
37 ZLIB_PMD_ERR("Invalid z_stream\n");
40 /* Update z_stream with the inputs provided by application */
41 strm
->next_in
= rte_pktmbuf_mtod_offset(mbuf_src
, uint8_t *,
44 strm
->avail_in
= rte_pktmbuf_data_len(mbuf_src
) - op
->src
.offset
;
46 strm
->next_out
= rte_pktmbuf_mtod_offset(mbuf_dst
, uint8_t *,
49 strm
->avail_out
= rte_pktmbuf_data_len(mbuf_dst
) - op
->dst
.offset
;
51 /* Set flush value to NO_FLUSH unless it is last mbuf */
53 /* Initialize status to SUCCESS */
54 op
->status
= RTE_COMP_OP_STATUS_SUCCESS
;
57 /* Set flush value to Z_FINISH for last block */
58 if ((op
->src
.length
- strm
->total_in
) <= strm
->avail_in
) {
59 strm
->avail_in
= (op
->src
.length
- strm
->total_in
);
63 ret
= deflate(strm
, flush
);
64 if (unlikely(ret
== Z_STREAM_ERROR
)) {
65 /* error return, do not process further */
66 op
->status
= RTE_COMP_OP_STATUS_ERROR
;
69 /* Break if Z_STREAM_END is encountered */
70 if (ret
== Z_STREAM_END
)
73 /* Keep looping until input mbuf is consumed.
74 * Exit if destination mbuf gets exhausted.
76 } while ((strm
->avail_out
== 0) &&
77 COMPUTE_BUF(mbuf_dst
, strm
->next_out
, strm
->avail_out
));
79 if (!strm
->avail_out
) {
80 /* there is no space for compressed output */
81 op
->status
= RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED
;
85 /* Update source buffer to next mbuf
86 * Exit if input buffers are fully consumed
88 } while (COMPUTE_BUF(mbuf_src
, strm
->next_in
, strm
->avail_in
));
93 case RTE_COMP_OP_STATUS_SUCCESS
:
94 op
->consumed
+= strm
->total_in
;
96 case RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED
:
97 op
->produced
+= strm
->total_out
;
100 ZLIB_PMD_ERR("stats not updated for status:%d\n",
108 process_zlib_inflate(struct rte_comp_op
*op
, z_stream
*strm
)
111 struct rte_mbuf
*mbuf_src
= op
->m_src
;
112 struct rte_mbuf
*mbuf_dst
= op
->m_dst
;
114 if (unlikely(!strm
)) {
115 op
->status
= RTE_COMP_OP_STATUS_INVALID_ARGS
;
116 ZLIB_PMD_ERR("Invalid z_stream\n");
119 strm
->next_in
= rte_pktmbuf_mtod_offset(mbuf_src
, uint8_t *,
122 strm
->avail_in
= rte_pktmbuf_data_len(mbuf_src
) - op
->src
.offset
;
124 strm
->next_out
= rte_pktmbuf_mtod_offset(mbuf_dst
, uint8_t *,
127 strm
->avail_out
= rte_pktmbuf_data_len(mbuf_dst
) - op
->dst
.offset
;
129 /** Ignoring flush value provided from application for decompression */
131 /* initialize status to SUCCESS */
132 op
->status
= RTE_COMP_OP_STATUS_SUCCESS
;
136 ret
= inflate(strm
, flush
);
148 op
->status
= RTE_COMP_OP_STATUS_ERROR
;
151 /* no further computation needed if
152 * Z_STREAM_END is encountered
160 /* Keep looping until input mbuf is consumed.
161 * Exit if destination mbuf gets exhausted.
163 } while ((strm
->avail_out
== 0) &&
164 COMPUTE_BUF(mbuf_dst
, strm
->next_out
, strm
->avail_out
));
166 if (!strm
->avail_out
) {
167 /* there is no more space for decompressed output */
168 op
->status
= RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED
;
171 /* Read next input buffer to be processed, exit if compressed
172 * blocks are fully read
174 } while (COMPUTE_BUF(mbuf_src
, strm
->next_in
, strm
->avail_in
));
177 /* Update op stats */
178 switch (op
->status
) {
179 case RTE_COMP_OP_STATUS_SUCCESS
:
180 op
->consumed
+= strm
->total_in
;
182 case RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED
:
183 op
->produced
+= strm
->total_out
;
186 ZLIB_PMD_ERR("stats not produced for status:%d\n",
193 /** Process comp operation for mbuf */
195 process_zlib_op(struct zlib_qp
*qp
, struct rte_comp_op
*op
)
197 struct zlib_stream
*stream
;
198 struct zlib_priv_xform
*private_xform
;
200 if ((op
->op_type
== RTE_COMP_OP_STATEFUL
) ||
201 (op
->src
.offset
> rte_pktmbuf_data_len(op
->m_src
)) ||
202 (op
->dst
.offset
> rte_pktmbuf_data_len(op
->m_dst
))) {
203 op
->status
= RTE_COMP_OP_STATUS_INVALID_ARGS
;
204 ZLIB_PMD_ERR("Invalid source or destination buffers or "
205 "invalid Operation requested\n");
207 private_xform
= (struct zlib_priv_xform
*)op
->private_xform
;
208 stream
= &private_xform
->stream
;
209 stream
->comp(op
, &stream
->strm
);
211 /* whatever is out of op, put it into completion queue with
214 return rte_ring_enqueue(qp
->processed_pkts
, (void *)op
);
217 /** Parse comp xform and set private xform/Stream parameters */
219 zlib_set_stream_parameters(const struct rte_comp_xform
*xform
,
220 struct zlib_stream
*stream
)
222 int strategy
, level
, wbits
;
223 z_stream
*strm
= &stream
->strm
;
225 /* allocate deflate state */
226 strm
->zalloc
= Z_NULL
;
227 strm
->zfree
= Z_NULL
;
228 strm
->opaque
= Z_NULL
;
230 switch (xform
->type
) {
231 case RTE_COMP_COMPRESS
:
232 stream
->comp
= process_zlib_deflate
;
233 stream
->free
= deflateEnd
;
234 /** Compression window bits */
235 switch (xform
->compress
.algo
) {
236 case RTE_COMP_ALGO_DEFLATE
:
237 wbits
= -(xform
->compress
.window_size
);
240 ZLIB_PMD_ERR("Compression algorithm not supported\n");
243 /** Compression Level */
244 switch (xform
->compress
.level
) {
245 case RTE_COMP_LEVEL_PMD_DEFAULT
:
246 level
= Z_DEFAULT_COMPRESSION
;
248 case RTE_COMP_LEVEL_NONE
:
249 level
= Z_NO_COMPRESSION
;
251 case RTE_COMP_LEVEL_MIN
:
252 level
= Z_BEST_SPEED
;
254 case RTE_COMP_LEVEL_MAX
:
255 level
= Z_BEST_COMPRESSION
;
258 level
= xform
->compress
.level
;
259 if (level
< RTE_COMP_LEVEL_MIN
||
260 level
> RTE_COMP_LEVEL_MAX
) {
261 ZLIB_PMD_ERR("Compression level %d "
268 /** Compression strategy */
269 switch (xform
->compress
.deflate
.huffman
) {
270 case RTE_COMP_HUFFMAN_DEFAULT
:
271 strategy
= Z_DEFAULT_STRATEGY
;
273 case RTE_COMP_HUFFMAN_FIXED
:
276 case RTE_COMP_HUFFMAN_DYNAMIC
:
277 strategy
= Z_DEFAULT_STRATEGY
;
280 ZLIB_PMD_ERR("Compression strategy not supported\n");
283 if (deflateInit2(strm
, level
,
285 DEF_MEM_LEVEL
, strategy
) != Z_OK
) {
286 ZLIB_PMD_ERR("Deflate init failed\n");
291 case RTE_COMP_DECOMPRESS
:
292 stream
->comp
= process_zlib_inflate
;
293 stream
->free
= inflateEnd
;
295 switch (xform
->decompress
.algo
) {
296 case RTE_COMP_ALGO_DEFLATE
:
297 wbits
= -(xform
->decompress
.window_size
);
300 ZLIB_PMD_ERR("Compression algorithm not supported\n");
304 if (inflateInit2(strm
, wbits
) != Z_OK
) {
305 ZLIB_PMD_ERR("Inflate init failed\n");
316 zlib_pmd_enqueue_burst(void *queue_pair
,
317 struct rte_comp_op
**ops
, uint16_t nb_ops
)
319 struct zlib_qp
*qp
= queue_pair
;
323 for (i
= 0; i
< nb_ops
; i
++) {
324 ret
= process_zlib_op(qp
, ops
[i
]);
325 if (unlikely(ret
< 0)) {
326 /* increment count if failed to push to completion
329 qp
->qp_stats
.enqueue_err_count
++;
331 qp
->qp_stats
.enqueued_count
++;
339 zlib_pmd_dequeue_burst(void *queue_pair
,
340 struct rte_comp_op
**ops
, uint16_t nb_ops
)
342 struct zlib_qp
*qp
= queue_pair
;
344 unsigned int nb_dequeued
= 0;
346 nb_dequeued
= rte_ring_dequeue_burst(qp
->processed_pkts
,
347 (void **)ops
, nb_ops
, NULL
);
348 qp
->qp_stats
.dequeued_count
+= nb_dequeued
;
354 zlib_create(const char *name
,
355 struct rte_vdev_device
*vdev
,
356 struct rte_compressdev_pmd_init_params
*init_params
)
358 struct rte_compressdev
*dev
;
360 dev
= rte_compressdev_pmd_create(name
, &vdev
->device
,
361 sizeof(struct zlib_private
), init_params
);
363 ZLIB_PMD_ERR("driver %s: create failed", init_params
->name
);
367 dev
->dev_ops
= rte_zlib_pmd_ops
;
369 /* register rx/tx burst functions for data path */
370 dev
->dequeue_burst
= zlib_pmd_dequeue_burst
;
371 dev
->enqueue_burst
= zlib_pmd_enqueue_burst
;
377 zlib_probe(struct rte_vdev_device
*vdev
)
379 struct rte_compressdev_pmd_init_params init_params
= {
384 const char *input_args
;
387 name
= rte_vdev_device_name(vdev
);
392 input_args
= rte_vdev_device_args(vdev
);
394 retval
= rte_compressdev_pmd_parse_input_args(&init_params
, input_args
);
397 "Failed to parse initialisation arguments[%s]\n",
402 return zlib_create(name
, vdev
, &init_params
);
406 zlib_remove(struct rte_vdev_device
*vdev
)
408 struct rte_compressdev
*compressdev
;
411 name
= rte_vdev_device_name(vdev
);
415 compressdev
= rte_compressdev_pmd_get_named_dev(name
);
416 if (compressdev
== NULL
)
419 return rte_compressdev_pmd_destroy(compressdev
);
422 static struct rte_vdev_driver zlib_pmd_drv
= {
424 .remove
= zlib_remove
427 RTE_PMD_REGISTER_VDEV(COMPRESSDEV_NAME_ZLIB_PMD
, zlib_pmd_drv
);
429 RTE_INIT(zlib_init_log
)
431 zlib_logtype_driver
= rte_log_register("pmd.compress.zlib");
432 if (zlib_logtype_driver
>= 0)
433 rte_log_set_level(zlib_logtype_driver
, RTE_LOG_INFO
);