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