examples/l2fwd-crypto: add signal handler for exit
[dpdk.git] / examples / ipsec-secgw / event_helper.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (C) 2020 Marvell International Ltd.
3  */
4 #include <rte_bitmap.h>
5 #include <rte_ethdev.h>
6 #include <rte_eventdev.h>
7 #include <rte_event_eth_rx_adapter.h>
8 #include <rte_event_eth_tx_adapter.h>
9 #include <rte_malloc.h>
10 #include <stdbool.h>
11
12 #include "event_helper.h"
13 #include "ipsec-secgw.h"
14
15 #define DEFAULT_VECTOR_SIZE  16
16 #define DEFAULT_VECTOR_TMO   102400
17
18 static volatile bool eth_core_running;
19
20 static int
21 eh_get_enabled_cores(struct rte_bitmap *eth_core_mask)
22 {
23         int i, count = 0;
24
25         RTE_LCORE_FOREACH(i) {
26                 /* Check if this core is enabled in core mask*/
27                 if (rte_bitmap_get(eth_core_mask, i)) {
28                         /* Found enabled core */
29                         count++;
30                 }
31         }
32         return count;
33 }
34
35 static inline unsigned int
36 eh_get_next_eth_core(struct eventmode_conf *em_conf)
37 {
38         static unsigned int prev_core = -1;
39         unsigned int next_core;
40
41         /*
42          * Make sure we have at least one eth core running, else the following
43          * logic would lead to an infinite loop.
44          */
45         if (eh_get_enabled_cores(em_conf->eth_core_mask) == 0) {
46                 EH_LOG_ERR("No enabled eth core found");
47                 return RTE_MAX_LCORE;
48         }
49
50         /* Only some cores are marked as eth cores, skip others */
51         do {
52                 /* Get the next core */
53                 next_core = rte_get_next_lcore(prev_core, 0, 1);
54
55                 /* Check if we have reached max lcores */
56                 if (next_core == RTE_MAX_LCORE)
57                         return next_core;
58
59                 /* Update prev_core */
60                 prev_core = next_core;
61         } while (!(rte_bitmap_get(em_conf->eth_core_mask, next_core)));
62
63         return next_core;
64 }
65
66 static inline unsigned int
67 eh_get_next_active_core(struct eventmode_conf *em_conf, unsigned int prev_core)
68 {
69         unsigned int next_core;
70
71         /* Get next active core skipping cores reserved as eth cores */
72         do {
73                 /* Get the next core */
74                 next_core = rte_get_next_lcore(prev_core, 0, 0);
75
76                 /* Check if we have reached max lcores */
77                 if (next_core == RTE_MAX_LCORE)
78                         return next_core;
79
80                 prev_core = next_core;
81         } while (rte_bitmap_get(em_conf->eth_core_mask, next_core));
82
83         return next_core;
84 }
85
86 static struct eventdev_params *
87 eh_get_eventdev_params(struct eventmode_conf *em_conf, uint8_t eventdev_id)
88 {
89         int i;
90
91         for (i = 0; i < em_conf->nb_eventdev; i++) {
92                 if (em_conf->eventdev_config[i].eventdev_id == eventdev_id)
93                         break;
94         }
95
96         /* No match */
97         if (i == em_conf->nb_eventdev)
98                 return NULL;
99
100         return &(em_conf->eventdev_config[i]);
101 }
102
103 static inline bool
104 eh_dev_has_rx_internal_port(uint8_t eventdev_id)
105 {
106         bool flag = true;
107         int j, ret;
108
109         RTE_ETH_FOREACH_DEV(j) {
110                 uint32_t caps = 0;
111
112                 ret = rte_event_eth_rx_adapter_caps_get(eventdev_id, j, &caps);
113                 if (ret < 0)
114                         return false;
115
116                 if (!(caps & RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT))
117                         flag = false;
118         }
119         return flag;
120 }
121
122 static inline bool
123 eh_dev_has_tx_internal_port(uint8_t eventdev_id)
124 {
125         bool flag = true;
126         int j, ret;
127
128         RTE_ETH_FOREACH_DEV(j) {
129                 uint32_t caps = 0;
130
131                 ret = rte_event_eth_tx_adapter_caps_get(eventdev_id, j, &caps);
132                 if (ret < 0)
133                         return false;
134
135                 if (!(caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT))
136                         flag = false;
137         }
138         return flag;
139 }
140
141 static inline bool
142 eh_dev_has_burst_mode(uint8_t dev_id)
143 {
144         struct rte_event_dev_info dev_info;
145
146         rte_event_dev_info_get(dev_id, &dev_info);
147         return (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_BURST_MODE) ?
148                         true : false;
149 }
150
151 static int
152 eh_set_default_conf_eventdev(struct eventmode_conf *em_conf)
153 {
154         int lcore_count, nb_eventdev, nb_eth_dev, ret;
155         struct eventdev_params *eventdev_config;
156         struct rte_event_dev_info dev_info;
157
158         /* Get the number of event devices */
159         nb_eventdev = rte_event_dev_count();
160         if (nb_eventdev == 0) {
161                 EH_LOG_ERR("No event devices detected");
162                 return -EINVAL;
163         }
164
165         if (nb_eventdev != 1) {
166                 EH_LOG_ERR("Event mode does not support multiple event devices. "
167                            "Please provide only one event device.");
168                 return -EINVAL;
169         }
170
171         /* Get the number of eth devs */
172         nb_eth_dev = rte_eth_dev_count_avail();
173         if (nb_eth_dev == 0) {
174                 EH_LOG_ERR("No eth devices detected");
175                 return -EINVAL;
176         }
177
178         /* Get the number of lcores */
179         lcore_count = rte_lcore_count();
180
181         /* Read event device info */
182         ret = rte_event_dev_info_get(0, &dev_info);
183         if (ret < 0) {
184                 EH_LOG_ERR("Failed to read event device info %d", ret);
185                 return ret;
186         }
187
188         /* Check if enough ports are available */
189         if (dev_info.max_event_ports < 2) {
190                 EH_LOG_ERR("Not enough event ports available");
191                 return -EINVAL;
192         }
193
194         /* Get the first event dev conf */
195         eventdev_config = &(em_conf->eventdev_config[0]);
196
197         /* Save number of queues & ports available */
198         eventdev_config->eventdev_id = 0;
199         eventdev_config->nb_eventqueue = dev_info.max_event_queues;
200         eventdev_config->nb_eventport = dev_info.max_event_ports;
201         eventdev_config->ev_queue_mode = RTE_EVENT_QUEUE_CFG_ALL_TYPES;
202
203         /* Check if there are more queues than required */
204         if (eventdev_config->nb_eventqueue > nb_eth_dev + 1) {
205                 /* One queue is reserved for Tx */
206                 eventdev_config->nb_eventqueue = nb_eth_dev + 1;
207         }
208
209         /* Check if there are more ports than required */
210         if (eventdev_config->nb_eventport > lcore_count) {
211                 /* One port per lcore is enough */
212                 eventdev_config->nb_eventport = lcore_count;
213         }
214
215         /* Update the number of event devices */
216         em_conf->nb_eventdev++;
217
218         return 0;
219 }
220
221 static void
222 eh_do_capability_check(struct eventmode_conf *em_conf)
223 {
224         struct eventdev_params *eventdev_config;
225         int all_internal_ports = 1;
226         uint32_t eventdev_id;
227         int i;
228
229         for (i = 0; i < em_conf->nb_eventdev; i++) {
230
231                 /* Get the event dev conf */
232                 eventdev_config = &(em_conf->eventdev_config[i]);
233                 eventdev_id = eventdev_config->eventdev_id;
234
235                 /* Check if event device has internal port for Rx & Tx */
236                 if (eh_dev_has_rx_internal_port(eventdev_id) &&
237                     eh_dev_has_tx_internal_port(eventdev_id)) {
238                         eventdev_config->all_internal_ports = 1;
239                 } else {
240                         all_internal_ports = 0;
241                 }
242         }
243
244         /*
245          * If Rx & Tx internal ports are supported by all event devices then
246          * eth cores won't be required. Override the eth core mask requested
247          * and decrement number of event queues by one as it won't be needed
248          * for Tx.
249          */
250         if (all_internal_ports) {
251                 rte_bitmap_reset(em_conf->eth_core_mask);
252                 for (i = 0; i < em_conf->nb_eventdev; i++)
253                         em_conf->eventdev_config[i].nb_eventqueue--;
254         }
255 }
256
257 static int
258 eh_set_default_conf_link(struct eventmode_conf *em_conf)
259 {
260         struct eventdev_params *eventdev_config;
261         struct eh_event_link_info *link;
262         unsigned int lcore_id = -1;
263         int i, link_index;
264
265         /*
266          * Create a 1:1 mapping from event ports to cores. If the number
267          * of event ports is lesser than the cores, some cores won't
268          * execute worker. If there are more event ports, then some ports
269          * won't be used.
270          *
271          */
272
273         /*
274          * The event queue-port mapping is done according to the link. Since
275          * we are falling back to the default link config, enabling
276          * "all_ev_queue_to_ev_port" mode flag. This will map all queues
277          * to the port.
278          */
279         em_conf->ext_params.all_ev_queue_to_ev_port = 1;
280
281         /* Get first event dev conf */
282         eventdev_config = &(em_conf->eventdev_config[0]);
283
284         /* Loop through the ports */
285         for (i = 0; i < eventdev_config->nb_eventport; i++) {
286
287                 /* Get next active core id */
288                 lcore_id = eh_get_next_active_core(em_conf,
289                                 lcore_id);
290
291                 if (lcore_id == RTE_MAX_LCORE) {
292                         /* Reached max cores */
293                         return 0;
294                 }
295
296                 /* Save the current combination as one link */
297
298                 /* Get the index */
299                 link_index = em_conf->nb_link;
300
301                 /* Get the corresponding link */
302                 link = &(em_conf->link[link_index]);
303
304                 /* Save link */
305                 link->eventdev_id = eventdev_config->eventdev_id;
306                 link->event_port_id = i;
307                 link->lcore_id = lcore_id;
308
309                 /*
310                  * Don't set eventq_id as by default all queues
311                  * need to be mapped to the port, which is controlled
312                  * by the operating mode.
313                  */
314
315                 /* Update number of links */
316                 em_conf->nb_link++;
317         }
318
319         return 0;
320 }
321
322 static int
323 eh_set_default_conf_rx_adapter(struct eventmode_conf *em_conf)
324 {
325         struct rx_adapter_connection_info *conn;
326         struct eventdev_params *eventdev_config;
327         struct rx_adapter_conf *adapter;
328         bool rx_internal_port = true;
329         bool single_ev_queue = false;
330         int nb_eventqueue;
331         uint32_t caps = 0;
332         int eventdev_id;
333         int nb_eth_dev;
334         int adapter_id;
335         int conn_id;
336         int ret;
337         int i;
338
339         /* Create one adapter with eth queues mapped to event queue(s) */
340
341         if (em_conf->nb_eventdev == 0) {
342                 EH_LOG_ERR("No event devs registered");
343                 return -EINVAL;
344         }
345
346         /* Get the number of eth devs */
347         nb_eth_dev = rte_eth_dev_count_avail();
348
349         /* Use the first event dev */
350         eventdev_config = &(em_conf->eventdev_config[0]);
351
352         /* Get eventdev ID */
353         eventdev_id = eventdev_config->eventdev_id;
354         adapter_id = 0;
355
356         /* Get adapter conf */
357         adapter = &(em_conf->rx_adapter[adapter_id]);
358
359         /* Set adapter conf */
360         adapter->eventdev_id = eventdev_id;
361         adapter->adapter_id = adapter_id;
362
363         /*
364          * If event device does not have internal ports for passing
365          * packets then reserved one queue for Tx path
366          */
367         nb_eventqueue = eventdev_config->all_internal_ports ?
368                         eventdev_config->nb_eventqueue :
369                         eventdev_config->nb_eventqueue - 1;
370
371         /*
372          * Map all queues of eth device (port) to an event queue. If there
373          * are more event queues than eth ports then create 1:1 mapping.
374          * Otherwise map all eth ports to a single event queue.
375          */
376         if (nb_eth_dev > nb_eventqueue)
377                 single_ev_queue = true;
378
379         for (i = 0; i < nb_eth_dev; i++) {
380
381                 /* Use only the ports enabled */
382                 if ((em_conf->eth_portmask & (1 << i)) == 0)
383                         continue;
384
385                 /* Get the connection id */
386                 conn_id = adapter->nb_connections;
387
388                 /* Get the connection */
389                 conn = &(adapter->conn[conn_id]);
390
391                 /* Set mapping between eth ports & event queues*/
392                 conn->ethdev_id = i;
393                 conn->eventq_id = single_ev_queue ? 0 : i;
394
395                 /* Add all eth queues eth port to event queue */
396                 conn->ethdev_rx_qid = -1;
397
398                 /* Get Rx adapter capabilities */
399                 ret = rte_event_eth_rx_adapter_caps_get(eventdev_id, i, &caps);
400                 if (ret < 0) {
401                         EH_LOG_ERR("Failed to get event device %d eth rx adapter"
402                                    " capabilities for port %d", eventdev_id, i);
403                         return ret;
404                 }
405                 if (!(caps & RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT))
406                         rx_internal_port = false;
407
408                 /* Update no of connections */
409                 adapter->nb_connections++;
410
411         }
412
413         if (rx_internal_port) {
414                 /* Rx core is not required */
415                 adapter->rx_core_id = -1;
416         } else {
417                 /* Rx core is required */
418                 adapter->rx_core_id = eh_get_next_eth_core(em_conf);
419         }
420
421         /* We have setup one adapter */
422         em_conf->nb_rx_adapter = 1;
423
424         return 0;
425 }
426
427 static int
428 eh_set_default_conf_tx_adapter(struct eventmode_conf *em_conf)
429 {
430         struct tx_adapter_connection_info *conn;
431         struct eventdev_params *eventdev_config;
432         struct tx_adapter_conf *tx_adapter;
433         bool tx_internal_port = true;
434         uint32_t caps = 0;
435         int eventdev_id;
436         int adapter_id;
437         int nb_eth_dev;
438         int conn_id;
439         int ret;
440         int i;
441
442         /*
443          * Create one Tx adapter with all eth queues mapped to event queues
444          * 1:1.
445          */
446
447         if (em_conf->nb_eventdev == 0) {
448                 EH_LOG_ERR("No event devs registered");
449                 return -EINVAL;
450         }
451
452         /* Get the number of eth devs */
453         nb_eth_dev = rte_eth_dev_count_avail();
454
455         /* Use the first event dev */
456         eventdev_config = &(em_conf->eventdev_config[0]);
457
458         /* Get eventdev ID */
459         eventdev_id = eventdev_config->eventdev_id;
460         adapter_id = 0;
461
462         /* Get adapter conf */
463         tx_adapter = &(em_conf->tx_adapter[adapter_id]);
464
465         /* Set adapter conf */
466         tx_adapter->eventdev_id = eventdev_id;
467         tx_adapter->adapter_id = adapter_id;
468
469         /*
470          * Map all Tx queues of the eth device (port) to the event device.
471          */
472
473         /* Set defaults for connections */
474
475         /*
476          * One eth device (port) is one connection. Map all Tx queues
477          * of the device to the Tx adapter.
478          */
479
480         for (i = 0; i < nb_eth_dev; i++) {
481
482                 /* Use only the ports enabled */
483                 if ((em_conf->eth_portmask & (1 << i)) == 0)
484                         continue;
485
486                 /* Get the connection id */
487                 conn_id = tx_adapter->nb_connections;
488
489                 /* Get the connection */
490                 conn = &(tx_adapter->conn[conn_id]);
491
492                 /* Add ethdev to connections */
493                 conn->ethdev_id = i;
494
495                 /* Add all eth tx queues to adapter */
496                 conn->ethdev_tx_qid = -1;
497
498                 /* Get Tx adapter capabilities */
499                 ret = rte_event_eth_tx_adapter_caps_get(eventdev_id, i, &caps);
500                 if (ret < 0) {
501                         EH_LOG_ERR("Failed to get event device %d eth tx adapter"
502                                    " capabilities for port %d", eventdev_id, i);
503                         return ret;
504                 }
505                 if (!(caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT))
506                         tx_internal_port = false;
507
508                 /* Update no of connections */
509                 tx_adapter->nb_connections++;
510         }
511
512         if (tx_internal_port) {
513                 /* Tx core is not required */
514                 tx_adapter->tx_core_id = -1;
515         } else {
516                 /* Tx core is required */
517                 tx_adapter->tx_core_id = eh_get_next_eth_core(em_conf);
518
519                 /*
520                  * Use one event queue per adapter for submitting packets
521                  * for Tx. Reserving the last queue available
522                  */
523                 /* Queue numbers start at 0 */
524                 tx_adapter->tx_ev_queue = eventdev_config->nb_eventqueue - 1;
525         }
526
527         /* We have setup one adapter */
528         em_conf->nb_tx_adapter = 1;
529         return 0;
530 }
531
532 static int
533 eh_validate_conf(struct eventmode_conf *em_conf)
534 {
535         int ret;
536
537         /*
538          * Check if event devs are specified. Else probe the event devices
539          * and initialize the config with all ports & queues available
540          */
541         if (em_conf->nb_eventdev == 0) {
542                 ret = eh_set_default_conf_eventdev(em_conf);
543                 if (ret != 0)
544                         return ret;
545         }
546
547         /* Perform capability check for the selected event devices */
548         eh_do_capability_check(em_conf);
549
550         /*
551          * Check if links are specified. Else generate a default config for
552          * the event ports used.
553          */
554         if (em_conf->nb_link == 0) {
555                 ret = eh_set_default_conf_link(em_conf);
556                 if (ret != 0)
557                         return ret;
558         }
559
560         /*
561          * Check if rx adapters are specified. Else generate a default config
562          * with one rx adapter and all eth queues - event queue mapped.
563          */
564         if (em_conf->nb_rx_adapter == 0) {
565                 ret = eh_set_default_conf_rx_adapter(em_conf);
566                 if (ret != 0)
567                         return ret;
568         }
569
570         /*
571          * Check if tx adapters are specified. Else generate a default config
572          * with one tx adapter.
573          */
574         if (em_conf->nb_tx_adapter == 0) {
575                 ret = eh_set_default_conf_tx_adapter(em_conf);
576                 if (ret != 0)
577                         return ret;
578         }
579
580         return 0;
581 }
582
583 static int
584 eh_initialize_eventdev(struct eventmode_conf *em_conf)
585 {
586         struct rte_event_queue_conf eventq_conf = {0};
587         struct rte_event_dev_info evdev_default_conf;
588         struct rte_event_dev_config eventdev_conf;
589         struct eventdev_params *eventdev_config;
590         int nb_eventdev = em_conf->nb_eventdev;
591         struct eh_event_link_info *link;
592         uint8_t *queue = NULL;
593         uint8_t eventdev_id;
594         int nb_eventqueue;
595         uint8_t i, j;
596         int ret;
597
598         for (i = 0; i < nb_eventdev; i++) {
599
600                 /* Get eventdev config */
601                 eventdev_config = &(em_conf->eventdev_config[i]);
602
603                 /* Get event dev ID */
604                 eventdev_id = eventdev_config->eventdev_id;
605
606                 /* Get the number of queues */
607                 nb_eventqueue = eventdev_config->nb_eventqueue;
608
609                 /* Reset the default conf */
610                 memset(&evdev_default_conf, 0,
611                         sizeof(struct rte_event_dev_info));
612
613                 /* Get default conf of eventdev */
614                 ret = rte_event_dev_info_get(eventdev_id, &evdev_default_conf);
615                 if (ret < 0) {
616                         EH_LOG_ERR(
617                                 "Error in getting event device info[devID:%d]",
618                                 eventdev_id);
619                         return ret;
620                 }
621
622                 memset(&eventdev_conf, 0, sizeof(struct rte_event_dev_config));
623                 eventdev_conf.nb_events_limit =
624                                 evdev_default_conf.max_num_events;
625                 eventdev_conf.nb_event_queues = nb_eventqueue;
626                 eventdev_conf.nb_event_ports =
627                                 eventdev_config->nb_eventport;
628                 eventdev_conf.nb_event_queue_flows =
629                                 evdev_default_conf.max_event_queue_flows;
630                 eventdev_conf.nb_event_port_dequeue_depth =
631                                 evdev_default_conf.max_event_port_dequeue_depth;
632                 eventdev_conf.nb_event_port_enqueue_depth =
633                                 evdev_default_conf.max_event_port_enqueue_depth;
634
635                 /* Configure event device */
636                 ret = rte_event_dev_configure(eventdev_id, &eventdev_conf);
637                 if (ret < 0) {
638                         EH_LOG_ERR("Error in configuring event device");
639                         return ret;
640                 }
641
642                 /* Configure event queues */
643                 for (j = 0; j < nb_eventqueue; j++) {
644
645                         memset(&eventq_conf, 0,
646                                         sizeof(struct rte_event_queue_conf));
647
648                         /* Per event dev queues can be ATQ or SINGLE LINK */
649                         eventq_conf.event_queue_cfg =
650                                         eventdev_config->ev_queue_mode;
651                         /*
652                          * All queues need to be set with sched_type as
653                          * schedule type for the application stage. One
654                          * queue would be reserved for the final eth tx
655                          * stage if event device does not have internal
656                          * ports. This will be an atomic queue.
657                          */
658                         if (!eventdev_config->all_internal_ports &&
659                             j == nb_eventqueue-1) {
660                                 eventq_conf.schedule_type =
661                                         RTE_SCHED_TYPE_ATOMIC;
662                         } else {
663                                 eventq_conf.schedule_type =
664                                         em_conf->ext_params.sched_type;
665                         }
666
667                         /* Set max atomic flows to 1024 */
668                         eventq_conf.nb_atomic_flows = 1024;
669                         eventq_conf.nb_atomic_order_sequences = 1024;
670
671                         /* Setup the queue */
672                         ret = rte_event_queue_setup(eventdev_id, j,
673                                         &eventq_conf);
674                         if (ret < 0) {
675                                 EH_LOG_ERR("Failed to setup event queue %d",
676                                            ret);
677                                 return ret;
678                         }
679                 }
680
681                 /* Configure event ports */
682                 for (j = 0; j <  eventdev_config->nb_eventport; j++) {
683                         ret = rte_event_port_setup(eventdev_id, j, NULL);
684                         if (ret < 0) {
685                                 EH_LOG_ERR("Failed to setup event port %d",
686                                            ret);
687                                 return ret;
688                         }
689                 }
690         }
691
692         /* Make event queue - event port link */
693         for (j = 0; j <  em_conf->nb_link; j++) {
694
695                 /* Get link info */
696                 link = &(em_conf->link[j]);
697
698                 /* Get event dev ID */
699                 eventdev_id = link->eventdev_id;
700
701                 /*
702                  * If "all_ev_queue_to_ev_port" params flag is selected, all
703                  * queues need to be mapped to the port.
704                  */
705                 if (em_conf->ext_params.all_ev_queue_to_ev_port)
706                         queue = NULL;
707                 else
708                         queue = &(link->eventq_id);
709
710                 /* Link queue to port */
711                 ret = rte_event_port_link(eventdev_id, link->event_port_id,
712                                 queue, NULL, 1);
713                 if (ret < 0) {
714                         EH_LOG_ERR("Failed to link event port %d", ret);
715                         return ret;
716                 }
717         }
718
719         return 0;
720 }
721
722 static int
723 eh_start_eventdev(struct eventmode_conf *em_conf)
724 {
725         struct eventdev_params *eventdev_config;
726         int nb_eventdev = em_conf->nb_eventdev;
727         int i, ret;
728
729         /* Start event devices */
730         for (i = 0; i < nb_eventdev; i++) {
731
732                 /* Get eventdev config */
733                 eventdev_config = &(em_conf->eventdev_config[i]);
734
735                 ret = rte_event_dev_start(eventdev_config->eventdev_id);
736                 if (ret < 0) {
737                         EH_LOG_ERR("Failed to start event device %d, %d",
738                                    i, ret);
739                         return ret;
740                 }
741         }
742         return 0;
743 }
744
745 static int
746 eh_event_vector_limits_validate(struct eventmode_conf *em_conf,
747                                 uint8_t ev_dev_id, uint8_t ethdev_id)
748 {
749         struct rte_event_eth_rx_adapter_vector_limits limits = {0};
750         uint16_t vector_size = em_conf->ext_params.vector_size;
751         int ret;
752
753         ret = rte_event_eth_rx_adapter_vector_limits_get(ev_dev_id, ethdev_id,
754                                                          &limits);
755         if (ret) {
756                 EH_LOG_ERR("failed to get vector limits");
757                 return ret;
758         }
759
760         if (vector_size < limits.min_sz || vector_size > limits.max_sz) {
761                 EH_LOG_ERR("Vector size [%d] not within limits min[%d] max[%d]",
762                            vector_size, limits.min_sz, limits.max_sz);
763                 return -EINVAL;
764         }
765
766         if (limits.log2_sz && !rte_is_power_of_2(vector_size)) {
767                 EH_LOG_ERR("Vector size [%d] not power of 2", vector_size);
768                 return -EINVAL;
769         }
770
771         if (em_conf->vector_tmo_ns > limits.max_timeout_ns ||
772             em_conf->vector_tmo_ns < limits.min_timeout_ns) {
773                 EH_LOG_ERR("Vector timeout [%" PRIu64
774                            "] not within limits max[%" PRIu64
775                            "] min[%" PRIu64 "]",
776                            em_conf->vector_tmo_ns,
777                            limits.max_timeout_ns,
778                            limits.min_timeout_ns);
779                 return -EINVAL;
780         }
781         return 0;
782 }
783
784 static int
785 eh_rx_adapter_configure(struct eventmode_conf *em_conf,
786                 struct rx_adapter_conf *adapter)
787 {
788         struct rte_event_eth_rx_adapter_queue_conf queue_conf = {0};
789         struct rte_event_dev_info evdev_default_conf = {0};
790         struct rte_event_port_conf port_conf = {0};
791         struct rx_adapter_connection_info *conn;
792         uint32_t service_id, socket_id, nb_elem;
793         struct rte_mempool *vector_pool = NULL;
794         uint32_t lcore_id = rte_lcore_id();
795         int ret, portid, nb_ports = 0;
796         uint8_t eventdev_id;
797         int j;
798
799         /* Get event dev ID */
800         eventdev_id = adapter->eventdev_id;
801
802         /* Get default configuration of event dev */
803         ret = rte_event_dev_info_get(eventdev_id, &evdev_default_conf);
804         if (ret < 0) {
805                 EH_LOG_ERR("Failed to get event dev info %d", ret);
806                 return ret;
807         }
808
809         RTE_ETH_FOREACH_DEV(portid)
810                 if ((em_conf->eth_portmask & (1 << portid)))
811                         nb_ports++;
812
813         if (em_conf->ext_params.event_vector) {
814                 socket_id = rte_lcore_to_socket_id(lcore_id);
815
816                 if (em_conf->vector_pool_sz) {
817                         nb_elem = em_conf->vector_pool_sz;
818                 } else {
819                         nb_elem = (nb_bufs_in_pool /
820                                    em_conf->ext_params.vector_size) + 1;
821                         if (per_port_pool)
822                                 nb_elem = nb_ports * nb_elem;
823                 }
824
825                 vector_pool = rte_event_vector_pool_create(
826                         "vector_pool", nb_elem, 0,
827                         em_conf->ext_params.vector_size,
828                         socket_id);
829                 if (vector_pool == NULL) {
830                         EH_LOG_ERR("failed to create event vector pool");
831                         return -ENOMEM;
832                 }
833         }
834         /* Setup port conf */
835         port_conf.new_event_threshold = 1200;
836         port_conf.dequeue_depth =
837                         evdev_default_conf.max_event_port_dequeue_depth;
838         port_conf.enqueue_depth =
839                         evdev_default_conf.max_event_port_enqueue_depth;
840
841         /* Create Rx adapter */
842         ret = rte_event_eth_rx_adapter_create(adapter->adapter_id,
843                         adapter->eventdev_id, &port_conf);
844         if (ret < 0) {
845                 EH_LOG_ERR("Failed to create rx adapter %d", ret);
846                 return ret;
847         }
848
849         /* Setup various connections in the adapter */
850         for (j = 0; j < adapter->nb_connections; j++) {
851                 /* Get connection */
852                 conn = &(adapter->conn[j]);
853
854                 /* Setup queue conf */
855                 queue_conf.ev.queue_id = conn->eventq_id;
856                 queue_conf.ev.sched_type = em_conf->ext_params.sched_type;
857                 queue_conf.ev.event_type = RTE_EVENT_TYPE_ETHDEV;
858
859                 if (em_conf->ext_params.event_vector) {
860                         ret = eh_event_vector_limits_validate(em_conf,
861                                                               eventdev_id,
862                                                               conn->ethdev_id);
863                         if (ret)
864                                 return ret;
865
866                         queue_conf.vector_sz = em_conf->ext_params.vector_size;
867                         queue_conf.vector_timeout_ns = em_conf->vector_tmo_ns;
868                         queue_conf.vector_mp = vector_pool;
869                         queue_conf.rx_queue_flags =
870                                 RTE_EVENT_ETH_RX_ADAPTER_QUEUE_EVENT_VECTOR;
871                 }
872
873                 /* Add queue to the adapter */
874                 ret = rte_event_eth_rx_adapter_queue_add(adapter->adapter_id,
875                                 conn->ethdev_id, conn->ethdev_rx_qid,
876                                 &queue_conf);
877                 if (ret < 0) {
878                         EH_LOG_ERR("Failed to add eth queue to rx adapter %d",
879                                    ret);
880                         return ret;
881                 }
882         }
883
884         /* Get the service ID used by rx adapter */
885         ret = rte_event_eth_rx_adapter_service_id_get(adapter->adapter_id,
886                                                       &service_id);
887         if (ret != -ESRCH && ret < 0) {
888                 EH_LOG_ERR("Failed to get service id used by rx adapter %d",
889                            ret);
890                 return ret;
891         }
892
893         rte_service_set_runstate_mapped_check(service_id, 0);
894
895         /* Start adapter */
896         ret = rte_event_eth_rx_adapter_start(adapter->adapter_id);
897         if (ret < 0) {
898                 EH_LOG_ERR("Failed to start rx adapter %d", ret);
899                 return ret;
900         }
901
902         return 0;
903 }
904
905 static int
906 eh_initialize_rx_adapter(struct eventmode_conf *em_conf)
907 {
908         struct rx_adapter_conf *adapter;
909         int i, ret;
910
911         /* Configure rx adapters */
912         for (i = 0; i < em_conf->nb_rx_adapter; i++) {
913                 adapter = &(em_conf->rx_adapter[i]);
914                 ret = eh_rx_adapter_configure(em_conf, adapter);
915                 if (ret < 0) {
916                         EH_LOG_ERR("Failed to configure rx adapter %d", ret);
917                         return ret;
918                 }
919         }
920         return 0;
921 }
922
923 static int32_t
924 eh_start_worker_eth_core(struct eventmode_conf *conf, uint32_t lcore_id)
925 {
926         uint32_t service_id[EVENT_MODE_MAX_ADAPTERS_PER_RX_CORE];
927         struct rx_adapter_conf *rx_adapter;
928         struct tx_adapter_conf *tx_adapter;
929         int service_count = 0;
930         int adapter_id;
931         int32_t ret;
932         int i;
933
934         EH_LOG_INFO("Entering eth_core processing on lcore %u", lcore_id);
935
936         /*
937          * Parse adapter config to check which of all Rx adapters need
938          * to be handled by this core.
939          */
940         for (i = 0; i < conf->nb_rx_adapter; i++) {
941                 /* Check if we have exceeded the max allowed */
942                 if (service_count > EVENT_MODE_MAX_ADAPTERS_PER_RX_CORE) {
943                         EH_LOG_ERR(
944                               "Exceeded the max allowed adapters per rx core");
945                         break;
946                 }
947
948                 rx_adapter = &(conf->rx_adapter[i]);
949                 if (rx_adapter->rx_core_id != lcore_id)
950                         continue;
951
952                 /* Adapter is handled by this core */
953                 adapter_id = rx_adapter->adapter_id;
954
955                 /* Get the service ID for the adapters */
956                 ret = rte_event_eth_rx_adapter_service_id_get(adapter_id,
957                                 &(service_id[service_count]));
958
959                 if (ret != -ESRCH && ret < 0) {
960                         EH_LOG_ERR(
961                                 "Failed to get service id used by rx adapter");
962                         return ret;
963                 }
964
965                 /* Update service count */
966                 service_count++;
967         }
968
969         /*
970          * Parse adapter config to see which of all Tx adapters need
971          * to be handled by this core.
972          */
973         for (i = 0; i < conf->nb_tx_adapter; i++) {
974                 /* Check if we have exceeded the max allowed */
975                 if (service_count > EVENT_MODE_MAX_ADAPTERS_PER_TX_CORE) {
976                         EH_LOG_ERR(
977                                 "Exceeded the max allowed adapters per tx core");
978                         break;
979                 }
980
981                 tx_adapter = &conf->tx_adapter[i];
982                 if (tx_adapter->tx_core_id != lcore_id)
983                         continue;
984
985                 /* Adapter is handled by this core */
986                 adapter_id = tx_adapter->adapter_id;
987
988                 /* Get the service ID for the adapters */
989                 ret = rte_event_eth_tx_adapter_service_id_get(adapter_id,
990                                 &(service_id[service_count]));
991
992                 if (ret != -ESRCH && ret < 0) {
993                         EH_LOG_ERR(
994                                 "Failed to get service id used by tx adapter");
995                         return ret;
996                 }
997
998                 /* Update service count */
999                 service_count++;
1000         }
1001
1002         eth_core_running = true;
1003
1004         while (eth_core_running) {
1005                 for (i = 0; i < service_count; i++) {
1006                         /* Initiate adapter service */
1007                         rte_service_run_iter_on_app_lcore(service_id[i], 0);
1008                 }
1009         }
1010
1011         return 0;
1012 }
1013
1014 static int32_t
1015 eh_stop_worker_eth_core(void)
1016 {
1017         if (eth_core_running) {
1018                 EH_LOG_INFO("Stopping eth cores");
1019                 eth_core_running = false;
1020         }
1021         return 0;
1022 }
1023
1024 static struct eh_app_worker_params *
1025 eh_find_worker(uint32_t lcore_id, struct eh_conf *conf,
1026                 struct eh_app_worker_params *app_wrkrs, uint8_t nb_wrkr_param)
1027 {
1028         struct eh_app_worker_params curr_conf = { {{0} }, NULL};
1029         struct eh_event_link_info *link = NULL;
1030         struct eh_app_worker_params *tmp_wrkr;
1031         struct eventmode_conf *em_conf;
1032         uint8_t eventdev_id;
1033         int i;
1034
1035         /* Get eventmode config */
1036         em_conf = conf->mode_params;
1037
1038         /*
1039          * Use event device from the first lcore-event link.
1040          *
1041          * Assumption: All lcore-event links tied to a core are using the
1042          * same event device. In other words, one core would be polling on
1043          * queues of a single event device only.
1044          */
1045
1046         /* Get a link for this lcore */
1047         for (i = 0; i < em_conf->nb_link; i++) {
1048                 link = &(em_conf->link[i]);
1049                 if (link->lcore_id == lcore_id)
1050                         break;
1051         }
1052
1053         if (link == NULL) {
1054                 EH_LOG_ERR("No valid link found for lcore %d", lcore_id);
1055                 return NULL;
1056         }
1057
1058         /* Get event dev ID */
1059         eventdev_id = link->eventdev_id;
1060
1061         /* Populate the curr_conf with the capabilities */
1062
1063         /* Check for Tx internal port */
1064         if (eh_dev_has_tx_internal_port(eventdev_id))
1065                 curr_conf.cap.tx_internal_port = EH_TX_TYPE_INTERNAL_PORT;
1066         else
1067                 curr_conf.cap.tx_internal_port = EH_TX_TYPE_NO_INTERNAL_PORT;
1068
1069         /* Check for burst mode */
1070         if (eh_dev_has_burst_mode(eventdev_id))
1071                 curr_conf.cap.burst = EH_RX_TYPE_BURST;
1072         else
1073                 curr_conf.cap.burst = EH_RX_TYPE_NON_BURST;
1074
1075         curr_conf.cap.ipsec_mode = conf->ipsec_mode;
1076
1077         /* Parse the passed list and see if we have matching capabilities */
1078
1079         /* Initialize the pointer used to traverse the list */
1080         tmp_wrkr = app_wrkrs;
1081
1082         for (i = 0; i < nb_wrkr_param; i++, tmp_wrkr++) {
1083
1084                 /* Skip this if capabilities are not matching */
1085                 if (tmp_wrkr->cap.u64 != curr_conf.cap.u64)
1086                         continue;
1087
1088                 /* If the checks pass, we have a match */
1089                 return tmp_wrkr;
1090         }
1091
1092         return NULL;
1093 }
1094
1095 static int
1096 eh_verify_match_worker(struct eh_app_worker_params *match_wrkr)
1097 {
1098         /* Verify registered worker */
1099         if (match_wrkr->worker_thread == NULL) {
1100                 EH_LOG_ERR("No worker registered");
1101                 return 0;
1102         }
1103
1104         /* Success */
1105         return 1;
1106 }
1107
1108 static uint8_t
1109 eh_get_event_lcore_links(uint32_t lcore_id, struct eh_conf *conf,
1110                 struct eh_event_link_info **links)
1111 {
1112         struct eh_event_link_info *link_cache;
1113         struct eventmode_conf *em_conf = NULL;
1114         struct eh_event_link_info *link;
1115         uint8_t lcore_nb_link = 0;
1116         size_t single_link_size;
1117         size_t cache_size;
1118         int index = 0;
1119         int i;
1120
1121         if (conf == NULL || links == NULL) {
1122                 EH_LOG_ERR("Invalid args");
1123                 return -EINVAL;
1124         }
1125
1126         /* Get eventmode conf */
1127         em_conf = conf->mode_params;
1128
1129         if (em_conf == NULL) {
1130                 EH_LOG_ERR("Invalid event mode parameters");
1131                 return -EINVAL;
1132         }
1133
1134         /* Get the number of links registered */
1135         for (i = 0; i < em_conf->nb_link; i++) {
1136
1137                 /* Get link */
1138                 link = &(em_conf->link[i]);
1139
1140                 /* Check if we have link intended for this lcore */
1141                 if (link->lcore_id == lcore_id) {
1142
1143                         /* Update the number of links for this core */
1144                         lcore_nb_link++;
1145
1146                 }
1147         }
1148
1149         /* Compute size of one entry to be copied */
1150         single_link_size = sizeof(struct eh_event_link_info);
1151
1152         /* Compute size of the buffer required */
1153         cache_size = lcore_nb_link * sizeof(struct eh_event_link_info);
1154
1155         /* Compute size of the buffer required */
1156         link_cache = calloc(1, cache_size);
1157
1158         /* Get the number of links registered */
1159         for (i = 0; i < em_conf->nb_link; i++) {
1160
1161                 /* Get link */
1162                 link = &(em_conf->link[i]);
1163
1164                 /* Check if we have link intended for this lcore */
1165                 if (link->lcore_id == lcore_id) {
1166
1167                         /* Cache the link */
1168                         memcpy(&link_cache[index], link, single_link_size);
1169
1170                         /* Update index */
1171                         index++;
1172                 }
1173         }
1174
1175         /* Update the links for application to use the cached links */
1176         *links = link_cache;
1177
1178         /* Return the number of cached links */
1179         return lcore_nb_link;
1180 }
1181
1182 static int
1183 eh_tx_adapter_configure(struct eventmode_conf *em_conf,
1184                 struct tx_adapter_conf *adapter)
1185 {
1186         struct rte_event_dev_info evdev_default_conf = {0};
1187         struct rte_event_port_conf port_conf = {0};
1188         struct tx_adapter_connection_info *conn;
1189         struct eventdev_params *eventdev_config;
1190         uint8_t tx_port_id = 0;
1191         uint8_t eventdev_id;
1192         uint32_t service_id;
1193         int ret, j;
1194
1195         /* Get event dev ID */
1196         eventdev_id = adapter->eventdev_id;
1197
1198         /* Get event device conf */
1199         eventdev_config = eh_get_eventdev_params(em_conf, eventdev_id);
1200
1201         /* Create Tx adapter */
1202
1203         /* Get default configuration of event dev */
1204         ret = rte_event_dev_info_get(eventdev_id, &evdev_default_conf);
1205         if (ret < 0) {
1206                 EH_LOG_ERR("Failed to get event dev info %d", ret);
1207                 return ret;
1208         }
1209
1210         /* Setup port conf */
1211         port_conf.new_event_threshold =
1212                         evdev_default_conf.max_num_events;
1213         port_conf.dequeue_depth =
1214                         evdev_default_conf.max_event_port_dequeue_depth;
1215         port_conf.enqueue_depth =
1216                         evdev_default_conf.max_event_port_enqueue_depth;
1217
1218         /* Create adapter */
1219         ret = rte_event_eth_tx_adapter_create(adapter->adapter_id,
1220                         adapter->eventdev_id, &port_conf);
1221         if (ret < 0) {
1222                 EH_LOG_ERR("Failed to create tx adapter %d", ret);
1223                 return ret;
1224         }
1225
1226         /* Setup various connections in the adapter */
1227         for (j = 0; j < adapter->nb_connections; j++) {
1228
1229                 /* Get connection */
1230                 conn = &(adapter->conn[j]);
1231
1232                 /* Add queue to the adapter */
1233                 ret = rte_event_eth_tx_adapter_queue_add(adapter->adapter_id,
1234                                 conn->ethdev_id, conn->ethdev_tx_qid);
1235                 if (ret < 0) {
1236                         EH_LOG_ERR("Failed to add eth queue to tx adapter %d",
1237                                    ret);
1238                         return ret;
1239                 }
1240         }
1241
1242         /*
1243          * Check if Tx core is assigned. If Tx core is not assigned then
1244          * the adapter has internal port for submitting Tx packets and
1245          * Tx event queue & port setup is not required
1246          */
1247         if (adapter->tx_core_id == (uint32_t) (-1)) {
1248                 /* Internal port is present */
1249                 goto skip_tx_queue_port_setup;
1250         }
1251
1252         /* Setup Tx queue & port */
1253
1254         /* Get event port used by the adapter */
1255         ret = rte_event_eth_tx_adapter_event_port_get(
1256                         adapter->adapter_id, &tx_port_id);
1257         if (ret) {
1258                 EH_LOG_ERR("Failed to get tx adapter port id %d", ret);
1259                 return ret;
1260         }
1261
1262         /*
1263          * Tx event queue is reserved for Tx adapter. Unlink this queue
1264          * from all other ports
1265          *
1266          */
1267         for (j = 0; j < eventdev_config->nb_eventport; j++) {
1268                 rte_event_port_unlink(eventdev_id, j,
1269                                       &(adapter->tx_ev_queue), 1);
1270         }
1271
1272         /* Link Tx event queue to Tx port */
1273         ret = rte_event_port_link(eventdev_id, tx_port_id,
1274                         &(adapter->tx_ev_queue), NULL, 1);
1275         if (ret != 1) {
1276                 EH_LOG_ERR("Failed to link event queue to port");
1277                 return ret;
1278         }
1279
1280         /* Get the service ID used by Tx adapter */
1281         ret = rte_event_eth_tx_adapter_service_id_get(adapter->adapter_id,
1282                                                       &service_id);
1283         if (ret != -ESRCH && ret < 0) {
1284                 EH_LOG_ERR("Failed to get service id used by tx adapter %d",
1285                            ret);
1286                 return ret;
1287         }
1288
1289         rte_service_set_runstate_mapped_check(service_id, 0);
1290
1291 skip_tx_queue_port_setup:
1292         /* Start adapter */
1293         ret = rte_event_eth_tx_adapter_start(adapter->adapter_id);
1294         if (ret < 0) {
1295                 EH_LOG_ERR("Failed to start tx adapter %d", ret);
1296                 return ret;
1297         }
1298
1299         return 0;
1300 }
1301
1302 static int
1303 eh_initialize_tx_adapter(struct eventmode_conf *em_conf)
1304 {
1305         struct tx_adapter_conf *adapter;
1306         int i, ret;
1307
1308         /* Configure Tx adapters */
1309         for (i = 0; i < em_conf->nb_tx_adapter; i++) {
1310                 adapter = &(em_conf->tx_adapter[i]);
1311                 ret = eh_tx_adapter_configure(em_conf, adapter);
1312                 if (ret < 0) {
1313                         EH_LOG_ERR("Failed to configure tx adapter %d", ret);
1314                         return ret;
1315                 }
1316         }
1317         return 0;
1318 }
1319
1320 static void
1321 eh_display_operating_mode(struct eventmode_conf *em_conf)
1322 {
1323         char sched_types[][32] = {
1324                 "RTE_SCHED_TYPE_ORDERED",
1325                 "RTE_SCHED_TYPE_ATOMIC",
1326                 "RTE_SCHED_TYPE_PARALLEL",
1327         };
1328         EH_LOG_INFO("Operating mode:");
1329
1330         EH_LOG_INFO("\tScheduling type: \t%s",
1331                 sched_types[em_conf->ext_params.sched_type]);
1332
1333         EH_LOG_INFO("");
1334 }
1335
1336 static void
1337 eh_display_event_dev_conf(struct eventmode_conf *em_conf)
1338 {
1339         char queue_mode[][32] = {
1340                 "",
1341                 "ATQ (ALL TYPE QUEUE)",
1342                 "SINGLE LINK",
1343         };
1344         char print_buf[256] = { 0 };
1345         int i;
1346
1347         EH_LOG_INFO("Event Device Configuration:");
1348
1349         for (i = 0; i < em_conf->nb_eventdev; i++) {
1350                 sprintf(print_buf,
1351                         "\tDev ID: %-2d \tQueues: %-2d \tPorts: %-2d",
1352                         em_conf->eventdev_config[i].eventdev_id,
1353                         em_conf->eventdev_config[i].nb_eventqueue,
1354                         em_conf->eventdev_config[i].nb_eventport);
1355                 sprintf(print_buf + strlen(print_buf),
1356                         "\tQueue mode: %s",
1357                         queue_mode[em_conf->eventdev_config[i].ev_queue_mode]);
1358                 EH_LOG_INFO("%s", print_buf);
1359         }
1360         EH_LOG_INFO("");
1361 }
1362
1363 static void
1364 eh_display_rx_adapter_conf(struct eventmode_conf *em_conf)
1365 {
1366         int nb_rx_adapter = em_conf->nb_rx_adapter;
1367         struct rx_adapter_connection_info *conn;
1368         struct rx_adapter_conf *adapter;
1369         char print_buf[256] = { 0 };
1370         int i, j;
1371
1372         EH_LOG_INFO("Rx adapters configured: %d", nb_rx_adapter);
1373
1374         for (i = 0; i < nb_rx_adapter; i++) {
1375                 adapter = &(em_conf->rx_adapter[i]);
1376                 sprintf(print_buf,
1377                         "\tRx adapter ID: %-2d\tConnections: %-2d\tEvent dev ID: %-2d",
1378                         adapter->adapter_id,
1379                         adapter->nb_connections,
1380                         adapter->eventdev_id);
1381                 if (adapter->rx_core_id == (uint32_t)-1)
1382                         sprintf(print_buf + strlen(print_buf),
1383                                 "\tRx core: %-2s", "[INTERNAL PORT]");
1384                 else if (adapter->rx_core_id == RTE_MAX_LCORE)
1385                         sprintf(print_buf + strlen(print_buf),
1386                                 "\tRx core: %-2s", "[NONE]");
1387                 else
1388                         sprintf(print_buf + strlen(print_buf),
1389                                 "\tRx core: %-2d", adapter->rx_core_id);
1390
1391                 EH_LOG_INFO("%s", print_buf);
1392
1393                 for (j = 0; j < adapter->nb_connections; j++) {
1394                         conn = &(adapter->conn[j]);
1395
1396                         sprintf(print_buf,
1397                                 "\t\tEthdev ID: %-2d", conn->ethdev_id);
1398
1399                         if (conn->ethdev_rx_qid == -1)
1400                                 sprintf(print_buf + strlen(print_buf),
1401                                         "\tEth rx queue: %-2s", "ALL");
1402                         else
1403                                 sprintf(print_buf + strlen(print_buf),
1404                                         "\tEth rx queue: %-2d",
1405                                         conn->ethdev_rx_qid);
1406
1407                         sprintf(print_buf + strlen(print_buf),
1408                                 "\tEvent queue: %-2d", conn->eventq_id);
1409                         EH_LOG_INFO("%s", print_buf);
1410                 }
1411         }
1412         EH_LOG_INFO("");
1413 }
1414
1415 static void
1416 eh_display_tx_adapter_conf(struct eventmode_conf *em_conf)
1417 {
1418         int nb_tx_adapter = em_conf->nb_tx_adapter;
1419         struct tx_adapter_connection_info *conn;
1420         struct tx_adapter_conf *adapter;
1421         char print_buf[256] = { 0 };
1422         int i, j;
1423
1424         EH_LOG_INFO("Tx adapters configured: %d", nb_tx_adapter);
1425
1426         for (i = 0; i < nb_tx_adapter; i++) {
1427                 adapter = &(em_conf->tx_adapter[i]);
1428                 sprintf(print_buf,
1429                         "\tTx adapter ID: %-2d\tConnections: %-2d\tEvent dev ID: %-2d",
1430                         adapter->adapter_id,
1431                         adapter->nb_connections,
1432                         adapter->eventdev_id);
1433                 if (adapter->tx_core_id == (uint32_t)-1)
1434                         sprintf(print_buf + strlen(print_buf),
1435                                 "\tTx core: %-2s", "[INTERNAL PORT]");
1436                 else if (adapter->tx_core_id == RTE_MAX_LCORE)
1437                         sprintf(print_buf + strlen(print_buf),
1438                                 "\tTx core: %-2s", "[NONE]");
1439                 else
1440                         sprintf(print_buf + strlen(print_buf),
1441                                 "\tTx core: %-2d,\tInput event queue: %-2d",
1442                                 adapter->tx_core_id, adapter->tx_ev_queue);
1443
1444                 EH_LOG_INFO("%s", print_buf);
1445
1446                 for (j = 0; j < adapter->nb_connections; j++) {
1447                         conn = &(adapter->conn[j]);
1448
1449                         sprintf(print_buf,
1450                                 "\t\tEthdev ID: %-2d", conn->ethdev_id);
1451
1452                         if (conn->ethdev_tx_qid == -1)
1453                                 sprintf(print_buf + strlen(print_buf),
1454                                         "\tEth tx queue: %-2s", "ALL");
1455                         else
1456                                 sprintf(print_buf + strlen(print_buf),
1457                                         "\tEth tx queue: %-2d",
1458                                         conn->ethdev_tx_qid);
1459                         EH_LOG_INFO("%s", print_buf);
1460                 }
1461         }
1462         EH_LOG_INFO("");
1463 }
1464
1465 static void
1466 eh_display_link_conf(struct eventmode_conf *em_conf)
1467 {
1468         struct eh_event_link_info *link;
1469         char print_buf[256] = { 0 };
1470         int i;
1471
1472         EH_LOG_INFO("Links configured: %d", em_conf->nb_link);
1473
1474         for (i = 0; i < em_conf->nb_link; i++) {
1475                 link = &(em_conf->link[i]);
1476
1477                 sprintf(print_buf,
1478                         "\tEvent dev ID: %-2d\tEvent port: %-2d",
1479                         link->eventdev_id,
1480                         link->event_port_id);
1481
1482                 if (em_conf->ext_params.all_ev_queue_to_ev_port)
1483                         sprintf(print_buf + strlen(print_buf),
1484                                 "Event queue: %-2s\t", "ALL");
1485                 else
1486                         sprintf(print_buf + strlen(print_buf),
1487                                 "Event queue: %-2d\t", link->eventq_id);
1488
1489                 sprintf(print_buf + strlen(print_buf),
1490                         "Lcore: %-2d", link->lcore_id);
1491                 EH_LOG_INFO("%s", print_buf);
1492         }
1493         EH_LOG_INFO("");
1494 }
1495
1496 struct eh_conf *
1497 eh_conf_init(void)
1498 {
1499         struct eventmode_conf *em_conf = NULL;
1500         struct eh_conf *conf = NULL;
1501         unsigned int eth_core_id;
1502         void *bitmap = NULL;
1503         uint32_t nb_bytes;
1504
1505         /* Allocate memory for config */
1506         conf = calloc(1, sizeof(struct eh_conf));
1507         if (conf == NULL) {
1508                 EH_LOG_ERR("Failed to allocate memory for eventmode helper "
1509                            "config");
1510                 return NULL;
1511         }
1512
1513         /* Set default conf */
1514
1515         /* Packet transfer mode: poll */
1516         conf->mode = EH_PKT_TRANSFER_MODE_POLL;
1517         conf->ipsec_mode = EH_IPSEC_MODE_TYPE_APP;
1518
1519         /* Keep all ethernet ports enabled by default */
1520         conf->eth_portmask = -1;
1521
1522         /* Allocate memory for event mode params */
1523         conf->mode_params = calloc(1, sizeof(struct eventmode_conf));
1524         if (conf->mode_params == NULL) {
1525                 EH_LOG_ERR("Failed to allocate memory for event mode params");
1526                 goto free_conf;
1527         }
1528
1529         /* Get eventmode conf */
1530         em_conf = conf->mode_params;
1531
1532         /* Allocate and initialize bitmap for eth cores */
1533         nb_bytes = rte_bitmap_get_memory_footprint(RTE_MAX_LCORE);
1534         if (!nb_bytes) {
1535                 EH_LOG_ERR("Failed to get bitmap footprint");
1536                 goto free_em_conf;
1537         }
1538
1539         bitmap = rte_zmalloc("event-helper-ethcore-bitmap", nb_bytes,
1540                              RTE_CACHE_LINE_SIZE);
1541         if (!bitmap) {
1542                 EH_LOG_ERR("Failed to allocate memory for eth cores bitmap\n");
1543                 goto free_em_conf;
1544         }
1545
1546         em_conf->eth_core_mask = rte_bitmap_init(RTE_MAX_LCORE, bitmap,
1547                                                  nb_bytes);
1548         if (!em_conf->eth_core_mask) {
1549                 EH_LOG_ERR("Failed to initialize bitmap");
1550                 goto free_bitmap;
1551         }
1552
1553         /* Set schedule type as not set */
1554         em_conf->ext_params.sched_type = SCHED_TYPE_NOT_SET;
1555
1556         /* Set two cores as eth cores for Rx & Tx */
1557
1558         /* Use first core other than main core as Rx core */
1559         eth_core_id = rte_get_next_lcore(0,     /* curr core */
1560                                          1,     /* skip main core */
1561                                          0      /* wrap */);
1562
1563         rte_bitmap_set(em_conf->eth_core_mask, eth_core_id);
1564
1565         /* Use next core as Tx core */
1566         eth_core_id = rte_get_next_lcore(eth_core_id,   /* curr core */
1567                                          1,             /* skip main core */
1568                                          0              /* wrap */);
1569
1570         rte_bitmap_set(em_conf->eth_core_mask, eth_core_id);
1571
1572         em_conf->ext_params.vector_size = DEFAULT_VECTOR_SIZE;
1573         em_conf->vector_tmo_ns = DEFAULT_VECTOR_TMO;
1574
1575         return conf;
1576
1577 free_bitmap:
1578         rte_free(bitmap);
1579 free_em_conf:
1580         free(em_conf);
1581 free_conf:
1582         free(conf);
1583         return NULL;
1584 }
1585
1586 void
1587 eh_conf_uninit(struct eh_conf *conf)
1588 {
1589         struct eventmode_conf *em_conf = NULL;
1590
1591         if (!conf || !conf->mode_params)
1592                 return;
1593
1594         /* Get eventmode conf */
1595         em_conf = conf->mode_params;
1596
1597         /* Free evenmode configuration memory */
1598         rte_free(em_conf->eth_core_mask);
1599         free(em_conf);
1600         free(conf);
1601 }
1602
1603 void
1604 eh_display_conf(struct eh_conf *conf)
1605 {
1606         struct eventmode_conf *em_conf;
1607
1608         if (conf == NULL) {
1609                 EH_LOG_ERR("Invalid event helper configuration");
1610                 return;
1611         }
1612
1613         if (conf->mode != EH_PKT_TRANSFER_MODE_EVENT)
1614                 return;
1615
1616         if (conf->mode_params == NULL) {
1617                 EH_LOG_ERR("Invalid event mode parameters");
1618                 return;
1619         }
1620
1621         /* Get eventmode conf */
1622         em_conf = (struct eventmode_conf *)(conf->mode_params);
1623
1624         /* Display user exposed operating modes */
1625         eh_display_operating_mode(em_conf);
1626
1627         /* Display event device conf */
1628         eh_display_event_dev_conf(em_conf);
1629
1630         /* Display Rx adapter conf */
1631         eh_display_rx_adapter_conf(em_conf);
1632
1633         /* Display Tx adapter conf */
1634         eh_display_tx_adapter_conf(em_conf);
1635
1636         /* Display event-lcore link */
1637         eh_display_link_conf(em_conf);
1638 }
1639
1640 int32_t
1641 eh_devs_init(struct eh_conf *conf)
1642 {
1643         struct eventmode_conf *em_conf;
1644         uint16_t port_id;
1645         int ret;
1646
1647         if (conf == NULL) {
1648                 EH_LOG_ERR("Invalid event helper configuration");
1649                 return -EINVAL;
1650         }
1651
1652         if (conf->mode != EH_PKT_TRANSFER_MODE_EVENT)
1653                 return 0;
1654
1655         if (conf->mode_params == NULL) {
1656                 EH_LOG_ERR("Invalid event mode parameters");
1657                 return -EINVAL;
1658         }
1659
1660         /* Get eventmode conf */
1661         em_conf = conf->mode_params;
1662
1663         /* Eventmode conf would need eth portmask */
1664         em_conf->eth_portmask = conf->eth_portmask;
1665
1666         /* Validate the requested config */
1667         ret = eh_validate_conf(em_conf);
1668         if (ret < 0) {
1669                 EH_LOG_ERR("Failed to validate the requested config %d", ret);
1670                 return ret;
1671         }
1672
1673         /* Display the current configuration */
1674         eh_display_conf(conf);
1675
1676         /* Stop eth devices before setting up adapter */
1677         RTE_ETH_FOREACH_DEV(port_id) {
1678
1679                 /* Use only the ports enabled */
1680                 if ((conf->eth_portmask & (1 << port_id)) == 0)
1681                         continue;
1682
1683                 ret = rte_eth_dev_stop(port_id);
1684                 if (ret != 0) {
1685                         EH_LOG_ERR("Failed to stop port %u, err: %d",
1686                                         port_id, ret);
1687                         return ret;
1688                 }
1689         }
1690
1691         /* Setup eventdev */
1692         ret = eh_initialize_eventdev(em_conf);
1693         if (ret < 0) {
1694                 EH_LOG_ERR("Failed to initialize event dev %d", ret);
1695                 return ret;
1696         }
1697
1698         /* Setup Rx adapter */
1699         ret = eh_initialize_rx_adapter(em_conf);
1700         if (ret < 0) {
1701                 EH_LOG_ERR("Failed to initialize rx adapter %d", ret);
1702                 return ret;
1703         }
1704
1705         /* Setup Tx adapter */
1706         ret = eh_initialize_tx_adapter(em_conf);
1707         if (ret < 0) {
1708                 EH_LOG_ERR("Failed to initialize tx adapter %d", ret);
1709                 return ret;
1710         }
1711
1712         /* Start eventdev */
1713         ret = eh_start_eventdev(em_conf);
1714         if (ret < 0) {
1715                 EH_LOG_ERR("Failed to start event dev %d", ret);
1716                 return ret;
1717         }
1718
1719         /* Start eth devices after setting up adapter */
1720         RTE_ETH_FOREACH_DEV(port_id) {
1721
1722                 /* Use only the ports enabled */
1723                 if ((conf->eth_portmask & (1 << port_id)) == 0)
1724                         continue;
1725
1726                 ret = rte_eth_dev_start(port_id);
1727                 if (ret < 0) {
1728                         EH_LOG_ERR("Failed to start eth dev %d, %d",
1729                                    port_id, ret);
1730                         return ret;
1731                 }
1732         }
1733
1734         return 0;
1735 }
1736
1737 int32_t
1738 eh_devs_uninit(struct eh_conf *conf)
1739 {
1740         struct eventmode_conf *em_conf;
1741         int ret, i, j;
1742         uint16_t id;
1743
1744         if (conf == NULL) {
1745                 EH_LOG_ERR("Invalid event helper configuration");
1746                 return -EINVAL;
1747         }
1748
1749         if (conf->mode != EH_PKT_TRANSFER_MODE_EVENT)
1750                 return 0;
1751
1752         if (conf->mode_params == NULL) {
1753                 EH_LOG_ERR("Invalid event mode parameters");
1754                 return -EINVAL;
1755         }
1756
1757         /* Get eventmode conf */
1758         em_conf = conf->mode_params;
1759
1760         /* Stop and release rx adapters */
1761         for (i = 0; i < em_conf->nb_rx_adapter; i++) {
1762
1763                 id = em_conf->rx_adapter[i].adapter_id;
1764                 ret = rte_event_eth_rx_adapter_stop(id);
1765                 if (ret < 0) {
1766                         EH_LOG_ERR("Failed to stop rx adapter %d", ret);
1767                         return ret;
1768                 }
1769
1770                 for (j = 0; j < em_conf->rx_adapter[i].nb_connections; j++) {
1771
1772                         ret = rte_event_eth_rx_adapter_queue_del(id,
1773                                 em_conf->rx_adapter[i].conn[j].ethdev_id, -1);
1774                         if (ret < 0) {
1775                                 EH_LOG_ERR(
1776                                        "Failed to remove rx adapter queues %d",
1777                                        ret);
1778                                 return ret;
1779                         }
1780                 }
1781
1782                 ret = rte_event_eth_rx_adapter_free(id);
1783                 if (ret < 0) {
1784                         EH_LOG_ERR("Failed to free rx adapter %d", ret);
1785                         return ret;
1786                 }
1787         }
1788
1789         /* Stop and release event devices */
1790         for (i = 0; i < em_conf->nb_eventdev; i++) {
1791
1792                 id = em_conf->eventdev_config[i].eventdev_id;
1793                 rte_event_dev_stop(id);
1794
1795                 ret = rte_event_dev_close(id);
1796                 if (ret < 0) {
1797                         EH_LOG_ERR("Failed to close event dev %d, %d", id, ret);
1798                         return ret;
1799                 }
1800         }
1801
1802         /* Stop and release tx adapters */
1803         for (i = 0; i < em_conf->nb_tx_adapter; i++) {
1804
1805                 id = em_conf->tx_adapter[i].adapter_id;
1806                 ret = rte_event_eth_tx_adapter_stop(id);
1807                 if (ret < 0) {
1808                         EH_LOG_ERR("Failed to stop tx adapter %d", ret);
1809                         return ret;
1810                 }
1811
1812                 for (j = 0; j < em_conf->tx_adapter[i].nb_connections; j++) {
1813
1814                         ret = rte_event_eth_tx_adapter_queue_del(id,
1815                                 em_conf->tx_adapter[i].conn[j].ethdev_id, -1);
1816                         if (ret < 0) {
1817                                 EH_LOG_ERR(
1818                                         "Failed to remove tx adapter queues %d",
1819                                         ret);
1820                                 return ret;
1821                         }
1822                 }
1823
1824                 ret = rte_event_eth_tx_adapter_free(id);
1825                 if (ret < 0) {
1826                         EH_LOG_ERR("Failed to free tx adapter %d", ret);
1827                         return ret;
1828                 }
1829         }
1830
1831         return 0;
1832 }
1833
1834 void
1835 eh_launch_worker(struct eh_conf *conf, struct eh_app_worker_params *app_wrkr,
1836                 uint8_t nb_wrkr_param)
1837 {
1838         struct eh_app_worker_params *match_wrkr;
1839         struct eh_event_link_info *links = NULL;
1840         struct eventmode_conf *em_conf;
1841         uint32_t lcore_id;
1842         uint8_t nb_links;
1843
1844         if (conf == NULL) {
1845                 EH_LOG_ERR("Invalid event helper configuration");
1846                 return;
1847         }
1848
1849         if (conf->mode_params == NULL) {
1850                 EH_LOG_ERR("Invalid event mode parameters");
1851                 return;
1852         }
1853
1854         /* Get eventmode conf */
1855         em_conf = conf->mode_params;
1856
1857         /* Get core ID */
1858         lcore_id = rte_lcore_id();
1859
1860         /* Check if this is eth core */
1861         if (rte_bitmap_get(em_conf->eth_core_mask, lcore_id)) {
1862                 eh_start_worker_eth_core(em_conf, lcore_id);
1863                 return;
1864         }
1865
1866         if (app_wrkr == NULL || nb_wrkr_param == 0) {
1867                 EH_LOG_ERR("Invalid args");
1868                 return;
1869         }
1870
1871         /*
1872          * This is a regular worker thread. The application registers
1873          * multiple workers with various capabilities. Run worker
1874          * based on the selected capabilities of the event
1875          * device configured.
1876          */
1877
1878         /* Get the first matching worker for the event device */
1879         match_wrkr = eh_find_worker(lcore_id, conf, app_wrkr, nb_wrkr_param);
1880         if (match_wrkr == NULL) {
1881                 EH_LOG_ERR("Failed to match worker registered for lcore %d",
1882                            lcore_id);
1883                 goto clean_and_exit;
1884         }
1885
1886         /* Verify sanity of the matched worker */
1887         if (eh_verify_match_worker(match_wrkr) != 1) {
1888                 EH_LOG_ERR("Failed to validate the matched worker");
1889                 goto clean_and_exit;
1890         }
1891
1892         /* Get worker links */
1893         nb_links = eh_get_event_lcore_links(lcore_id, conf, &links);
1894
1895         /* Launch the worker thread */
1896         match_wrkr->worker_thread(links, nb_links);
1897
1898         /* Free links info memory */
1899         free(links);
1900
1901 clean_and_exit:
1902
1903         /* Flag eth_cores to stop, if started */
1904         eh_stop_worker_eth_core();
1905 }
1906
1907 uint8_t
1908 eh_get_tx_queue(struct eh_conf *conf, uint8_t eventdev_id)
1909 {
1910         struct eventdev_params *eventdev_config;
1911         struct eventmode_conf *em_conf;
1912
1913         if (conf == NULL) {
1914                 EH_LOG_ERR("Invalid event helper configuration");
1915                 return -EINVAL;
1916         }
1917
1918         if (conf->mode_params == NULL) {
1919                 EH_LOG_ERR("Invalid event mode parameters");
1920                 return -EINVAL;
1921         }
1922
1923         /* Get eventmode conf */
1924         em_conf = conf->mode_params;
1925
1926         /* Get event device conf */
1927         eventdev_config = eh_get_eventdev_params(em_conf, eventdev_id);
1928
1929         if (eventdev_config == NULL) {
1930                 EH_LOG_ERR("Failed to read eventdev config");
1931                 return -EINVAL;
1932         }
1933
1934         /*
1935          * The last queue is reserved to be used as atomic queue for the
1936          * last stage (eth packet tx stage)
1937          */
1938         return eventdev_config->nb_eventqueue - 1;
1939 }