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