1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Cavium, Inc
5 #include "test_order_common.h"
8 order_test_result(struct evt_test *test, struct evt_options *opt)
11 struct test_order *t = evt_test_priv(test);
17 order_producer(void *arg)
19 struct prod_data *p = arg;
20 struct test_order *t = p->t;
21 struct evt_options *opt = t->opt;
22 const uint8_t dev_id = p->dev_id;
23 const uint8_t port = p->port_id;
24 struct rte_mempool *pool = t->pool;
25 const uint64_t nb_pkts = t->nb_pkts;
26 uint32_t *producer_flow_seq = t->producer_flow_seq;
27 const uint32_t nb_flows = t->nb_flows;
32 if (opt->verbose_level > 1)
33 printf("%s(): lcore %d dev_id %d port=%d queue=%d\n",
34 __func__, rte_lcore_id(), dev_id, port, p->queue_id);
37 ev.op = RTE_EVENT_OP_NEW;
38 ev.queue_id = p->queue_id;
39 ev.sched_type = RTE_SCHED_TYPE_ORDERED;
40 ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
41 ev.event_type = RTE_EVENT_TYPE_CPU;
42 ev.sub_event_type = 0; /* stage 0 */
44 while (count < nb_pkts && t->err == false) {
45 m = rte_pktmbuf_alloc(pool);
49 const uint32_t flow = (uintptr_t)m % nb_flows;
50 /* Maintain seq number per flow */
51 m->seqn = producer_flow_seq[flow]++;
56 while (rte_event_enqueue_burst(dev_id, port, &ev, 1) != 1) {
68 order_opt_check(struct evt_options *opt)
70 if (opt->prod_type != EVT_PROD_TYPE_SYNT) {
71 evt_err("Invalid producer type '%s' valid producer '%s'",
72 evt_prod_id_to_name(opt->prod_type),
73 evt_prod_id_to_name(EVT_PROD_TYPE_SYNT));
77 /* 1 producer + N workers + 1 master */
78 if (rte_lcore_count() < 3) {
79 evt_err("test need minimum 3 lcores");
83 /* Validate worker lcores */
84 if (evt_lcores_has_overlap(opt->wlcores, rte_get_master_lcore())) {
85 evt_err("worker lcores overlaps with master lcore");
89 if (evt_nr_active_lcores(opt->plcores) == 0) {
90 evt_err("missing the producer lcore");
94 if (evt_nr_active_lcores(opt->plcores) != 1) {
95 evt_err("only one producer lcore must be selected");
99 int plcore = evt_get_first_active_lcore(opt->plcores);
102 evt_err("failed to find active producer");
106 if (evt_lcores_has_overlap(opt->wlcores, plcore)) {
107 evt_err("worker lcores overlaps producer lcore");
110 if (evt_has_disabled_lcore(opt->wlcores)) {
111 evt_err("one or more workers lcores are not enabled");
114 if (!evt_has_active_lcore(opt->wlcores)) {
115 evt_err("minimum one worker is required");
119 /* Validate producer lcore */
120 if (plcore == (int)rte_get_master_lcore()) {
121 evt_err("producer lcore and master lcore should be different");
124 if (!rte_lcore_is_enabled(plcore)) {
125 evt_err("producer lcore is not enabled");
130 if (opt->nb_pkts == 0)
131 opt->nb_pkts = INT64_MAX;
137 order_test_setup(struct evt_test *test, struct evt_options *opt)
141 test_order = rte_zmalloc_socket(test->name, sizeof(struct test_order),
142 RTE_CACHE_LINE_SIZE, opt->socket_id);
143 if (test_order == NULL) {
144 evt_err("failed to allocate test_order memory");
147 test->test_priv = test_order;
149 struct test_order *t = evt_test_priv(test);
151 t->producer_flow_seq = rte_zmalloc_socket("test_producer_flow_seq",
152 sizeof(*t->producer_flow_seq) * opt->nb_flows,
153 RTE_CACHE_LINE_SIZE, opt->socket_id);
155 if (t->producer_flow_seq == NULL) {
156 evt_err("failed to allocate t->producer_flow_seq memory");
160 t->expected_flow_seq = rte_zmalloc_socket("test_expected_flow_seq",
161 sizeof(*t->expected_flow_seq) * opt->nb_flows,
162 RTE_CACHE_LINE_SIZE, opt->socket_id);
164 if (t->expected_flow_seq == NULL) {
165 evt_err("failed to allocate t->expected_flow_seq memory");
168 rte_atomic64_set(&t->outstand_pkts, opt->nb_pkts);
170 t->nb_pkts = opt->nb_pkts;
171 t->nb_flows = opt->nb_flows;
172 t->result = EVT_TEST_FAILED;
177 rte_free(t->producer_flow_seq);
179 rte_free(test->test_priv);
185 order_test_destroy(struct evt_test *test, struct evt_options *opt)
188 struct test_order *t = evt_test_priv(test);
190 rte_free(t->expected_flow_seq);
191 rte_free(t->producer_flow_seq);
192 rte_free(test->test_priv);
196 order_mempool_setup(struct evt_test *test, struct evt_options *opt)
198 struct test_order *t = evt_test_priv(test);
200 t->pool = rte_pktmbuf_pool_create(test->name, opt->pool_sz,
202 512, /* Use very small mbufs */
204 if (t->pool == NULL) {
205 evt_err("failed to create mempool");
213 order_mempool_destroy(struct evt_test *test, struct evt_options *opt)
216 struct test_order *t = evt_test_priv(test);
218 rte_mempool_free(t->pool);
222 order_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
226 rte_event_dev_stop(opt->dev_id);
227 rte_event_dev_close(opt->dev_id);
231 order_opt_dump(struct evt_options *opt)
233 evt_dump_producer_lcores(opt);
234 evt_dump("nb_wrker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
235 evt_dump_worker_lcores(opt);
236 evt_dump("nb_evdev_ports", "%d", order_nb_event_ports(opt));
240 order_launch_lcores(struct evt_test *test, struct evt_options *opt,
241 int (*worker)(void *))
244 struct test_order *t = evt_test_priv(test);
248 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
249 if (!(opt->wlcores[lcore_id]))
252 ret = rte_eal_remote_launch(worker, &t->worker[wkr_idx],
255 evt_err("failed to launch worker %d", lcore_id);
261 /* launch producer */
262 int plcore = evt_get_first_active_lcore(opt->plcores);
264 ret = rte_eal_remote_launch(order_producer, &t->prod, plcore);
266 evt_err("failed to launch order_producer %d", plcore);
270 uint64_t cycles = rte_get_timer_cycles();
271 int64_t old_remaining = -1;
273 while (t->err == false) {
274 uint64_t new_cycles = rte_get_timer_cycles();
275 int64_t remaining = rte_atomic64_read(&t->outstand_pkts);
277 if (remaining <= 0) {
278 t->result = EVT_TEST_SUCCESS;
282 if (new_cycles - cycles > rte_get_timer_hz() * 1) {
283 printf(CLGRN"\r%"PRId64""CLNRM, remaining);
285 if (old_remaining == remaining) {
286 rte_event_dev_dump(opt->dev_id, stdout);
287 evt_err("No schedules for seconds, deadlock");
292 old_remaining = remaining;
302 order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
303 uint8_t nb_workers, uint8_t nb_queues)
307 struct test_order *t = evt_test_priv(test);
308 struct rte_event_dev_info dev_info;
310 memset(&dev_info, 0, sizeof(struct rte_event_dev_info));
311 ret = rte_event_dev_info_get(opt->dev_id, &dev_info);
313 evt_err("failed to get eventdev info %d", opt->dev_id);
317 if (opt->wkr_deq_dep > dev_info.max_event_port_dequeue_depth)
318 opt->wkr_deq_dep = dev_info.max_event_port_dequeue_depth;
320 /* port configuration */
321 const struct rte_event_port_conf p_conf = {
322 .dequeue_depth = opt->wkr_deq_dep,
323 .enqueue_depth = dev_info.max_event_port_dequeue_depth,
324 .new_event_threshold = dev_info.max_num_events,
327 /* setup one port per worker, linking to all queues */
328 for (port = 0; port < nb_workers; port++) {
329 struct worker_data *w = &t->worker[port];
331 w->dev_id = opt->dev_id;
335 ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
337 evt_err("failed to setup port %d", port);
341 ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0);
342 if (ret != nb_queues) {
343 evt_err("failed to link all queues to port %d", port);
347 struct prod_data *p = &t->prod;
349 p->dev_id = opt->dev_id;
350 p->port_id = port; /* last port */
354 ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
356 evt_err("failed to setup producer port %d", port);