Imported Upstream version 16.07-rc1
[deb_dpdk.git] / examples / ip_pipeline / app.h
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #ifndef __INCLUDE_APP_H__
35 #define __INCLUDE_APP_H__
36
37 #include <stdint.h>
38 #include <string.h>
39
40 #include <rte_common.h>
41 #include <rte_mempool.h>
42 #include <rte_ring.h>
43 #include <rte_sched.h>
44 #include <cmdline_parse.h>
45
46 #include <rte_ethdev.h>
47 #ifdef RTE_LIBRTE_KNI
48 #include <rte_kni.h>
49 #endif
50
51 #include "cpu_core_map.h"
52 #include "pipeline.h"
53
54 #define APP_PARAM_NAME_SIZE                      PIPELINE_NAME_SIZE
55 #define APP_LINK_PCI_BDF_SIZE                    16
56
57 #ifndef APP_LINK_MAX_HWQ_IN
58 #define APP_LINK_MAX_HWQ_IN                      128
59 #endif
60
61 #ifndef APP_LINK_MAX_HWQ_OUT
62 #define APP_LINK_MAX_HWQ_OUT                     128
63 #endif
64
65 struct app_mempool_params {
66         char *name;
67         uint32_t parsed;
68         uint32_t buffer_size;
69         uint32_t pool_size;
70         uint32_t cache_size;
71         uint32_t cpu_socket_id;
72 };
73
74 struct app_link_params {
75         char *name;
76         uint32_t parsed;
77         uint32_t pmd_id; /* Generated based on port mask */
78         uint32_t arp_q; /* 0 = Disabled (packets go to default queue 0) */
79         uint32_t tcp_syn_q; /* 0 = Disabled (pkts go to default queue) */
80         uint32_t ip_local_q; /* 0 = Disabled (pkts go to default queue 0) */
81         uint32_t tcp_local_q; /* 0 = Disabled (pkts go to default queue 0) */
82         uint32_t udp_local_q; /* 0 = Disabled (pkts go to default queue 0) */
83         uint32_t sctp_local_q; /* 0 = Disabled (pkts go to default queue 0) */
84         uint32_t rss_qs[APP_LINK_MAX_HWQ_IN];
85         uint32_t n_rss_qs;
86         uint64_t rss_proto_ipv4;
87         uint64_t rss_proto_ipv6;
88         uint64_t rss_proto_l2;
89         uint32_t promisc;
90         uint32_t state; /* DOWN = 0, UP = 1 */
91         uint32_t ip; /* 0 = Invalid */
92         uint32_t depth; /* Valid only when IP is valid */
93         uint64_t mac_addr; /* Read from HW */
94         char pci_bdf[APP_LINK_PCI_BDF_SIZE];
95
96         struct rte_eth_conf conf;
97 };
98
99 struct app_pktq_hwq_in_params {
100         char *name;
101         uint32_t parsed;
102         uint32_t mempool_id; /* Position in the app->mempool_params */
103         uint32_t size;
104         uint32_t burst;
105
106         struct rte_eth_rxconf conf;
107 };
108
109 struct app_pktq_hwq_out_params {
110         char *name;
111         uint32_t parsed;
112         uint32_t size;
113         uint32_t burst;
114         uint32_t dropless;
115         uint64_t n_retries;
116         struct rte_eth_txconf conf;
117 };
118
119 struct app_pktq_swq_params {
120         char *name;
121         uint32_t parsed;
122         uint32_t size;
123         uint32_t burst_read;
124         uint32_t burst_write;
125         uint32_t dropless;
126         uint64_t n_retries;
127         uint32_t cpu_socket_id;
128         uint32_t ipv4_frag;
129         uint32_t ipv6_frag;
130         uint32_t ipv4_ras;
131         uint32_t ipv6_ras;
132         uint32_t mtu;
133         uint32_t metadata_size;
134         uint32_t mempool_direct_id;
135         uint32_t mempool_indirect_id;
136 };
137
138 struct app_pktq_kni_params {
139         char *name;
140         uint32_t parsed;
141
142         uint32_t socket_id;
143         uint32_t core_id;
144         uint32_t hyper_th_id;
145         uint32_t force_bind;
146
147         uint32_t mempool_id; /* Position in the app->mempool_params */
148         uint32_t burst_read;
149         uint32_t burst_write;
150         uint32_t dropless;
151         uint64_t n_retries;
152 };
153
154 #ifndef APP_FILE_NAME_SIZE
155 #define APP_FILE_NAME_SIZE                       256
156 #endif
157
158 #ifndef APP_MAX_SCHED_SUBPORTS
159 #define APP_MAX_SCHED_SUBPORTS                   8
160 #endif
161
162 #ifndef APP_MAX_SCHED_PIPES
163 #define APP_MAX_SCHED_PIPES                      4096
164 #endif
165
166 struct app_pktq_tm_params {
167         char *name;
168         uint32_t parsed;
169         const char *file_name;
170         struct rte_sched_port_params sched_port_params;
171         struct rte_sched_subport_params
172                 sched_subport_params[APP_MAX_SCHED_SUBPORTS];
173         struct rte_sched_pipe_params
174                 sched_pipe_profiles[RTE_SCHED_PIPE_PROFILES_PER_PORT];
175         int sched_pipe_to_profile[APP_MAX_SCHED_SUBPORTS * APP_MAX_SCHED_PIPES];
176         uint32_t burst_read;
177         uint32_t burst_write;
178 };
179
180 struct app_pktq_source_params {
181         char *name;
182         uint32_t parsed;
183         uint32_t mempool_id; /* Position in the app->mempool_params array */
184         uint32_t burst;
185         char *file_name; /* Full path of PCAP file to be copied to mbufs */
186         uint32_t n_bytes_per_pkt;
187 };
188
189 struct app_pktq_sink_params {
190         char *name;
191         uint8_t parsed;
192         char *file_name; /* Full path of PCAP file to be copied to mbufs */
193         uint32_t n_pkts_to_dump;
194 };
195
196 struct app_msgq_params {
197         char *name;
198         uint32_t parsed;
199         uint32_t size;
200         uint32_t cpu_socket_id;
201 };
202
203 enum app_pktq_in_type {
204         APP_PKTQ_IN_HWQ,
205         APP_PKTQ_IN_SWQ,
206         APP_PKTQ_IN_TM,
207         APP_PKTQ_IN_KNI,
208         APP_PKTQ_IN_SOURCE,
209 };
210
211 struct app_pktq_in_params {
212         enum app_pktq_in_type type;
213         uint32_t id; /* Position in the appropriate app array */
214 };
215
216 enum app_pktq_out_type {
217         APP_PKTQ_OUT_HWQ,
218         APP_PKTQ_OUT_SWQ,
219         APP_PKTQ_OUT_TM,
220         APP_PKTQ_OUT_KNI,
221         APP_PKTQ_OUT_SINK,
222 };
223
224 struct app_pktq_out_params {
225         enum app_pktq_out_type type;
226         uint32_t id; /* Position in the appropriate app array */
227 };
228
229 #define APP_PIPELINE_TYPE_SIZE                   PIPELINE_TYPE_SIZE
230
231 #define APP_MAX_PIPELINE_PKTQ_IN                 PIPELINE_MAX_PORT_IN
232 #define APP_MAX_PIPELINE_PKTQ_OUT                PIPELINE_MAX_PORT_OUT
233 #define APP_MAX_PIPELINE_MSGQ_IN                 PIPELINE_MAX_MSGQ_IN
234 #define APP_MAX_PIPELINE_MSGQ_OUT                PIPELINE_MAX_MSGQ_OUT
235
236 #define APP_MAX_PIPELINE_ARGS                    PIPELINE_MAX_ARGS
237
238 struct app_pipeline_params {
239         char *name;
240         uint8_t parsed;
241
242         char type[APP_PIPELINE_TYPE_SIZE];
243
244         uint32_t socket_id;
245         uint32_t core_id;
246         uint32_t hyper_th_id;
247
248         struct app_pktq_in_params pktq_in[APP_MAX_PIPELINE_PKTQ_IN];
249         struct app_pktq_out_params pktq_out[APP_MAX_PIPELINE_PKTQ_OUT];
250         uint32_t msgq_in[APP_MAX_PIPELINE_MSGQ_IN];
251         uint32_t msgq_out[APP_MAX_PIPELINE_MSGQ_OUT];
252
253         uint32_t n_pktq_in;
254         uint32_t n_pktq_out;
255         uint32_t n_msgq_in;
256         uint32_t n_msgq_out;
257
258         uint32_t timer_period;
259
260         char *args_name[APP_MAX_PIPELINE_ARGS];
261         char *args_value[APP_MAX_PIPELINE_ARGS];
262         uint32_t n_args;
263 };
264
265 struct app_params;
266
267 typedef void (*app_link_op)(struct app_params *app,
268         uint32_t link_id,
269         uint32_t up,
270         void *arg);
271
272 #ifndef APP_MAX_PIPELINES
273 #define APP_MAX_PIPELINES                        64
274 #endif
275
276 struct app_link_data {
277         app_link_op f_link[APP_MAX_PIPELINES];
278         void *arg[APP_MAX_PIPELINES];
279 };
280
281 struct app_pipeline_data {
282         void *be;
283         void *fe;
284         struct pipeline_type *ptype;
285         uint64_t timer_period;
286         uint32_t enabled;
287 };
288
289 struct app_thread_pipeline_data {
290         uint32_t pipeline_id;
291         void *be;
292         pipeline_be_op_run f_run;
293         pipeline_be_op_timer f_timer;
294         uint64_t timer_period;
295         uint64_t deadline;
296 };
297
298 #ifndef APP_MAX_THREAD_PIPELINES
299 #define APP_MAX_THREAD_PIPELINES                 64
300 #endif
301
302 #ifndef APP_THREAD_TIMER_PERIOD
303 #define APP_THREAD_TIMER_PERIOD                  1
304 #endif
305
306 struct app_thread_data {
307         struct app_thread_pipeline_data regular[APP_MAX_THREAD_PIPELINES];
308         struct app_thread_pipeline_data custom[APP_MAX_THREAD_PIPELINES];
309
310         uint32_t n_regular;
311         uint32_t n_custom;
312
313         uint64_t timer_period;
314         uint64_t thread_req_deadline;
315
316         uint64_t deadline;
317
318         struct rte_ring *msgq_in;
319         struct rte_ring *msgq_out;
320
321         uint64_t headroom_time;
322         uint64_t headroom_cycles;
323         double headroom_ratio;
324 } __rte_cache_aligned;
325
326 #ifndef APP_MAX_LINKS
327 #define APP_MAX_LINKS                            16
328 #endif
329
330 struct app_eal_params {
331         /* Map lcore set to physical cpu set */
332         char *coremap;
333
334         /* Core ID that is used as master */
335         uint32_t master_lcore_present;
336         uint32_t master_lcore;
337
338         /* Number of memory channels */
339         uint32_t channels_present;
340         uint32_t channels;
341
342         /* Memory to allocate (see also --socket-mem) */
343         uint32_t memory_present;
344         uint32_t memory;
345
346         /* Force number of memory ranks (don't detect) */
347         uint32_t ranks_present;
348         uint32_t ranks;
349
350         /* Add a PCI device in black list. */
351         char *pci_blacklist[APP_MAX_LINKS];
352
353         /* Add a PCI device in white list. */
354         char *pci_whitelist[APP_MAX_LINKS];
355
356         /* Add a virtual device. */
357         char *vdev[APP_MAX_LINKS];
358
359          /* Use VMware TSC map instead of native RDTSC */
360         uint32_t vmware_tsc_map_present;
361         int vmware_tsc_map;
362
363          /* Type of this process (primary|secondary|auto) */
364         char *proc_type;
365
366          /* Set syslog facility */
367         char *syslog;
368
369         /* Set default log level */
370         uint32_t log_level_present;
371         uint32_t log_level;
372
373         /* Display version information on startup */
374         uint32_t version_present;
375         int version;
376
377         /* This help */
378         uint32_t help_present;
379         int help;
380
381          /* Use malloc instead of hugetlbfs */
382         uint32_t no_huge_present;
383         int no_huge;
384
385         /* Disable PCI */
386         uint32_t no_pci_present;
387         int no_pci;
388
389         /* Disable HPET */
390         uint32_t no_hpet_present;
391         int no_hpet;
392
393         /* No shared config (mmap'd files) */
394         uint32_t no_shconf_present;
395         int no_shconf;
396
397         /* Add driver */
398         char *add_driver;
399
400         /*  Memory to allocate on sockets (comma separated values)*/
401         char *socket_mem;
402
403         /* Directory where hugetlbfs is mounted */
404         char *huge_dir;
405
406         /* Prefix for hugepage filenames */
407         char *file_prefix;
408
409         /* Base virtual address */
410         char *base_virtaddr;
411
412         /* Create /dev/uioX (usually done by hotplug) */
413         uint32_t create_uio_dev_present;
414         int create_uio_dev;
415
416         /* Interrupt mode for VFIO (legacy|msi|msix) */
417         char *vfio_intr;
418
419         /* Support running on Xen dom0 without hugetlbfs */
420         uint32_t xen_dom0_present;
421         int xen_dom0;
422
423         uint32_t parsed;
424 };
425
426 #ifndef APP_APPNAME_SIZE
427 #define APP_APPNAME_SIZE                         256
428 #endif
429
430 #ifndef APP_MAX_MEMPOOLS
431 #define APP_MAX_MEMPOOLS                         8
432 #endif
433
434 #define APP_MAX_HWQ_IN                  (APP_MAX_LINKS * APP_LINK_MAX_HWQ_IN)
435
436 #define APP_MAX_HWQ_OUT                 (APP_MAX_LINKS * APP_LINK_MAX_HWQ_OUT)
437
438 #ifndef APP_MAX_PKTQ_SWQ
439 #define APP_MAX_PKTQ_SWQ                         256
440 #endif
441
442 #define APP_MAX_PKTQ_TM                          APP_MAX_LINKS
443
444 #define APP_MAX_PKTQ_KNI                         APP_MAX_LINKS
445
446 #ifndef APP_MAX_PKTQ_SOURCE
447 #define APP_MAX_PKTQ_SOURCE                      64
448 #endif
449
450 #ifndef APP_MAX_PKTQ_SINK
451 #define APP_MAX_PKTQ_SINK                        64
452 #endif
453
454 #ifndef APP_MAX_MSGQ
455 #define APP_MAX_MSGQ                             256
456 #endif
457
458 #ifndef APP_EAL_ARGC
459 #define APP_EAL_ARGC                             64
460 #endif
461
462 #ifndef APP_MAX_PIPELINE_TYPES
463 #define APP_MAX_PIPELINE_TYPES                   64
464 #endif
465
466 #ifndef APP_MAX_THREADS
467 #define APP_MAX_THREADS                          RTE_MAX_LCORE
468 #endif
469
470 #ifndef APP_MAX_CMDS
471 #define APP_MAX_CMDS                             64
472 #endif
473
474 #ifndef APP_THREAD_HEADROOM_STATS_COLLECT
475 #define APP_THREAD_HEADROOM_STATS_COLLECT        1
476 #endif
477
478 struct app_params {
479         /* Config */
480         char app_name[APP_APPNAME_SIZE];
481         const char *config_file;
482         const char *script_file;
483         const char *parser_file;
484         const char *output_file;
485         const char *preproc;
486         const char *preproc_args;
487         uint64_t port_mask;
488         uint32_t log_level;
489
490         struct app_eal_params eal_params;
491         struct app_mempool_params mempool_params[APP_MAX_MEMPOOLS];
492         struct app_link_params link_params[APP_MAX_LINKS];
493         struct app_pktq_hwq_in_params hwq_in_params[APP_MAX_HWQ_IN];
494         struct app_pktq_hwq_out_params hwq_out_params[APP_MAX_HWQ_OUT];
495         struct app_pktq_swq_params swq_params[APP_MAX_PKTQ_SWQ];
496         struct app_pktq_tm_params tm_params[APP_MAX_PKTQ_TM];
497         struct app_pktq_kni_params kni_params[APP_MAX_PKTQ_KNI];
498         struct app_pktq_source_params source_params[APP_MAX_PKTQ_SOURCE];
499         struct app_pktq_sink_params sink_params[APP_MAX_PKTQ_SINK];
500         struct app_msgq_params msgq_params[APP_MAX_MSGQ];
501         struct app_pipeline_params pipeline_params[APP_MAX_PIPELINES];
502
503         uint32_t n_mempools;
504         uint32_t n_links;
505         uint32_t n_pktq_hwq_in;
506         uint32_t n_pktq_hwq_out;
507         uint32_t n_pktq_swq;
508         uint32_t n_pktq_tm;
509         uint32_t n_pktq_kni;
510         uint32_t n_pktq_source;
511         uint32_t n_pktq_sink;
512         uint32_t n_msgq;
513         uint32_t n_pipelines;
514
515         /* Init */
516         char *eal_argv[1 + APP_EAL_ARGC];
517         struct cpu_core_map *core_map;
518         uint64_t core_mask;
519         struct rte_mempool *mempool[APP_MAX_MEMPOOLS];
520         struct app_link_data link_data[APP_MAX_LINKS];
521         struct rte_ring *swq[APP_MAX_PKTQ_SWQ];
522         struct rte_sched_port *tm[APP_MAX_PKTQ_TM];
523 #ifdef RTE_LIBRTE_KNI
524         struct rte_kni *kni[APP_MAX_PKTQ_KNI];
525 #endif /* RTE_LIBRTE_KNI */
526         struct rte_ring *msgq[APP_MAX_MSGQ];
527         struct pipeline_type pipeline_type[APP_MAX_PIPELINE_TYPES];
528         struct app_pipeline_data pipeline_data[APP_MAX_PIPELINES];
529         struct app_thread_data thread_data[APP_MAX_THREADS];
530         cmdline_parse_ctx_t cmds[APP_MAX_CMDS + 1];
531
532         int eal_argc;
533         uint32_t n_pipeline_types;
534         uint32_t n_cmds;
535 };
536
537 #define APP_PARAM_VALID(obj) ((obj)->name != NULL)
538
539 #define APP_PARAM_COUNT(obj_array, n_objs)                              \
540 {                                                                       \
541         size_t i;                                                       \
542                                                                         \
543         n_objs = 0;                                                     \
544         for (i = 0; i < RTE_DIM(obj_array); i++)                        \
545                 if (APP_PARAM_VALID(&((obj_array)[i])))                 \
546                         n_objs++;                                       \
547 }
548
549 #define APP_PARAM_FIND(obj_array, key)                                  \
550 ({                                                                      \
551         ssize_t obj_idx;                                                \
552         const ssize_t obj_count = RTE_DIM(obj_array);                   \
553                                                                         \
554         for (obj_idx = 0; obj_idx < obj_count; obj_idx++) {             \
555                 if (!APP_PARAM_VALID(&((obj_array)[obj_idx])))          \
556                         continue;                                       \
557                                                                         \
558                 if (strcmp(key, (obj_array)[obj_idx].name) == 0)        \
559                         break;                                          \
560         }                                                               \
561         obj_idx < obj_count ? obj_idx : -ENOENT;                        \
562 })
563
564 #define APP_PARAM_FIND_BY_ID(obj_array, prefix, id, obj)                \
565 do {                                                                    \
566         char name[APP_PARAM_NAME_SIZE];                                 \
567         ssize_t pos;                                                    \
568                                                                         \
569         sprintf(name, prefix "%" PRIu32, id);                           \
570         pos = APP_PARAM_FIND(obj_array, name);                          \
571         obj = (pos < 0) ? NULL : &((obj_array)[pos]);                   \
572 } while (0)
573
574 #define APP_PARAM_GET_ID(obj, prefix, id)                               \
575 do                                                                      \
576         sscanf(obj->name, prefix "%" SCNu32, &id);                              \
577 while (0)                                                               \
578
579 #define APP_CHECK(exp, fmt, ...)                                        \
580 do {                                                                    \
581         if (!(exp)) {                                                   \
582                 fprintf(stderr, fmt "\n", ## __VA_ARGS__);              \
583                 abort();                                                \
584         }                                                               \
585 } while (0)
586
587 enum app_log_level {
588         APP_LOG_LEVEL_HIGH = 1,
589         APP_LOG_LEVEL_LOW,
590         APP_LOG_LEVELS
591 };
592
593 #define APP_LOG(app, level, fmt, ...)                                   \
594 do {                                                                    \
595         if (app->log_level >= APP_LOG_LEVEL_ ## level)                  \
596                 fprintf(stdout, "[APP] " fmt "\n", ## __VA_ARGS__);     \
597 } while (0)
598
599 static inline uint32_t
600 app_link_get_n_rxq(struct app_params *app, struct app_link_params *link)
601 {
602         uint32_t n_rxq = 0, link_id, i;
603         uint32_t n_pktq_hwq_in = RTE_MIN(app->n_pktq_hwq_in,
604                 RTE_DIM(app->hwq_in_params));
605
606         APP_PARAM_GET_ID(link, "LINK", link_id);
607
608         for (i = 0; i < n_pktq_hwq_in; i++) {
609                 struct app_pktq_hwq_in_params *p = &app->hwq_in_params[i];
610                 uint32_t rxq_link_id, rxq_queue_id;
611
612                 sscanf(p->name, "RXQ%" SCNu32 ".%" SCNu32,
613                         &rxq_link_id, &rxq_queue_id);
614                 if (rxq_link_id == link_id)
615                         n_rxq++;
616         }
617
618         return n_rxq;
619 }
620
621 static inline uint32_t
622 app_link_get_n_txq(struct app_params *app, struct app_link_params *link)
623 {
624         uint32_t n_txq = 0, link_id, i;
625         uint32_t n_pktq_hwq_out = RTE_MIN(app->n_pktq_hwq_out,
626                 RTE_DIM(app->hwq_out_params));
627
628         APP_PARAM_GET_ID(link, "LINK", link_id);
629
630         for (i = 0; i < n_pktq_hwq_out; i++) {
631                 struct app_pktq_hwq_out_params *p = &app->hwq_out_params[i];
632                 uint32_t txq_link_id, txq_queue_id;
633
634                 sscanf(p->name, "TXQ%" SCNu32 ".%" SCNu32,
635                         &txq_link_id, &txq_queue_id);
636                 if (txq_link_id == link_id)
637                         n_txq++;
638         }
639
640         return n_txq;
641 }
642
643 static inline uint32_t
644 app_rxq_get_readers(struct app_params *app, struct app_pktq_hwq_in_params *rxq)
645 {
646         uint32_t pos = rxq - app->hwq_in_params;
647         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
648                 RTE_DIM(app->pipeline_params));
649         uint32_t n_readers = 0, i;
650
651         for (i = 0; i < n_pipelines; i++) {
652                 struct app_pipeline_params *p = &app->pipeline_params[i];
653                 uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
654                 uint32_t j;
655
656                 for (j = 0; j < n_pktq_in; j++) {
657                         struct app_pktq_in_params *pktq = &p->pktq_in[j];
658
659                         if ((pktq->type == APP_PKTQ_IN_HWQ) &&
660                                 (pktq->id == pos))
661                                 n_readers++;
662                 }
663         }
664
665         return n_readers;
666 }
667
668 static inline uint32_t
669 app_swq_get_readers(struct app_params *app, struct app_pktq_swq_params *swq)
670 {
671         uint32_t pos = swq - app->swq_params;
672         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
673                 RTE_DIM(app->pipeline_params));
674         uint32_t n_readers = 0, i;
675
676         for (i = 0; i < n_pipelines; i++) {
677                 struct app_pipeline_params *p = &app->pipeline_params[i];
678                 uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
679                 uint32_t j;
680
681                 for (j = 0; j < n_pktq_in; j++) {
682                         struct app_pktq_in_params *pktq = &p->pktq_in[j];
683
684                         if ((pktq->type == APP_PKTQ_IN_SWQ) &&
685                                 (pktq->id == pos))
686                                 n_readers++;
687                 }
688         }
689
690         return n_readers;
691 }
692
693 static inline struct app_pipeline_params *
694 app_swq_get_reader(struct app_params *app,
695         struct app_pktq_swq_params *swq,
696         uint32_t *pktq_in_id)
697 {
698         struct app_pipeline_params *reader = NULL;
699         uint32_t pos = swq - app->swq_params;
700         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
701                 RTE_DIM(app->pipeline_params));
702         uint32_t n_readers = 0, id = 0, i;
703
704         for (i = 0; i < n_pipelines; i++) {
705                 struct app_pipeline_params *p = &app->pipeline_params[i];
706                 uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
707                 uint32_t j;
708
709                 for (j = 0; j < n_pktq_in; j++) {
710                         struct app_pktq_in_params *pktq = &p->pktq_in[j];
711
712                         if ((pktq->type == APP_PKTQ_IN_SWQ) &&
713                                 (pktq->id == pos)) {
714                                 n_readers++;
715                                 reader = p;
716                                 id = j;
717                         }
718                 }
719         }
720
721         if (n_readers != 1)
722                 return NULL;
723
724         *pktq_in_id = id;
725         return reader;
726 }
727
728 static inline uint32_t
729 app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm)
730 {
731         uint32_t pos = tm - app->tm_params;
732         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
733                 RTE_DIM(app->pipeline_params));
734         uint32_t n_readers = 0, i;
735
736         for (i = 0; i < n_pipelines; i++) {
737                 struct app_pipeline_params *p = &app->pipeline_params[i];
738                 uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
739                 uint32_t j;
740
741                 for (j = 0; j < n_pktq_in; j++) {
742                         struct app_pktq_in_params *pktq = &p->pktq_in[j];
743
744                         if ((pktq->type == APP_PKTQ_IN_TM) &&
745                                 (pktq->id == pos))
746                                 n_readers++;
747                 }
748         }
749
750         return n_readers;
751 }
752
753 static inline struct app_pipeline_params *
754 app_tm_get_reader(struct app_params *app,
755         struct app_pktq_tm_params *tm,
756         uint32_t *pktq_in_id)
757 {
758         struct app_pipeline_params *reader = NULL;
759         uint32_t pos = tm - app->tm_params;
760         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
761                 RTE_DIM(app->pipeline_params));
762         uint32_t n_readers = 0, id = 0, i;
763
764         for (i = 0; i < n_pipelines; i++) {
765                 struct app_pipeline_params *p = &app->pipeline_params[i];
766                 uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
767                 uint32_t j;
768
769                 for (j = 0; j < n_pktq_in; j++) {
770                         struct app_pktq_in_params *pktq = &p->pktq_in[j];
771
772                         if ((pktq->type == APP_PKTQ_IN_TM) &&
773                                 (pktq->id == pos)) {
774                                 n_readers++;
775                                 reader = p;
776                                 id = j;
777                         }
778                 }
779         }
780
781         if (n_readers != 1)
782                 return NULL;
783
784         *pktq_in_id = id;
785         return reader;
786 }
787
788 static inline uint32_t
789 app_kni_get_readers(struct app_params *app, struct app_pktq_kni_params *kni)
790 {
791         uint32_t pos = kni - app->kni_params;
792         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
793                 RTE_DIM(app->pipeline_params));
794         uint32_t n_readers = 0, i;
795
796         for (i = 0; i < n_pipelines; i++) {
797                 struct app_pipeline_params *p = &app->pipeline_params[i];
798                 uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
799                 uint32_t j;
800
801                 for (j = 0; j < n_pktq_in; j++) {
802                         struct app_pktq_in_params *pktq = &p->pktq_in[j];
803
804                         if ((pktq->type == APP_PKTQ_IN_KNI) &&
805                                 (pktq->id == pos))
806                                 n_readers++;
807                 }
808         }
809
810         return n_readers;
811 }
812
813 static inline struct app_pipeline_params *
814 app_kni_get_reader(struct app_params *app,
815                                   struct app_pktq_kni_params *kni,
816                                   uint32_t *pktq_in_id)
817 {
818         struct app_pipeline_params *reader = NULL;
819         uint32_t pos = kni - app->kni_params;
820         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
821                 RTE_DIM(app->pipeline_params));
822         uint32_t n_readers = 0, id = 0, i;
823
824         for (i = 0; i < n_pipelines; i++) {
825                 struct app_pipeline_params *p = &app->pipeline_params[i];
826                 uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
827                 uint32_t j;
828
829                 for (j = 0; j < n_pktq_in; j++) {
830                         struct app_pktq_in_params *pktq = &p->pktq_in[j];
831
832                         if ((pktq->type == APP_PKTQ_IN_KNI) &&
833                                 (pktq->id == pos)) {
834                                 n_readers++;
835                                 reader = p;
836                                 id = j;
837                         }
838                 }
839         }
840
841         if (n_readers != 1)
842                 return NULL;
843
844         *pktq_in_id = id;
845         return reader;
846 }
847
848 static inline uint32_t
849 app_source_get_readers(struct app_params *app,
850 struct app_pktq_source_params *source)
851 {
852         uint32_t pos = source - app->source_params;
853         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
854                 RTE_DIM(app->pipeline_params));
855         uint32_t n_readers = 0, i;
856
857         for (i = 0; i < n_pipelines; i++) {
858                 struct app_pipeline_params *p = &app->pipeline_params[i];
859                 uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
860                 uint32_t j;
861
862                 for (j = 0; j < n_pktq_in; j++) {
863                         struct app_pktq_in_params *pktq = &p->pktq_in[j];
864
865                         if ((pktq->type == APP_PKTQ_IN_SOURCE) &&
866                                 (pktq->id == pos))
867                                 n_readers++;
868                 }
869         }
870
871         return n_readers;
872 }
873
874 static inline uint32_t
875 app_msgq_get_readers(struct app_params *app, struct app_msgq_params *msgq)
876 {
877         uint32_t pos = msgq - app->msgq_params;
878         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
879                 RTE_DIM(app->pipeline_params));
880         uint32_t n_readers = 0, i;
881
882         for (i = 0; i < n_pipelines; i++) {
883                 struct app_pipeline_params *p = &app->pipeline_params[i];
884                 uint32_t n_msgq_in = RTE_MIN(p->n_msgq_in, RTE_DIM(p->msgq_in));
885                 uint32_t j;
886
887                 for (j = 0; j < n_msgq_in; j++)
888                         if (p->msgq_in[j] == pos)
889                                 n_readers++;
890         }
891
892         return n_readers;
893 }
894
895 static inline uint32_t
896 app_txq_get_writers(struct app_params *app, struct app_pktq_hwq_out_params *txq)
897 {
898         uint32_t pos = txq - app->hwq_out_params;
899         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
900                 RTE_DIM(app->pipeline_params));
901         uint32_t n_writers = 0, i;
902
903         for (i = 0; i < n_pipelines; i++) {
904                 struct app_pipeline_params *p = &app->pipeline_params[i];
905                 uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
906                         RTE_DIM(p->pktq_out));
907                 uint32_t j;
908
909                 for (j = 0; j < n_pktq_out; j++) {
910                         struct app_pktq_out_params *pktq = &p->pktq_out[j];
911
912                         if ((pktq->type == APP_PKTQ_OUT_HWQ) &&
913                                 (pktq->id == pos))
914                                 n_writers++;
915                 }
916         }
917
918         return n_writers;
919 }
920
921 static inline uint32_t
922 app_swq_get_writers(struct app_params *app, struct app_pktq_swq_params *swq)
923 {
924         uint32_t pos = swq - app->swq_params;
925         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
926                 RTE_DIM(app->pipeline_params));
927         uint32_t n_writers = 0, i;
928
929         for (i = 0; i < n_pipelines; i++) {
930                 struct app_pipeline_params *p = &app->pipeline_params[i];
931                 uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
932                         RTE_DIM(p->pktq_out));
933                 uint32_t j;
934
935                 for (j = 0; j < n_pktq_out; j++) {
936                         struct app_pktq_out_params *pktq = &p->pktq_out[j];
937
938                         if ((pktq->type == APP_PKTQ_OUT_SWQ) &&
939                                 (pktq->id == pos))
940                                 n_writers++;
941                 }
942         }
943
944         return n_writers;
945 }
946
947 static inline struct app_pipeline_params *
948 app_swq_get_writer(struct app_params *app,
949         struct app_pktq_swq_params *swq,
950         uint32_t *pktq_out_id)
951 {
952         struct app_pipeline_params *writer = NULL;
953         uint32_t pos = swq - app->swq_params;
954         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
955                 RTE_DIM(app->pipeline_params));
956         uint32_t n_writers = 0, id = 0, i;
957
958         for (i = 0; i < n_pipelines; i++) {
959                 struct app_pipeline_params *p = &app->pipeline_params[i];
960                 uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
961                         RTE_DIM(p->pktq_out));
962                 uint32_t j;
963
964                 for (j = 0; j < n_pktq_out; j++) {
965                         struct app_pktq_out_params *pktq = &p->pktq_out[j];
966
967                         if ((pktq->type == APP_PKTQ_OUT_SWQ) &&
968                                 (pktq->id == pos)) {
969                                 n_writers++;
970                                 writer = p;
971                                 id = j;
972                         }
973                 }
974         }
975
976         if (n_writers != 1)
977                 return NULL;
978
979         *pktq_out_id = id;
980         return writer;
981 }
982
983 static inline uint32_t
984 app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm)
985 {
986         uint32_t pos = tm - app->tm_params;
987         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
988                 RTE_DIM(app->pipeline_params));
989         uint32_t n_writers = 0, i;
990
991         for (i = 0; i < n_pipelines; i++) {
992                 struct app_pipeline_params *p = &app->pipeline_params[i];
993                 uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
994                         RTE_DIM(p->pktq_out));
995                 uint32_t j;
996
997                 for (j = 0; j < n_pktq_out; j++) {
998                         struct app_pktq_out_params *pktq = &p->pktq_out[j];
999
1000                         if ((pktq->type == APP_PKTQ_OUT_TM) &&
1001                                 (pktq->id == pos))
1002                                 n_writers++;
1003                 }
1004         }
1005
1006         return n_writers;
1007 }
1008
1009 static inline struct app_pipeline_params *
1010 app_tm_get_writer(struct app_params *app,
1011         struct app_pktq_tm_params *tm,
1012         uint32_t *pktq_out_id)
1013 {
1014         struct app_pipeline_params *writer = NULL;
1015         uint32_t pos = tm - app->tm_params;
1016         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
1017                 RTE_DIM(app->pipeline_params));
1018         uint32_t n_writers = 0, id = 0, i;
1019
1020         for (i = 0; i < n_pipelines; i++) {
1021                 struct app_pipeline_params *p = &app->pipeline_params[i];
1022                 uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
1023                         RTE_DIM(p->pktq_out));
1024                 uint32_t j;
1025
1026                 for (j = 0; j < n_pktq_out; j++) {
1027                         struct app_pktq_out_params *pktq = &p->pktq_out[j];
1028
1029                         if ((pktq->type == APP_PKTQ_OUT_TM) &&
1030                                 (pktq->id == pos)) {
1031                                 n_writers++;
1032                                 writer = p;
1033                                 id = j;
1034                         }
1035                 }
1036         }
1037
1038         if (n_writers != 1)
1039                 return NULL;
1040
1041         *pktq_out_id = id;
1042         return writer;
1043 }
1044
1045 static inline uint32_t
1046 app_kni_get_writers(struct app_params *app, struct app_pktq_kni_params *kni)
1047 {
1048         uint32_t pos = kni - app->kni_params;
1049         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
1050                 RTE_DIM(app->pipeline_params));
1051         uint32_t n_writers = 0, i;
1052
1053         for (i = 0; i < n_pipelines; i++) {
1054                 struct app_pipeline_params *p = &app->pipeline_params[i];
1055                 uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
1056                         RTE_DIM(p->pktq_out));
1057                 uint32_t j;
1058
1059                 for (j = 0; j < n_pktq_out; j++) {
1060                         struct app_pktq_out_params *pktq = &p->pktq_out[j];
1061
1062                         if ((pktq->type == APP_PKTQ_OUT_KNI) &&
1063                                 (pktq->id == pos))
1064                                 n_writers++;
1065                 }
1066         }
1067
1068         return n_writers;
1069 }
1070
1071 static inline struct app_pipeline_params *
1072 app_kni_get_writer(struct app_params *app,
1073                                   struct app_pktq_kni_params *kni,
1074                                   uint32_t *pktq_out_id)
1075 {
1076         struct app_pipeline_params *writer = NULL;
1077         uint32_t pos = kni - app->kni_params;
1078         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
1079                 RTE_DIM(app->pipeline_params));
1080         uint32_t n_writers = 0, id = 0, i;
1081
1082         for (i = 0; i < n_pipelines; i++) {
1083                 struct app_pipeline_params *p = &app->pipeline_params[i];
1084                 uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
1085                         RTE_DIM(p->pktq_out));
1086                 uint32_t j;
1087
1088                 for (j = 0; j < n_pktq_out; j++) {
1089                         struct app_pktq_out_params *pktq = &p->pktq_out[j];
1090
1091                         if ((pktq->type == APP_PKTQ_OUT_KNI) &&
1092                                 (pktq->id == pos)) {
1093                                 n_writers++;
1094                                 writer = p;
1095                                 id = j;
1096                         }
1097                 }
1098         }
1099
1100         if (n_writers != 1)
1101                 return NULL;
1102
1103         *pktq_out_id = id;
1104         return writer;
1105 }
1106
1107 static inline uint32_t
1108 app_sink_get_writers(struct app_params *app, struct app_pktq_sink_params *sink)
1109 {
1110         uint32_t pos = sink - app->sink_params;
1111         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
1112                 RTE_DIM(app->pipeline_params));
1113         uint32_t n_writers = 0, i;
1114
1115         for (i = 0; i < n_pipelines; i++) {
1116                 struct app_pipeline_params *p = &app->pipeline_params[i];
1117                 uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
1118                         RTE_DIM(p->pktq_out));
1119                 uint32_t j;
1120
1121                 for (j = 0; j < n_pktq_out; j++) {
1122                         struct app_pktq_out_params *pktq = &p->pktq_out[j];
1123
1124                         if ((pktq->type == APP_PKTQ_OUT_SINK) &&
1125                                 (pktq->id == pos))
1126                                 n_writers++;
1127                 }
1128         }
1129
1130         return n_writers;
1131 }
1132
1133 static inline uint32_t
1134 app_msgq_get_writers(struct app_params *app, struct app_msgq_params *msgq)
1135 {
1136         uint32_t pos = msgq - app->msgq_params;
1137         uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
1138                 RTE_DIM(app->pipeline_params));
1139         uint32_t n_writers = 0, i;
1140
1141         for (i = 0; i < n_pipelines; i++) {
1142                 struct app_pipeline_params *p = &app->pipeline_params[i];
1143                 uint32_t n_msgq_out = RTE_MIN(p->n_msgq_out,
1144                         RTE_DIM(p->msgq_out));
1145                 uint32_t j;
1146
1147                 for (j = 0; j < n_msgq_out; j++)
1148                         if (p->msgq_out[j] == pos)
1149                                 n_writers++;
1150         }
1151
1152         return n_writers;
1153 }
1154
1155 static inline struct app_link_params *
1156 app_get_link_for_rxq(struct app_params *app, struct app_pktq_hwq_in_params *p)
1157 {
1158         char link_name[APP_PARAM_NAME_SIZE];
1159         ssize_t link_param_idx;
1160         uint32_t rxq_link_id, rxq_queue_id;
1161
1162         sscanf(p->name, "RXQ%" SCNu32 ".%" SCNu32,
1163                 &rxq_link_id, &rxq_queue_id);
1164         sprintf(link_name, "LINK%" PRIu32, rxq_link_id);
1165         link_param_idx = APP_PARAM_FIND(app->link_params, link_name);
1166         APP_CHECK((link_param_idx >= 0),
1167                 "Cannot find %s for %s", link_name, p->name);
1168
1169         return &app->link_params[link_param_idx];
1170 }
1171
1172 static inline struct app_link_params *
1173 app_get_link_for_txq(struct app_params *app, struct app_pktq_hwq_out_params *p)
1174 {
1175         char link_name[APP_PARAM_NAME_SIZE];
1176         ssize_t link_param_idx;
1177         uint32_t txq_link_id, txq_queue_id;
1178
1179         sscanf(p->name, "TXQ%" SCNu32 ".%" SCNu32,
1180                 &txq_link_id, &txq_queue_id);
1181         sprintf(link_name, "LINK%" PRIu32, txq_link_id);
1182         link_param_idx = APP_PARAM_FIND(app->link_params, link_name);
1183         APP_CHECK((link_param_idx >= 0),
1184                 "Cannot find %s for %s", link_name, p->name);
1185
1186         return &app->link_params[link_param_idx];
1187 }
1188
1189 static inline struct app_link_params *
1190 app_get_link_for_tm(struct app_params *app, struct app_pktq_tm_params *p_tm)
1191 {
1192         char link_name[APP_PARAM_NAME_SIZE];
1193         uint32_t link_id;
1194         ssize_t link_param_idx;
1195
1196         sscanf(p_tm->name, "TM%" PRIu32, &link_id);
1197         sprintf(link_name, "LINK%" PRIu32, link_id);
1198         link_param_idx = APP_PARAM_FIND(app->link_params, link_name);
1199         APP_CHECK((link_param_idx >= 0),
1200                 "Cannot find %s for %s", link_name, p_tm->name);
1201
1202         return &app->link_params[link_param_idx];
1203 }
1204
1205 static inline struct app_link_params *
1206 app_get_link_for_kni(struct app_params *app, struct app_pktq_kni_params *p_kni)
1207 {
1208         char link_name[APP_PARAM_NAME_SIZE];
1209         uint32_t link_id;
1210         ssize_t link_param_idx;
1211
1212         sscanf(p_kni->name, "KNI%" PRIu32, &link_id);
1213         sprintf(link_name, "LINK%" PRIu32, link_id);
1214         link_param_idx = APP_PARAM_FIND(app->link_params, link_name);
1215         APP_CHECK((link_param_idx >= 0),
1216                           "Cannot find %s for %s", link_name, p_kni->name);
1217
1218         return &app->link_params[link_param_idx];
1219 }
1220
1221 void app_pipeline_params_get(struct app_params *app,
1222         struct app_pipeline_params *p_in,
1223         struct pipeline_params *p_out);
1224
1225 int app_config_init(struct app_params *app);
1226
1227 int app_config_args(struct app_params *app,
1228         int argc, char **argv);
1229
1230 int app_config_preproc(struct app_params *app);
1231
1232 int app_config_parse(struct app_params *app,
1233         const char *file_name);
1234
1235 int app_config_parse_tm(struct app_params *app);
1236
1237 void app_config_save(struct app_params *app,
1238         const char *file_name);
1239
1240 int app_config_check(struct app_params *app);
1241
1242 int app_init(struct app_params *app);
1243
1244 int app_post_init(struct app_params *app);
1245
1246 int app_thread(void *arg);
1247
1248 int app_pipeline_type_register(struct app_params *app,
1249         struct pipeline_type *ptype);
1250
1251 struct pipeline_type *app_pipeline_type_find(struct app_params *app,
1252         char *name);
1253
1254 void app_link_up_internal(struct app_params *app,
1255         struct app_link_params *cp);
1256
1257 void app_link_down_internal(struct app_params *app,
1258         struct app_link_params *cp);
1259
1260 #endif