examples/ip_pipeline: rework routing pipeline
[dpdk.git] / examples / ip_pipeline / init.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 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 #include <inttypes.h>
35 #include <stdio.h>
36 #include <string.h>
37
38 #include <rte_cycles.h>
39 #include <rte_ethdev.h>
40 #include <rte_ether.h>
41 #include <rte_ip.h>
42 #include <rte_eal.h>
43 #include <rte_malloc.h>
44
45 #include "app.h"
46 #include "pipeline.h"
47 #include "pipeline_common_fe.h"
48 #include "pipeline_master.h"
49 #include "pipeline_passthrough.h"
50 #include "pipeline_firewall.h"
51 #include "pipeline_routing.h"
52
53 #define APP_NAME_SIZE   32
54
55 static void
56 app_init_core_map(struct app_params *app)
57 {
58         APP_LOG(app, HIGH, "Initializing CPU core map ...");
59         app->core_map = cpu_core_map_init(4, 32, 4, 0);
60
61         if (app->core_map == NULL)
62                 rte_panic("Cannot create CPU core map\n");
63
64         if (app->log_level >= APP_LOG_LEVEL_LOW)
65                 cpu_core_map_print(app->core_map);
66 }
67
68 static void
69 app_init_core_mask(struct app_params *app)
70 {
71         uint64_t mask = 0;
72         uint32_t i;
73
74         for (i = 0; i < app->n_pipelines; i++) {
75                 struct app_pipeline_params *p = &app->pipeline_params[i];
76                 int lcore_id;
77
78                 lcore_id = cpu_core_map_get_lcore_id(app->core_map,
79                         p->socket_id,
80                         p->core_id,
81                         p->hyper_th_id);
82
83                 if (lcore_id < 0)
84                         rte_panic("Cannot create CPU core mask\n");
85
86                 mask |= 1LLU << lcore_id;
87         }
88
89         app->core_mask = mask;
90         APP_LOG(app, HIGH, "CPU core mask = 0x%016" PRIx64, app->core_mask);
91 }
92
93 static void
94 app_init_eal(struct app_params *app)
95 {
96         char buffer[32];
97         struct app_eal_params *p = &app->eal_params;
98         uint32_t n_args = 0;
99         int status;
100
101         app->eal_argv[n_args++] = strdup(app->app_name);
102
103         snprintf(buffer, sizeof(buffer), "-c%" PRIx64, app->core_mask);
104         app->eal_argv[n_args++] = strdup(buffer);
105
106         if (p->coremap) {
107                 snprintf(buffer, sizeof(buffer), "--lcores=%s", p->coremap);
108                 app->eal_argv[n_args++] = strdup(buffer);
109         }
110
111         if (p->master_lcore_present) {
112                 snprintf(buffer,
113                         sizeof(buffer),
114                         "--master-lcore=%" PRIu32,
115                         p->master_lcore);
116                 app->eal_argv[n_args++] = strdup(buffer);
117         }
118
119         snprintf(buffer, sizeof(buffer), "-n%" PRIu32, p->channels);
120         app->eal_argv[n_args++] = strdup(buffer);
121
122         if (p->memory_present) {
123                 snprintf(buffer, sizeof(buffer), "-m%" PRIu32, p->memory);
124                 app->eal_argv[n_args++] = strdup(buffer);
125         }
126
127         if (p->ranks_present) {
128                 snprintf(buffer, sizeof(buffer), "-r%" PRIu32, p->ranks);
129                 app->eal_argv[n_args++] = strdup(buffer);
130         }
131
132         if (p->pci_blacklist) {
133                 snprintf(buffer,
134                         sizeof(buffer),
135                         "--pci-blacklist=%s",
136                         p->pci_blacklist);
137                 app->eal_argv[n_args++] = strdup(buffer);
138         }
139
140         if (p->pci_whitelist) {
141                 snprintf(buffer,
142                         sizeof(buffer),
143                         "--pci-whitelist=%s",
144                         p->pci_whitelist);
145                 app->eal_argv[n_args++] = strdup(buffer);
146         }
147
148         if (p->vdev) {
149                 snprintf(buffer, sizeof(buffer), "--vdev=%s", p->vdev);
150                 app->eal_argv[n_args++] = strdup(buffer);
151         }
152
153         if ((p->vmware_tsc_map_present) && p->vmware_tsc_map) {
154                 snprintf(buffer, sizeof(buffer), "--vmware-tsc-map");
155                 app->eal_argv[n_args++] = strdup(buffer);
156         }
157
158         if (p->proc_type) {
159                 snprintf(buffer,
160                         sizeof(buffer),
161                         "--proc-type=%s",
162                         p->proc_type);
163                 app->eal_argv[n_args++] = strdup(buffer);
164         }
165
166         if (p->syslog) {
167                 snprintf(buffer, sizeof(buffer), "--syslog=%s", p->syslog);
168                 app->eal_argv[n_args++] = strdup(buffer);
169         }
170
171         if (p->log_level_present) {
172                 snprintf(buffer,
173                         sizeof(buffer),
174                         "--log-level=%" PRIu32,
175                         p->log_level);
176                 app->eal_argv[n_args++] = strdup(buffer);
177         }
178
179         if ((p->version_present) && p->version) {
180                 snprintf(buffer, sizeof(buffer), "-v");
181                 app->eal_argv[n_args++] = strdup(buffer);
182         }
183
184         if ((p->help_present) && p->help) {
185                 snprintf(buffer, sizeof(buffer), "--help");
186                 app->eal_argv[n_args++] = strdup(buffer);
187         }
188
189         if ((p->no_huge_present) && p->no_huge) {
190                 snprintf(buffer, sizeof(buffer), "--no-huge");
191                 app->eal_argv[n_args++] = strdup(buffer);
192         }
193
194         if ((p->no_pci_present) && p->no_pci) {
195                 snprintf(buffer, sizeof(buffer), "--no-pci");
196                 app->eal_argv[n_args++] = strdup(buffer);
197         }
198
199         if ((p->no_hpet_present) && p->no_hpet) {
200                 snprintf(buffer, sizeof(buffer), "--no-hpet");
201                 app->eal_argv[n_args++] = strdup(buffer);
202         }
203
204         if ((p->no_shconf_present) && p->no_shconf) {
205                 snprintf(buffer, sizeof(buffer), "--no-shconf");
206                 app->eal_argv[n_args++] = strdup(buffer);
207         }
208
209         if (p->add_driver) {
210                 snprintf(buffer, sizeof(buffer), "-d=%s", p->add_driver);
211                 app->eal_argv[n_args++] = strdup(buffer);
212         }
213
214         if (p->socket_mem) {
215                 snprintf(buffer,
216                         sizeof(buffer),
217                         "--socket-mem=%s",
218                         p->socket_mem);
219                 app->eal_argv[n_args++] = strdup(buffer);
220         }
221
222         if (p->huge_dir) {
223                 snprintf(buffer, sizeof(buffer), "--huge-dir=%s", p->huge_dir);
224                 app->eal_argv[n_args++] = strdup(buffer);
225         }
226
227         if (p->file_prefix) {
228                 snprintf(buffer,
229                         sizeof(buffer),
230                         "--file-prefix=%s",
231                         p->file_prefix);
232                 app->eal_argv[n_args++] = strdup(buffer);
233         }
234
235         if (p->base_virtaddr) {
236                 snprintf(buffer,
237                         sizeof(buffer),
238                         "--base-virtaddr=%s",
239                         p->base_virtaddr);
240                 app->eal_argv[n_args++] = strdup(buffer);
241         }
242
243         if ((p->create_uio_dev_present) && p->create_uio_dev) {
244                 snprintf(buffer, sizeof(buffer), "--create-uio-dev");
245                 app->eal_argv[n_args++] = strdup(buffer);
246         }
247
248         if (p->vfio_intr) {
249                 snprintf(buffer,
250                         sizeof(buffer),
251                         "--vfio-intr=%s",
252                         p->vfio_intr);
253                 app->eal_argv[n_args++] = strdup(buffer);
254         }
255
256         if ((p->xen_dom0_present) && (p->xen_dom0)) {
257                 snprintf(buffer, sizeof(buffer), "--xen-dom0");
258                 app->eal_argv[n_args++] = strdup(buffer);
259         }
260
261         snprintf(buffer, sizeof(buffer), "--");
262         app->eal_argv[n_args++] = strdup(buffer);
263
264         app->eal_argc = n_args;
265
266         APP_LOG(app, HIGH, "Initializing EAL ...");
267         status = rte_eal_init(app->eal_argc, app->eal_argv);
268         if (status < 0)
269                 rte_panic("EAL init error\n");
270 }
271
272 static void
273 app_init_mempool(struct app_params *app)
274 {
275         uint32_t i;
276
277         for (i = 0; i < app->n_mempools; i++) {
278                 struct app_mempool_params *p = &app->mempool_params[i];
279
280                 APP_LOG(app, HIGH, "Initializing %s ...", p->name);
281                 app->mempool[i] = rte_mempool_create(
282                                 p->name,
283                                 p->pool_size,
284                                 p->buffer_size,
285                                 p->cache_size,
286                                 sizeof(struct rte_pktmbuf_pool_private),
287                                 rte_pktmbuf_pool_init, NULL,
288                                 rte_pktmbuf_init, NULL,
289                                 p->cpu_socket_id,
290                                 0);
291
292                 if (app->mempool[i] == NULL)
293                         rte_panic("%s init error\n", p->name);
294         }
295 }
296
297 static inline int
298 app_link_filter_arp_add(struct app_link_params *link)
299 {
300         struct rte_eth_ethertype_filter filter = {
301                 .ether_type = ETHER_TYPE_ARP,
302                 .flags = 0,
303                 .queue = link->arp_q,
304         };
305
306         return rte_eth_dev_filter_ctrl(link->pmd_id,
307                 RTE_ETH_FILTER_ETHERTYPE,
308                 RTE_ETH_FILTER_ADD,
309                 &filter);
310 }
311
312 static inline int
313 app_link_filter_tcp_syn_add(struct app_link_params *link)
314 {
315         struct rte_eth_syn_filter filter = {
316                 .hig_pri = 1,
317                 .queue = link->tcp_syn_local_q,
318         };
319
320         return rte_eth_dev_filter_ctrl(link->pmd_id,
321                 RTE_ETH_FILTER_SYN,
322                 RTE_ETH_FILTER_ADD,
323                 &filter);
324 }
325
326 static inline int
327 app_link_filter_ip_add(struct app_link_params *l1, struct app_link_params *l2)
328 {
329         struct rte_eth_ntuple_filter filter = {
330                 .flags = RTE_5TUPLE_FLAGS,
331                 .dst_ip = rte_bswap32(l2->ip),
332                 .dst_ip_mask = UINT32_MAX, /* Enable */
333                 .src_ip = 0,
334                 .src_ip_mask = 0, /* Disable */
335                 .dst_port = 0,
336                 .dst_port_mask = 0, /* Disable */
337                 .src_port = 0,
338                 .src_port_mask = 0, /* Disable */
339                 .proto = 0,
340                 .proto_mask = 0, /* Disable */
341                 .tcp_flags = 0,
342                 .priority = 1, /* Lowest */
343                 .queue = l1->ip_local_q,
344         };
345
346         return rte_eth_dev_filter_ctrl(l1->pmd_id,
347                 RTE_ETH_FILTER_NTUPLE,
348                 RTE_ETH_FILTER_ADD,
349                 &filter);
350 }
351
352 static inline int
353 app_link_filter_ip_del(struct app_link_params *l1, struct app_link_params *l2)
354 {
355         struct rte_eth_ntuple_filter filter = {
356                 .flags = RTE_5TUPLE_FLAGS,
357                 .dst_ip = rte_bswap32(l2->ip),
358                 .dst_ip_mask = UINT32_MAX, /* Enable */
359                 .src_ip = 0,
360                 .src_ip_mask = 0, /* Disable */
361                 .dst_port = 0,
362                 .dst_port_mask = 0, /* Disable */
363                 .src_port = 0,
364                 .src_port_mask = 0, /* Disable */
365                 .proto = 0,
366                 .proto_mask = 0, /* Disable */
367                 .tcp_flags = 0,
368                 .priority = 1, /* Lowest */
369                 .queue = l1->ip_local_q,
370         };
371
372         return rte_eth_dev_filter_ctrl(l1->pmd_id,
373                 RTE_ETH_FILTER_NTUPLE,
374                 RTE_ETH_FILTER_DELETE,
375                 &filter);
376 }
377
378 static inline int
379 app_link_filter_tcp_add(struct app_link_params *l1, struct app_link_params *l2)
380 {
381         struct rte_eth_ntuple_filter filter = {
382                 .flags = RTE_5TUPLE_FLAGS,
383                 .dst_ip = rte_bswap32(l2->ip),
384                 .dst_ip_mask = UINT32_MAX, /* Enable */
385                 .src_ip = 0,
386                 .src_ip_mask = 0, /* Disable */
387                 .dst_port = 0,
388                 .dst_port_mask = 0, /* Disable */
389                 .src_port = 0,
390                 .src_port_mask = 0, /* Disable */
391                 .proto = IPPROTO_TCP,
392                 .proto_mask = UINT8_MAX, /* Enable */
393                 .tcp_flags = 0,
394                 .priority = 2, /* Higher priority than IP */
395                 .queue = l1->tcp_local_q,
396         };
397
398         return rte_eth_dev_filter_ctrl(l1->pmd_id,
399                 RTE_ETH_FILTER_NTUPLE,
400                 RTE_ETH_FILTER_ADD,
401                 &filter);
402 }
403
404 static inline int
405 app_link_filter_tcp_del(struct app_link_params *l1, struct app_link_params *l2)
406 {
407         struct rte_eth_ntuple_filter filter = {
408                 .flags = RTE_5TUPLE_FLAGS,
409                 .dst_ip = rte_bswap32(l2->ip),
410                 .dst_ip_mask = UINT32_MAX, /* Enable */
411                 .src_ip = 0,
412                 .src_ip_mask = 0, /* Disable */
413                 .dst_port = 0,
414                 .dst_port_mask = 0, /* Disable */
415                 .src_port = 0,
416                 .src_port_mask = 0, /* Disable */
417                 .proto = IPPROTO_TCP,
418                 .proto_mask = UINT8_MAX, /* Enable */
419                 .tcp_flags = 0,
420                 .priority = 2, /* Higher priority than IP */
421                 .queue = l1->tcp_local_q,
422         };
423
424         return rte_eth_dev_filter_ctrl(l1->pmd_id,
425                 RTE_ETH_FILTER_NTUPLE,
426                 RTE_ETH_FILTER_DELETE,
427                 &filter);
428 }
429
430 static inline int
431 app_link_filter_udp_add(struct app_link_params *l1, struct app_link_params *l2)
432 {
433         struct rte_eth_ntuple_filter filter = {
434                 .flags = RTE_5TUPLE_FLAGS,
435                 .dst_ip = rte_bswap32(l2->ip),
436                 .dst_ip_mask = UINT32_MAX, /* Enable */
437                 .src_ip = 0,
438                 .src_ip_mask = 0, /* Disable */
439                 .dst_port = 0,
440                 .dst_port_mask = 0, /* Disable */
441                 .src_port = 0,
442                 .src_port_mask = 0, /* Disable */
443                 .proto = IPPROTO_UDP,
444                 .proto_mask = UINT8_MAX, /* Enable */
445                 .tcp_flags = 0,
446                 .priority = 2, /* Higher priority than IP */
447                 .queue = l1->udp_local_q,
448         };
449
450         return rte_eth_dev_filter_ctrl(l1->pmd_id,
451                 RTE_ETH_FILTER_NTUPLE,
452                 RTE_ETH_FILTER_ADD,
453                 &filter);
454 }
455
456 static inline int
457 app_link_filter_udp_del(struct app_link_params *l1, struct app_link_params *l2)
458 {
459         struct rte_eth_ntuple_filter filter = {
460                 .flags = RTE_5TUPLE_FLAGS,
461                 .dst_ip = rte_bswap32(l2->ip),
462                 .dst_ip_mask = UINT32_MAX, /* Enable */
463                 .src_ip = 0,
464                 .src_ip_mask = 0, /* Disable */
465                 .dst_port = 0,
466                 .dst_port_mask = 0, /* Disable */
467                 .src_port = 0,
468                 .src_port_mask = 0, /* Disable */
469                 .proto = IPPROTO_UDP,
470                 .proto_mask = UINT8_MAX, /* Enable */
471                 .tcp_flags = 0,
472                 .priority = 2, /* Higher priority than IP */
473                 .queue = l1->udp_local_q,
474         };
475
476         return rte_eth_dev_filter_ctrl(l1->pmd_id,
477                 RTE_ETH_FILTER_NTUPLE,
478                 RTE_ETH_FILTER_DELETE,
479                 &filter);
480 }
481
482 static inline int
483 app_link_filter_sctp_add(struct app_link_params *l1, struct app_link_params *l2)
484 {
485         struct rte_eth_ntuple_filter filter = {
486                 .flags = RTE_5TUPLE_FLAGS,
487                 .dst_ip = rte_bswap32(l2->ip),
488                 .dst_ip_mask = UINT32_MAX, /* Enable */
489                 .src_ip = 0,
490                 .src_ip_mask = 0, /* Disable */
491                 .dst_port = 0,
492                 .dst_port_mask = 0, /* Disable */
493                 .src_port = 0,
494                 .src_port_mask = 0, /* Disable */
495                 .proto = IPPROTO_SCTP,
496                 .proto_mask = UINT8_MAX, /* Enable */
497                 .tcp_flags = 0,
498                 .priority = 2, /* Higher priority than IP */
499                 .queue = l1->sctp_local_q,
500         };
501
502         return rte_eth_dev_filter_ctrl(l1->pmd_id,
503                 RTE_ETH_FILTER_NTUPLE,
504                 RTE_ETH_FILTER_ADD,
505                 &filter);
506 }
507
508 static inline int
509 app_link_filter_sctp_del(struct app_link_params *l1, struct app_link_params *l2)
510 {
511         struct rte_eth_ntuple_filter filter = {
512                 .flags = RTE_5TUPLE_FLAGS,
513                 .dst_ip = rte_bswap32(l2->ip),
514                 .dst_ip_mask = UINT32_MAX, /* Enable */
515                 .src_ip = 0,
516                 .src_ip_mask = 0, /* Disable */
517                 .dst_port = 0,
518                 .dst_port_mask = 0, /* Disable */
519                 .src_port = 0,
520                 .src_port_mask = 0, /* Disable */
521                 .proto = IPPROTO_SCTP,
522                 .proto_mask = UINT8_MAX, /* Enable */
523                 .tcp_flags = 0,
524                 .priority = 2, /* Higher priority than IP */
525                 .queue = l1->sctp_local_q,
526         };
527
528         return rte_eth_dev_filter_ctrl(l1->pmd_id,
529                 RTE_ETH_FILTER_NTUPLE,
530                 RTE_ETH_FILTER_DELETE,
531                 &filter);
532 }
533
534 static void
535 app_link_set_arp_filter(struct app_params *app, struct app_link_params *cp)
536 {
537         if (cp->arp_q != 0) {
538                 int status = app_link_filter_arp_add(cp);
539
540                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
541                         "Adding ARP filter (queue = %" PRIu32 ")",
542                         cp->name, cp->pmd_id, cp->arp_q);
543
544                 if (status)
545                         rte_panic("%s (%" PRIu32 "): "
546                                 "Error adding ARP filter "
547                                 "(queue = %" PRIu32 ") (%" PRId32 ")\n",
548                                 cp->name, cp->pmd_id, cp->arp_q, status);
549         }
550 }
551
552 static void
553 app_link_set_tcp_syn_filter(struct app_params *app, struct app_link_params *cp)
554 {
555         if (cp->tcp_syn_local_q != 0) {
556                 int status = app_link_filter_tcp_syn_add(cp);
557
558                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
559                         "Adding TCP SYN filter (queue = %" PRIu32 ")",
560                         cp->name, cp->pmd_id, cp->tcp_syn_local_q);
561
562                 if (status)
563                         rte_panic("%s (%" PRIu32 "): "
564                                 "Error adding TCP SYN filter "
565                                 "(queue = %" PRIu32 ") (%" PRId32 ")\n",
566                                 cp->name, cp->pmd_id, cp->tcp_syn_local_q,
567                                 status);
568         }
569 }
570
571 void
572 app_link_up_internal(struct app_params *app, struct app_link_params *cp)
573 {
574         uint32_t i;
575         int status;
576
577         /* For each link, add filters for IP of current link */
578         if (cp->ip != 0) {
579                 for (i = 0; i < app->n_links; i++) {
580                         struct app_link_params *p = &app->link_params[i];
581
582                         /* IP */
583                         if (p->ip_local_q != 0) {
584                                 int status = app_link_filter_ip_add(p, cp);
585
586                                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
587                                         "Adding IP filter (queue= %" PRIu32
588                                         ", IP = 0x%08" PRIx32 ")",
589                                         p->name, p->pmd_id, p->ip_local_q,
590                                         cp->ip);
591
592                                 if (status)
593                                         rte_panic("%s (%" PRIu32 "): "
594                                                 "Error adding IP "
595                                                 "filter (queue= %" PRIu32 ", "
596                                                 "IP = 0x%08" PRIx32
597                                                 ") (%" PRId32 ")\n",
598                                                 p->name, p->pmd_id,
599                                                 p->ip_local_q, cp->ip, status);
600                         }
601
602                         /* TCP */
603                         if (p->tcp_local_q != 0) {
604                                 int status = app_link_filter_tcp_add(p, cp);
605
606                                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
607                                         "Adding TCP filter "
608                                         "(queue = %" PRIu32
609                                         ", IP = 0x%08" PRIx32 ")",
610                                         p->name, p->pmd_id, p->tcp_local_q,
611                                         cp->ip);
612
613                                 if (status)
614                                         rte_panic("%s (%" PRIu32 "): "
615                                                 "Error adding TCP "
616                                                 "filter (queue = %" PRIu32 ", "
617                                                 "IP = 0x%08" PRIx32
618                                                 ") (%" PRId32 ")\n",
619                                                 p->name, p->pmd_id,
620                                                 p->tcp_local_q, cp->ip, status);
621                         }
622
623                         /* UDP */
624                         if (p->udp_local_q != 0) {
625                                 int status = app_link_filter_udp_add(p, cp);
626
627                                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
628                                         "Adding UDP filter "
629                                         "(queue = %" PRIu32
630                                         ", IP = 0x%08" PRIx32 ")",
631                                         p->name, p->pmd_id, p->udp_local_q,
632                                         cp->ip);
633
634                                 if (status)
635                                         rte_panic("%s (%" PRIu32 "): "
636                                                 "Error adding UDP "
637                                                 "filter (queue = %" PRIu32 ", "
638                                                 "IP = 0x%08" PRIx32
639                                                 ") (%" PRId32 ")\n",
640                                                 p->name, p->pmd_id,
641                                                 p->udp_local_q, cp->ip, status);
642                         }
643
644                         /* SCTP */
645                         if (p->sctp_local_q != 0) {
646                                 int status = app_link_filter_sctp_add(p, cp);
647
648                                 APP_LOG(app, LOW, "%s (%" PRIu32
649                                         "): Adding SCTP filter "
650                                         "(queue = %" PRIu32
651                                         ", IP = 0x%08" PRIx32 ")",
652                                         p->name, p->pmd_id, p->sctp_local_q,
653                                         cp->ip);
654
655                                 if (status)
656                                         rte_panic("%s (%" PRIu32 "): "
657                                                 "Error adding SCTP "
658                                                 "filter (queue = %" PRIu32 ", "
659                                                 "IP = 0x%08" PRIx32
660                                                 ") (%" PRId32 ")\n",
661                                                 p->name, p->pmd_id,
662                                                 p->sctp_local_q, cp->ip,
663                                                 status);
664                         }
665                 }
666         }
667
668         /* PMD link up */
669         status = rte_eth_dev_set_link_up(cp->pmd_id);
670         if (status < 0)
671                 rte_panic("%s (%" PRIu32 "): PMD set up error %" PRId32 "\n",
672                         cp->name, cp->pmd_id, status);
673
674         /* Mark link as UP */
675         cp->state = 1;
676 }
677
678 void
679 app_link_down_internal(struct app_params *app, struct app_link_params *cp)
680 {
681         uint32_t i;
682
683         /* PMD link down */
684         rte_eth_dev_set_link_down(cp->pmd_id);
685
686         /* Mark link as DOWN */
687         cp->state = 0;
688
689         /* Return if current link IP is not valid */
690         if (cp->ip == 0)
691                 return;
692
693         /* For each link, remove filters for IP of current link */
694         for (i = 0; i < app->n_links; i++) {
695                 struct app_link_params *p = &app->link_params[i];
696
697                 /* IP */
698                 if (p->ip_local_q != 0) {
699                         int status = app_link_filter_ip_del(p, cp);
700
701                         APP_LOG(app, LOW, "%s (%" PRIu32
702                                 "): Deleting IP filter "
703                                 "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")",
704                                 p->name, p->pmd_id, p->ip_local_q, cp->ip);
705
706                         if (status)
707                                 rte_panic("%s (%" PRIu32
708                                         "): Error deleting IP filter "
709                                         "(queue = %" PRIu32
710                                         ", IP = 0x%" PRIx32
711                                         ") (%" PRId32 ")\n",
712                                         p->name, p->pmd_id, p->ip_local_q,
713                                         cp->ip, status);
714                 }
715
716                 /* TCP */
717                 if (p->tcp_local_q != 0) {
718                         int status = app_link_filter_tcp_del(p, cp);
719
720                         APP_LOG(app, LOW, "%s (%" PRIu32
721                                 "): Deleting TCP filter "
722                                 "(queue = %" PRIu32
723                                 ", IP = 0x%" PRIx32 ")",
724                                 p->name, p->pmd_id, p->tcp_local_q, cp->ip);
725
726                         if (status)
727                                 rte_panic("%s (%" PRIu32
728                                         "): Error deleting TCP filter "
729                                         "(queue = %" PRIu32
730                                         ", IP = 0x%" PRIx32
731                                         ") (%" PRId32 ")\n",
732                                         p->name, p->pmd_id, p->tcp_local_q,
733                                         cp->ip, status);
734                 }
735
736                 /* UDP */
737                 if (p->udp_local_q != 0) {
738                         int status = app_link_filter_udp_del(p, cp);
739
740                         APP_LOG(app, LOW, "%s (%" PRIu32
741                                 "): Deleting UDP filter "
742                                 "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")",
743                                 p->name, p->pmd_id, p->udp_local_q, cp->ip);
744
745                         if (status)
746                                 rte_panic("%s (%" PRIu32
747                                         "): Error deleting UDP filter "
748                                         "(queue = %" PRIu32
749                                         ", IP = 0x%" PRIx32
750                                         ") (%" PRId32 ")\n",
751                                         p->name, p->pmd_id, p->udp_local_q,
752                                         cp->ip, status);
753                 }
754
755                 /* SCTP */
756                 if (p->sctp_local_q != 0) {
757                         int status = app_link_filter_sctp_del(p, cp);
758
759                         APP_LOG(app, LOW, "%s (%" PRIu32
760                                 "): Deleting SCTP filter "
761                                 "(queue = %" PRIu32
762                                 ", IP = 0x%" PRIx32 ")",
763                                 p->name, p->pmd_id, p->sctp_local_q, cp->ip);
764
765                         if (status)
766                                 rte_panic("%s (%" PRIu32
767                                         "): Error deleting SCTP filter "
768                                         "(queue = %" PRIu32
769                                         ", IP = 0x%" PRIx32
770                                         ") (%" PRId32 ")\n",
771                                         p->name, p->pmd_id, p->sctp_local_q,
772                                         cp->ip, status);
773                 }
774         }
775 }
776
777 static void
778 app_check_link(struct app_params *app)
779 {
780         uint32_t all_links_up, i;
781
782         all_links_up = 1;
783
784         for (i = 0; i < app->n_links; i++) {
785                 struct app_link_params *p = &app->link_params[i];
786                 struct rte_eth_link link_params;
787
788                 memset(&link_params, 0, sizeof(link_params));
789                 rte_eth_link_get(p->pmd_id, &link_params);
790
791                 APP_LOG(app, HIGH, "%s (%" PRIu32 ") (%" PRIu32 " Gbps) %s",
792                         p->name,
793                         p->pmd_id,
794                         link_params.link_speed / 1000,
795                         link_params.link_status ? "UP" : "DOWN");
796
797                 if (link_params.link_status == 0)
798                         all_links_up = 0;
799         }
800
801         if (all_links_up == 0)
802                 rte_panic("Some links are DOWN\n");
803 }
804
805 static void
806 app_init_link(struct app_params *app)
807 {
808         uint32_t i;
809
810         for (i = 0; i < app->n_links; i++) {
811                 struct app_link_params *p_link = &app->link_params[i];
812                 uint32_t link_id, n_hwq_in, n_hwq_out, j;
813                 int status;
814
815                 sscanf(p_link->name, "LINK%" PRIu32, &link_id);
816                 n_hwq_in = app_link_get_n_rxq(app, p_link);
817                 n_hwq_out = app_link_get_n_txq(app, p_link);
818
819                 APP_LOG(app, HIGH, "Initializing %s (%" PRIu32") "
820                         "(%" PRIu32 " RXQ, %" PRIu32 " TXQ) ...",
821                         p_link->name,
822                         p_link->pmd_id,
823                         n_hwq_in,
824                         n_hwq_out);
825
826                 /* LINK */
827                 status = rte_eth_dev_configure(
828                         p_link->pmd_id,
829                         n_hwq_in,
830                         n_hwq_out,
831                         &p_link->conf);
832                 if (status < 0)
833                         rte_panic("%s (%" PRId32 "): "
834                                 "init error (%" PRId32 ")\n",
835                                 p_link->name, p_link->pmd_id, status);
836
837                 rte_eth_macaddr_get(p_link->pmd_id,
838                         (struct ether_addr *) &p_link->mac_addr);
839
840                 if (p_link->promisc)
841                         rte_eth_promiscuous_enable(p_link->pmd_id);
842
843                 /* RXQ */
844                 for (j = 0; j < app->n_pktq_hwq_in; j++) {
845                         struct app_pktq_hwq_in_params *p_rxq =
846                                 &app->hwq_in_params[j];
847                         uint32_t rxq_link_id, rxq_queue_id;
848
849                         sscanf(p_rxq->name, "RXQ%" PRIu32 ".%" PRIu32,
850                                 &rxq_link_id, &rxq_queue_id);
851                         if (rxq_link_id != link_id)
852                                 continue;
853
854                         status = rte_eth_rx_queue_setup(
855                                 p_link->pmd_id,
856                                 rxq_queue_id,
857                                 p_rxq->size,
858                                 rte_eth_dev_socket_id(p_link->pmd_id),
859                                 &p_rxq->conf,
860                                 app->mempool[p_rxq->mempool_id]);
861                         if (status < 0)
862                                 rte_panic("%s (%" PRIu32 "): "
863                                         "%s init error (%" PRId32 ")\n",
864                                         p_link->name,
865                                         p_link->pmd_id,
866                                         p_rxq->name,
867                                         status);
868                 }
869
870                 /* TXQ */
871                 for (j = 0; j < app->n_pktq_hwq_out; j++) {
872                         struct app_pktq_hwq_out_params *p_txq =
873                                 &app->hwq_out_params[j];
874                         uint32_t txq_link_id, txq_queue_id;
875
876                         sscanf(p_txq->name, "TXQ%" PRIu32 ".%" PRIu32,
877                                 &txq_link_id, &txq_queue_id);
878                         if (txq_link_id != link_id)
879                                 continue;
880
881                         status = rte_eth_tx_queue_setup(
882                                 p_link->pmd_id,
883                                 txq_queue_id,
884                                 p_txq->size,
885                                 rte_eth_dev_socket_id(p_link->pmd_id),
886                                 &p_txq->conf);
887                         if (status < 0)
888                                 rte_panic("%s (%" PRIu32 "): "
889                                         "%s init error (%" PRId32 ")\n",
890                                         p_link->name,
891                                         p_link->pmd_id,
892                                         p_txq->name,
893                                         status);
894                 }
895
896                 /* LINK START */
897                 status = rte_eth_dev_start(p_link->pmd_id);
898                 if (status < 0)
899                         rte_panic("Cannot start %s (error %" PRId32 ")\n",
900                                 p_link->name, status);
901
902                 /* LINK UP */
903                 app_link_set_arp_filter(app, p_link);
904                 app_link_set_tcp_syn_filter(app, p_link);
905                 app_link_up_internal(app, p_link);
906         }
907
908         app_check_link(app);
909 }
910
911 static void
912 app_init_swq(struct app_params *app)
913 {
914         uint32_t i;
915
916         for (i = 0; i < app->n_pktq_swq; i++) {
917                 struct app_pktq_swq_params *p = &app->swq_params[i];
918
919                 APP_LOG(app, HIGH, "Initializing %s...", p->name);
920                 app->swq[i] = rte_ring_create(
921                                 p->name,
922                                 p->size,
923                                 p->cpu_socket_id,
924                                 RING_F_SP_ENQ | RING_F_SC_DEQ);
925
926                 if (app->swq[i] == NULL)
927                         rte_panic("%s init error\n", p->name);
928         }
929 }
930
931 static void
932 app_init_tm(struct app_params *app)
933 {
934         uint32_t i;
935
936         for (i = 0; i < app->n_pktq_tm; i++) {
937                 struct app_pktq_tm_params *p_tm = &app->tm_params[i];
938                 struct app_link_params *p_link;
939                 struct rte_eth_link link_eth_params;
940                 struct rte_sched_port *sched;
941                 uint32_t n_subports, subport_id;
942                 int status;
943
944                 p_link = app_get_link_for_tm(app, p_tm);
945                 /* LINK */
946                 rte_eth_link_get(p_link->pmd_id, &link_eth_params);
947
948                 /* TM */
949                 p_tm->sched_port_params.name = p_tm->name;
950                 p_tm->sched_port_params.socket =
951                         rte_eth_dev_socket_id(p_link->pmd_id);
952                 p_tm->sched_port_params.rate =
953                         (uint64_t) link_eth_params.link_speed * 1000 * 1000 / 8;
954
955                 APP_LOG(app, HIGH, "Initializing %s ...", p_tm->name);
956                 sched = rte_sched_port_config(&p_tm->sched_port_params);
957                 if (sched == NULL)
958                         rte_panic("%s init error\n", p_tm->name);
959                 app->tm[i] = sched;
960
961                 /* Subport */
962                 n_subports = p_tm->sched_port_params.n_subports_per_port;
963                 for (subport_id = 0; subport_id < n_subports; subport_id++) {
964                         uint32_t n_pipes_per_subport, pipe_id;
965
966                         status = rte_sched_subport_config(sched,
967                                 subport_id,
968                                 &p_tm->sched_subport_params[subport_id]);
969                         if (status)
970                                 rte_panic("%s subport %" PRIu32
971                                         " init error (%" PRId32 ")\n",
972                                         p_tm->name, subport_id, status);
973
974                         /* Pipe */
975                         n_pipes_per_subport =
976                                 p_tm->sched_port_params.n_pipes_per_subport;
977                         for (pipe_id = 0;
978                                 pipe_id < n_pipes_per_subport;
979                                 pipe_id++) {
980                                 int profile_id = p_tm->sched_pipe_to_profile[
981                                         subport_id * APP_MAX_SCHED_PIPES +
982                                         pipe_id];
983
984                                 if (profile_id == -1)
985                                         continue;
986
987                                 status = rte_sched_pipe_config(sched,
988                                         subport_id,
989                                         pipe_id,
990                                         profile_id);
991                                 if (status)
992                                         rte_panic("%s subport %" PRIu32
993                                                 " pipe %" PRIu32
994                                                 " (profile %" PRId32 ") "
995                                                 "init error (% " PRId32 ")\n",
996                                                 p_tm->name, subport_id, pipe_id,
997                                                 profile_id, status);
998                         }
999                 }
1000         }
1001 }
1002
1003 static void
1004 app_init_msgq(struct app_params *app)
1005 {
1006         uint32_t i;
1007
1008         for (i = 0; i < app->n_msgq; i++) {
1009                 struct app_msgq_params *p = &app->msgq_params[i];
1010
1011                 APP_LOG(app, HIGH, "Initializing %s ...", p->name);
1012                 app->msgq[i] = rte_ring_create(
1013                                 p->name,
1014                                 p->size,
1015                                 p->cpu_socket_id,
1016                                 RING_F_SP_ENQ | RING_F_SC_DEQ);
1017
1018                 if (app->msgq[i] == NULL)
1019                         rte_panic("%s init error\n", p->name);
1020         }
1021 }
1022
1023 static void app_pipeline_params_get(struct app_params *app,
1024         struct app_pipeline_params *p_in,
1025         struct pipeline_params *p_out)
1026 {
1027         uint32_t i;
1028
1029         strcpy(p_out->name, p_in->name);
1030
1031         p_out->socket_id = (int) p_in->socket_id;
1032
1033         p_out->log_level = app->log_level;
1034
1035         /* pktq_in */
1036         p_out->n_ports_in = p_in->n_pktq_in;
1037         for (i = 0; i < p_in->n_pktq_in; i++) {
1038                 struct app_pktq_in_params *in = &p_in->pktq_in[i];
1039                 struct pipeline_port_in_params *out = &p_out->port_in[i];
1040
1041                 switch (in->type) {
1042                 case APP_PKTQ_IN_HWQ:
1043                 {
1044                         struct app_pktq_hwq_in_params *p_hwq_in =
1045                                 &app->hwq_in_params[in->id];
1046                         struct app_link_params *p_link =
1047                                 app_get_link_for_rxq(app, p_hwq_in);
1048                         uint32_t rxq_link_id, rxq_queue_id;
1049
1050                         sscanf(p_hwq_in->name, "RXQ%" SCNu32 ".%" SCNu32,
1051                                 &rxq_link_id,
1052                                 &rxq_queue_id);
1053
1054                         out->type = PIPELINE_PORT_IN_ETHDEV_READER;
1055                         out->params.ethdev.port_id = p_link->pmd_id;
1056                         out->params.ethdev.queue_id = rxq_queue_id;
1057                         out->burst_size = p_hwq_in->burst;
1058                         break;
1059                 }
1060                 case APP_PKTQ_IN_SWQ:
1061                         out->type = PIPELINE_PORT_IN_RING_READER;
1062                         out->params.ring.ring = app->swq[in->id];
1063                         out->burst_size = app->swq_params[in->id].burst_read;
1064                         /* What about frag and ras ports? */
1065                         break;
1066                 case APP_PKTQ_IN_TM:
1067                         out->type = PIPELINE_PORT_IN_SCHED_READER;
1068                         out->params.sched.sched = app->tm[in->id];
1069                         out->burst_size = app->tm_params[in->id].burst_read;
1070                         break;
1071                 case APP_PKTQ_IN_SOURCE:
1072                         out->type = PIPELINE_PORT_IN_SOURCE;
1073                         out->params.source.mempool = app->mempool[in->id];
1074                         out->burst_size = app->source_params[in->id].burst;
1075                         break;
1076                 default:
1077                         break;
1078                 }
1079         }
1080
1081         /* pktq_out */
1082         p_out->n_ports_out = p_in->n_pktq_out;
1083         for (i = 0; i < p_in->n_pktq_out; i++) {
1084                 struct app_pktq_out_params *in = &p_in->pktq_out[i];
1085                 struct pipeline_port_out_params *out = &p_out->port_out[i];
1086
1087                 switch (in->type) {
1088                 case APP_PKTQ_OUT_HWQ:
1089                 {
1090                         struct app_pktq_hwq_out_params *p_hwq_out =
1091                                 &app->hwq_out_params[in->id];
1092                         struct app_link_params *p_link =
1093                                 app_get_link_for_txq(app, p_hwq_out);
1094                         uint32_t txq_link_id, txq_queue_id;
1095
1096                         sscanf(p_hwq_out->name,
1097                                 "TXQ%" SCNu32 ".%" SCNu32,
1098                                 &txq_link_id,
1099                                 &txq_queue_id);
1100
1101                         if (p_hwq_out->dropless == 0) {
1102                                 struct rte_port_ethdev_writer_params *params =
1103                                         &out->params.ethdev;
1104
1105                                 out->type = PIPELINE_PORT_OUT_ETHDEV_WRITER;
1106                                 params->port_id = p_link->pmd_id;
1107                                 params->queue_id = txq_queue_id;
1108                                 params->tx_burst_sz =
1109                                         app->hwq_out_params[in->id].burst;
1110                         } else {
1111                                 struct rte_port_ethdev_writer_nodrop_params
1112                                         *params = &out->params.ethdev_nodrop;
1113
1114                                 out->type =
1115                                         PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP;
1116                                 params->port_id = p_link->pmd_id;
1117                                 params->queue_id = txq_queue_id;
1118                                 params->tx_burst_sz = p_hwq_out->burst;
1119                                 params->n_retries = p_hwq_out->n_retries;
1120                         }
1121                         break;
1122                 }
1123                 case APP_PKTQ_OUT_SWQ:
1124                         if (app->swq_params[in->id].dropless == 0) {
1125                                 struct rte_port_ring_writer_params *params =
1126                                         &out->params.ring;
1127
1128                                 out->type = PIPELINE_PORT_OUT_RING_WRITER;
1129                                 params->ring = app->swq[in->id];
1130                                 params->tx_burst_sz =
1131                                         app->swq_params[in->id].burst_write;
1132                         } else {
1133                                 struct rte_port_ring_writer_nodrop_params
1134                                         *params = &out->params.ring_nodrop;
1135
1136                                 out->type =
1137                                         PIPELINE_PORT_OUT_RING_WRITER_NODROP;
1138                                 params->ring = app->swq[in->id];
1139                                 params->tx_burst_sz =
1140                                         app->swq_params[in->id].burst_write;
1141                                 params->n_retries =
1142                                         app->swq_params[in->id].n_retries;
1143                         }
1144                         /* What about frag and ras ports? */
1145                         break;
1146                 case APP_PKTQ_OUT_TM: {
1147                         struct rte_port_sched_writer_params *params =
1148                                 &out->params.sched;
1149
1150                         out->type = PIPELINE_PORT_OUT_SCHED_WRITER;
1151                         params->sched = app->tm[in->id];
1152                         params->tx_burst_sz =
1153                                 app->tm_params[in->id].burst_write;
1154                         break;
1155                 }
1156                 case APP_PKTQ_OUT_SINK:
1157                         out->type = PIPELINE_PORT_OUT_SINK;
1158                         break;
1159                 default:
1160                         break;
1161                 }
1162         }
1163
1164         /* msgq */
1165         p_out->n_msgq = p_in->n_msgq_in;
1166
1167         for (i = 0; i < p_in->n_msgq_in; i++)
1168                 p_out->msgq_in[i] = app->msgq[p_in->msgq_in[i]];
1169
1170         for (i = 0; i < p_in->n_msgq_out; i++)
1171                 p_out->msgq_out[i] = app->msgq[p_in->msgq_out[i]];
1172
1173         /* args */
1174         p_out->n_args = p_in->n_args;
1175         for (i = 0; i < p_in->n_args; i++) {
1176                 p_out->args_name[i] = p_in->args_name[i];
1177                 p_out->args_value[i] = p_in->args_value[i];
1178         }
1179 }
1180
1181 static void
1182 app_init_pipelines(struct app_params *app)
1183 {
1184         uint32_t p_id;
1185
1186         for (p_id = 0; p_id < app->n_pipelines; p_id++) {
1187                 struct app_pipeline_params *params =
1188                         &app->pipeline_params[p_id];
1189                 struct app_pipeline_data *data = &app->pipeline_data[p_id];
1190                 struct pipeline_type *ptype;
1191                 struct pipeline_params pp;
1192
1193                 APP_LOG(app, HIGH, "Initializing %s ...", params->name);
1194
1195                 ptype = app_pipeline_type_find(app, params->type);
1196                 if (ptype == NULL)
1197                         rte_panic("Init error: Unknown pipeline type \"%s\"\n",
1198                                 params->type);
1199
1200                 app_pipeline_params_get(app, params, &pp);
1201
1202                 /* Back-end */
1203                 data->be = NULL;
1204                 if (ptype->be_ops->f_init) {
1205                         data->be = ptype->be_ops->f_init(&pp, (void *) app);
1206
1207                         if (data->be == NULL)
1208                                 rte_panic("Pipeline instance \"%s\" back-end "
1209                                         "init error\n", params->name);
1210                 }
1211
1212                 /* Front-end */
1213                 data->fe = NULL;
1214                 if (ptype->fe_ops->f_init) {
1215                         data->fe = ptype->fe_ops->f_init(&pp, (void *) app);
1216
1217                         if (data->fe == NULL)
1218                                 rte_panic("Pipeline instance \"%s\" front-end "
1219                                 "init error\n", params->name);
1220                 }
1221
1222                 data->timer_period = (rte_get_tsc_hz() * params->timer_period)
1223                         / 1000;
1224         }
1225 }
1226
1227 static void
1228 app_init_threads(struct app_params *app)
1229 {
1230         uint64_t time = rte_get_tsc_cycles();
1231         uint32_t p_id;
1232
1233         for (p_id = 0; p_id < app->n_pipelines; p_id++) {
1234                 struct app_pipeline_params *params =
1235                         &app->pipeline_params[p_id];
1236                 struct app_pipeline_data *data = &app->pipeline_data[p_id];
1237                 struct pipeline_type *ptype;
1238                 struct app_thread_data *t;
1239                 struct app_thread_pipeline_data *p;
1240                 int lcore_id;
1241
1242                 lcore_id = cpu_core_map_get_lcore_id(app->core_map,
1243                         params->socket_id,
1244                         params->core_id,
1245                         params->hyper_th_id);
1246
1247                 if (lcore_id < 0)
1248                         rte_panic("Invalid core s%" PRIu32 "c%" PRIu32 "%s\n",
1249                                 params->socket_id,
1250                                 params->core_id,
1251                                 (params->hyper_th_id) ? "h" : "");
1252
1253                 t = &app->thread_data[lcore_id];
1254
1255                 ptype = app_pipeline_type_find(app, params->type);
1256                 if (ptype == NULL)
1257                         rte_panic("Init error: Unknown pipeline "
1258                                 "type \"%s\"\n", params->type);
1259
1260                 p = (ptype->be_ops->f_run == NULL) ?
1261                         &t->regular[t->n_regular] :
1262                         &t->custom[t->n_custom];
1263
1264                 p->be = data->be;
1265                 p->f_run = ptype->be_ops->f_run;
1266                 p->f_timer = ptype->be_ops->f_timer;
1267                 p->timer_period = data->timer_period;
1268                 p->deadline = time + data->timer_period;
1269
1270                 if (ptype->be_ops->f_run == NULL)
1271                         t->n_regular++;
1272                 else
1273                         t->n_custom++;
1274         }
1275 }
1276
1277 int app_init(struct app_params *app)
1278 {
1279         app_init_core_map(app);
1280         app_init_core_mask(app);
1281
1282         app_init_eal(app);
1283         app_init_mempool(app);
1284         app_init_link(app);
1285         app_init_swq(app);
1286         app_init_tm(app);
1287         app_init_msgq(app);
1288
1289         app_pipeline_common_cmd_push(app);
1290         app_pipeline_type_register(app, &pipeline_master);
1291         app_pipeline_type_register(app, &pipeline_passthrough);
1292         app_pipeline_type_register(app, &pipeline_firewall);
1293         app_pipeline_type_register(app, &pipeline_routing);
1294
1295         app_init_pipelines(app);
1296         app_init_threads(app);
1297
1298         return 0;
1299 }
1300
1301 static int
1302 app_pipeline_type_cmd_push(struct app_params *app,
1303         struct pipeline_type *ptype)
1304 {
1305         cmdline_parse_ctx_t *cmds;
1306         uint32_t n_cmds, i;
1307
1308         /* Check input arguments */
1309         if ((app == NULL) ||
1310                 (ptype == NULL))
1311                 return -EINVAL;
1312
1313         n_cmds = pipeline_type_cmds_count(ptype);
1314         if (n_cmds == 0)
1315                 return 0;
1316
1317         cmds = ptype->fe_ops->cmds;
1318
1319         /* Check for available slots in the application commands array */
1320         if (n_cmds > APP_MAX_CMDS - app->n_cmds)
1321                 return -ENOMEM;
1322
1323         /* Push pipeline commands into the application */
1324         memcpy(&app->cmds[app->n_cmds],
1325                 cmds,
1326                 n_cmds * sizeof(cmdline_parse_ctx_t *));
1327
1328         for (i = 0; i < n_cmds; i++)
1329                 app->cmds[app->n_cmds + i]->data = app;
1330
1331         app->n_cmds += n_cmds;
1332         app->cmds[app->n_cmds] = NULL;
1333
1334         return 0;
1335 }
1336
1337 int
1338 app_pipeline_type_register(struct app_params *app, struct pipeline_type *ptype)
1339 {
1340         uint32_t n_cmds, i;
1341
1342         /* Check input arguments */
1343         if ((app == NULL) ||
1344                 (ptype == NULL) ||
1345                 (ptype->name == NULL) ||
1346                 (strlen(ptype->name) == 0) ||
1347                 (ptype->be_ops->f_init == NULL) ||
1348                 (ptype->be_ops->f_timer == NULL))
1349                 return -EINVAL;
1350
1351         /* Check for duplicate entry */
1352         for (i = 0; i < app->n_pipeline_types; i++)
1353                 if (strcmp(app->pipeline_type[i].name, ptype->name) == 0)
1354                         return -EEXIST;
1355
1356         /* Check for resource availability */
1357         n_cmds = pipeline_type_cmds_count(ptype);
1358         if ((app->n_pipeline_types == APP_MAX_PIPELINE_TYPES) ||
1359                 (n_cmds > APP_MAX_CMDS - app->n_cmds))
1360                 return -ENOMEM;
1361
1362         /* Copy pipeline type */
1363         memcpy(&app->pipeline_type[app->n_pipeline_types++],
1364                 ptype,
1365                 sizeof(struct pipeline_type));
1366
1367         /* Copy CLI commands */
1368         if (n_cmds)
1369                 app_pipeline_type_cmd_push(app, ptype);
1370
1371         return 0;
1372 }
1373
1374 struct
1375 pipeline_type *app_pipeline_type_find(struct app_params *app, char *name)
1376 {
1377         uint32_t i;
1378
1379         for (i = 0; i < app->n_pipeline_types; i++)
1380                 if (strcmp(app->pipeline_type[i].name, name) == 0)
1381                         return &app->pipeline_type[i];
1382
1383         return NULL;
1384 }