1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Intel Corporation
10 #include <rte_common.h>
12 #include <rte_launch.h>
13 #include <rte_bbdev.h>
14 #include <rte_cycles.h>
15 #include <rte_lcore.h>
16 #include <rte_malloc.h>
17 #include <rte_random.h>
18 #include <rte_hexdump.h>
21 #include "test_bbdev_vector.h"
23 #define GET_SOCKET(socket_id) (((socket_id) == SOCKET_ID_ANY) ? 0 : (socket_id))
25 #define MAX_QUEUES RTE_MAX_LCORE
27 #define OPS_CACHE_SIZE 256U
28 #define OPS_POOL_SIZE_MIN 511U /* 0.5K per queue */
33 #define INVALID_QUEUE_ID -1
35 static struct test_bbdev_vector test_vector;
37 /* Switch between PMD and Interrupt for throughput TC */
38 static bool intr_enabled;
40 /* Represents tested active devices */
41 static struct active_device {
42 const char *driver_name;
44 uint16_t supported_ops;
45 uint16_t queue_ids[MAX_QUEUES];
47 struct rte_mempool *ops_mempool;
48 struct rte_mempool *in_mbuf_pool;
49 struct rte_mempool *hard_out_mbuf_pool;
50 struct rte_mempool *soft_out_mbuf_pool;
51 } active_devs[RTE_BBDEV_MAX_DEVS];
53 static uint8_t nb_active_devs;
55 /* Data buffers used by BBDEV ops */
57 struct rte_bbdev_op_data *inputs;
58 struct rte_bbdev_op_data *hard_outputs;
59 struct rte_bbdev_op_data *soft_outputs;
62 /* Operation parameters specific for given test case */
63 struct test_op_params {
64 struct rte_mempool *mp;
65 struct rte_bbdev_dec_op *ref_dec_op;
66 struct rte_bbdev_enc_op *ref_enc_op;
68 uint16_t num_to_process;
72 struct test_buffers q_bufs[RTE_MAX_NUMA_NODES][MAX_QUEUES];
75 /* Contains per lcore params */
76 struct thread_params {
82 rte_atomic16_t nb_dequeued;
83 rte_atomic16_t processing_status;
84 struct test_op_params *op_params;
87 typedef int (test_case_function)(struct active_device *ad,
88 struct test_op_params *op_params);
91 set_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
93 ad->supported_ops |= (1 << op_type);
97 is_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
99 return ad->supported_ops & (1 << op_type);
103 flags_match(uint32_t flags_req, uint32_t flags_present)
105 return (flags_req & flags_present) == flags_req;
109 clear_soft_out_cap(uint32_t *op_flags)
111 *op_flags &= ~RTE_BBDEV_TURBO_SOFT_OUTPUT;
112 *op_flags &= ~RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT;
113 *op_flags &= ~RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT;
117 check_dev_cap(const struct rte_bbdev_info *dev_info)
120 unsigned int nb_inputs, nb_soft_outputs, nb_hard_outputs;
121 const struct rte_bbdev_op_cap *op_cap = dev_info->drv.capabilities;
123 nb_inputs = test_vector.entries[DATA_INPUT].nb_segments;
124 nb_soft_outputs = test_vector.entries[DATA_SOFT_OUTPUT].nb_segments;
125 nb_hard_outputs = test_vector.entries[DATA_HARD_OUTPUT].nb_segments;
127 for (i = 0; op_cap->type != RTE_BBDEV_OP_NONE; ++i, ++op_cap) {
128 if (op_cap->type != test_vector.op_type)
131 if (op_cap->type == RTE_BBDEV_OP_TURBO_DEC) {
132 const struct rte_bbdev_op_cap_turbo_dec *cap =
133 &op_cap->cap.turbo_dec;
134 /* Ignore lack of soft output capability, just skip
135 * checking if soft output is valid.
137 if ((test_vector.turbo_dec.op_flags &
138 RTE_BBDEV_TURBO_SOFT_OUTPUT) &&
139 !(cap->capability_flags &
140 RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
142 "WARNING: Device \"%s\" does not support soft output - soft output flags will be ignored.\n",
145 &test_vector.turbo_dec.op_flags);
148 if (!flags_match(test_vector.turbo_dec.op_flags,
149 cap->capability_flags))
151 if (nb_inputs > cap->num_buffers_src) {
152 printf("Too many inputs defined: %u, max: %u\n",
153 nb_inputs, cap->num_buffers_src);
156 if (nb_soft_outputs > cap->num_buffers_soft_out &&
157 (test_vector.turbo_dec.op_flags &
158 RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
160 "Too many soft outputs defined: %u, max: %u\n",
162 cap->num_buffers_soft_out);
165 if (nb_hard_outputs > cap->num_buffers_hard_out) {
167 "Too many hard outputs defined: %u, max: %u\n",
169 cap->num_buffers_hard_out);
172 if (intr_enabled && !(cap->capability_flags &
173 RTE_BBDEV_TURBO_DEC_INTERRUPTS)) {
175 "Dequeue interrupts are not supported!\n");
180 } else if (op_cap->type == RTE_BBDEV_OP_TURBO_ENC) {
181 const struct rte_bbdev_op_cap_turbo_enc *cap =
182 &op_cap->cap.turbo_enc;
184 if (!flags_match(test_vector.turbo_enc.op_flags,
185 cap->capability_flags))
187 if (nb_inputs > cap->num_buffers_src) {
188 printf("Too many inputs defined: %u, max: %u\n",
189 nb_inputs, cap->num_buffers_src);
192 if (nb_hard_outputs > cap->num_buffers_dst) {
194 "Too many hard outputs defined: %u, max: %u\n",
195 nb_hard_outputs, cap->num_buffers_src);
198 if (intr_enabled && !(cap->capability_flags &
199 RTE_BBDEV_TURBO_ENC_INTERRUPTS)) {
201 "Dequeue interrupts are not supported!\n");
209 if ((i == 0) && (test_vector.op_type == RTE_BBDEV_OP_NONE))
210 return TEST_SUCCESS; /* Special case for NULL device */
215 /* calculates optimal mempool size not smaller than the val */
217 optimal_mempool_size(unsigned int val)
219 return rte_align32pow2(val + 1) - 1;
222 /* allocates mbuf mempool for inputs and outputs */
223 static struct rte_mempool *
224 create_mbuf_pool(struct op_data_entries *entries, uint8_t dev_id,
225 int socket_id, unsigned int mbuf_pool_size,
226 const char *op_type_str)
229 uint32_t max_seg_sz = 0;
230 char pool_name[RTE_MEMPOOL_NAMESIZE];
232 /* find max input segment size */
233 for (i = 0; i < entries->nb_segments; ++i)
234 if (entries->segments[i].length > max_seg_sz)
235 max_seg_sz = entries->segments[i].length;
237 snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
239 return rte_pktmbuf_pool_create(pool_name, mbuf_pool_size, 0, 0,
240 RTE_MAX(max_seg_sz + RTE_PKTMBUF_HEADROOM,
241 (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE), socket_id);
245 create_mempools(struct active_device *ad, int socket_id,
246 enum rte_bbdev_op_type op_type, uint16_t num_ops)
248 struct rte_mempool *mp;
249 unsigned int ops_pool_size, mbuf_pool_size = 0;
250 char pool_name[RTE_MEMPOOL_NAMESIZE];
251 const char *op_type_str;
253 struct op_data_entries *in = &test_vector.entries[DATA_INPUT];
254 struct op_data_entries *hard_out =
255 &test_vector.entries[DATA_HARD_OUTPUT];
256 struct op_data_entries *soft_out =
257 &test_vector.entries[DATA_SOFT_OUTPUT];
259 /* allocate ops mempool */
260 ops_pool_size = optimal_mempool_size(RTE_MAX(
261 /* Ops used plus 1 reference op */
262 RTE_MAX((unsigned int)(ad->nb_queues * num_ops + 1),
263 /* Minimal cache size plus 1 reference op */
264 (unsigned int)(1.5 * rte_lcore_count() *
265 OPS_CACHE_SIZE + 1)),
268 op_type_str = rte_bbdev_op_type_str(op_type);
269 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
271 snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
273 mp = rte_bbdev_op_pool_create(pool_name, op_type,
274 ops_pool_size, OPS_CACHE_SIZE, socket_id);
275 TEST_ASSERT_NOT_NULL(mp,
276 "ERROR Failed to create %u items ops pool for dev %u on socket %u.",
280 ad->ops_mempool = mp;
283 mbuf_pool_size = optimal_mempool_size(ops_pool_size * in->nb_segments);
284 mp = create_mbuf_pool(in, ad->dev_id, socket_id, mbuf_pool_size, "in");
285 TEST_ASSERT_NOT_NULL(mp,
286 "ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %u.",
290 ad->in_mbuf_pool = mp;
293 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
294 hard_out->nb_segments);
295 mp = create_mbuf_pool(hard_out, ad->dev_id, socket_id, mbuf_pool_size,
297 TEST_ASSERT_NOT_NULL(mp,
298 "ERROR Failed to create %u items hard output pktmbuf pool for dev %u on socket %u.",
302 ad->hard_out_mbuf_pool = mp;
304 if (soft_out->nb_segments == 0)
308 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
309 soft_out->nb_segments);
310 mp = create_mbuf_pool(soft_out, ad->dev_id, socket_id, mbuf_pool_size,
312 TEST_ASSERT_NOT_NULL(mp,
313 "ERROR Failed to create %uB soft output pktmbuf pool for dev %u on socket %u.",
317 ad->soft_out_mbuf_pool = mp;
323 add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
324 struct test_bbdev_vector *vector)
327 unsigned int queue_id;
328 struct rte_bbdev_queue_conf qconf;
329 struct active_device *ad = &active_devs[nb_active_devs];
330 unsigned int nb_queues;
331 enum rte_bbdev_op_type op_type = vector->op_type;
333 nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues);
335 ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id);
337 printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n",
338 dev_id, nb_queues, info->socket_id, ret);
342 /* configure interrupts if needed */
344 ret = rte_bbdev_intr_enable(dev_id);
346 printf("rte_bbdev_intr_enable(%u) ret %i\n", dev_id,
352 /* setup device queues */
353 qconf.socket = info->socket_id;
354 qconf.queue_size = info->drv.default_queue_conf.queue_size;
356 qconf.deferred_start = 0;
357 qconf.op_type = op_type;
359 for (queue_id = 0; queue_id < nb_queues; ++queue_id) {
360 ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf);
363 "Allocated all queues (id=%u) at prio%u on dev%u\n",
364 queue_id, qconf.priority, dev_id);
366 ret = rte_bbdev_queue_configure(ad->dev_id, queue_id,
370 printf("All queues on dev %u allocated: %u\n",
374 ad->queue_ids[queue_id] = queue_id;
376 TEST_ASSERT(queue_id != 0,
377 "ERROR Failed to configure any queues on dev %u",
379 ad->nb_queues = queue_id;
381 set_avail_op(ad, op_type);
387 add_active_device(uint8_t dev_id, struct rte_bbdev_info *info,
388 struct test_bbdev_vector *vector)
392 active_devs[nb_active_devs].driver_name = info->drv.driver_name;
393 active_devs[nb_active_devs].dev_id = dev_id;
395 ret = add_bbdev_dev(dev_id, info, vector);
396 if (ret == TEST_SUCCESS)
402 populate_active_devices(void)
406 uint8_t nb_devs_added = 0;
407 struct rte_bbdev_info info;
409 RTE_BBDEV_FOREACH(dev_id) {
410 rte_bbdev_info_get(dev_id, &info);
412 if (check_dev_cap(&info)) {
414 "Device %d (%s) does not support specified capabilities\n",
415 dev_id, info.dev_name);
419 ret = add_active_device(dev_id, &info, &test_vector);
421 printf("Adding active bbdev %s skipped\n",
428 return nb_devs_added;
432 read_test_vector(void)
436 memset(&test_vector, 0, sizeof(test_vector));
437 printf("Test vector file = %s\n", get_vector_filename());
438 ret = test_bbdev_vector_read(get_vector_filename(), &test_vector);
439 TEST_ASSERT_SUCCESS(ret, "Failed to parse file %s\n",
440 get_vector_filename());
446 testsuite_setup(void)
448 TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
450 if (populate_active_devices() == 0) {
451 printf("No suitable devices found!\n");
459 interrupt_testsuite_setup(void)
461 TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
463 /* Enable interrupts */
466 /* Special case for NULL device (RTE_BBDEV_OP_NONE) */
467 if (populate_active_devices() == 0 ||
468 test_vector.op_type == RTE_BBDEV_OP_NONE) {
469 intr_enabled = false;
470 printf("No suitable devices found!\n");
478 testsuite_teardown(void)
482 /* Unconfigure devices */
483 RTE_BBDEV_FOREACH(dev_id)
484 rte_bbdev_close(dev_id);
486 /* Clear active devices structs. */
487 memset(active_devs, 0, sizeof(active_devs));
496 for (i = 0; i < nb_active_devs; i++) {
497 dev_id = active_devs[i].dev_id;
498 /* reset bbdev stats */
499 TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
500 "Failed to reset stats of bbdev %u", dev_id);
501 /* start the device */
502 TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
503 "Failed to start bbdev %u", dev_id);
513 struct rte_bbdev_stats stats;
515 for (i = 0; i < nb_active_devs; i++) {
516 dev_id = active_devs[i].dev_id;
517 /* read stats and print */
518 rte_bbdev_stats_get(dev_id, &stats);
519 /* Stop the device */
520 rte_bbdev_stop(dev_id);
525 init_op_data_objs(struct rte_bbdev_op_data *bufs,
526 struct op_data_entries *ref_entries,
527 struct rte_mempool *mbuf_pool, const uint16_t n,
528 enum op_data_type op_type, uint16_t min_alignment)
533 for (i = 0; i < n; ++i) {
535 struct op_data_buf *seg = &ref_entries->segments[0];
536 struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
537 TEST_ASSERT_NOT_NULL(m_head,
538 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
539 op_type, n * ref_entries->nb_segments,
542 bufs[i].data = m_head;
546 if (op_type == DATA_INPUT) {
547 data = rte_pktmbuf_append(m_head, seg->length);
548 TEST_ASSERT_NOT_NULL(data,
549 "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
550 seg->length, op_type);
552 TEST_ASSERT(data == RTE_PTR_ALIGN(data, min_alignment),
553 "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
554 data, min_alignment);
555 rte_memcpy(data, seg->addr, seg->length);
556 bufs[i].length += seg->length;
559 for (j = 1; j < ref_entries->nb_segments; ++j) {
560 struct rte_mbuf *m_tail =
561 rte_pktmbuf_alloc(mbuf_pool);
562 TEST_ASSERT_NOT_NULL(m_tail,
563 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
565 n * ref_entries->nb_segments,
569 data = rte_pktmbuf_append(m_tail, seg->length);
570 TEST_ASSERT_NOT_NULL(data,
571 "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
572 seg->length, op_type);
574 TEST_ASSERT(data == RTE_PTR_ALIGN(data,
576 "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
577 data, min_alignment);
578 rte_memcpy(data, seg->addr, seg->length);
579 bufs[i].length += seg->length;
581 ret = rte_pktmbuf_chain(m_head, m_tail);
582 TEST_ASSERT_SUCCESS(ret,
583 "Couldn't chain mbufs from %d data type mbuf pool",
593 allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len,
598 *buffers = rte_zmalloc_socket(NULL, len, 0, socket);
599 if (*buffers == NULL) {
600 printf("WARNING: Failed to allocate op_data on socket %d\n",
602 /* try to allocate memory on other detected sockets */
603 for (i = 0; i < socket; i++) {
604 *buffers = rte_zmalloc_socket(NULL, len, 0, i);
605 if (*buffers != NULL)
610 return (*buffers == NULL) ? TEST_FAILED : TEST_SUCCESS;
614 limit_input_llr_val_range(struct rte_bbdev_op_data *input_ops,
615 uint16_t n, int8_t max_llr_modulus)
617 uint16_t i, byte_idx;
619 for (i = 0; i < n; ++i) {
620 struct rte_mbuf *m = input_ops[i].data;
622 int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
623 input_ops[i].offset);
624 for (byte_idx = 0; byte_idx < input_ops[i].length;
626 llr[byte_idx] = round((double)max_llr_modulus *
627 llr[byte_idx] / INT8_MAX);
635 fill_queue_buffers(struct test_op_params *op_params,
636 struct rte_mempool *in_mp, struct rte_mempool *hard_out_mp,
637 struct rte_mempool *soft_out_mp, uint16_t queue_id,
638 const struct rte_bbdev_op_cap *capabilities,
639 uint16_t min_alignment, const int socket_id)
642 enum op_data_type type;
643 const uint16_t n = op_params->num_to_process;
645 struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {
651 struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {
652 &op_params->q_bufs[socket_id][queue_id].inputs,
653 &op_params->q_bufs[socket_id][queue_id].soft_outputs,
654 &op_params->q_bufs[socket_id][queue_id].hard_outputs,
657 for (type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) {
658 struct op_data_entries *ref_entries =
659 &test_vector.entries[type];
660 if (ref_entries->nb_segments == 0)
663 ret = allocate_buffers_on_socket(queue_ops[type],
664 n * sizeof(struct rte_bbdev_op_data),
666 TEST_ASSERT_SUCCESS(ret,
667 "Couldn't allocate memory for rte_bbdev_op_data structs");
669 ret = init_op_data_objs(*queue_ops[type], ref_entries,
670 mbuf_pools[type], n, type, min_alignment);
671 TEST_ASSERT_SUCCESS(ret,
672 "Couldn't init rte_bbdev_op_data structs");
675 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
676 limit_input_llr_val_range(*queue_ops[DATA_INPUT], n,
677 capabilities->cap.turbo_dec.max_llr_modulus);
683 free_buffers(struct active_device *ad, struct test_op_params *op_params)
687 rte_mempool_free(ad->ops_mempool);
688 rte_mempool_free(ad->in_mbuf_pool);
689 rte_mempool_free(ad->hard_out_mbuf_pool);
690 rte_mempool_free(ad->soft_out_mbuf_pool);
692 for (i = 0; i < rte_lcore_count(); ++i) {
693 for (j = 0; j < RTE_MAX_NUMA_NODES; ++j) {
694 rte_free(op_params->q_bufs[j][i].inputs);
695 rte_free(op_params->q_bufs[j][i].hard_outputs);
696 rte_free(op_params->q_bufs[j][i].soft_outputs);
702 copy_reference_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
703 unsigned int start_idx,
704 struct rte_bbdev_op_data *inputs,
705 struct rte_bbdev_op_data *hard_outputs,
706 struct rte_bbdev_op_data *soft_outputs,
707 struct rte_bbdev_dec_op *ref_op)
710 struct rte_bbdev_op_turbo_dec *turbo_dec = &ref_op->turbo_dec;
712 for (i = 0; i < n; ++i) {
713 if (turbo_dec->code_block_mode == 0) {
714 ops[i]->turbo_dec.tb_params.ea =
715 turbo_dec->tb_params.ea;
716 ops[i]->turbo_dec.tb_params.eb =
717 turbo_dec->tb_params.eb;
718 ops[i]->turbo_dec.tb_params.k_pos =
719 turbo_dec->tb_params.k_pos;
720 ops[i]->turbo_dec.tb_params.k_neg =
721 turbo_dec->tb_params.k_neg;
722 ops[i]->turbo_dec.tb_params.c =
723 turbo_dec->tb_params.c;
724 ops[i]->turbo_dec.tb_params.c_neg =
725 turbo_dec->tb_params.c_neg;
726 ops[i]->turbo_dec.tb_params.cab =
727 turbo_dec->tb_params.cab;
729 ops[i]->turbo_dec.cb_params.e = turbo_dec->cb_params.e;
730 ops[i]->turbo_dec.cb_params.k = turbo_dec->cb_params.k;
733 ops[i]->turbo_dec.ext_scale = turbo_dec->ext_scale;
734 ops[i]->turbo_dec.iter_max = turbo_dec->iter_max;
735 ops[i]->turbo_dec.iter_min = turbo_dec->iter_min;
736 ops[i]->turbo_dec.op_flags = turbo_dec->op_flags;
737 ops[i]->turbo_dec.rv_index = turbo_dec->rv_index;
738 ops[i]->turbo_dec.num_maps = turbo_dec->num_maps;
739 ops[i]->turbo_dec.code_block_mode = turbo_dec->code_block_mode;
741 ops[i]->turbo_dec.hard_output = hard_outputs[start_idx + i];
742 ops[i]->turbo_dec.input = inputs[start_idx + i];
743 if (soft_outputs != NULL)
744 ops[i]->turbo_dec.soft_output =
745 soft_outputs[start_idx + i];
750 copy_reference_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
751 unsigned int start_idx,
752 struct rte_bbdev_op_data *inputs,
753 struct rte_bbdev_op_data *outputs,
754 struct rte_bbdev_enc_op *ref_op)
757 struct rte_bbdev_op_turbo_enc *turbo_enc = &ref_op->turbo_enc;
758 for (i = 0; i < n; ++i) {
759 if (turbo_enc->code_block_mode == 0) {
760 ops[i]->turbo_enc.tb_params.ea =
761 turbo_enc->tb_params.ea;
762 ops[i]->turbo_enc.tb_params.eb =
763 turbo_enc->tb_params.eb;
764 ops[i]->turbo_enc.tb_params.k_pos =
765 turbo_enc->tb_params.k_pos;
766 ops[i]->turbo_enc.tb_params.k_neg =
767 turbo_enc->tb_params.k_neg;
768 ops[i]->turbo_enc.tb_params.c =
769 turbo_enc->tb_params.c;
770 ops[i]->turbo_enc.tb_params.c_neg =
771 turbo_enc->tb_params.c_neg;
772 ops[i]->turbo_enc.tb_params.cab =
773 turbo_enc->tb_params.cab;
774 ops[i]->turbo_enc.tb_params.ncb_pos =
775 turbo_enc->tb_params.ncb_pos;
776 ops[i]->turbo_enc.tb_params.ncb_neg =
777 turbo_enc->tb_params.ncb_neg;
778 ops[i]->turbo_enc.tb_params.r = turbo_enc->tb_params.r;
780 ops[i]->turbo_enc.cb_params.e = turbo_enc->cb_params.e;
781 ops[i]->turbo_enc.cb_params.k = turbo_enc->cb_params.k;
782 ops[i]->turbo_enc.cb_params.ncb =
783 turbo_enc->cb_params.ncb;
785 ops[i]->turbo_enc.rv_index = turbo_enc->rv_index;
786 ops[i]->turbo_enc.op_flags = turbo_enc->op_flags;
787 ops[i]->turbo_enc.code_block_mode = turbo_enc->code_block_mode;
789 ops[i]->turbo_enc.output = outputs[start_idx + i];
790 ops[i]->turbo_enc.input = inputs[start_idx + i];
795 check_dec_status_and_ordering(struct rte_bbdev_dec_op *op,
796 unsigned int order_idx, const int expected_status)
798 TEST_ASSERT(op->status == expected_status,
799 "op_status (%d) != expected_status (%d)",
800 op->status, expected_status);
802 TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
803 "Ordering error, expected %p, got %p",
804 (void *)(uintptr_t)order_idx, op->opaque_data);
810 check_enc_status_and_ordering(struct rte_bbdev_enc_op *op,
811 unsigned int order_idx, const int expected_status)
813 TEST_ASSERT(op->status == expected_status,
814 "op_status (%d) != expected_status (%d)",
815 op->status, expected_status);
817 TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
818 "Ordering error, expected %p, got %p",
819 (void *)(uintptr_t)order_idx, op->opaque_data);
825 validate_op_chain(struct rte_bbdev_op_data *op,
826 struct op_data_entries *orig_op)
829 struct rte_mbuf *m = op->data;
830 uint8_t nb_dst_segments = orig_op->nb_segments;
832 TEST_ASSERT(nb_dst_segments == m->nb_segs,
833 "Number of segments differ in original (%u) and filled (%u) op",
834 nb_dst_segments, m->nb_segs);
836 for (i = 0; i < nb_dst_segments; ++i) {
837 /* Apply offset to the first mbuf segment */
838 uint16_t offset = (i == 0) ? op->offset : 0;
839 uint16_t data_len = m->data_len - offset;
841 TEST_ASSERT(orig_op->segments[i].length == data_len,
842 "Length of segment differ in original (%u) and filled (%u) op",
843 orig_op->segments[i].length, data_len);
844 TEST_ASSERT_BUFFERS_ARE_EQUAL(orig_op->segments[i].addr,
845 rte_pktmbuf_mtod_offset(m, uint32_t *, offset),
847 "Output buffers (CB=%u) are not equal", i);
855 validate_dec_buffers(struct rte_bbdev_dec_op *ref_op, struct test_buffers *bufs,
856 const uint16_t num_to_process)
860 struct op_data_entries *hard_data_orig =
861 &test_vector.entries[DATA_HARD_OUTPUT];
862 struct op_data_entries *soft_data_orig =
863 &test_vector.entries[DATA_SOFT_OUTPUT];
865 for (i = 0; i < num_to_process; i++) {
866 TEST_ASSERT_SUCCESS(validate_op_chain(&bufs->hard_outputs[i],
868 "Hard output buffers are not equal");
869 if (ref_op->turbo_dec.op_flags &
870 RTE_BBDEV_TURBO_SOFT_OUTPUT)
871 TEST_ASSERT_SUCCESS(validate_op_chain(
872 &bufs->soft_outputs[i],
874 "Soft output buffers are not equal");
881 validate_enc_buffers(struct test_buffers *bufs, const uint16_t num_to_process)
885 struct op_data_entries *hard_data_orig =
886 &test_vector.entries[DATA_HARD_OUTPUT];
888 for (i = 0; i < num_to_process; i++)
889 TEST_ASSERT_SUCCESS(validate_op_chain(&bufs->hard_outputs[i],
890 hard_data_orig), "");
896 validate_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
897 struct rte_bbdev_dec_op *ref_op, const int vector_mask)
901 struct op_data_entries *hard_data_orig =
902 &test_vector.entries[DATA_HARD_OUTPUT];
903 struct op_data_entries *soft_data_orig =
904 &test_vector.entries[DATA_SOFT_OUTPUT];
905 struct rte_bbdev_op_turbo_dec *ops_td;
906 struct rte_bbdev_op_data *hard_output;
907 struct rte_bbdev_op_data *soft_output;
908 struct rte_bbdev_op_turbo_dec *ref_td = &ref_op->turbo_dec;
910 for (i = 0; i < n; ++i) {
911 ops_td = &ops[i]->turbo_dec;
912 hard_output = &ops_td->hard_output;
913 soft_output = &ops_td->soft_output;
915 if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
916 TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
917 "Returned iter_count (%d) > expected iter_count (%d)",
918 ops_td->iter_count, ref_td->iter_count);
919 ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
920 TEST_ASSERT_SUCCESS(ret,
921 "Checking status and ordering for decoder failed");
923 TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
925 "Hard output buffers (CB=%u) are not equal",
928 if (ref_op->turbo_dec.op_flags & RTE_BBDEV_TURBO_SOFT_OUTPUT)
929 TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
931 "Soft output buffers (CB=%u) are not equal",
939 validate_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
940 struct rte_bbdev_enc_op *ref_op)
944 struct op_data_entries *hard_data_orig =
945 &test_vector.entries[DATA_HARD_OUTPUT];
947 for (i = 0; i < n; ++i) {
948 ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
949 TEST_ASSERT_SUCCESS(ret,
950 "Checking status and ordering for encoder failed");
951 TEST_ASSERT_SUCCESS(validate_op_chain(
952 &ops[i]->turbo_enc.output,
954 "Output buffers (CB=%u) are not equal",
962 create_reference_dec_op(struct rte_bbdev_dec_op *op)
965 struct op_data_entries *entry;
967 op->turbo_dec = test_vector.turbo_dec;
968 entry = &test_vector.entries[DATA_INPUT];
969 for (i = 0; i < entry->nb_segments; ++i)
970 op->turbo_dec.input.length +=
971 entry->segments[i].length;
975 create_reference_enc_op(struct rte_bbdev_enc_op *op)
978 struct op_data_entries *entry;
980 op->turbo_enc = test_vector.turbo_enc;
981 entry = &test_vector.entries[DATA_INPUT];
982 for (i = 0; i < entry->nb_segments; ++i)
983 op->turbo_enc.input.length +=
984 entry->segments[i].length;
988 init_test_op_params(struct test_op_params *op_params,
989 enum rte_bbdev_op_type op_type, const int expected_status,
990 const int vector_mask, struct rte_mempool *ops_mp,
991 uint16_t burst_sz, uint16_t num_to_process, uint16_t num_lcores)
994 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
995 ret = rte_bbdev_dec_op_alloc_bulk(ops_mp,
996 &op_params->ref_dec_op, 1);
998 ret = rte_bbdev_enc_op_alloc_bulk(ops_mp,
999 &op_params->ref_enc_op, 1);
1001 TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed");
1003 op_params->mp = ops_mp;
1004 op_params->burst_sz = burst_sz;
1005 op_params->num_to_process = num_to_process;
1006 op_params->num_lcores = num_lcores;
1007 op_params->vector_mask = vector_mask;
1008 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
1009 op_params->ref_dec_op->status = expected_status;
1010 else if (op_type == RTE_BBDEV_OP_TURBO_ENC)
1011 op_params->ref_enc_op->status = expected_status;
1017 run_test_case_on_device(test_case_function *test_case_func, uint8_t dev_id,
1018 struct test_op_params *op_params)
1020 int t_ret, f_ret, socket_id = SOCKET_ID_ANY;
1022 struct active_device *ad;
1023 unsigned int burst_sz = get_burst_sz();
1024 enum rte_bbdev_op_type op_type = test_vector.op_type;
1025 const struct rte_bbdev_op_cap *capabilities = NULL;
1027 ad = &active_devs[dev_id];
1029 /* Check if device supports op_type */
1030 if (!is_avail_op(ad, test_vector.op_type))
1031 return TEST_SUCCESS;
1033 struct rte_bbdev_info info;
1034 rte_bbdev_info_get(ad->dev_id, &info);
1035 socket_id = GET_SOCKET(info.socket_id);
1037 if (op_type == RTE_BBDEV_OP_NONE)
1038 op_type = RTE_BBDEV_OP_TURBO_ENC;
1039 f_ret = create_mempools(ad, socket_id, op_type,
1041 if (f_ret != TEST_SUCCESS) {
1042 printf("Couldn't create mempools");
1046 f_ret = init_test_op_params(op_params, test_vector.op_type,
1047 test_vector.expected_status,
1053 if (f_ret != TEST_SUCCESS) {
1054 printf("Couldn't init test op params");
1058 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
1059 /* Find Decoder capabilities */
1060 const struct rte_bbdev_op_cap *cap = info.drv.capabilities;
1061 while (cap->type != RTE_BBDEV_OP_NONE) {
1062 if (cap->type == RTE_BBDEV_OP_TURBO_DEC) {
1067 TEST_ASSERT_NOT_NULL(capabilities,
1068 "Couldn't find Decoder capabilities");
1070 create_reference_dec_op(op_params->ref_dec_op);
1071 } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
1072 create_reference_enc_op(op_params->ref_enc_op);
1074 for (i = 0; i < ad->nb_queues; ++i) {
1075 f_ret = fill_queue_buffers(op_params,
1077 ad->hard_out_mbuf_pool,
1078 ad->soft_out_mbuf_pool,
1081 info.drv.min_alignment,
1083 if (f_ret != TEST_SUCCESS) {
1084 printf("Couldn't init queue buffers");
1089 /* Run test case function */
1090 t_ret = test_case_func(ad, op_params);
1092 /* Free active device resources and return */
1093 free_buffers(ad, op_params);
1097 free_buffers(ad, op_params);
1101 /* Run given test function per active device per supported op type
1105 run_test_case(test_case_function *test_case_func)
1110 /* Alloc op_params */
1111 struct test_op_params *op_params = rte_zmalloc(NULL,
1112 sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE);
1113 TEST_ASSERT_NOT_NULL(op_params, "Failed to alloc %zuB for op_params",
1114 RTE_ALIGN(sizeof(struct test_op_params),
1115 RTE_CACHE_LINE_SIZE));
1117 /* For each device run test case function */
1118 for (dev = 0; dev < nb_active_devs; ++dev)
1119 ret |= run_test_case_on_device(test_case_func, dev, op_params);
1121 rte_free(op_params);
1127 dequeue_event_callback(uint16_t dev_id,
1128 enum rte_bbdev_event_type event, void *cb_arg,
1133 uint64_t total_time;
1134 uint16_t deq, burst_sz, num_to_process;
1135 uint16_t queue_id = INVALID_QUEUE_ID;
1136 struct rte_bbdev_dec_op *dec_ops[MAX_BURST];
1137 struct rte_bbdev_enc_op *enc_ops[MAX_BURST];
1138 struct test_buffers *bufs;
1139 struct rte_bbdev_info info;
1141 /* Input length in bytes, million operations per second,
1142 * million bits per second.
1146 struct thread_params *tp = cb_arg;
1148 RTE_SET_USED(ret_param);
1149 queue_id = tp->queue_id;
1151 /* Find matching thread params using queue_id */
1152 for (i = 0; i < MAX_QUEUES; ++i, ++tp)
1153 if (tp->queue_id == queue_id)
1156 if (i == MAX_QUEUES) {
1157 printf("%s: Queue_id from interrupt details was not found!\n",
1162 if (unlikely(event != RTE_BBDEV_EVENT_DEQUEUE)) {
1163 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1165 "Dequeue interrupt handler called for incorrect event!\n");
1169 burst_sz = tp->op_params->burst_sz;
1170 num_to_process = tp->op_params->num_to_process;
1172 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1173 deq = rte_bbdev_dequeue_dec_ops(dev_id, queue_id, dec_ops,
1176 deq = rte_bbdev_dequeue_enc_ops(dev_id, queue_id, enc_ops,
1179 if (deq < burst_sz) {
1181 "After receiving the interrupt all operations should be dequeued. Expected: %u, got: %u\n",
1183 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1187 if (rte_atomic16_read(&tp->nb_dequeued) + deq < num_to_process) {
1188 rte_atomic16_add(&tp->nb_dequeued, deq);
1192 total_time = rte_rdtsc_precise() - tp->start_time;
1194 rte_bbdev_info_get(dev_id, &info);
1196 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1199 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1200 ret = validate_dec_buffers(tp->op_params->ref_dec_op, bufs,
1202 else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
1203 ret = validate_enc_buffers(bufs, num_to_process);
1206 printf("Buffers validation failed\n");
1207 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1210 switch (test_vector.op_type) {
1211 case RTE_BBDEV_OP_TURBO_DEC:
1212 in_len = tp->op_params->ref_dec_op->turbo_dec.input.length;
1214 case RTE_BBDEV_OP_TURBO_ENC:
1215 in_len = tp->op_params->ref_enc_op->turbo_enc.input.length;
1217 case RTE_BBDEV_OP_NONE:
1221 printf("Unknown op type: %d\n", test_vector.op_type);
1222 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1226 tp->mops = ((double)num_to_process / 1000000.0) /
1227 ((double)total_time / (double)rte_get_tsc_hz());
1228 tp->mbps = ((double)num_to_process * in_len * 8 / 1000000.0) /
1229 ((double)total_time / (double)rte_get_tsc_hz());
1231 rte_atomic16_add(&tp->nb_dequeued, deq);
1235 throughput_intr_lcore_dec(void *arg)
1237 struct thread_params *tp = arg;
1238 unsigned int enqueued;
1239 struct rte_bbdev_dec_op *ops[MAX_BURST];
1240 const uint16_t queue_id = tp->queue_id;
1241 const uint16_t burst_sz = tp->op_params->burst_sz;
1242 const uint16_t num_to_process = tp->op_params->num_to_process;
1243 struct test_buffers *bufs = NULL;
1244 unsigned int allocs_failed = 0;
1245 struct rte_bbdev_info info;
1248 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1249 "BURST_SIZE should be <= %u", MAX_BURST);
1251 TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
1252 "Failed to enable interrupts for dev: %u, queue_id: %u",
1253 tp->dev_id, queue_id);
1255 rte_bbdev_info_get(tp->dev_id, &info);
1256 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1258 rte_atomic16_clear(&tp->processing_status);
1259 rte_atomic16_clear(&tp->nb_dequeued);
1261 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1264 tp->start_time = rte_rdtsc_precise();
1265 for (enqueued = 0; enqueued < num_to_process;) {
1267 uint16_t num_to_enq = burst_sz;
1269 if (unlikely(num_to_process - enqueued < num_to_enq))
1270 num_to_enq = num_to_process - enqueued;
1272 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
1279 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1280 copy_reference_dec_op(ops, num_to_enq, enqueued,
1284 tp->op_params->ref_dec_op);
1286 enqueued += rte_bbdev_enqueue_dec_ops(tp->dev_id, queue_id, ops,
1289 rte_bbdev_dec_op_free_bulk(ops, num_to_enq);
1292 if (allocs_failed > 0)
1293 printf("WARNING: op allocations failed: %u times\n",
1296 return TEST_SUCCESS;
1300 throughput_intr_lcore_enc(void *arg)
1302 struct thread_params *tp = arg;
1303 unsigned int enqueued;
1304 struct rte_bbdev_enc_op *ops[MAX_BURST];
1305 const uint16_t queue_id = tp->queue_id;
1306 const uint16_t burst_sz = tp->op_params->burst_sz;
1307 const uint16_t num_to_process = tp->op_params->num_to_process;
1308 struct test_buffers *bufs = NULL;
1309 unsigned int allocs_failed = 0;
1310 struct rte_bbdev_info info;
1313 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1314 "BURST_SIZE should be <= %u", MAX_BURST);
1316 TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
1317 "Failed to enable interrupts for dev: %u, queue_id: %u",
1318 tp->dev_id, queue_id);
1320 rte_bbdev_info_get(tp->dev_id, &info);
1321 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1323 rte_atomic16_clear(&tp->processing_status);
1324 rte_atomic16_clear(&tp->nb_dequeued);
1326 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1329 tp->start_time = rte_rdtsc_precise();
1330 for (enqueued = 0; enqueued < num_to_process;) {
1332 uint16_t num_to_enq = burst_sz;
1334 if (unlikely(num_to_process - enqueued < num_to_enq))
1335 num_to_enq = num_to_process - enqueued;
1337 ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
1344 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1345 copy_reference_enc_op(ops, num_to_enq, enqueued,
1348 tp->op_params->ref_enc_op);
1350 enqueued += rte_bbdev_enqueue_enc_ops(tp->dev_id, queue_id, ops,
1353 rte_bbdev_enc_op_free_bulk(ops, num_to_enq);
1356 if (allocs_failed > 0)
1357 printf("WARNING: op allocations failed: %u times\n",
1360 return TEST_SUCCESS;
1364 throughput_pmd_lcore_dec(void *arg)
1366 struct thread_params *tp = arg;
1367 unsigned int enqueued, dequeued;
1368 struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1369 uint64_t total_time, start_time;
1370 const uint16_t queue_id = tp->queue_id;
1371 const uint16_t burst_sz = tp->op_params->burst_sz;
1372 const uint16_t num_to_process = tp->op_params->num_to_process;
1373 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
1374 struct test_buffers *bufs = NULL;
1375 unsigned int allocs_failed = 0;
1377 struct rte_bbdev_info info;
1379 /* Input length in bytes, million operations per second, million bits
1384 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1385 "BURST_SIZE should be <= %u", MAX_BURST);
1387 rte_bbdev_info_get(tp->dev_id, &info);
1388 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1390 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1393 start_time = rte_rdtsc_precise();
1394 for (enqueued = 0, dequeued = 0; dequeued < num_to_process;) {
1397 if (likely(enqueued < num_to_process)) {
1399 uint16_t num_to_enq = burst_sz;
1401 if (unlikely(num_to_process - enqueued < num_to_enq))
1402 num_to_enq = num_to_process - enqueued;
1404 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp,
1405 ops_enq, num_to_enq);
1411 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1412 copy_reference_dec_op(ops_enq, num_to_enq,
1419 enqueued += rte_bbdev_enqueue_dec_ops(tp->dev_id,
1420 queue_id, ops_enq, num_to_enq);
1423 deq = rte_bbdev_dequeue_dec_ops(tp->dev_id, queue_id, ops_deq,
1426 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
1428 total_time = rte_rdtsc_precise() - start_time;
1430 if (allocs_failed > 0)
1431 printf("WARNING: op allocations failed: %u times\n",
1434 TEST_ASSERT(enqueued == dequeued, "enqueued (%u) != dequeued (%u)",
1435 enqueued, dequeued);
1437 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1438 ret = validate_dec_buffers(ref_op, bufs, num_to_process);
1439 TEST_ASSERT_SUCCESS(ret, "Buffers validation failed");
1442 in_len = ref_op->turbo_dec.input.length;
1443 tp->mops = ((double)num_to_process / 1000000.0) /
1444 ((double)total_time / (double)rte_get_tsc_hz());
1445 tp->mbps = ((double)num_to_process * in_len * 8 / 1000000.0) /
1446 ((double)total_time / (double)rte_get_tsc_hz());
1448 return TEST_SUCCESS;
1452 throughput_pmd_lcore_enc(void *arg)
1454 struct thread_params *tp = arg;
1455 unsigned int enqueued, dequeued;
1456 struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1457 uint64_t total_time, start_time;
1458 const uint16_t queue_id = tp->queue_id;
1459 const uint16_t burst_sz = tp->op_params->burst_sz;
1460 const uint16_t num_to_process = tp->op_params->num_to_process;
1461 struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
1462 struct test_buffers *bufs = NULL;
1463 unsigned int allocs_failed = 0;
1465 struct rte_bbdev_info info;
1467 /* Input length in bytes, million operations per second, million bits
1472 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1473 "BURST_SIZE should be <= %u", MAX_BURST);
1475 rte_bbdev_info_get(tp->dev_id, &info);
1476 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1478 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1481 start_time = rte_rdtsc_precise();
1482 for (enqueued = 0, dequeued = 0; dequeued < num_to_process;) {
1485 if (likely(enqueued < num_to_process)) {
1487 uint16_t num_to_enq = burst_sz;
1489 if (unlikely(num_to_process - enqueued < num_to_enq))
1490 num_to_enq = num_to_process - enqueued;
1492 ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp,
1493 ops_enq, num_to_enq);
1499 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1500 copy_reference_enc_op(ops_enq, num_to_enq,
1506 enqueued += rte_bbdev_enqueue_enc_ops(tp->dev_id,
1507 queue_id, ops_enq, num_to_enq);
1510 deq = rte_bbdev_dequeue_enc_ops(tp->dev_id, queue_id, ops_deq,
1513 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
1515 total_time = rte_rdtsc_precise() - start_time;
1517 if (allocs_failed > 0)
1518 printf("WARNING: op allocations failed: %u times\n",
1521 TEST_ASSERT(enqueued == dequeued, "enqueued (%u) != dequeued (%u)",
1522 enqueued, dequeued);
1524 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1525 ret = validate_enc_buffers(bufs, num_to_process);
1526 TEST_ASSERT_SUCCESS(ret, "Buffers validation failed");
1529 in_len = ref_op->turbo_enc.input.length;
1531 tp->mops = ((double)num_to_process / 1000000.0) /
1532 ((double)total_time / (double)rte_get_tsc_hz());
1533 tp->mbps = ((double)num_to_process * in_len * 8 / 1000000.0) /
1534 ((double)total_time / (double)rte_get_tsc_hz());
1536 return TEST_SUCCESS;
1539 print_throughput(struct thread_params *t_params, unsigned int used_cores)
1541 unsigned int lcore_id, iter = 0;
1542 double total_mops = 0, total_mbps = 0;
1544 RTE_LCORE_FOREACH(lcore_id) {
1545 if (iter++ >= used_cores)
1547 printf("\tlcore_id: %u, throughput: %.8lg MOPS, %.8lg Mbps\n",
1548 lcore_id, t_params[lcore_id].mops, t_params[lcore_id].mbps);
1549 total_mops += t_params[lcore_id].mops;
1550 total_mbps += t_params[lcore_id].mbps;
1553 "\n\tTotal stats for %u cores: throughput: %.8lg MOPS, %.8lg Mbps\n",
1554 used_cores, total_mops, total_mbps);
1558 * Test function that determines how long an enqueue + dequeue of a burst
1559 * takes on available lcores.
1562 throughput_test(struct active_device *ad,
1563 struct test_op_params *op_params)
1566 unsigned int lcore_id, used_cores = 0;
1567 struct thread_params t_params[MAX_QUEUES];
1568 struct rte_bbdev_info info;
1569 lcore_function_t *throughput_function;
1570 struct thread_params *tp;
1571 uint16_t num_lcores;
1572 const char *op_type_str;
1574 rte_bbdev_info_get(ad->dev_id, &info);
1576 op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
1577 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
1578 test_vector.op_type);
1581 "Throughput test: dev: %s, nb_queues: %u, burst size: %u, num ops: %u, num_lcores: %u, op type: %s, int mode: %s, GHz: %lg\n",
1582 info.dev_name, ad->nb_queues, op_params->burst_sz,
1583 op_params->num_to_process, op_params->num_lcores,
1585 intr_enabled ? "Interrupt mode" : "PMD mode",
1586 (double)rte_get_tsc_hz() / 1000000000.0);
1588 /* Set number of lcores */
1589 num_lcores = (ad->nb_queues < (op_params->num_lcores))
1591 : op_params->num_lcores;
1594 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1595 throughput_function = throughput_intr_lcore_dec;
1597 throughput_function = throughput_intr_lcore_enc;
1599 /* Dequeue interrupt callback registration */
1600 ret = rte_bbdev_callback_register(ad->dev_id,
1601 RTE_BBDEV_EVENT_DEQUEUE, dequeue_event_callback,
1606 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1607 throughput_function = throughput_pmd_lcore_dec;
1609 throughput_function = throughput_pmd_lcore_enc;
1612 rte_atomic16_set(&op_params->sync, SYNC_WAIT);
1614 t_params[rte_lcore_id()].dev_id = ad->dev_id;
1615 t_params[rte_lcore_id()].op_params = op_params;
1616 t_params[rte_lcore_id()].queue_id =
1617 ad->queue_ids[used_cores++];
1619 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1620 if (used_cores >= num_lcores)
1623 t_params[lcore_id].dev_id = ad->dev_id;
1624 t_params[lcore_id].op_params = op_params;
1625 t_params[lcore_id].queue_id = ad->queue_ids[used_cores++];
1627 rte_eal_remote_launch(throughput_function, &t_params[lcore_id],
1631 rte_atomic16_set(&op_params->sync, SYNC_START);
1632 ret = throughput_function(&t_params[rte_lcore_id()]);
1634 /* Master core is always used */
1636 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1637 if (used_cores++ >= num_lcores)
1640 ret |= rte_eal_wait_lcore(lcore_id);
1643 /* Return if test failed */
1647 /* Print throughput if interrupts are disabled and test passed */
1648 if (!intr_enabled) {
1649 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1650 print_throughput(t_params, num_lcores);
1654 /* In interrupt TC we need to wait for the interrupt callback to deqeue
1655 * all pending operations. Skip waiting for queues which reported an
1656 * error using processing_status variable.
1657 * Wait for master lcore operations.
1659 tp = &t_params[rte_lcore_id()];
1660 while ((rte_atomic16_read(&tp->nb_dequeued) <
1661 op_params->num_to_process) &&
1662 (rte_atomic16_read(&tp->processing_status) !=
1666 ret |= rte_atomic16_read(&tp->processing_status);
1668 /* Wait for slave lcores operations */
1670 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1671 tp = &t_params[lcore_id];
1672 if (used_cores++ >= num_lcores)
1675 while ((rte_atomic16_read(&tp->nb_dequeued) <
1676 op_params->num_to_process) &&
1677 (rte_atomic16_read(&tp->processing_status) !=
1681 ret |= rte_atomic16_read(&tp->processing_status);
1684 /* Print throughput if test passed */
1685 if (!ret && test_vector.op_type != RTE_BBDEV_OP_NONE)
1686 print_throughput(t_params, num_lcores);
1692 operation_latency_test_dec(struct rte_mempool *mempool,
1693 struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
1694 int vector_mask, uint16_t dev_id, uint16_t queue_id,
1695 const uint16_t num_to_process, uint16_t burst_sz,
1696 uint64_t *total_time)
1698 int ret = TEST_SUCCESS;
1699 uint16_t i, j, dequeued;
1700 struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1701 uint64_t start_time = 0;
1703 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1704 uint16_t enq = 0, deq = 0;
1705 bool first_time = true;
1707 if (unlikely(num_to_process - dequeued < burst_sz))
1708 burst_sz = num_to_process - dequeued;
1710 rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
1711 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1712 copy_reference_dec_op(ops_enq, burst_sz, dequeued,
1718 /* Set counter to validate the ordering */
1719 for (j = 0; j < burst_sz; ++j)
1720 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
1722 start_time = rte_rdtsc_precise();
1724 enq = rte_bbdev_enqueue_dec_ops(dev_id, queue_id, &ops_enq[enq],
1726 TEST_ASSERT(enq == burst_sz,
1727 "Error enqueueing burst, expected %u, got %u",
1732 deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
1733 &ops_deq[deq], burst_sz - deq);
1734 if (likely(first_time && (deq > 0))) {
1735 *total_time += rte_rdtsc_precise() - start_time;
1738 } while (unlikely(burst_sz != deq));
1740 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1741 ret = validate_dec_op(ops_deq, burst_sz, ref_op,
1743 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
1746 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
1754 operation_latency_test_enc(struct rte_mempool *mempool,
1755 struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
1756 uint16_t dev_id, uint16_t queue_id,
1757 const uint16_t num_to_process, uint16_t burst_sz,
1758 uint64_t *total_time)
1760 int ret = TEST_SUCCESS;
1761 uint16_t i, j, dequeued;
1762 struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1763 uint64_t start_time = 0;
1765 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1766 uint16_t enq = 0, deq = 0;
1767 bool first_time = true;
1769 if (unlikely(num_to_process - dequeued < burst_sz))
1770 burst_sz = num_to_process - dequeued;
1772 rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
1773 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1774 copy_reference_enc_op(ops_enq, burst_sz, dequeued,
1779 /* Set counter to validate the ordering */
1780 for (j = 0; j < burst_sz; ++j)
1781 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
1783 start_time = rte_rdtsc_precise();
1785 enq = rte_bbdev_enqueue_enc_ops(dev_id, queue_id, &ops_enq[enq],
1787 TEST_ASSERT(enq == burst_sz,
1788 "Error enqueueing burst, expected %u, got %u",
1793 deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
1794 &ops_deq[deq], burst_sz - deq);
1795 if (likely(first_time && (deq > 0))) {
1796 *total_time += rte_rdtsc_precise() - start_time;
1799 } while (unlikely(burst_sz != deq));
1801 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1802 ret = validate_enc_op(ops_deq, burst_sz, ref_op);
1803 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
1806 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
1814 operation_latency_test(struct active_device *ad,
1815 struct test_op_params *op_params)
1818 uint16_t burst_sz = op_params->burst_sz;
1819 const uint16_t num_to_process = op_params->num_to_process;
1820 const enum rte_bbdev_op_type op_type = test_vector.op_type;
1821 const uint16_t queue_id = ad->queue_ids[0];
1822 struct test_buffers *bufs = NULL;
1823 struct rte_bbdev_info info;
1824 uint64_t total_time = 0;
1825 const char *op_type_str;
1827 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1828 "BURST_SIZE should be <= %u", MAX_BURST);
1830 rte_bbdev_info_get(ad->dev_id, &info);
1831 bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1833 op_type_str = rte_bbdev_op_type_str(op_type);
1834 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
1837 "Validation/Latency test: dev: %s, burst size: %u, num ops: %u, op type: %s\n",
1838 info.dev_name, burst_sz, num_to_process, op_type_str);
1840 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
1841 iter = operation_latency_test_dec(op_params->mp, bufs,
1842 op_params->ref_dec_op, op_params->vector_mask,
1843 ad->dev_id, queue_id, num_to_process,
1844 burst_sz, &total_time);
1846 iter = operation_latency_test_enc(op_params->mp, bufs,
1847 op_params->ref_enc_op, ad->dev_id, queue_id,
1848 num_to_process, burst_sz, &total_time);
1853 printf("\toperation avg. latency: %lg cycles, %lg us\n",
1854 (double)total_time / (double)iter,
1855 (double)(total_time * 1000000) / (double)iter /
1856 (double)rte_get_tsc_hz());
1858 return TEST_SUCCESS;
1862 offload_latency_test_dec(struct rte_mempool *mempool, struct test_buffers *bufs,
1863 struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
1864 uint16_t queue_id, const uint16_t num_to_process,
1865 uint16_t burst_sz, uint64_t *enq_total_time,
1866 uint64_t *deq_total_time)
1869 struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1870 uint64_t enq_start_time, deq_start_time;
1872 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1873 uint16_t enq = 0, deq = 0;
1875 if (unlikely(num_to_process - dequeued < burst_sz))
1876 burst_sz = num_to_process - dequeued;
1878 rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
1879 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1880 copy_reference_dec_op(ops_enq, burst_sz, dequeued,
1886 /* Start time measurment for enqueue function offload latency */
1887 enq_start_time = rte_rdtsc();
1889 enq += rte_bbdev_enqueue_dec_ops(dev_id, queue_id,
1890 &ops_enq[enq], burst_sz - enq);
1891 } while (unlikely(burst_sz != enq));
1892 *enq_total_time += rte_rdtsc() - enq_start_time;
1894 /* ensure enqueue has been completed */
1897 /* Start time measurment for dequeue function offload latency */
1898 deq_start_time = rte_rdtsc();
1900 deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
1901 &ops_deq[deq], burst_sz - deq);
1902 } while (unlikely(burst_sz != deq));
1903 *deq_total_time += rte_rdtsc() - deq_start_time;
1905 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
1913 offload_latency_test_enc(struct rte_mempool *mempool, struct test_buffers *bufs,
1914 struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
1915 uint16_t queue_id, const uint16_t num_to_process,
1916 uint16_t burst_sz, uint64_t *enq_total_time,
1917 uint64_t *deq_total_time)
1920 struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1921 uint64_t enq_start_time, deq_start_time;
1923 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1924 uint16_t enq = 0, deq = 0;
1926 if (unlikely(num_to_process - dequeued < burst_sz))
1927 burst_sz = num_to_process - dequeued;
1929 rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
1930 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1931 copy_reference_enc_op(ops_enq, burst_sz, dequeued,
1936 /* Start time measurment for enqueue function offload latency */
1937 enq_start_time = rte_rdtsc();
1939 enq += rte_bbdev_enqueue_enc_ops(dev_id, queue_id,
1940 &ops_enq[enq], burst_sz - enq);
1941 } while (unlikely(burst_sz != enq));
1942 *enq_total_time += rte_rdtsc() - enq_start_time;
1944 /* ensure enqueue has been completed */
1947 /* Start time measurment for dequeue function offload latency */
1948 deq_start_time = rte_rdtsc();
1950 deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
1951 &ops_deq[deq], burst_sz - deq);
1952 } while (unlikely(burst_sz != deq));
1953 *deq_total_time += rte_rdtsc() - deq_start_time;
1955 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
1963 offload_latency_test(struct active_device *ad,
1964 struct test_op_params *op_params)
1967 uint64_t enq_total_time = 0, deq_total_time = 0;
1968 uint16_t burst_sz = op_params->burst_sz;
1969 const uint16_t num_to_process = op_params->num_to_process;
1970 const enum rte_bbdev_op_type op_type = test_vector.op_type;
1971 const uint16_t queue_id = ad->queue_ids[0];
1972 struct test_buffers *bufs = NULL;
1973 struct rte_bbdev_info info;
1974 const char *op_type_str;
1976 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1977 "BURST_SIZE should be <= %u", MAX_BURST);
1979 rte_bbdev_info_get(ad->dev_id, &info);
1980 bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1982 op_type_str = rte_bbdev_op_type_str(op_type);
1983 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
1986 "Offload latency test: dev: %s, burst size: %u, num ops: %u, op type: %s\n",
1987 info.dev_name, burst_sz, num_to_process, op_type_str);
1989 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
1990 iter = offload_latency_test_dec(op_params->mp, bufs,
1991 op_params->ref_dec_op, ad->dev_id, queue_id,
1992 num_to_process, burst_sz, &enq_total_time,
1995 iter = offload_latency_test_enc(op_params->mp, bufs,
1996 op_params->ref_enc_op, ad->dev_id, queue_id,
1997 num_to_process, burst_sz, &enq_total_time,
2003 printf("\tenq offload avg. latency: %lg cycles, %lg us\n",
2004 (double)enq_total_time / (double)iter,
2005 (double)(enq_total_time * 1000000) / (double)iter /
2006 (double)rte_get_tsc_hz());
2008 printf("\tdeq offload avg. latency: %lg cycles, %lg us\n",
2009 (double)deq_total_time / (double)iter,
2010 (double)(deq_total_time * 1000000) / (double)iter /
2011 (double)rte_get_tsc_hz());
2013 return TEST_SUCCESS;
2017 offload_latency_empty_q_test_dec(uint16_t dev_id, uint16_t queue_id,
2018 const uint16_t num_to_process, uint16_t burst_sz,
2019 uint64_t *deq_total_time)
2022 struct rte_bbdev_dec_op *ops[MAX_BURST];
2023 uint64_t deq_start_time;
2025 /* Test deq offload latency from an empty queue */
2026 deq_start_time = rte_rdtsc_precise();
2027 for (i = 0, deq_total = 0; deq_total < num_to_process;
2028 ++i, deq_total += burst_sz) {
2029 if (unlikely(num_to_process - deq_total < burst_sz))
2030 burst_sz = num_to_process - deq_total;
2031 rte_bbdev_dequeue_dec_ops(dev_id, queue_id, ops, burst_sz);
2033 *deq_total_time = rte_rdtsc_precise() - deq_start_time;
2039 offload_latency_empty_q_test_enc(uint16_t dev_id, uint16_t queue_id,
2040 const uint16_t num_to_process, uint16_t burst_sz,
2041 uint64_t *deq_total_time)
2044 struct rte_bbdev_enc_op *ops[MAX_BURST];
2045 uint64_t deq_start_time;
2047 /* Test deq offload latency from an empty queue */
2048 deq_start_time = rte_rdtsc_precise();
2049 for (i = 0, deq_total = 0; deq_total < num_to_process;
2050 ++i, deq_total += burst_sz) {
2051 if (unlikely(num_to_process - deq_total < burst_sz))
2052 burst_sz = num_to_process - deq_total;
2053 rte_bbdev_dequeue_enc_ops(dev_id, queue_id, ops, burst_sz);
2055 *deq_total_time = rte_rdtsc_precise() - deq_start_time;
2061 offload_latency_empty_q_test(struct active_device *ad,
2062 struct test_op_params *op_params)
2065 uint64_t deq_total_time = 0;
2066 uint16_t burst_sz = op_params->burst_sz;
2067 const uint16_t num_to_process = op_params->num_to_process;
2068 const enum rte_bbdev_op_type op_type = test_vector.op_type;
2069 const uint16_t queue_id = ad->queue_ids[0];
2070 struct rte_bbdev_info info;
2071 const char *op_type_str;
2073 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2074 "BURST_SIZE should be <= %u", MAX_BURST);
2076 rte_bbdev_info_get(ad->dev_id, &info);
2078 op_type_str = rte_bbdev_op_type_str(op_type);
2079 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
2082 "Offload latency empty dequeue test: dev: %s, burst size: %u, num ops: %u, op type: %s\n",
2083 info.dev_name, burst_sz, num_to_process, op_type_str);
2085 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
2086 iter = offload_latency_empty_q_test_dec(ad->dev_id, queue_id,
2087 num_to_process, burst_sz, &deq_total_time);
2089 iter = offload_latency_empty_q_test_enc(ad->dev_id, queue_id,
2090 num_to_process, burst_sz, &deq_total_time);
2095 printf("\tempty deq offload avg. latency: %lg cycles, %lg us\n",
2096 (double)deq_total_time / (double)iter,
2097 (double)(deq_total_time * 1000000) / (double)iter /
2098 (double)rte_get_tsc_hz());
2100 return TEST_SUCCESS;
2106 return run_test_case(throughput_test);
2110 offload_latency_tc(void)
2112 return run_test_case(offload_latency_test);
2116 offload_latency_empty_q_tc(void)
2118 return run_test_case(offload_latency_empty_q_test);
2122 operation_latency_tc(void)
2124 return run_test_case(operation_latency_test);
2130 return run_test_case(throughput_test);
2133 static struct unit_test_suite bbdev_throughput_testsuite = {
2134 .suite_name = "BBdev Throughput Tests",
2135 .setup = testsuite_setup,
2136 .teardown = testsuite_teardown,
2137 .unit_test_cases = {
2138 TEST_CASE_ST(ut_setup, ut_teardown, throughput_tc),
2139 TEST_CASES_END() /**< NULL terminate unit test array */
2143 static struct unit_test_suite bbdev_validation_testsuite = {
2144 .suite_name = "BBdev Validation Tests",
2145 .setup = testsuite_setup,
2146 .teardown = testsuite_teardown,
2147 .unit_test_cases = {
2148 TEST_CASE_ST(ut_setup, ut_teardown, operation_latency_tc),
2149 TEST_CASES_END() /**< NULL terminate unit test array */
2153 static struct unit_test_suite bbdev_latency_testsuite = {
2154 .suite_name = "BBdev Latency Tests",
2155 .setup = testsuite_setup,
2156 .teardown = testsuite_teardown,
2157 .unit_test_cases = {
2158 TEST_CASE_ST(ut_setup, ut_teardown, offload_latency_tc),
2159 TEST_CASE_ST(ut_setup, ut_teardown, offload_latency_empty_q_tc),
2160 TEST_CASE_ST(ut_setup, ut_teardown, operation_latency_tc),
2161 TEST_CASES_END() /**< NULL terminate unit test array */
2165 static struct unit_test_suite bbdev_interrupt_testsuite = {
2166 .suite_name = "BBdev Interrupt Tests",
2167 .setup = interrupt_testsuite_setup,
2168 .teardown = testsuite_teardown,
2169 .unit_test_cases = {
2170 TEST_CASE_ST(ut_setup, ut_teardown, interrupt_tc),
2171 TEST_CASES_END() /**< NULL terminate unit test array */
2175 REGISTER_TEST_COMMAND(throughput, bbdev_throughput_testsuite);
2176 REGISTER_TEST_COMMAND(validation, bbdev_validation_testsuite);
2177 REGISTER_TEST_COMMAND(latency, bbdev_latency_testsuite);
2178 REGISTER_TEST_COMMAND(interrupt, bbdev_interrupt_testsuite);