Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2017 Cavium, Inc
3 : : */
4 : :
5 : : #include <stdalign.h>
6 : :
7 : : #include "test_order_common.h"
8 : :
9 : : int
10 : 0 : order_test_result(struct evt_test *test, struct evt_options *opt)
11 : : {
12 : : RTE_SET_USED(opt);
13 : : struct test_order *t = evt_test_priv(test);
14 : :
15 : 0 : return t->result;
16 : : }
17 : :
18 : : static inline int
19 : 0 : order_producer(void *arg)
20 : : {
21 : : struct prod_data *p = arg;
22 : 0 : struct test_order *t = p->t;
23 : 0 : struct evt_options *opt = t->opt;
24 : 0 : const uint8_t dev_id = p->dev_id;
25 : 0 : const uint8_t port = p->port_id;
26 : 0 : struct rte_mempool *pool = t->pool;
27 : 0 : const uint64_t nb_pkts = t->nb_pkts;
28 : 0 : uint32_t *producer_flow_seq = t->producer_flow_seq;
29 : 0 : const uint32_t nb_flows = t->nb_flows;
30 : : uint64_t count = 0;
31 : : struct rte_mbuf *m;
32 : : struct rte_event ev;
33 : :
34 : 0 : if (opt->verbose_level > 1)
35 : 0 : printf("%s(): lcore %d dev_id %d port=%d queue=%d\n",
36 : 0 : __func__, rte_lcore_id(), dev_id, port, p->queue_id);
37 : :
38 : 0 : ev.event = 0;
39 : : ev.op = RTE_EVENT_OP_NEW;
40 : 0 : ev.queue_id = p->queue_id;
41 : : ev.sched_type = RTE_SCHED_TYPE_ORDERED;
42 : 0 : ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
43 : 0 : ev.event_type = RTE_EVENT_TYPE_CPU;
44 : : ev.sub_event_type = 0; /* stage 0 */
45 : :
46 : 0 : while (count < nb_pkts && t->err == false) {
47 : 0 : m = rte_pktmbuf_alloc(pool);
48 : 0 : if (m == NULL)
49 : 0 : continue;
50 : :
51 : 0 : const flow_id_t flow = (uintptr_t)m % nb_flows;
52 : : /* Maintain seq number per flow */
53 : 0 : *order_mbuf_seqn(t, m) = producer_flow_seq[flow]++;
54 : : order_flow_id_save(t, flow, m, &ev);
55 : :
56 : 0 : while (rte_event_enqueue_burst(dev_id, port, &ev, 1) != 1) {
57 : 0 : if (t->err)
58 : : break;
59 : : rte_pause();
60 : : }
61 : :
62 : 0 : count++;
63 : : }
64 : 0 : return 0;
65 : : }
66 : :
67 : : int
68 : 0 : order_opt_check(struct evt_options *opt)
69 : : {
70 : 0 : if (opt->prod_type != EVT_PROD_TYPE_SYNT) {
71 : 0 : 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));
74 : 0 : return -1;
75 : : }
76 : :
77 : : /* 1 producer + N workers + main */
78 : 0 : if (rte_lcore_count() < 3) {
79 : 0 : evt_err("test need minimum 3 lcores");
80 : 0 : return -1;
81 : : }
82 : :
83 : : /* Validate worker lcores */
84 : 0 : if (evt_lcores_has_overlap(opt->wlcores, rte_get_main_lcore())) {
85 : 0 : evt_err("worker lcores overlaps with main lcore");
86 : 0 : return -1;
87 : : }
88 : :
89 : 0 : if (evt_nr_active_lcores(opt->plcores) == 0) {
90 : 0 : evt_err("missing the producer lcore");
91 : 0 : return -1;
92 : : }
93 : :
94 : 0 : if (evt_nr_active_lcores(opt->plcores) != 1) {
95 : 0 : evt_err("only one producer lcore must be selected");
96 : 0 : return -1;
97 : : }
98 : :
99 : : int plcore = evt_get_first_active_lcore(opt->plcores);
100 : :
101 : 0 : if (plcore < 0) {
102 : 0 : evt_err("failed to find active producer");
103 : 0 : return plcore;
104 : : }
105 : :
106 : : if (evt_lcores_has_overlap(opt->wlcores, plcore)) {
107 : 0 : evt_err("worker lcores overlaps producer lcore");
108 : 0 : return -1;
109 : : }
110 : 0 : if (evt_has_disabled_lcore(opt->wlcores)) {
111 : 0 : evt_err("one or more workers lcores are not enabled");
112 : 0 : return -1;
113 : : }
114 : 0 : if (!evt_has_active_lcore(opt->wlcores)) {
115 : 0 : evt_err("minimum one worker is required");
116 : 0 : return -1;
117 : : }
118 : :
119 : : /* Validate producer lcore */
120 : 0 : if (plcore == (int)rte_get_main_lcore()) {
121 : 0 : evt_err("producer lcore and main lcore should be different");
122 : 0 : return -1;
123 : : }
124 : 0 : if (!rte_lcore_is_enabled(plcore)) {
125 : 0 : evt_err("producer lcore is not enabled");
126 : 0 : return -1;
127 : : }
128 : :
129 : : /* Fixups */
130 : 0 : if (opt->nb_pkts == 0)
131 : 0 : opt->nb_pkts = INT64_MAX;
132 : :
133 : : return 0;
134 : : }
135 : :
136 : : int
137 : 0 : order_test_setup(struct evt_test *test, struct evt_options *opt)
138 : : {
139 : : void *test_order;
140 : : struct test_order *t;
141 : : static const struct rte_mbuf_dynfield flow_id_dynfield_desc = {
142 : : .name = "test_event_dynfield_flow_id",
143 : : .size = sizeof(flow_id_t),
144 : : .align = alignof(flow_id_t),
145 : : };
146 : : static const struct rte_mbuf_dynfield seqn_dynfield_desc = {
147 : : .name = "test_event_dynfield_seqn",
148 : : .size = sizeof(seqn_t),
149 : : .align = alignof(seqn_t),
150 : : };
151 : :
152 : 0 : test_order = rte_zmalloc_socket(test->name, sizeof(struct test_order),
153 : : RTE_CACHE_LINE_SIZE, opt->socket_id);
154 : 0 : if (test_order == NULL) {
155 : 0 : evt_err("failed to allocate test_order memory");
156 : 0 : goto nomem;
157 : : }
158 : 0 : test->test_priv = test_order;
159 : : t = evt_test_priv(test);
160 : :
161 : 0 : t->flow_id_dynfield_offset =
162 : 0 : rte_mbuf_dynfield_register(&flow_id_dynfield_desc);
163 : 0 : if (t->flow_id_dynfield_offset < 0) {
164 : 0 : evt_err("failed to register mbuf field");
165 : 0 : return -rte_errno;
166 : : }
167 : :
168 : 0 : t->seqn_dynfield_offset =
169 : 0 : rte_mbuf_dynfield_register(&seqn_dynfield_desc);
170 : 0 : if (t->seqn_dynfield_offset < 0) {
171 : 0 : evt_err("failed to register mbuf field");
172 : 0 : return -rte_errno;
173 : : }
174 : :
175 : 0 : t->producer_flow_seq = rte_zmalloc_socket("test_producer_flow_seq",
176 : 0 : sizeof(*t->producer_flow_seq) * opt->nb_flows,
177 : : RTE_CACHE_LINE_SIZE, opt->socket_id);
178 : :
179 : 0 : if (t->producer_flow_seq == NULL) {
180 : 0 : evt_err("failed to allocate t->producer_flow_seq memory");
181 : 0 : goto prod_nomem;
182 : : }
183 : :
184 : 0 : t->expected_flow_seq = rte_zmalloc_socket("test_expected_flow_seq",
185 : 0 : sizeof(*t->expected_flow_seq) * opt->nb_flows,
186 : : RTE_CACHE_LINE_SIZE, opt->socket_id);
187 : :
188 : 0 : if (t->expected_flow_seq == NULL) {
189 : 0 : evt_err("failed to allocate t->expected_flow_seq memory");
190 : 0 : goto exp_nomem;
191 : : }
192 : 0 : rte_atomic_store_explicit(&t->outstand_pkts, opt->nb_pkts, rte_memory_order_relaxed);
193 : 0 : t->err = false;
194 : 0 : t->nb_pkts = opt->nb_pkts;
195 : 0 : t->nb_flows = opt->nb_flows;
196 : 0 : t->result = EVT_TEST_FAILED;
197 : 0 : t->opt = opt;
198 : 0 : return 0;
199 : :
200 : : exp_nomem:
201 : 0 : rte_free(t->producer_flow_seq);
202 : 0 : prod_nomem:
203 : 0 : rte_free(test->test_priv);
204 : : nomem:
205 : : return -ENOMEM;
206 : : }
207 : :
208 : : void
209 : 0 : order_test_destroy(struct evt_test *test, struct evt_options *opt)
210 : : {
211 : : RTE_SET_USED(opt);
212 : : struct test_order *t = evt_test_priv(test);
213 : :
214 : 0 : rte_free(t->expected_flow_seq);
215 : 0 : rte_free(t->producer_flow_seq);
216 : 0 : rte_free(test->test_priv);
217 : 0 : }
218 : :
219 : : int
220 : 0 : order_mempool_setup(struct evt_test *test, struct evt_options *opt)
221 : : {
222 : : struct test_order *t = evt_test_priv(test);
223 : :
224 : 0 : t->pool = rte_pktmbuf_pool_create(test->name, opt->pool_sz,
225 : : 256 /* Cache */, 0,
226 : : 512, /* Use very small mbufs */
227 : : opt->socket_id);
228 : 0 : if (t->pool == NULL) {
229 : 0 : evt_err("failed to create mempool");
230 : 0 : return -ENOMEM;
231 : : }
232 : :
233 : : return 0;
234 : : }
235 : :
236 : : void
237 : 0 : order_mempool_destroy(struct evt_test *test, struct evt_options *opt)
238 : : {
239 : : RTE_SET_USED(opt);
240 : : struct test_order *t = evt_test_priv(test);
241 : :
242 : 0 : rte_mempool_free(t->pool);
243 : 0 : }
244 : :
245 : : void
246 : 0 : order_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
247 : : {
248 : : RTE_SET_USED(test);
249 : :
250 : 0 : rte_event_dev_stop(opt->dev_id);
251 : 0 : rte_event_dev_close(opt->dev_id);
252 : 0 : }
253 : :
254 : : void
255 : 0 : order_opt_dump(struct evt_options *opt)
256 : : {
257 : 0 : evt_dump_producer_lcores(opt);
258 : 0 : evt_dump("nb_worker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
259 : 0 : evt_dump_worker_lcores(opt);
260 : : evt_dump("nb_evdev_ports", "%d", order_nb_event_ports(opt));
261 : 0 : }
262 : :
263 : : int
264 : 0 : order_launch_lcores(struct evt_test *test, struct evt_options *opt,
265 : : int (*worker)(void *))
266 : : {
267 : : int ret, lcore_id;
268 : : struct test_order *t = evt_test_priv(test);
269 : :
270 : : int wkr_idx = 0;
271 : : /* launch workers */
272 : 0 : RTE_LCORE_FOREACH_WORKER(lcore_id) {
273 : 0 : if (!(opt->wlcores[lcore_id]))
274 : 0 : continue;
275 : :
276 : 0 : ret = rte_eal_remote_launch(worker, &t->worker[wkr_idx],
277 : : lcore_id);
278 : 0 : if (ret) {
279 : 0 : evt_err("failed to launch worker %d", lcore_id);
280 : 0 : return ret;
281 : : }
282 : 0 : wkr_idx++;
283 : : }
284 : :
285 : : /* launch producer */
286 : 0 : int plcore = evt_get_first_active_lcore(opt->plcores);
287 : :
288 : 0 : ret = rte_eal_remote_launch(order_producer, &t->prod, plcore);
289 : 0 : if (ret) {
290 : 0 : evt_err("failed to launch order_producer %d", plcore);
291 : 0 : return ret;
292 : : }
293 : :
294 : : uint64_t cycles = rte_get_timer_cycles();
295 : : int64_t old_remaining = -1;
296 : :
297 : 0 : while (t->err == false) {
298 : : uint64_t new_cycles = rte_get_timer_cycles();
299 : 0 : int64_t remaining = rte_atomic_load_explicit(&t->outstand_pkts,
300 : : rte_memory_order_relaxed);
301 : :
302 : 0 : if (remaining <= 0) {
303 : 0 : t->result = EVT_TEST_SUCCESS;
304 : 0 : break;
305 : : }
306 : :
307 : 0 : if (new_cycles - cycles > rte_get_timer_hz() * 1) {
308 : : printf(CLGRN"\r%"PRId64""CLNRM, remaining);
309 : 0 : fflush(stdout);
310 : 0 : if (old_remaining == remaining) {
311 : 0 : rte_event_dev_dump(opt->dev_id, stdout);
312 : 0 : evt_err("No schedules for seconds, deadlock");
313 : 0 : t->err = true;
314 : 0 : break;
315 : : }
316 : : old_remaining = remaining;
317 : : cycles = new_cycles;
318 : : }
319 : : }
320 : : printf("\r");
321 : :
322 : 0 : return 0;
323 : : }
324 : :
325 : : int
326 : 0 : order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
327 : : uint8_t nb_workers, uint8_t nb_queues)
328 : : {
329 : : int ret;
330 : : uint8_t port;
331 : : struct test_order *t = evt_test_priv(test);
332 : : struct rte_event_dev_info dev_info;
333 : :
334 : 0 : ret = rte_event_dev_info_get(opt->dev_id, &dev_info);
335 : 0 : if (ret) {
336 : 0 : evt_err("failed to get eventdev info %d", opt->dev_id);
337 : 0 : return ret;
338 : : }
339 : :
340 : 0 : if (opt->wkr_deq_dep > dev_info.max_event_port_dequeue_depth)
341 : 0 : opt->wkr_deq_dep = dev_info.max_event_port_dequeue_depth;
342 : :
343 : : /* port configuration */
344 : 0 : const struct rte_event_port_conf p_conf = {
345 : 0 : .dequeue_depth = opt->wkr_deq_dep,
346 : : .enqueue_depth = dev_info.max_event_port_dequeue_depth,
347 : 0 : .new_event_threshold = dev_info.max_num_events,
348 : : };
349 : :
350 : : /* setup one port per worker, linking to all queues */
351 : 0 : for (port = 0; port < nb_workers; port++) {
352 : 0 : struct worker_data *w = &t->worker[port];
353 : :
354 : 0 : w->dev_id = opt->dev_id;
355 : 0 : w->port_id = port;
356 : 0 : w->t = t;
357 : :
358 : 0 : ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
359 : 0 : if (ret) {
360 : 0 : evt_err("failed to setup port %d", port);
361 : 0 : return ret;
362 : : }
363 : :
364 : 0 : ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0);
365 : 0 : if (ret != nb_queues) {
366 : 0 : evt_err("failed to link all queues to port %d", port);
367 : 0 : return -EINVAL;
368 : : }
369 : : }
370 : : struct prod_data *p = &t->prod;
371 : :
372 : 0 : p->dev_id = opt->dev_id;
373 : 0 : p->port_id = port; /* last port */
374 : 0 : p->queue_id = 0;
375 : 0 : p->t = t;
376 : :
377 : 0 : ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
378 : 0 : if (ret) {
379 : 0 : evt_err("failed to setup producer port %d", port);
380 : 0 : return ret;
381 : : }
382 : :
383 : : return ret;
384 : : }
|