app/eventdev: add event port and Rx adapter setup
[dpdk.git] / app / test-eventdev / test_pipeline_common.c
1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * Copyright 2017 Cavium, Inc.
4  */
5
6 #include "test_pipeline_common.h"
7
8 int
9 pipeline_test_result(struct evt_test *test, struct evt_options *opt)
10 {
11         RTE_SET_USED(opt);
12         int i;
13         uint64_t total = 0;
14         struct test_pipeline *t = evt_test_priv(test);
15
16         printf("Packet distribution across worker cores :\n");
17         for (i = 0; i < t->nb_workers; i++)
18                 total += t->worker[i].processed_pkts;
19         for (i = 0; i < t->nb_workers; i++)
20                 printf("Worker %d packets: "CLGRN"%"PRIx64" "CLNRM"percentage:"
21                                 CLGRN" %3.2f\n"CLNRM, i,
22                                 t->worker[i].processed_pkts,
23                                 (((double)t->worker[i].processed_pkts)/total)
24                                 * 100);
25         return t->result;
26 }
27
28 void
29 pipeline_opt_dump(struct evt_options *opt, uint8_t nb_queues)
30 {
31         evt_dump("nb_worker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
32         evt_dump_worker_lcores(opt);
33         evt_dump_nb_stages(opt);
34         evt_dump("nb_evdev_ports", "%d", pipeline_nb_event_ports(opt));
35         evt_dump("nb_evdev_queues", "%d", nb_queues);
36         evt_dump_queue_priority(opt);
37         evt_dump_sched_type_list(opt);
38         evt_dump_producer_type(opt);
39 }
40
41 int
42 pipeline_opt_check(struct evt_options *opt, uint64_t nb_queues)
43 {
44         unsigned int lcores;
45         /*
46          * N worker + 1 master
47          */
48         lcores = 2;
49
50         if (!rte_eth_dev_count()) {
51                 evt_err("test needs minimum 1 ethernet dev");
52                 return -1;
53         }
54
55         if (rte_lcore_count() < lcores) {
56                 evt_err("test need minimum %d lcores", lcores);
57                 return -1;
58         }
59
60         /* Validate worker lcores */
61         if (evt_lcores_has_overlap(opt->wlcores, rte_get_master_lcore())) {
62                 evt_err("worker lcores overlaps with master lcore");
63                 return -1;
64         }
65         if (evt_has_disabled_lcore(opt->wlcores)) {
66                 evt_err("one or more workers lcores are not enabled");
67                 return -1;
68         }
69         if (!evt_has_active_lcore(opt->wlcores)) {
70                 evt_err("minimum one worker is required");
71                 return -1;
72         }
73
74         if (nb_queues > EVT_MAX_QUEUES) {
75                 evt_err("number of queues exceeds %d", EVT_MAX_QUEUES);
76                 return -1;
77         }
78         if (pipeline_nb_event_ports(opt) > EVT_MAX_PORTS) {
79                 evt_err("number of ports exceeds %d", EVT_MAX_PORTS);
80                 return -1;
81         }
82
83         if (evt_has_invalid_stage(opt))
84                 return -1;
85
86         if (evt_has_invalid_sched_type(opt))
87                 return -1;
88
89         return 0;
90 }
91
92 #define NB_RX_DESC                      128
93 #define NB_TX_DESC                      512
94 int
95 pipeline_ethdev_setup(struct evt_test *test, struct evt_options *opt)
96 {
97         int i;
98         uint8_t nb_queues = 1;
99         uint8_t mt_state = 0;
100         struct test_pipeline *t = evt_test_priv(test);
101         struct rte_eth_rxconf rx_conf;
102         struct rte_eth_conf port_conf = {
103                 .rxmode = {
104                         .mq_mode = ETH_MQ_RX_RSS,
105                         .max_rx_pkt_len = ETHER_MAX_LEN,
106                         .offloads = DEV_RX_OFFLOAD_CRC_STRIP,
107                         .ignore_offload_bitfield = 1,
108                 },
109                 .rx_adv_conf = {
110                         .rss_conf = {
111                                 .rss_key = NULL,
112                                 .rss_hf = ETH_RSS_IP,
113                         },
114                 },
115         };
116
117         RTE_SET_USED(opt);
118         if (!rte_eth_dev_count()) {
119                 evt_err("No ethernet ports found.\n");
120                 return -ENODEV;
121         }
122
123         for (i = 0; i < rte_eth_dev_count(); i++) {
124                 struct rte_eth_dev_info dev_info;
125
126                 memset(&dev_info, 0, sizeof(struct rte_eth_dev_info));
127                 rte_eth_dev_info_get(i, &dev_info);
128                 mt_state = !(dev_info.tx_offload_capa &
129                                 DEV_TX_OFFLOAD_MT_LOCKFREE);
130                 rx_conf = dev_info.default_rxconf;
131                 rx_conf.offloads = port_conf.rxmode.offloads;
132
133                 if (rte_eth_dev_configure(i, nb_queues, nb_queues,
134                                         &port_conf)
135                                 < 0) {
136                         evt_err("Failed to configure eth port [%d]\n", i);
137                         return -EINVAL;
138                 }
139
140                 if (rte_eth_rx_queue_setup(i, 0, NB_RX_DESC,
141                                 rte_socket_id(), &rx_conf, t->pool) < 0) {
142                         evt_err("Failed to setup eth port [%d] rx_queue: %d.\n",
143                                         i, 0);
144                         return -EINVAL;
145                 }
146                 if (rte_eth_tx_queue_setup(i, 0, NB_TX_DESC,
147                                         rte_socket_id(), NULL) < 0) {
148                         evt_err("Failed to setup eth port [%d] tx_queue: %d.\n",
149                                         i, 0);
150                         return -EINVAL;
151                 }
152
153                 t->mt_unsafe |= mt_state;
154                 rte_eth_promiscuous_enable(i);
155         }
156
157         return 0;
158 }
159
160 int
161 pipeline_event_port_setup(struct evt_test *test, struct evt_options *opt,
162                 uint8_t *queue_arr, uint8_t nb_queues,
163                 const struct rte_event_port_conf p_conf)
164 {
165         int i;
166         int ret;
167         uint8_t port;
168         struct test_pipeline *t = evt_test_priv(test);
169
170
171         /* setup one port per worker, linking to all queues */
172         for (port = 0; port < evt_nr_active_lcores(opt->wlcores); port++) {
173                 struct worker_data *w = &t->worker[port];
174
175                 w->dev_id = opt->dev_id;
176                 w->port_id = port;
177                 w->t = t;
178                 w->processed_pkts = 0;
179
180                 ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
181                 if (ret) {
182                         evt_err("failed to setup port %d", port);
183                         return ret;
184                 }
185
186                 if (queue_arr == NULL) {
187                         if (rte_event_port_link(opt->dev_id, port, NULL, NULL,
188                                                 0) != nb_queues)
189                                 goto link_fail;
190                 } else {
191                         for (i = 0; i < nb_queues; i++) {
192                                 if (rte_event_port_link(opt->dev_id, port,
193                                                 &queue_arr[i], NULL, 1) != 1)
194                                         goto link_fail;
195                         }
196                 }
197         }
198
199         return 0;
200
201 link_fail:
202         evt_err("failed to link all queues to port %d", port);
203         return -EINVAL;
204 }
205
206 int
207 pipeline_event_rx_adapter_setup(struct evt_options *opt, uint8_t stride,
208                 struct rte_event_port_conf prod_conf)
209 {
210         int ret = 0;
211         uint16_t prod;
212         struct rte_event_eth_rx_adapter_queue_conf queue_conf;
213
214         memset(&queue_conf, 0,
215                         sizeof(struct rte_event_eth_rx_adapter_queue_conf));
216         queue_conf.ev.sched_type = opt->sched_type_list[0];
217         for (prod = 0; prod < rte_eth_dev_count(); prod++) {
218                 uint32_t cap;
219
220                 ret = rte_event_eth_rx_adapter_caps_get(opt->dev_id,
221                                 prod, &cap);
222                 if (ret) {
223                         evt_err("failed to get event rx adapter[%d]"
224                                         " capabilities",
225                                         opt->dev_id);
226                         return ret;
227                 }
228                 queue_conf.ev.queue_id = prod * stride;
229                 ret = rte_event_eth_rx_adapter_create(prod, opt->dev_id,
230                                 &prod_conf);
231                 if (ret) {
232                         evt_err("failed to create rx adapter[%d]", prod);
233                         return ret;
234                 }
235                 ret = rte_event_eth_rx_adapter_queue_add(prod, prod, -1,
236                                 &queue_conf);
237                 if (ret) {
238                         evt_err("failed to add rx queues to adapter[%d]", prod);
239                         return ret;
240                 }
241
242                 if (!(cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT)) {
243                         uint32_t service_id;
244
245                         rte_event_eth_rx_adapter_service_id_get(prod,
246                                         &service_id);
247                         ret = evt_service_setup(service_id);
248                         if (ret) {
249                                 evt_err("Failed to setup service core"
250                                                 " for Rx adapter\n");
251                                 return ret;
252                         }
253                 }
254
255                 ret = rte_eth_dev_start(prod);
256                 if (ret) {
257                         evt_err("Ethernet dev [%d] failed to start."
258                                         " Using synthetic producer", prod);
259                         return ret;
260                 }
261
262                 ret = rte_event_eth_rx_adapter_start(prod);
263                 if (ret) {
264                         evt_err("Rx adapter[%d] start failed", prod);
265                         return ret;
266                 }
267                 printf("%s: Port[%d] using Rx adapter[%d] started\n", __func__,
268                                 prod, prod);
269         }
270
271         return ret;
272 }
273
274 void
275 pipeline_ethdev_destroy(struct evt_test *test, struct evt_options *opt)
276 {
277         int i;
278         RTE_SET_USED(test);
279         RTE_SET_USED(opt);
280
281         for (i = 0; i < rte_eth_dev_count(); i++) {
282                 rte_event_eth_rx_adapter_stop(i);
283                 rte_eth_dev_stop(i);
284                 rte_eth_dev_close(i);
285         }
286 }
287
288 void
289 pipeline_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
290 {
291         RTE_SET_USED(test);
292
293         rte_event_dev_stop(opt->dev_id);
294         rte_event_dev_close(opt->dev_id);
295 }
296
297 int
298 pipeline_mempool_setup(struct evt_test *test, struct evt_options *opt)
299 {
300         struct test_pipeline *t = evt_test_priv(test);
301
302         t->pool = rte_pktmbuf_pool_create(test->name, /* mempool name */
303                         opt->pool_sz, /* number of elements*/
304                         512, /* cache size*/
305                         0,
306                         RTE_MBUF_DEFAULT_BUF_SIZE,
307                         opt->socket_id); /* flags */
308
309         if (t->pool == NULL) {
310                 evt_err("failed to create mempool");
311                 return -ENOMEM;
312         }
313
314         return 0;
315 }
316
317 void
318 pipeline_mempool_destroy(struct evt_test *test, struct evt_options *opt)
319 {
320         RTE_SET_USED(opt);
321         struct test_pipeline *t = evt_test_priv(test);
322
323         rte_mempool_free(t->pool);
324 }
325
326 int
327 pipeline_test_setup(struct evt_test *test, struct evt_options *opt)
328 {
329         void *test_pipeline;
330
331         test_pipeline = rte_zmalloc_socket(test->name,
332                         sizeof(struct test_pipeline), RTE_CACHE_LINE_SIZE,
333                         opt->socket_id);
334         if (test_pipeline  == NULL) {
335                 evt_err("failed to allocate test_pipeline memory");
336                 goto nomem;
337         }
338         test->test_priv = test_pipeline;
339
340         struct test_pipeline *t = evt_test_priv(test);
341
342         t->nb_workers = evt_nr_active_lcores(opt->wlcores);
343         t->outstand_pkts = opt->nb_pkts * evt_nr_active_lcores(opt->wlcores);
344         t->done = false;
345         t->nb_flows = opt->nb_flows;
346         t->result = EVT_TEST_FAILED;
347         t->opt = opt;
348         opt->prod_type = EVT_PROD_TYPE_ETH_RX_ADPTR;
349         memcpy(t->sched_type_list, opt->sched_type_list,
350                         sizeof(opt->sched_type_list));
351         return 0;
352 nomem:
353         return -ENOMEM;
354 }
355
356 void
357 pipeline_test_destroy(struct evt_test *test, struct evt_options *opt)
358 {
359         RTE_SET_USED(opt);
360
361         rte_free(test->test_priv);
362 }