Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Intel Corporation
3 : : */
4 : :
5 : : #include <stdlib.h>
6 : :
7 : : #include <rte_malloc.h>
8 : : #include <rte_eal.h>
9 : : #include <rte_log.h>
10 : : #include <rte_compressdev.h>
11 : :
12 : : #include "comp_perf_test_verify.h"
13 : : #include "comp_perf_test_common.h"
14 : :
15 : : void
16 : 0 : cperf_verify_test_destructor(void *arg)
17 : : {
18 : 0 : if (arg) {
19 : 0 : comp_perf_free_memory(
20 : : ((struct cperf_verify_ctx *)arg)->options,
21 : : &((struct cperf_verify_ctx *)arg)->mem);
22 : 0 : rte_free(arg);
23 : : }
24 : 0 : }
25 : :
26 : : void *
27 : 0 : cperf_verify_test_constructor(uint8_t dev_id, uint16_t qp_id,
28 : : struct comp_test_data *options)
29 : : {
30 : : struct cperf_verify_ctx *ctx = NULL;
31 : :
32 : 0 : ctx = rte_malloc(NULL, sizeof(struct cperf_verify_ctx), 0);
33 : :
34 : 0 : if (ctx == NULL)
35 : : return NULL;
36 : :
37 : 0 : ctx->mem.dev_id = dev_id;
38 : 0 : ctx->mem.qp_id = qp_id;
39 : 0 : ctx->options = options;
40 : :
41 : 0 : if (!comp_perf_allocate_memory(ctx->options, &ctx->mem) &&
42 : 0 : !prepare_bufs(ctx->options, &ctx->mem))
43 : : return ctx;
44 : :
45 : 0 : cperf_verify_test_destructor(ctx);
46 : 0 : return NULL;
47 : : }
48 : :
49 : : static int
50 : 0 : main_loop(struct cperf_verify_ctx *ctx, enum rte_comp_xform_type type)
51 : : {
52 : 0 : struct comp_test_data *test_data = ctx->options;
53 : : uint8_t *output_data_ptr = NULL;
54 : : size_t *output_data_sz = NULL;
55 : : struct cperf_mem_resources *mem = &ctx->mem;
56 : :
57 : 0 : uint8_t dev_id = mem->dev_id;
58 : : uint32_t i, iter, num_iter;
59 : : struct rte_comp_op **ops, **deq_ops;
60 : 0 : void *priv_xform = NULL;
61 : : struct rte_comp_xform xform;
62 : : size_t output_size = 0;
63 : : struct rte_mbuf **input_bufs, **output_bufs;
64 : : int res = 0;
65 : : int allocated = 0;
66 : : uint32_t out_seg_sz;
67 : 0 : uint8_t dict[MAX_DICT_SIZE] = {0};
68 : 0 : uint16_t window_size = (1ULL << test_data->window_sz);
69 : : uint8_t *udc_header = NULL;
70 : :
71 : 0 : if (test_data == NULL || !test_data->burst_sz) {
72 : 0 : RTE_LOG(ERR, USER1,
73 : : "Unknown burst size\n");
74 : 0 : return -1;
75 : : }
76 : :
77 : 0 : if (test_data->dictionary_data) {
78 : 0 : if (test_data->dictionary_data_sz >= window_size) {
79 : : memcpy(dict,
80 : : test_data->dictionary_data
81 : 0 : + (test_data->dictionary_data_sz - window_size),
82 : : window_size);
83 : : } else if (test_data->dictionary_data_sz < window_size) {
84 : 0 : memcpy(dict + (window_size - test_data->dictionary_data_sz),
85 : : test_data->dictionary_data,
86 : : test_data->dictionary_data_sz);
87 : : }
88 : : }
89 : :
90 : :
91 : 0 : ops = rte_zmalloc_socket(NULL,
92 : 0 : 2 * mem->total_bufs * sizeof(struct rte_comp_op *),
93 : 0 : 0, rte_socket_id());
94 : :
95 : 0 : if (ops == NULL) {
96 : 0 : RTE_LOG(ERR, USER1,
97 : : "Can't allocate memory for ops structures\n");
98 : 0 : return -1;
99 : : }
100 : :
101 : 0 : deq_ops = &ops[mem->total_bufs];
102 : :
103 : 0 : if (type == RTE_COMP_COMPRESS) {
104 : 0 : xform = (struct rte_comp_xform) {
105 : : .type = RTE_COMP_COMPRESS,
106 : : .compress = {
107 : 0 : .algo = test_data->test_algo,
108 : 0 : .level = test_data->level,
109 : 0 : .window_size = test_data->window_sz,
110 : : .chksum = RTE_COMP_CHECKSUM_NONE,
111 : : .hash_algo = RTE_COMP_HASH_ALGO_NONE,
112 : : }
113 : : };
114 : 0 : if (test_data->test_algo == RTE_COMP_ALGO_DEFLATE) {
115 : 0 : xform.compress.deflate.huffman = test_data->huffman_enc;
116 : 0 : xform.compress.deflate.dictionary = dict;
117 : 0 : xform.compress.deflate.dictionary_len = window_size;
118 : 0 : } else if (test_data->test_algo == RTE_COMP_ALGO_LZ4)
119 : 0 : xform.compress.lz4.flags = test_data->lz4_flags;
120 : 0 : output_data_ptr = ctx->mem.compressed_data;
121 : 0 : output_data_sz = &ctx->comp_data_sz;
122 : 0 : input_bufs = mem->decomp_bufs;
123 : 0 : output_bufs = mem->comp_bufs;
124 : 0 : out_seg_sz = test_data->out_seg_sz;
125 : : } else {
126 : 0 : xform = (struct rte_comp_xform) {
127 : : .type = RTE_COMP_DECOMPRESS,
128 : : .decompress = {
129 : 0 : .algo = test_data->test_algo,
130 : : .chksum = RTE_COMP_CHECKSUM_NONE,
131 : 0 : .window_size = test_data->window_sz,
132 : : .hash_algo = RTE_COMP_HASH_ALGO_NONE
133 : : }
134 : : };
135 : 0 : if (test_data->test_algo == RTE_COMP_ALGO_DEFLATE) {
136 : 0 : xform.decompress.inflate.dictionary = dict;
137 : 0 : xform.decompress.inflate.dictionary_len = window_size;
138 : 0 : } else if (test_data->test_algo == RTE_COMP_ALGO_LZ4)
139 : 0 : xform.decompress.lz4.flags = test_data->lz4_flags;
140 : 0 : output_data_ptr = ctx->mem.decompressed_data;
141 : 0 : output_data_sz = &ctx->decomp_data_sz;
142 : 0 : input_bufs = mem->comp_bufs;
143 : 0 : output_bufs = mem->decomp_bufs;
144 : 0 : out_seg_sz = (test_data->test_op & COMPRESS) ?
145 : 0 : test_data->seg_sz : test_data->out_seg_sz;
146 : : }
147 : :
148 : : /* Create private xform */
149 : 0 : if (rte_compressdev_private_xform_create(dev_id, &xform,
150 : : &priv_xform) < 0) {
151 : 0 : RTE_LOG(ERR, USER1, "Private xform could not be created\n");
152 : : res = -1;
153 : 0 : goto end;
154 : : }
155 : :
156 : : num_iter = 1;
157 : :
158 : 0 : for (iter = 0; iter < num_iter; iter++) {
159 : 0 : uint32_t total_ops = mem->total_bufs;
160 : : uint32_t remaining_ops = mem->total_bufs;
161 : : uint32_t total_deq_ops = 0;
162 : : uint32_t total_enq_ops = 0;
163 : : uint16_t ops_unused = 0;
164 : : uint16_t num_enq = 0;
165 : : uint16_t num_deq = 0;
166 : :
167 : : output_size = 0;
168 : :
169 : 0 : while (remaining_ops > 0) {
170 : 0 : uint16_t num_ops = RTE_MIN(remaining_ops,
171 : : test_data->burst_sz);
172 : 0 : uint16_t ops_needed = num_ops - ops_unused;
173 : :
174 : : /*
175 : : * Move the unused operations from the previous
176 : : * enqueue_burst call to the front, to maintain order
177 : : */
178 : 0 : if ((ops_unused > 0) && (num_enq > 0)) {
179 : 0 : size_t nb_b_to_mov =
180 : 0 : ops_unused * sizeof(struct rte_comp_op *);
181 : :
182 : 0 : memmove(ops, &ops[num_enq], nb_b_to_mov);
183 : : }
184 : :
185 : : /* Allocate compression operations */
186 : 0 : if (ops_needed && !rte_comp_op_bulk_alloc(
187 : : mem->op_pool,
188 : 0 : &ops[ops_unused],
189 : : ops_needed)) {
190 : 0 : RTE_LOG(ERR, USER1,
191 : : "Could not allocate enough operations\n");
192 : : res = -1;
193 : 0 : goto end;
194 : : }
195 : 0 : allocated += ops_needed;
196 : :
197 : 0 : for (i = 0; i < ops_needed; i++) {
198 : : /*
199 : : * Calculate next buffer to attach to operation
200 : : */
201 : 0 : uint32_t buf_id = total_enq_ops + i +
202 : : ops_unused;
203 : 0 : uint16_t op_id = ops_unused + i;
204 : : /* Reset all data in output buffers */
205 : 0 : struct rte_mbuf *m = output_bufs[buf_id];
206 : :
207 : 0 : m->pkt_len = out_seg_sz * m->nb_segs;
208 : 0 : while (m) {
209 : 0 : m->data_len = m->buf_len - m->data_off;
210 : 0 : m = m->next;
211 : : }
212 : 0 : ops[op_id]->m_src = input_bufs[buf_id];
213 : 0 : ops[op_id]->m_dst = output_bufs[buf_id];
214 : 0 : ops[op_id]->src.offset = 0;
215 : 0 : ops[op_id]->src.length =
216 : 0 : rte_pktmbuf_pkt_len(input_bufs[buf_id]);
217 : 0 : ops[op_id]->dst.offset = 0;
218 : 0 : ops[op_id]->flush_flag = RTE_COMP_FLUSH_FINAL;
219 : 0 : if ((xform.type == RTE_COMP_DECOMPRESS) &&
220 : 0 : (xform.decompress.chksum
221 : : == RTE_COMP_CHECKSUM_3GPP_PDCP_UDC)) {
222 : : udc_header
223 : 0 : = rte_pktmbuf_mtod(ops[op_id]->m_src, uint8_t *);
224 : 0 : ops[op_id]->input_chksum = *udc_header & 0xf;
225 : 0 : ops[op_id]->src.offset = 1;
226 : : } else {
227 : 0 : ops[op_id]->input_chksum = buf_id;
228 : : ops[op_id]->src.offset = 0;
229 : : }
230 : 0 : ops[op_id]->private_xform = priv_xform;
231 : : }
232 : :
233 : 0 : if (unlikely(test_data->perf_comp_force_stop))
234 : 0 : goto end;
235 : :
236 : 0 : num_enq = rte_compressdev_enqueue_burst(dev_id,
237 : 0 : mem->qp_id, ops,
238 : : num_ops);
239 : 0 : if (num_enq == 0) {
240 : : struct rte_compressdev_stats stats;
241 : :
242 : 0 : rte_compressdev_stats_get(dev_id, &stats);
243 : 0 : if (stats.enqueue_err_count) {
244 : : res = -1;
245 : 0 : goto end;
246 : : }
247 : : }
248 : :
249 : 0 : ops_unused = num_ops - num_enq;
250 : 0 : remaining_ops -= num_enq;
251 : 0 : total_enq_ops += num_enq;
252 : :
253 : 0 : num_deq = rte_compressdev_dequeue_burst(dev_id,
254 : 0 : mem->qp_id,
255 : : deq_ops,
256 : 0 : test_data->burst_sz);
257 : 0 : total_deq_ops += num_deq;
258 : :
259 : 0 : for (i = 0; i < num_deq; i++) {
260 : 0 : struct rte_comp_op *op = deq_ops[i];
261 : :
262 : 0 : if (op->status ==
263 : 0 : RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED ||
264 : : op->status ==
265 : : RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE) {
266 : 0 : RTE_LOG(ERR, USER1,
267 : : "Out of space error occurred due to incompressible input data expanding to larger than destination buffer. Increase the EXPANSE_RATIO constant to use this data.\n");
268 : : res = -1;
269 : 0 : goto end;
270 : 0 : } else if (op->status !=
271 : : RTE_COMP_OP_STATUS_SUCCESS) {
272 : 0 : RTE_LOG(ERR, USER1,
273 : : "Some operations were not successful\n");
274 : 0 : goto end;
275 : : }
276 : :
277 : : const void *read_data_addr =
278 : 0 : rte_pktmbuf_read(op->m_dst, 0,
279 : : op->produced, output_data_ptr);
280 : 0 : if (read_data_addr == NULL) {
281 : 0 : RTE_LOG(ERR, USER1,
282 : : "Could not copy buffer in destination\n");
283 : : res = -1;
284 : 0 : goto end;
285 : : }
286 : :
287 : 0 : if (read_data_addr != output_data_ptr)
288 : 0 : rte_memcpy(output_data_ptr,
289 : 0 : rte_pktmbuf_mtod(op->m_dst,
290 : : uint8_t *),
291 : 0 : op->produced);
292 : 0 : output_data_ptr += op->produced;
293 : 0 : output_size += op->produced;
294 : :
295 : : }
296 : :
297 : :
298 : : if (iter == num_iter - 1) {
299 : 0 : for (i = 0; i < num_deq; i++) {
300 : 0 : struct rte_comp_op *op = deq_ops[i];
301 : 0 : struct rte_mbuf *m = op->m_dst;
302 : :
303 : 0 : m->pkt_len = op->produced;
304 : : uint32_t remaining_data = op->produced;
305 : : uint16_t data_to_append;
306 : :
307 : 0 : while (remaining_data > 0) {
308 : 0 : data_to_append =
309 : 0 : RTE_MIN(remaining_data,
310 : : out_seg_sz);
311 : 0 : m->data_len = data_to_append;
312 : 0 : remaining_data -=
313 : : data_to_append;
314 : 0 : m = m->next;
315 : : }
316 : : }
317 : : }
318 : 0 : rte_mempool_put_bulk(mem->op_pool,
319 : : (void **)deq_ops, num_deq);
320 : 0 : allocated -= num_deq;
321 : : }
322 : :
323 : : /* Dequeue the last operations */
324 : 0 : while (total_deq_ops < total_ops) {
325 : 0 : if (unlikely(test_data->perf_comp_force_stop))
326 : 0 : goto end;
327 : :
328 : 0 : num_deq = rte_compressdev_dequeue_burst(dev_id,
329 : 0 : mem->qp_id,
330 : : deq_ops,
331 : 0 : test_data->burst_sz);
332 : 0 : if (num_deq == 0) {
333 : : struct rte_compressdev_stats stats;
334 : :
335 : 0 : rte_compressdev_stats_get(dev_id, &stats);
336 : 0 : if (stats.dequeue_err_count) {
337 : : res = -1;
338 : 0 : goto end;
339 : : }
340 : : }
341 : :
342 : 0 : total_deq_ops += num_deq;
343 : :
344 : 0 : for (i = 0; i < num_deq; i++) {
345 : 0 : struct rte_comp_op *op = deq_ops[i];
346 : :
347 : 0 : if (op->status ==
348 : 0 : RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED ||
349 : : op->status ==
350 : : RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE) {
351 : 0 : RTE_LOG(ERR, USER1,
352 : : "Out of space error occurred due to incompressible input data expanding to larger than destination buffer. Increase the EXPANSE_RATIO constant to use this data.\n");
353 : : res = -1;
354 : 0 : goto end;
355 : 0 : } else if (op->status !=
356 : : RTE_COMP_OP_STATUS_SUCCESS) {
357 : 0 : RTE_LOG(ERR, USER1,
358 : : "Some operations were not successful\n");
359 : 0 : goto end;
360 : : }
361 : : const void *read_data_addr =
362 : 0 : rte_pktmbuf_read(op->m_dst,
363 : : op->dst.offset,
364 : : op->produced, output_data_ptr);
365 : 0 : if (read_data_addr == NULL) {
366 : 0 : RTE_LOG(ERR, USER1,
367 : : "Could not copy buffer in destination\n");
368 : : res = -1;
369 : 0 : goto end;
370 : : }
371 : :
372 : 0 : if (read_data_addr != output_data_ptr)
373 : 0 : rte_memcpy(output_data_ptr,
374 : 0 : rte_pktmbuf_mtod(
375 : : op->m_dst, uint8_t *),
376 : 0 : op->produced);
377 : 0 : output_data_ptr += op->produced;
378 : 0 : output_size += op->produced;
379 : :
380 : : }
381 : :
382 : : if (iter == num_iter - 1) {
383 : 0 : for (i = 0; i < num_deq; i++) {
384 : 0 : struct rte_comp_op *op = deq_ops[i];
385 : 0 : struct rte_mbuf *m = op->m_dst;
386 : :
387 : 0 : m->pkt_len = op->produced;
388 : : uint32_t remaining_data = op->produced;
389 : : uint16_t data_to_append;
390 : :
391 : 0 : while (remaining_data > 0) {
392 : 0 : data_to_append =
393 : 0 : RTE_MIN(remaining_data,
394 : : out_seg_sz);
395 : 0 : m->data_len = data_to_append;
396 : 0 : remaining_data -=
397 : : data_to_append;
398 : 0 : m = m->next;
399 : : }
400 : : }
401 : : }
402 : 0 : rte_mempool_put_bulk(mem->op_pool,
403 : : (void **)deq_ops, num_deq);
404 : 0 : allocated -= num_deq;
405 : : }
406 : : }
407 : :
408 : : if (output_data_sz)
409 : 0 : *output_data_sz = output_size;
410 : 0 : end:
411 : 0 : rte_mempool_put_bulk(mem->op_pool, (void **)ops, allocated);
412 : 0 : rte_compressdev_private_xform_free(dev_id, priv_xform);
413 : 0 : rte_free(ops);
414 : :
415 : 0 : if (test_data->perf_comp_force_stop) {
416 : 0 : RTE_LOG(ERR, USER1,
417 : : "lcore: %d Perf. test has been aborted by user\n",
418 : : mem->lcore_id);
419 : : res = -1;
420 : : }
421 : :
422 : : return res;
423 : : }
424 : :
425 : : int
426 : 0 : cperf_verify_test_runner(void *test_ctx)
427 : : {
428 : : struct cperf_verify_ctx *ctx = test_ctx;
429 : 0 : struct comp_test_data *test_data = ctx->options;
430 : : int ret = EXIT_SUCCESS;
431 : : static RTE_ATOMIC(uint16_t) display_once;
432 : : uint32_t lcore = rte_lcore_id();
433 : : uint16_t exp = 0;
434 : :
435 : 0 : ctx->mem.lcore_id = lcore;
436 : :
437 : 0 : test_data->ratio = 0;
438 : :
439 : 0 : if (test_data->test_op & COMPRESS) {
440 : 0 : if (main_loop(ctx, RTE_COMP_COMPRESS) < 0) {
441 : : ret = EXIT_FAILURE;
442 : 0 : goto end;
443 : : }
444 : : }
445 : :
446 : 0 : if (test_data->test_op & DECOMPRESS) {
447 : 0 : if (main_loop(ctx, RTE_COMP_DECOMPRESS) < 0) {
448 : : ret = EXIT_FAILURE;
449 : 0 : goto end;
450 : : }
451 : :
452 : 0 : if (!(test_data->test_op & COMPRESS)) {
453 : : /*
454 : : * For DECOMPRESS_ONLY mode there is no more
455 : : * verifications, reset the 'ratio' and 'comp_data_sz'
456 : : * fields for other tests report.
457 : : */
458 : 0 : ctx->comp_data_sz = 0;
459 : 0 : ctx->ratio = 0;
460 : 0 : goto end;
461 : : }
462 : :
463 : 0 : if (ctx->decomp_data_sz != test_data->input_data_sz) {
464 : 0 : RTE_LOG(ERR, USER1,
465 : : "Decompressed data length not equal to input data length\n");
466 : 0 : RTE_LOG(ERR, USER1,
467 : : "Decompressed size = %zu, expected = %zu\n",
468 : : ctx->decomp_data_sz, test_data->input_data_sz);
469 : : ret = EXIT_FAILURE;
470 : 0 : goto end;
471 : : } else {
472 : 0 : if (memcmp(ctx->mem.decompressed_data,
473 : 0 : test_data->input_data,
474 : : test_data->input_data_sz) != 0) {
475 : 0 : RTE_LOG(ERR, USER1,
476 : : "Decompressed data is not the same as file data\n");
477 : : ret = EXIT_FAILURE;
478 : 0 : goto end;
479 : : }
480 : : }
481 : : }
482 : :
483 : 0 : ctx->ratio = (double) ctx->comp_data_sz /
484 : 0 : test_data->input_data_sz * 100;
485 : :
486 : 0 : if (!ctx->silent) {
487 : 0 : if (rte_atomic_compare_exchange_strong_explicit(&display_once, &exp, 1,
488 : : rte_memory_order_relaxed, rte_memory_order_relaxed)) {
489 : : printf("%12s%6s%12s%17s\n",
490 : : "lcore id", "Level", "Comp size", "Comp ratio [%]");
491 : : }
492 : 0 : printf("%12u%6u%12zu%17.2f\n",
493 : 0 : ctx->mem.lcore_id,
494 : 0 : test_data->level, ctx->comp_data_sz, ctx->ratio);
495 : : }
496 : :
497 : 0 : end:
498 : 0 : return ret;
499 : : }
|