New upstream version 18.02
[deb_dpdk.git] / app / test-eventdev / test_order_common.c
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 uint32_t flow = (uintptr_t)m % nb_flows;
50                 /* Maintain seq number per flow */
51                 m->seqn = producer_flow_seq[flow]++;
52
53                 ev.flow_id = flow;
54                 ev.mbuf = m;
55
56                 while (rte_event_enqueue_burst(dev_id, port, &ev, 1) != 1) {
57                         if (t->err)
58                                 break;
59                         rte_pause();
60                 }
61
62                 count++;
63         }
64         return 0;
65 }
66
67 int
68 order_opt_check(struct evt_options *opt)
69 {
70         /* 1 producer + N workers + 1 master */
71         if (rte_lcore_count() < 3) {
72                 evt_err("test need minimum 3 lcores");
73                 return -1;
74         }
75
76         /* Validate worker lcores */
77         if (evt_lcores_has_overlap(opt->wlcores, rte_get_master_lcore())) {
78                 evt_err("worker lcores overlaps with master lcore");
79                 return -1;
80         }
81
82         if (evt_nr_active_lcores(opt->plcores) == 0) {
83                 evt_err("missing the producer lcore");
84                 return -1;
85         }
86
87         if (evt_nr_active_lcores(opt->plcores) != 1) {
88                 evt_err("only one producer lcore must be selected");
89                 return -1;
90         }
91
92         int plcore = evt_get_first_active_lcore(opt->plcores);
93
94         if (plcore < 0) {
95                 evt_err("failed to find active producer");
96                 return plcore;
97         }
98
99         if (evt_lcores_has_overlap(opt->wlcores, plcore)) {
100                 evt_err("worker lcores overlaps producer lcore");
101                 return -1;
102         }
103         if (evt_has_disabled_lcore(opt->wlcores)) {
104                 evt_err("one or more workers lcores are not enabled");
105                 return -1;
106         }
107         if (!evt_has_active_lcore(opt->wlcores)) {
108                 evt_err("minimum one worker is required");
109                 return -1;
110         }
111
112         /* Validate producer lcore */
113         if (plcore == (int)rte_get_master_lcore()) {
114                 evt_err("producer lcore and master lcore should be different");
115                 return -1;
116         }
117         if (!rte_lcore_is_enabled(plcore)) {
118                 evt_err("producer lcore is not enabled");
119                 return -1;
120         }
121
122         /* Fixups */
123         if (opt->nb_pkts == 0)
124                 opt->nb_pkts = INT64_MAX;
125
126         return 0;
127 }
128
129 int
130 order_test_setup(struct evt_test *test, struct evt_options *opt)
131 {
132         void *test_order;
133
134         test_order = rte_zmalloc_socket(test->name, sizeof(struct test_order),
135                                 RTE_CACHE_LINE_SIZE, opt->socket_id);
136         if (test_order  == NULL) {
137                 evt_err("failed to allocate test_order memory");
138                 goto nomem;
139         }
140         test->test_priv = test_order;
141
142         struct test_order *t = evt_test_priv(test);
143
144         t->producer_flow_seq = rte_zmalloc_socket("test_producer_flow_seq",
145                                  sizeof(*t->producer_flow_seq) * opt->nb_flows,
146                                 RTE_CACHE_LINE_SIZE, opt->socket_id);
147
148         if (t->producer_flow_seq  == NULL) {
149                 evt_err("failed to allocate t->producer_flow_seq memory");
150                 goto prod_nomem;
151         }
152
153         t->expected_flow_seq = rte_zmalloc_socket("test_expected_flow_seq",
154                                  sizeof(*t->expected_flow_seq) * opt->nb_flows,
155                                 RTE_CACHE_LINE_SIZE, opt->socket_id);
156
157         if (t->expected_flow_seq  == NULL) {
158                 evt_err("failed to allocate t->expected_flow_seq memory");
159                 goto exp_nomem;
160         }
161         rte_atomic64_set(&t->outstand_pkts, opt->nb_pkts);
162         t->err = false;
163         t->nb_pkts = opt->nb_pkts;
164         t->nb_flows = opt->nb_flows;
165         t->result = EVT_TEST_FAILED;
166         t->opt = opt;
167         return 0;
168
169 exp_nomem:
170         rte_free(t->producer_flow_seq);
171 prod_nomem:
172         rte_free(test->test_priv);
173 nomem:
174         return -ENOMEM;
175 }
176
177 void
178 order_test_destroy(struct evt_test *test, struct evt_options *opt)
179 {
180         RTE_SET_USED(opt);
181         struct test_order *t = evt_test_priv(test);
182
183         rte_free(t->expected_flow_seq);
184         rte_free(t->producer_flow_seq);
185         rte_free(test->test_priv);
186 }
187
188 int
189 order_mempool_setup(struct evt_test *test, struct evt_options *opt)
190 {
191         struct test_order *t = evt_test_priv(test);
192
193         t->pool  = rte_pktmbuf_pool_create(test->name, opt->pool_sz,
194                                         256 /* Cache */, 0,
195                                         512, /* Use very small mbufs */
196                                         opt->socket_id);
197         if (t->pool == NULL) {
198                 evt_err("failed to create mempool");
199                 return -ENOMEM;
200         }
201
202         return 0;
203 }
204
205 void
206 order_mempool_destroy(struct evt_test *test, struct evt_options *opt)
207 {
208         RTE_SET_USED(opt);
209         struct test_order *t = evt_test_priv(test);
210
211         rte_mempool_free(t->pool);
212 }
213
214 void
215 order_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
216 {
217         RTE_SET_USED(test);
218
219         rte_event_dev_stop(opt->dev_id);
220         rte_event_dev_close(opt->dev_id);
221 }
222
223 void
224 order_opt_dump(struct evt_options *opt)
225 {
226         evt_dump_producer_lcores(opt);
227         evt_dump("nb_wrker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
228         evt_dump_worker_lcores(opt);
229         evt_dump("nb_evdev_ports", "%d", order_nb_event_ports(opt));
230 }
231
232 int
233 order_launch_lcores(struct evt_test *test, struct evt_options *opt,
234                         int (*worker)(void *))
235 {
236         int ret, lcore_id;
237         struct test_order *t = evt_test_priv(test);
238
239         int wkr_idx = 0;
240         /* launch workers */
241         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
242                 if (!(opt->wlcores[lcore_id]))
243                         continue;
244
245                 ret = rte_eal_remote_launch(worker, &t->worker[wkr_idx],
246                                          lcore_id);
247                 if (ret) {
248                         evt_err("failed to launch worker %d", lcore_id);
249                         return ret;
250                 }
251                 wkr_idx++;
252         }
253
254         /* launch producer */
255         int plcore = evt_get_first_active_lcore(opt->plcores);
256
257         ret = rte_eal_remote_launch(order_producer, &t->prod, plcore);
258         if (ret) {
259                 evt_err("failed to launch order_producer %d", plcore);
260                 return ret;
261         }
262
263         uint64_t cycles = rte_get_timer_cycles();
264         int64_t old_remaining  = -1;
265
266         while (t->err == false) {
267                 uint64_t new_cycles = rte_get_timer_cycles();
268                 int64_t remaining = rte_atomic64_read(&t->outstand_pkts);
269
270                 if (remaining <= 0) {
271                         t->result = EVT_TEST_SUCCESS;
272                         break;
273                 }
274
275                 if (new_cycles - cycles > rte_get_timer_hz() * 1) {
276                         printf(CLGRN"\r%"PRId64""CLNRM, remaining);
277                         fflush(stdout);
278                         if (old_remaining == remaining) {
279                                 rte_event_dev_dump(opt->dev_id, stdout);
280                                 evt_err("No schedules for seconds, deadlock");
281                                 t->err = true;
282                                 rte_smp_wmb();
283                                 break;
284                         }
285                         old_remaining = remaining;
286                         cycles = new_cycles;
287                 }
288         }
289         printf("\r");
290
291         return 0;
292 }
293
294 int
295 order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
296                                 uint8_t nb_workers, uint8_t nb_queues)
297 {
298         int ret;
299         uint8_t port;
300         struct test_order *t = evt_test_priv(test);
301
302         /* port configuration */
303         const struct rte_event_port_conf wkr_p_conf = {
304                         .dequeue_depth = opt->wkr_deq_dep,
305                         .enqueue_depth = 64,
306                         .new_event_threshold = 4096,
307         };
308
309         /* setup one port per worker, linking to all queues */
310         for (port = 0; port < nb_workers; port++) {
311                 struct worker_data *w = &t->worker[port];
312
313                 w->dev_id = opt->dev_id;
314                 w->port_id = port;
315                 w->t = t;
316
317                 ret = rte_event_port_setup(opt->dev_id, port, &wkr_p_conf);
318                 if (ret) {
319                         evt_err("failed to setup port %d", port);
320                         return ret;
321                 }
322
323                 ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0);
324                 if (ret != nb_queues) {
325                         evt_err("failed to link all queues to port %d", port);
326                         return -EINVAL;
327                 }
328         }
329         /* port for producer, no links */
330         const struct rte_event_port_conf prod_conf = {
331                         .dequeue_depth = 8,
332                         .enqueue_depth = 32,
333                         .new_event_threshold = 1200,
334         };
335         struct prod_data *p = &t->prod;
336
337         p->dev_id = opt->dev_id;
338         p->port_id = port; /* last port */
339         p->queue_id = 0;
340         p->t = t;
341
342         ret = rte_event_port_setup(opt->dev_id, port, &prod_conf);
343         if (ret) {
344                 evt_err("failed to setup producer port %d", port);
345                 return ret;
346         }
347
348         return ret;
349 }