4 * Copyright (C) Cavium, Inc 2017.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
16 * * Neither the name of Cavium, Inc nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "test_order_common.h"
36 order_test_result(struct evt_test *test, struct evt_options *opt)
39 struct test_order *t = evt_test_priv(test);
45 order_producer(void *arg)
47 struct prod_data *p = arg;
48 struct test_order *t = p->t;
49 struct evt_options *opt = t->opt;
50 const uint8_t dev_id = p->dev_id;
51 const uint8_t port = p->port_id;
52 struct rte_mempool *pool = t->pool;
53 const uint64_t nb_pkts = t->nb_pkts;
54 uint32_t *producer_flow_seq = t->producer_flow_seq;
55 const uint32_t nb_flows = t->nb_flows;
60 if (opt->verbose_level > 1)
61 printf("%s(): lcore %d dev_id %d port=%d queue=%d\n",
62 __func__, rte_lcore_id(), dev_id, port, p->queue_id);
65 ev.op = RTE_EVENT_OP_NEW;
66 ev.queue_id = p->queue_id;
67 ev.sched_type = RTE_SCHED_TYPE_ORDERED;
68 ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
69 ev.event_type = RTE_EVENT_TYPE_CPU;
70 ev.sub_event_type = 0; /* stage 0 */
72 while (count < nb_pkts && t->err == false) {
73 m = rte_pktmbuf_alloc(pool);
77 const uint32_t flow = (uintptr_t)m % nb_flows;
78 /* Maintain seq number per flow */
79 m->seqn = producer_flow_seq[flow]++;
84 while (rte_event_enqueue_burst(dev_id, port, &ev, 1) != 1) {
96 order_opt_check(struct evt_options *opt)
98 /* 1 producer + N workers + 1 master */
99 if (rte_lcore_count() < 3) {
100 evt_err("test need minimum 3 lcores");
104 /* Validate worker lcores */
105 if (evt_lcores_has_overlap(opt->wlcores, rte_get_master_lcore())) {
106 evt_err("worker lcores overlaps with master lcore");
110 if (evt_nr_active_lcores(opt->plcores) == 0) {
111 evt_err("missing the producer lcore");
115 if (evt_nr_active_lcores(opt->plcores) != 1) {
116 evt_err("only one producer lcore must be selected");
120 int plcore = evt_get_first_active_lcore(opt->plcores);
123 evt_err("failed to find active producer");
127 if (evt_lcores_has_overlap(opt->wlcores, plcore)) {
128 evt_err("worker lcores overlaps producer lcore");
131 if (evt_has_disabled_lcore(opt->wlcores)) {
132 evt_err("one or more workers lcores are not enabled");
135 if (!evt_has_active_lcore(opt->wlcores)) {
136 evt_err("minimum one worker is required");
140 /* Validate producer lcore */
141 if (plcore == (int)rte_get_master_lcore()) {
142 evt_err("producer lcore and master lcore should be different");
145 if (!rte_lcore_is_enabled(plcore)) {
146 evt_err("producer lcore is not enabled");
151 if (opt->nb_pkts == 0)
152 opt->nb_pkts = INT64_MAX;
158 order_test_setup(struct evt_test *test, struct evt_options *opt)
162 test_order = rte_zmalloc_socket(test->name, sizeof(struct test_order),
163 RTE_CACHE_LINE_SIZE, opt->socket_id);
164 if (test_order == NULL) {
165 evt_err("failed to allocate test_order memory");
168 test->test_priv = test_order;
170 struct test_order *t = evt_test_priv(test);
172 t->producer_flow_seq = rte_zmalloc_socket("test_producer_flow_seq",
173 sizeof(*t->producer_flow_seq) * opt->nb_flows,
174 RTE_CACHE_LINE_SIZE, opt->socket_id);
176 if (t->producer_flow_seq == NULL) {
177 evt_err("failed to allocate t->producer_flow_seq memory");
181 t->expected_flow_seq = rte_zmalloc_socket("test_expected_flow_seq",
182 sizeof(*t->expected_flow_seq) * opt->nb_flows,
183 RTE_CACHE_LINE_SIZE, opt->socket_id);
185 if (t->expected_flow_seq == NULL) {
186 evt_err("failed to allocate t->expected_flow_seq memory");
189 rte_atomic64_set(&t->outstand_pkts, opt->nb_pkts);
191 t->nb_pkts = opt->nb_pkts;
192 t->nb_flows = opt->nb_flows;
193 t->result = EVT_TEST_FAILED;
198 rte_free(t->producer_flow_seq);
200 rte_free(test->test_priv);
206 order_test_destroy(struct evt_test *test, struct evt_options *opt)
209 struct test_order *t = evt_test_priv(test);
211 rte_free(t->expected_flow_seq);
212 rte_free(t->producer_flow_seq);
213 rte_free(test->test_priv);
217 order_mempool_setup(struct evt_test *test, struct evt_options *opt)
219 struct test_order *t = evt_test_priv(test);
221 t->pool = rte_pktmbuf_pool_create(test->name, opt->pool_sz,
223 512, /* Use very small mbufs */
225 if (t->pool == NULL) {
226 evt_err("failed to create mempool");
234 order_mempool_destroy(struct evt_test *test, struct evt_options *opt)
237 struct test_order *t = evt_test_priv(test);
239 rte_mempool_free(t->pool);
243 order_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
247 rte_event_dev_stop(opt->dev_id);
248 rte_event_dev_close(opt->dev_id);
252 order_opt_dump(struct evt_options *opt)
254 evt_dump_producer_lcores(opt);
255 evt_dump("nb_wrker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
256 evt_dump_worker_lcores(opt);
257 evt_dump("nb_evdev_ports", "%d", order_nb_event_ports(opt));
261 order_launch_lcores(struct evt_test *test, struct evt_options *opt,
262 int (*worker)(void *))
265 struct test_order *t = evt_test_priv(test);
269 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
270 if (!(opt->wlcores[lcore_id]))
273 ret = rte_eal_remote_launch(worker, &t->worker[wkr_idx],
276 evt_err("failed to launch worker %d", lcore_id);
282 /* launch producer */
283 int plcore = evt_get_first_active_lcore(opt->plcores);
285 ret = rte_eal_remote_launch(order_producer, &t->prod, plcore);
287 evt_err("failed to launch order_producer %d", plcore);
291 uint64_t cycles = rte_get_timer_cycles();
292 int64_t old_remaining = -1;
294 while (t->err == false) {
295 uint64_t new_cycles = rte_get_timer_cycles();
296 int64_t remaining = rte_atomic64_read(&t->outstand_pkts);
298 if (remaining <= 0) {
299 t->result = EVT_TEST_SUCCESS;
303 if (new_cycles - cycles > rte_get_timer_hz() * 1) {
304 printf(CLGRN"\r%"PRId64""CLNRM, remaining);
306 if (old_remaining == remaining) {
307 rte_event_dev_dump(opt->dev_id, stdout);
308 evt_err("No schedules for seconds, deadlock");
313 old_remaining = remaining;
323 order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
324 uint8_t nb_workers, uint8_t nb_queues)
328 struct test_order *t = evt_test_priv(test);
330 /* port configuration */
331 const struct rte_event_port_conf wkr_p_conf = {
332 .dequeue_depth = opt->wkr_deq_dep,
334 .new_event_threshold = 4096,
337 /* setup one port per worker, linking to all queues */
338 for (port = 0; port < nb_workers; port++) {
339 struct worker_data *w = &t->worker[port];
341 w->dev_id = opt->dev_id;
345 ret = rte_event_port_setup(opt->dev_id, port, &wkr_p_conf);
347 evt_err("failed to setup port %d", port);
351 ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0);
352 if (ret != nb_queues) {
353 evt_err("failed to link all queues to port %d", port);
357 /* port for producer, no links */
358 const struct rte_event_port_conf prod_conf = {
361 .new_event_threshold = 1200,
363 struct prod_data *p = &t->prod;
365 p->dev_id = opt->dev_id;
366 p->port_id = port; /* last port */
370 ret = rte_event_port_setup(opt->dev_id, port, &prod_conf);
372 evt_err("failed to setup producer port %d", port);