Imported Upstream version 16.04
[deb_dpdk.git] / examples / ip_pipeline / init.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #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_flow_classification.h"
52 #include "pipeline_flow_actions.h"
53 #include "pipeline_routing.h"
54 #include "thread_fe.h"
55
56 #define APP_NAME_SIZE   32
57
58 static void
59 app_init_core_map(struct app_params *app)
60 {
61         APP_LOG(app, HIGH, "Initializing CPU core map ...");
62         app->core_map = cpu_core_map_init(4, 32, 4, 0);
63
64         if (app->core_map == NULL)
65                 rte_panic("Cannot create CPU core map\n");
66
67         if (app->log_level >= APP_LOG_LEVEL_LOW)
68                 cpu_core_map_print(app->core_map);
69 }
70
71 static void
72 app_init_core_mask(struct app_params *app)
73 {
74         uint64_t mask = 0;
75         uint32_t i;
76
77         for (i = 0; i < app->n_pipelines; i++) {
78                 struct app_pipeline_params *p = &app->pipeline_params[i];
79                 int lcore_id;
80
81                 lcore_id = cpu_core_map_get_lcore_id(app->core_map,
82                         p->socket_id,
83                         p->core_id,
84                         p->hyper_th_id);
85
86                 if (lcore_id < 0)
87                         rte_panic("Cannot create CPU core mask\n");
88
89                 mask |= 1LLU << lcore_id;
90         }
91
92         app->core_mask = mask;
93         APP_LOG(app, HIGH, "CPU core mask = 0x%016" PRIx64, app->core_mask);
94 }
95
96 static void
97 app_init_eal(struct app_params *app)
98 {
99         char buffer[256];
100         struct app_eal_params *p = &app->eal_params;
101         uint32_t n_args = 0;
102         uint32_t i;
103         int status;
104
105         app->eal_argv[n_args++] = strdup(app->app_name);
106
107         snprintf(buffer, sizeof(buffer), "-c%" PRIx64, app->core_mask);
108         app->eal_argv[n_args++] = strdup(buffer);
109
110         if (p->coremap) {
111                 snprintf(buffer, sizeof(buffer), "--lcores=%s", p->coremap);
112                 app->eal_argv[n_args++] = strdup(buffer);
113         }
114
115         if (p->master_lcore_present) {
116                 snprintf(buffer,
117                         sizeof(buffer),
118                         "--master-lcore=%" PRIu32,
119                         p->master_lcore);
120                 app->eal_argv[n_args++] = strdup(buffer);
121         }
122
123         snprintf(buffer, sizeof(buffer), "-n%" PRIu32, p->channels);
124         app->eal_argv[n_args++] = strdup(buffer);
125
126         if (p->memory_present) {
127                 snprintf(buffer, sizeof(buffer), "-m%" PRIu32, p->memory);
128                 app->eal_argv[n_args++] = strdup(buffer);
129         }
130
131         if (p->ranks_present) {
132                 snprintf(buffer, sizeof(buffer), "-r%" PRIu32, p->ranks);
133                 app->eal_argv[n_args++] = strdup(buffer);
134         }
135
136         for (i = 0; i < APP_MAX_LINKS; i++) {
137                 if (p->pci_blacklist[i] == NULL)
138                         break;
139
140                 snprintf(buffer,
141                         sizeof(buffer),
142                         "--pci-blacklist=%s",
143                         p->pci_blacklist[i]);
144                 app->eal_argv[n_args++] = strdup(buffer);
145         }
146
147         if (app->port_mask != 0)
148                 for (i = 0; i < APP_MAX_LINKS; i++) {
149                         if (p->pci_whitelist[i] == NULL)
150                                 break;
151
152                         snprintf(buffer,
153                                 sizeof(buffer),
154                                 "--pci-whitelist=%s",
155                                 p->pci_whitelist[i]);
156                         app->eal_argv[n_args++] = strdup(buffer);
157                 }
158         else
159                 for (i = 0; i < app->n_links; i++) {
160                         char *pci_bdf = app->link_params[i].pci_bdf;
161
162                         snprintf(buffer,
163                                 sizeof(buffer),
164                                 "--pci-whitelist=%s",
165                                 pci_bdf);
166                         app->eal_argv[n_args++] = strdup(buffer);
167                 }
168
169         for (i = 0; i < APP_MAX_LINKS; i++) {
170                 if (p->vdev[i] == NULL)
171                         break;
172
173                 snprintf(buffer,
174                         sizeof(buffer),
175                         "--vdev=%s",
176                         p->vdev[i]);
177                 app->eal_argv[n_args++] = strdup(buffer);
178         }
179
180         if ((p->vmware_tsc_map_present) && p->vmware_tsc_map) {
181                 snprintf(buffer, sizeof(buffer), "--vmware-tsc-map");
182                 app->eal_argv[n_args++] = strdup(buffer);
183         }
184
185         if (p->proc_type) {
186                 snprintf(buffer,
187                         sizeof(buffer),
188                         "--proc-type=%s",
189                         p->proc_type);
190                 app->eal_argv[n_args++] = strdup(buffer);
191         }
192
193         if (p->syslog) {
194                 snprintf(buffer, sizeof(buffer), "--syslog=%s", p->syslog);
195                 app->eal_argv[n_args++] = strdup(buffer);
196         }
197
198         if (p->log_level_present) {
199                 snprintf(buffer,
200                         sizeof(buffer),
201                         "--log-level=%" PRIu32,
202                         p->log_level);
203                 app->eal_argv[n_args++] = strdup(buffer);
204         }
205
206         if ((p->version_present) && p->version) {
207                 snprintf(buffer, sizeof(buffer), "-v");
208                 app->eal_argv[n_args++] = strdup(buffer);
209         }
210
211         if ((p->help_present) && p->help) {
212                 snprintf(buffer, sizeof(buffer), "--help");
213                 app->eal_argv[n_args++] = strdup(buffer);
214         }
215
216         if ((p->no_huge_present) && p->no_huge) {
217                 snprintf(buffer, sizeof(buffer), "--no-huge");
218                 app->eal_argv[n_args++] = strdup(buffer);
219         }
220
221         if ((p->no_pci_present) && p->no_pci) {
222                 snprintf(buffer, sizeof(buffer), "--no-pci");
223                 app->eal_argv[n_args++] = strdup(buffer);
224         }
225
226         if ((p->no_hpet_present) && p->no_hpet) {
227                 snprintf(buffer, sizeof(buffer), "--no-hpet");
228                 app->eal_argv[n_args++] = strdup(buffer);
229         }
230
231         if ((p->no_shconf_present) && p->no_shconf) {
232                 snprintf(buffer, sizeof(buffer), "--no-shconf");
233                 app->eal_argv[n_args++] = strdup(buffer);
234         }
235
236         if (p->add_driver) {
237                 snprintf(buffer, sizeof(buffer), "-d=%s", p->add_driver);
238                 app->eal_argv[n_args++] = strdup(buffer);
239         }
240
241         if (p->socket_mem) {
242                 snprintf(buffer,
243                         sizeof(buffer),
244                         "--socket-mem=%s",
245                         p->socket_mem);
246                 app->eal_argv[n_args++] = strdup(buffer);
247         }
248
249         if (p->huge_dir) {
250                 snprintf(buffer, sizeof(buffer), "--huge-dir=%s", p->huge_dir);
251                 app->eal_argv[n_args++] = strdup(buffer);
252         }
253
254         if (p->file_prefix) {
255                 snprintf(buffer,
256                         sizeof(buffer),
257                         "--file-prefix=%s",
258                         p->file_prefix);
259                 app->eal_argv[n_args++] = strdup(buffer);
260         }
261
262         if (p->base_virtaddr) {
263                 snprintf(buffer,
264                         sizeof(buffer),
265                         "--base-virtaddr=%s",
266                         p->base_virtaddr);
267                 app->eal_argv[n_args++] = strdup(buffer);
268         }
269
270         if ((p->create_uio_dev_present) && p->create_uio_dev) {
271                 snprintf(buffer, sizeof(buffer), "--create-uio-dev");
272                 app->eal_argv[n_args++] = strdup(buffer);
273         }
274
275         if (p->vfio_intr) {
276                 snprintf(buffer,
277                         sizeof(buffer),
278                         "--vfio-intr=%s",
279                         p->vfio_intr);
280                 app->eal_argv[n_args++] = strdup(buffer);
281         }
282
283         if ((p->xen_dom0_present) && (p->xen_dom0)) {
284                 snprintf(buffer, sizeof(buffer), "--xen-dom0");
285                 app->eal_argv[n_args++] = strdup(buffer);
286         }
287
288         snprintf(buffer, sizeof(buffer), "--");
289         app->eal_argv[n_args++] = strdup(buffer);
290
291         app->eal_argc = n_args;
292
293         APP_LOG(app, HIGH, "Initializing EAL ...");
294         if (app->log_level >= APP_LOG_LEVEL_LOW) {
295                 int i;
296
297                 fprintf(stdout, "[APP] EAL arguments: \"");
298                 for (i = 1; i < app->eal_argc; i++)
299                         fprintf(stdout, "%s ", app->eal_argv[i]);
300                 fprintf(stdout, "\"\n");
301         }
302
303         status = rte_eal_init(app->eal_argc, app->eal_argv);
304         if (status < 0)
305                 rte_panic("EAL init error\n");
306 }
307
308 static void
309 app_init_mempool(struct app_params *app)
310 {
311         uint32_t i;
312
313         for (i = 0; i < app->n_mempools; i++) {
314                 struct app_mempool_params *p = &app->mempool_params[i];
315
316                 APP_LOG(app, HIGH, "Initializing %s ...", p->name);
317                 app->mempool[i] = rte_mempool_create(
318                                 p->name,
319                                 p->pool_size,
320                                 p->buffer_size,
321                                 p->cache_size,
322                                 sizeof(struct rte_pktmbuf_pool_private),
323                                 rte_pktmbuf_pool_init, NULL,
324                                 rte_pktmbuf_init, NULL,
325                                 p->cpu_socket_id,
326                                 0);
327
328                 if (app->mempool[i] == NULL)
329                         rte_panic("%s init error\n", p->name);
330         }
331 }
332
333 static inline int
334 app_link_filter_arp_add(struct app_link_params *link)
335 {
336         struct rte_eth_ethertype_filter filter = {
337                 .ether_type = ETHER_TYPE_ARP,
338                 .flags = 0,
339                 .queue = link->arp_q,
340         };
341
342         return rte_eth_dev_filter_ctrl(link->pmd_id,
343                 RTE_ETH_FILTER_ETHERTYPE,
344                 RTE_ETH_FILTER_ADD,
345                 &filter);
346 }
347
348 static inline int
349 app_link_filter_tcp_syn_add(struct app_link_params *link)
350 {
351         struct rte_eth_syn_filter filter = {
352                 .hig_pri = 1,
353                 .queue = link->tcp_syn_q,
354         };
355
356         return rte_eth_dev_filter_ctrl(link->pmd_id,
357                 RTE_ETH_FILTER_SYN,
358                 RTE_ETH_FILTER_ADD,
359                 &filter);
360 }
361
362 static inline int
363 app_link_filter_ip_add(struct app_link_params *l1, struct app_link_params *l2)
364 {
365         struct rte_eth_ntuple_filter filter = {
366                 .flags = RTE_5TUPLE_FLAGS,
367                 .dst_ip = rte_bswap32(l2->ip),
368                 .dst_ip_mask = UINT32_MAX, /* Enable */
369                 .src_ip = 0,
370                 .src_ip_mask = 0, /* Disable */
371                 .dst_port = 0,
372                 .dst_port_mask = 0, /* Disable */
373                 .src_port = 0,
374                 .src_port_mask = 0, /* Disable */
375                 .proto = 0,
376                 .proto_mask = 0, /* Disable */
377                 .tcp_flags = 0,
378                 .priority = 1, /* Lowest */
379                 .queue = l1->ip_local_q,
380         };
381
382         return rte_eth_dev_filter_ctrl(l1->pmd_id,
383                 RTE_ETH_FILTER_NTUPLE,
384                 RTE_ETH_FILTER_ADD,
385                 &filter);
386 }
387
388 static inline int
389 app_link_filter_ip_del(struct app_link_params *l1, struct app_link_params *l2)
390 {
391         struct rte_eth_ntuple_filter filter = {
392                 .flags = RTE_5TUPLE_FLAGS,
393                 .dst_ip = rte_bswap32(l2->ip),
394                 .dst_ip_mask = UINT32_MAX, /* Enable */
395                 .src_ip = 0,
396                 .src_ip_mask = 0, /* Disable */
397                 .dst_port = 0,
398                 .dst_port_mask = 0, /* Disable */
399                 .src_port = 0,
400                 .src_port_mask = 0, /* Disable */
401                 .proto = 0,
402                 .proto_mask = 0, /* Disable */
403                 .tcp_flags = 0,
404                 .priority = 1, /* Lowest */
405                 .queue = l1->ip_local_q,
406         };
407
408         return rte_eth_dev_filter_ctrl(l1->pmd_id,
409                 RTE_ETH_FILTER_NTUPLE,
410                 RTE_ETH_FILTER_DELETE,
411                 &filter);
412 }
413
414 static inline int
415 app_link_filter_tcp_add(struct app_link_params *l1, struct app_link_params *l2)
416 {
417         struct rte_eth_ntuple_filter filter = {
418                 .flags = RTE_5TUPLE_FLAGS,
419                 .dst_ip = rte_bswap32(l2->ip),
420                 .dst_ip_mask = UINT32_MAX, /* Enable */
421                 .src_ip = 0,
422                 .src_ip_mask = 0, /* Disable */
423                 .dst_port = 0,
424                 .dst_port_mask = 0, /* Disable */
425                 .src_port = 0,
426                 .src_port_mask = 0, /* Disable */
427                 .proto = IPPROTO_TCP,
428                 .proto_mask = UINT8_MAX, /* Enable */
429                 .tcp_flags = 0,
430                 .priority = 2, /* Higher priority than IP */
431                 .queue = l1->tcp_local_q,
432         };
433
434         return rte_eth_dev_filter_ctrl(l1->pmd_id,
435                 RTE_ETH_FILTER_NTUPLE,
436                 RTE_ETH_FILTER_ADD,
437                 &filter);
438 }
439
440 static inline int
441 app_link_filter_tcp_del(struct app_link_params *l1, struct app_link_params *l2)
442 {
443         struct rte_eth_ntuple_filter filter = {
444                 .flags = RTE_5TUPLE_FLAGS,
445                 .dst_ip = rte_bswap32(l2->ip),
446                 .dst_ip_mask = UINT32_MAX, /* Enable */
447                 .src_ip = 0,
448                 .src_ip_mask = 0, /* Disable */
449                 .dst_port = 0,
450                 .dst_port_mask = 0, /* Disable */
451                 .src_port = 0,
452                 .src_port_mask = 0, /* Disable */
453                 .proto = IPPROTO_TCP,
454                 .proto_mask = UINT8_MAX, /* Enable */
455                 .tcp_flags = 0,
456                 .priority = 2, /* Higher priority than IP */
457                 .queue = l1->tcp_local_q,
458         };
459
460         return rte_eth_dev_filter_ctrl(l1->pmd_id,
461                 RTE_ETH_FILTER_NTUPLE,
462                 RTE_ETH_FILTER_DELETE,
463                 &filter);
464 }
465
466 static inline int
467 app_link_filter_udp_add(struct app_link_params *l1, struct app_link_params *l2)
468 {
469         struct rte_eth_ntuple_filter filter = {
470                 .flags = RTE_5TUPLE_FLAGS,
471                 .dst_ip = rte_bswap32(l2->ip),
472                 .dst_ip_mask = UINT32_MAX, /* Enable */
473                 .src_ip = 0,
474                 .src_ip_mask = 0, /* Disable */
475                 .dst_port = 0,
476                 .dst_port_mask = 0, /* Disable */
477                 .src_port = 0,
478                 .src_port_mask = 0, /* Disable */
479                 .proto = IPPROTO_UDP,
480                 .proto_mask = UINT8_MAX, /* Enable */
481                 .tcp_flags = 0,
482                 .priority = 2, /* Higher priority than IP */
483                 .queue = l1->udp_local_q,
484         };
485
486         return rte_eth_dev_filter_ctrl(l1->pmd_id,
487                 RTE_ETH_FILTER_NTUPLE,
488                 RTE_ETH_FILTER_ADD,
489                 &filter);
490 }
491
492 static inline int
493 app_link_filter_udp_del(struct app_link_params *l1, struct app_link_params *l2)
494 {
495         struct rte_eth_ntuple_filter filter = {
496                 .flags = RTE_5TUPLE_FLAGS,
497                 .dst_ip = rte_bswap32(l2->ip),
498                 .dst_ip_mask = UINT32_MAX, /* Enable */
499                 .src_ip = 0,
500                 .src_ip_mask = 0, /* Disable */
501                 .dst_port = 0,
502                 .dst_port_mask = 0, /* Disable */
503                 .src_port = 0,
504                 .src_port_mask = 0, /* Disable */
505                 .proto = IPPROTO_UDP,
506                 .proto_mask = UINT8_MAX, /* Enable */
507                 .tcp_flags = 0,
508                 .priority = 2, /* Higher priority than IP */
509                 .queue = l1->udp_local_q,
510         };
511
512         return rte_eth_dev_filter_ctrl(l1->pmd_id,
513                 RTE_ETH_FILTER_NTUPLE,
514                 RTE_ETH_FILTER_DELETE,
515                 &filter);
516 }
517
518 static inline int
519 app_link_filter_sctp_add(struct app_link_params *l1, struct app_link_params *l2)
520 {
521         struct rte_eth_ntuple_filter filter = {
522                 .flags = RTE_5TUPLE_FLAGS,
523                 .dst_ip = rte_bswap32(l2->ip),
524                 .dst_ip_mask = UINT32_MAX, /* Enable */
525                 .src_ip = 0,
526                 .src_ip_mask = 0, /* Disable */
527                 .dst_port = 0,
528                 .dst_port_mask = 0, /* Disable */
529                 .src_port = 0,
530                 .src_port_mask = 0, /* Disable */
531                 .proto = IPPROTO_SCTP,
532                 .proto_mask = UINT8_MAX, /* Enable */
533                 .tcp_flags = 0,
534                 .priority = 2, /* Higher priority than IP */
535                 .queue = l1->sctp_local_q,
536         };
537
538         return rte_eth_dev_filter_ctrl(l1->pmd_id,
539                 RTE_ETH_FILTER_NTUPLE,
540                 RTE_ETH_FILTER_ADD,
541                 &filter);
542 }
543
544 static inline int
545 app_link_filter_sctp_del(struct app_link_params *l1, struct app_link_params *l2)
546 {
547         struct rte_eth_ntuple_filter filter = {
548                 .flags = RTE_5TUPLE_FLAGS,
549                 .dst_ip = rte_bswap32(l2->ip),
550                 .dst_ip_mask = UINT32_MAX, /* Enable */
551                 .src_ip = 0,
552                 .src_ip_mask = 0, /* Disable */
553                 .dst_port = 0,
554                 .dst_port_mask = 0, /* Disable */
555                 .src_port = 0,
556                 .src_port_mask = 0, /* Disable */
557                 .proto = IPPROTO_SCTP,
558                 .proto_mask = UINT8_MAX, /* Enable */
559                 .tcp_flags = 0,
560                 .priority = 2, /* Higher priority than IP */
561                 .queue = l1->sctp_local_q,
562         };
563
564         return rte_eth_dev_filter_ctrl(l1->pmd_id,
565                 RTE_ETH_FILTER_NTUPLE,
566                 RTE_ETH_FILTER_DELETE,
567                 &filter);
568 }
569
570 static void
571 app_link_set_arp_filter(struct app_params *app, struct app_link_params *cp)
572 {
573         if (cp->arp_q != 0) {
574                 int status = app_link_filter_arp_add(cp);
575
576                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
577                         "Adding ARP filter (queue = %" PRIu32 ")",
578                         cp->name, cp->pmd_id, cp->arp_q);
579
580                 if (status)
581                         rte_panic("%s (%" PRIu32 "): "
582                                 "Error adding ARP filter "
583                                 "(queue = %" PRIu32 ") (%" PRId32 ")\n",
584                                 cp->name, cp->pmd_id, cp->arp_q, status);
585         }
586 }
587
588 static void
589 app_link_set_tcp_syn_filter(struct app_params *app, struct app_link_params *cp)
590 {
591         if (cp->tcp_syn_q != 0) {
592                 int status = app_link_filter_tcp_syn_add(cp);
593
594                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
595                         "Adding TCP SYN filter (queue = %" PRIu32 ")",
596                         cp->name, cp->pmd_id, cp->tcp_syn_q);
597
598                 if (status)
599                         rte_panic("%s (%" PRIu32 "): "
600                                 "Error adding TCP SYN filter "
601                                 "(queue = %" PRIu32 ") (%" PRId32 ")\n",
602                                 cp->name, cp->pmd_id, cp->tcp_syn_q,
603                                 status);
604         }
605 }
606
607 static int
608 app_link_is_virtual(struct app_link_params *p)
609 {
610         uint32_t pmd_id = p->pmd_id;
611         struct rte_eth_dev *dev = &rte_eth_devices[pmd_id];
612
613         if (dev->dev_type == RTE_ETH_DEV_VIRTUAL)
614                 return 1;
615
616         return 0;
617 }
618
619 void
620 app_link_up_internal(struct app_params *app, struct app_link_params *cp)
621 {
622         uint32_t i;
623         int status;
624
625         if (app_link_is_virtual(cp)) {
626                 cp->state = 1;
627                 return;
628         }
629
630         /* For each link, add filters for IP of current link */
631         if (cp->ip != 0) {
632                 for (i = 0; i < app->n_links; i++) {
633                         struct app_link_params *p = &app->link_params[i];
634
635                         /* IP */
636                         if (p->ip_local_q != 0) {
637                                 int status = app_link_filter_ip_add(p, cp);
638
639                                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
640                                         "Adding IP filter (queue= %" PRIu32
641                                         ", IP = 0x%08" PRIx32 ")",
642                                         p->name, p->pmd_id, p->ip_local_q,
643                                         cp->ip);
644
645                                 if (status)
646                                         rte_panic("%s (%" PRIu32 "): "
647                                                 "Error adding IP "
648                                                 "filter (queue= %" PRIu32 ", "
649                                                 "IP = 0x%08" PRIx32
650                                                 ") (%" PRId32 ")\n",
651                                                 p->name, p->pmd_id,
652                                                 p->ip_local_q, cp->ip, status);
653                         }
654
655                         /* TCP */
656                         if (p->tcp_local_q != 0) {
657                                 int status = app_link_filter_tcp_add(p, cp);
658
659                                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
660                                         "Adding TCP filter "
661                                         "(queue = %" PRIu32
662                                         ", IP = 0x%08" PRIx32 ")",
663                                         p->name, p->pmd_id, p->tcp_local_q,
664                                         cp->ip);
665
666                                 if (status)
667                                         rte_panic("%s (%" PRIu32 "): "
668                                                 "Error adding TCP "
669                                                 "filter (queue = %" PRIu32 ", "
670                                                 "IP = 0x%08" PRIx32
671                                                 ") (%" PRId32 ")\n",
672                                                 p->name, p->pmd_id,
673                                                 p->tcp_local_q, cp->ip, status);
674                         }
675
676                         /* UDP */
677                         if (p->udp_local_q != 0) {
678                                 int status = app_link_filter_udp_add(p, cp);
679
680                                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
681                                         "Adding UDP filter "
682                                         "(queue = %" PRIu32
683                                         ", IP = 0x%08" PRIx32 ")",
684                                         p->name, p->pmd_id, p->udp_local_q,
685                                         cp->ip);
686
687                                 if (status)
688                                         rte_panic("%s (%" PRIu32 "): "
689                                                 "Error adding UDP "
690                                                 "filter (queue = %" PRIu32 ", "
691                                                 "IP = 0x%08" PRIx32
692                                                 ") (%" PRId32 ")\n",
693                                                 p->name, p->pmd_id,
694                                                 p->udp_local_q, cp->ip, status);
695                         }
696
697                         /* SCTP */
698                         if (p->sctp_local_q != 0) {
699                                 int status = app_link_filter_sctp_add(p, cp);
700
701                                 APP_LOG(app, LOW, "%s (%" PRIu32
702                                         "): Adding SCTP filter "
703                                         "(queue = %" PRIu32
704                                         ", IP = 0x%08" PRIx32 ")",
705                                         p->name, p->pmd_id, p->sctp_local_q,
706                                         cp->ip);
707
708                                 if (status)
709                                         rte_panic("%s (%" PRIu32 "): "
710                                                 "Error adding SCTP "
711                                                 "filter (queue = %" PRIu32 ", "
712                                                 "IP = 0x%08" PRIx32
713                                                 ") (%" PRId32 ")\n",
714                                                 p->name, p->pmd_id,
715                                                 p->sctp_local_q, cp->ip,
716                                                 status);
717                         }
718                 }
719         }
720
721         /* PMD link up */
722         status = rte_eth_dev_set_link_up(cp->pmd_id);
723         if (status < 0)
724                 rte_panic("%s (%" PRIu32 "): PMD set link up error %"
725                         PRId32 "\n", cp->name, cp->pmd_id, status);
726
727         /* Mark link as UP */
728         cp->state = 1;
729 }
730
731 void
732 app_link_down_internal(struct app_params *app, struct app_link_params *cp)
733 {
734         uint32_t i;
735         int status;
736
737         if (app_link_is_virtual(cp)) {
738                 cp->state = 0;
739                 return;
740         }
741
742         /* PMD link down */
743         status = rte_eth_dev_set_link_down(cp->pmd_id);
744         if (status < 0)
745                 rte_panic("%s (%" PRIu32 "): PMD set link down error %"
746                         PRId32 "\n", cp->name, cp->pmd_id, status);
747
748         /* Mark link as DOWN */
749         cp->state = 0;
750
751         /* Return if current link IP is not valid */
752         if (cp->ip == 0)
753                 return;
754
755         /* For each link, remove filters for IP of current link */
756         for (i = 0; i < app->n_links; i++) {
757                 struct app_link_params *p = &app->link_params[i];
758
759                 /* IP */
760                 if (p->ip_local_q != 0) {
761                         int status = app_link_filter_ip_del(p, cp);
762
763                         APP_LOG(app, LOW, "%s (%" PRIu32
764                                 "): Deleting IP filter "
765                                 "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")",
766                                 p->name, p->pmd_id, p->ip_local_q, cp->ip);
767
768                         if (status)
769                                 rte_panic("%s (%" PRIu32
770                                         "): Error deleting IP filter "
771                                         "(queue = %" PRIu32
772                                         ", IP = 0x%" PRIx32
773                                         ") (%" PRId32 ")\n",
774                                         p->name, p->pmd_id, p->ip_local_q,
775                                         cp->ip, status);
776                 }
777
778                 /* TCP */
779                 if (p->tcp_local_q != 0) {
780                         int status = app_link_filter_tcp_del(p, cp);
781
782                         APP_LOG(app, LOW, "%s (%" PRIu32
783                                 "): Deleting TCP filter "
784                                 "(queue = %" PRIu32
785                                 ", IP = 0x%" PRIx32 ")",
786                                 p->name, p->pmd_id, p->tcp_local_q, cp->ip);
787
788                         if (status)
789                                 rte_panic("%s (%" PRIu32
790                                         "): Error deleting TCP filter "
791                                         "(queue = %" PRIu32
792                                         ", IP = 0x%" PRIx32
793                                         ") (%" PRId32 ")\n",
794                                         p->name, p->pmd_id, p->tcp_local_q,
795                                         cp->ip, status);
796                 }
797
798                 /* UDP */
799                 if (p->udp_local_q != 0) {
800                         int status = app_link_filter_udp_del(p, cp);
801
802                         APP_LOG(app, LOW, "%s (%" PRIu32
803                                 "): Deleting UDP filter "
804                                 "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")",
805                                 p->name, p->pmd_id, p->udp_local_q, cp->ip);
806
807                         if (status)
808                                 rte_panic("%s (%" PRIu32
809                                         "): Error deleting UDP filter "
810                                         "(queue = %" PRIu32
811                                         ", IP = 0x%" PRIx32
812                                         ") (%" PRId32 ")\n",
813                                         p->name, p->pmd_id, p->udp_local_q,
814                                         cp->ip, status);
815                 }
816
817                 /* SCTP */
818                 if (p->sctp_local_q != 0) {
819                         int status = app_link_filter_sctp_del(p, cp);
820
821                         APP_LOG(app, LOW, "%s (%" PRIu32
822                                 "): Deleting SCTP filter "
823                                 "(queue = %" PRIu32
824                                 ", IP = 0x%" PRIx32 ")",
825                                 p->name, p->pmd_id, p->sctp_local_q, cp->ip);
826
827                         if (status)
828                                 rte_panic("%s (%" PRIu32
829                                         "): Error deleting SCTP filter "
830                                         "(queue = %" PRIu32
831                                         ", IP = 0x%" PRIx32
832                                         ") (%" PRId32 ")\n",
833                                         p->name, p->pmd_id, p->sctp_local_q,
834                                         cp->ip, status);
835                 }
836         }
837 }
838
839 static void
840 app_check_link(struct app_params *app)
841 {
842         uint32_t all_links_up, i;
843
844         all_links_up = 1;
845
846         for (i = 0; i < app->n_links; i++) {
847                 struct app_link_params *p = &app->link_params[i];
848                 struct rte_eth_link link_params;
849
850                 memset(&link_params, 0, sizeof(link_params));
851                 rte_eth_link_get(p->pmd_id, &link_params);
852
853                 APP_LOG(app, HIGH, "%s (%" PRIu32 ") (%" PRIu32 " Gbps) %s",
854                         p->name,
855                         p->pmd_id,
856                         link_params.link_speed / 1000,
857                         link_params.link_status ? "UP" : "DOWN");
858
859                 if (link_params.link_status == ETH_LINK_DOWN)
860                         all_links_up = 0;
861         }
862
863         if (all_links_up == 0)
864                 rte_panic("Some links are DOWN\n");
865 }
866
867 static uint32_t
868 is_any_swq_frag_or_ras(struct app_params *app)
869 {
870         uint32_t i;
871
872         for (i = 0; i < app->n_pktq_swq; i++) {
873                 struct app_pktq_swq_params *p = &app->swq_params[i];
874
875                 if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1) ||
876                         (p->ipv4_ras == 1) || (p->ipv6_ras == 1))
877                         return 1;
878         }
879
880         return 0;
881 }
882
883 static void
884 app_init_link_frag_ras(struct app_params *app)
885 {
886         uint32_t i;
887
888         if (is_any_swq_frag_or_ras(app)) {
889                 for (i = 0; i < app->n_pktq_hwq_out; i++) {
890                         struct app_pktq_hwq_out_params *p_txq = &app->hwq_out_params[i];
891
892                         p_txq->conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;
893                 }
894         }
895 }
896
897 static inline int
898 app_get_cpu_socket_id(uint32_t pmd_id)
899 {
900         int status = rte_eth_dev_socket_id(pmd_id);
901
902         return (status != SOCKET_ID_ANY) ? status : 0;
903 }
904
905 static void
906 app_init_link(struct app_params *app)
907 {
908         uint32_t i;
909
910         app_init_link_frag_ras(app);
911
912         for (i = 0; i < app->n_links; i++) {
913                 struct app_link_params *p_link = &app->link_params[i];
914                 uint32_t link_id, n_hwq_in, n_hwq_out, j;
915                 int status;
916
917                 sscanf(p_link->name, "LINK%" PRIu32, &link_id);
918                 n_hwq_in = app_link_get_n_rxq(app, p_link);
919                 n_hwq_out = app_link_get_n_txq(app, p_link);
920
921                 APP_LOG(app, HIGH, "Initializing %s (%" PRIu32") "
922                         "(%" PRIu32 " RXQ, %" PRIu32 " TXQ) ...",
923                         p_link->name,
924                         p_link->pmd_id,
925                         n_hwq_in,
926                         n_hwq_out);
927
928                 /* LINK */
929                 status = rte_eth_dev_configure(
930                         p_link->pmd_id,
931                         n_hwq_in,
932                         n_hwq_out,
933                         &p_link->conf);
934                 if (status < 0)
935                         rte_panic("%s (%" PRId32 "): "
936                                 "init error (%" PRId32 ")\n",
937                                 p_link->name, p_link->pmd_id, status);
938
939                 rte_eth_macaddr_get(p_link->pmd_id,
940                         (struct ether_addr *) &p_link->mac_addr);
941
942                 if (p_link->promisc)
943                         rte_eth_promiscuous_enable(p_link->pmd_id);
944
945                 /* RXQ */
946                 for (j = 0; j < app->n_pktq_hwq_in; j++) {
947                         struct app_pktq_hwq_in_params *p_rxq =
948                                 &app->hwq_in_params[j];
949                         uint32_t rxq_link_id, rxq_queue_id;
950
951                         sscanf(p_rxq->name, "RXQ%" PRIu32 ".%" PRIu32,
952                                 &rxq_link_id, &rxq_queue_id);
953                         if (rxq_link_id != link_id)
954                                 continue;
955
956                         status = rte_eth_rx_queue_setup(
957                                 p_link->pmd_id,
958                                 rxq_queue_id,
959                                 p_rxq->size,
960                                 app_get_cpu_socket_id(p_link->pmd_id),
961                                 &p_rxq->conf,
962                                 app->mempool[p_rxq->mempool_id]);
963                         if (status < 0)
964                                 rte_panic("%s (%" PRIu32 "): "
965                                         "%s init error (%" PRId32 ")\n",
966                                         p_link->name,
967                                         p_link->pmd_id,
968                                         p_rxq->name,
969                                         status);
970                 }
971
972                 /* TXQ */
973                 for (j = 0; j < app->n_pktq_hwq_out; j++) {
974                         struct app_pktq_hwq_out_params *p_txq =
975                                 &app->hwq_out_params[j];
976                         uint32_t txq_link_id, txq_queue_id;
977
978                         sscanf(p_txq->name, "TXQ%" PRIu32 ".%" PRIu32,
979                                 &txq_link_id, &txq_queue_id);
980                         if (txq_link_id != link_id)
981                                 continue;
982
983                         status = rte_eth_tx_queue_setup(
984                                 p_link->pmd_id,
985                                 txq_queue_id,
986                                 p_txq->size,
987                                 app_get_cpu_socket_id(p_link->pmd_id),
988                                 &p_txq->conf);
989                         if (status < 0)
990                                 rte_panic("%s (%" PRIu32 "): "
991                                         "%s init error (%" PRId32 ")\n",
992                                         p_link->name,
993                                         p_link->pmd_id,
994                                         p_txq->name,
995                                         status);
996                 }
997
998                 /* LINK START */
999                 status = rte_eth_dev_start(p_link->pmd_id);
1000                 if (status < 0)
1001                         rte_panic("Cannot start %s (error %" PRId32 ")\n",
1002                                 p_link->name, status);
1003
1004                 /* LINK UP */
1005                 app_link_set_arp_filter(app, p_link);
1006                 app_link_set_tcp_syn_filter(app, p_link);
1007                 app_link_up_internal(app, p_link);
1008         }
1009
1010         app_check_link(app);
1011 }
1012
1013 static void
1014 app_init_swq(struct app_params *app)
1015 {
1016         uint32_t i;
1017
1018         for (i = 0; i < app->n_pktq_swq; i++) {
1019                 struct app_pktq_swq_params *p = &app->swq_params[i];
1020                 unsigned flags = 0;
1021
1022                 if (app_swq_get_readers(app, p) == 1)
1023                         flags |= RING_F_SC_DEQ;
1024                 if (app_swq_get_writers(app, p) == 1)
1025                         flags |= RING_F_SP_ENQ;
1026
1027                 APP_LOG(app, HIGH, "Initializing %s...", p->name);
1028                 app->swq[i] = rte_ring_create(
1029                                 p->name,
1030                                 p->size,
1031                                 p->cpu_socket_id,
1032                                 flags);
1033
1034                 if (app->swq[i] == NULL)
1035                         rte_panic("%s init error\n", p->name);
1036         }
1037 }
1038
1039 static void
1040 app_init_tm(struct app_params *app)
1041 {
1042         uint32_t i;
1043
1044         for (i = 0; i < app->n_pktq_tm; i++) {
1045                 struct app_pktq_tm_params *p_tm = &app->tm_params[i];
1046                 struct app_link_params *p_link;
1047                 struct rte_eth_link link_eth_params;
1048                 struct rte_sched_port *sched;
1049                 uint32_t n_subports, subport_id;
1050                 int status;
1051
1052                 p_link = app_get_link_for_tm(app, p_tm);
1053                 /* LINK */
1054                 rte_eth_link_get(p_link->pmd_id, &link_eth_params);
1055
1056                 /* TM */
1057                 p_tm->sched_port_params.name = p_tm->name;
1058                 p_tm->sched_port_params.socket =
1059                         app_get_cpu_socket_id(p_link->pmd_id);
1060                 p_tm->sched_port_params.rate =
1061                         (uint64_t) link_eth_params.link_speed * 1000 * 1000 / 8;
1062
1063                 APP_LOG(app, HIGH, "Initializing %s ...", p_tm->name);
1064                 sched = rte_sched_port_config(&p_tm->sched_port_params);
1065                 if (sched == NULL)
1066                         rte_panic("%s init error\n", p_tm->name);
1067                 app->tm[i] = sched;
1068
1069                 /* Subport */
1070                 n_subports = p_tm->sched_port_params.n_subports_per_port;
1071                 for (subport_id = 0; subport_id < n_subports; subport_id++) {
1072                         uint32_t n_pipes_per_subport, pipe_id;
1073
1074                         status = rte_sched_subport_config(sched,
1075                                 subport_id,
1076                                 &p_tm->sched_subport_params[subport_id]);
1077                         if (status)
1078                                 rte_panic("%s subport %" PRIu32
1079                                         " init error (%" PRId32 ")\n",
1080                                         p_tm->name, subport_id, status);
1081
1082                         /* Pipe */
1083                         n_pipes_per_subport =
1084                                 p_tm->sched_port_params.n_pipes_per_subport;
1085                         for (pipe_id = 0;
1086                                 pipe_id < n_pipes_per_subport;
1087                                 pipe_id++) {
1088                                 int profile_id = p_tm->sched_pipe_to_profile[
1089                                         subport_id * APP_MAX_SCHED_PIPES +
1090                                         pipe_id];
1091
1092                                 if (profile_id == -1)
1093                                         continue;
1094
1095                                 status = rte_sched_pipe_config(sched,
1096                                         subport_id,
1097                                         pipe_id,
1098                                         profile_id);
1099                                 if (status)
1100                                         rte_panic("%s subport %" PRIu32
1101                                                 " pipe %" PRIu32
1102                                                 " (profile %" PRId32 ") "
1103                                                 "init error (% " PRId32 ")\n",
1104                                                 p_tm->name, subport_id, pipe_id,
1105                                                 profile_id, status);
1106                         }
1107                 }
1108         }
1109 }
1110
1111 static void
1112 app_init_msgq(struct app_params *app)
1113 {
1114         uint32_t i;
1115
1116         for (i = 0; i < app->n_msgq; i++) {
1117                 struct app_msgq_params *p = &app->msgq_params[i];
1118
1119                 APP_LOG(app, HIGH, "Initializing %s ...", p->name);
1120                 app->msgq[i] = rte_ring_create(
1121                                 p->name,
1122                                 p->size,
1123                                 p->cpu_socket_id,
1124                                 RING_F_SP_ENQ | RING_F_SC_DEQ);
1125
1126                 if (app->msgq[i] == NULL)
1127                         rte_panic("%s init error\n", p->name);
1128         }
1129 }
1130
1131 static void app_pipeline_params_get(struct app_params *app,
1132         struct app_pipeline_params *p_in,
1133         struct pipeline_params *p_out)
1134 {
1135         uint32_t i;
1136         uint32_t mempool_id;
1137
1138         snprintf(p_out->name, PIPELINE_NAME_SIZE, "%s", p_in->name);
1139
1140         p_out->socket_id = (int) p_in->socket_id;
1141
1142         p_out->log_level = app->log_level;
1143
1144         /* pktq_in */
1145         p_out->n_ports_in = p_in->n_pktq_in;
1146         for (i = 0; i < p_in->n_pktq_in; i++) {
1147                 struct app_pktq_in_params *in = &p_in->pktq_in[i];
1148                 struct pipeline_port_in_params *out = &p_out->port_in[i];
1149
1150                 switch (in->type) {
1151                 case APP_PKTQ_IN_HWQ:
1152                 {
1153                         struct app_pktq_hwq_in_params *p_hwq_in =
1154                                 &app->hwq_in_params[in->id];
1155                         struct app_link_params *p_link =
1156                                 app_get_link_for_rxq(app, p_hwq_in);
1157                         uint32_t rxq_link_id, rxq_queue_id;
1158
1159                         sscanf(p_hwq_in->name, "RXQ%" SCNu32 ".%" SCNu32,
1160                                 &rxq_link_id,
1161                                 &rxq_queue_id);
1162
1163                         out->type = PIPELINE_PORT_IN_ETHDEV_READER;
1164                         out->params.ethdev.port_id = p_link->pmd_id;
1165                         out->params.ethdev.queue_id = rxq_queue_id;
1166                         out->burst_size = p_hwq_in->burst;
1167                         break;
1168                 }
1169                 case APP_PKTQ_IN_SWQ:
1170                 {
1171                         struct app_pktq_swq_params *swq_params = &app->swq_params[in->id];
1172
1173                         if ((swq_params->ipv4_frag == 0) && (swq_params->ipv6_frag == 0)) {
1174                                 if (app_swq_get_readers(app, swq_params) == 1) {
1175                                         out->type = PIPELINE_PORT_IN_RING_READER;
1176                                         out->params.ring.ring = app->swq[in->id];
1177                                         out->burst_size = app->swq_params[in->id].burst_read;
1178                                 } else {
1179                                         out->type = PIPELINE_PORT_IN_RING_MULTI_READER;
1180                                         out->params.ring_multi.ring = app->swq[in->id];
1181                                         out->burst_size = swq_params->burst_read;
1182                                 }
1183                         } else {
1184                                 if (swq_params->ipv4_frag == 1) {
1185                                         struct rte_port_ring_reader_ipv4_frag_params *params =
1186                                                 &out->params.ring_ipv4_frag;
1187
1188                                         out->type = PIPELINE_PORT_IN_RING_READER_IPV4_FRAG;
1189                                         params->ring = app->swq[in->id];
1190                                         params->mtu = swq_params->mtu;
1191                                         params->metadata_size = swq_params->metadata_size;
1192                                         params->pool_direct =
1193                                                 app->mempool[swq_params->mempool_direct_id];
1194                                         params->pool_indirect =
1195                                                 app->mempool[swq_params->mempool_indirect_id];
1196                                         out->burst_size = swq_params->burst_read;
1197                                 } else {
1198                                         struct rte_port_ring_reader_ipv6_frag_params *params =
1199                                                 &out->params.ring_ipv6_frag;
1200
1201                                         out->type = PIPELINE_PORT_IN_RING_READER_IPV6_FRAG;
1202                                         params->ring = app->swq[in->id];
1203                                         params->mtu = swq_params->mtu;
1204                                         params->metadata_size = swq_params->metadata_size;
1205                                         params->pool_direct =
1206                                                 app->mempool[swq_params->mempool_direct_id];
1207                                         params->pool_indirect =
1208                                                 app->mempool[swq_params->mempool_indirect_id];
1209                                         out->burst_size = swq_params->burst_read;
1210                                 }
1211                         }
1212                         break;
1213                 }
1214                 case APP_PKTQ_IN_TM:
1215                         out->type = PIPELINE_PORT_IN_SCHED_READER;
1216                         out->params.sched.sched = app->tm[in->id];
1217                         out->burst_size = app->tm_params[in->id].burst_read;
1218                         break;
1219                 case APP_PKTQ_IN_SOURCE:
1220                         mempool_id = app->source_params[in->id].mempool_id;
1221                         out->type = PIPELINE_PORT_IN_SOURCE;
1222                         out->params.source.mempool = app->mempool[mempool_id];
1223                         out->burst_size = app->source_params[in->id].burst;
1224
1225 #ifdef RTE_NEXT_ABI
1226                         if (app->source_params[in->id].file_name
1227                                 != NULL) {
1228                                 out->params.source.file_name = strdup(
1229                                         app->source_params[in->id].
1230                                         file_name);
1231                                 if (out->params.source.file_name == NULL) {
1232                                         out->params.source.
1233                                                 n_bytes_per_pkt = 0;
1234                                         break;
1235                                 }
1236                                 out->params.source.n_bytes_per_pkt =
1237                                         app->source_params[in->id].
1238                                         n_bytes_per_pkt;
1239                         }
1240 #endif
1241
1242                         break;
1243                 default:
1244                         break;
1245                 }
1246         }
1247
1248         /* pktq_out */
1249         p_out->n_ports_out = p_in->n_pktq_out;
1250         for (i = 0; i < p_in->n_pktq_out; i++) {
1251                 struct app_pktq_out_params *in = &p_in->pktq_out[i];
1252                 struct pipeline_port_out_params *out = &p_out->port_out[i];
1253
1254                 switch (in->type) {
1255                 case APP_PKTQ_OUT_HWQ:
1256                 {
1257                         struct app_pktq_hwq_out_params *p_hwq_out =
1258                                 &app->hwq_out_params[in->id];
1259                         struct app_link_params *p_link =
1260                                 app_get_link_for_txq(app, p_hwq_out);
1261                         uint32_t txq_link_id, txq_queue_id;
1262
1263                         sscanf(p_hwq_out->name,
1264                                 "TXQ%" SCNu32 ".%" SCNu32,
1265                                 &txq_link_id,
1266                                 &txq_queue_id);
1267
1268                         if (p_hwq_out->dropless == 0) {
1269                                 struct rte_port_ethdev_writer_params *params =
1270                                         &out->params.ethdev;
1271
1272                                 out->type = PIPELINE_PORT_OUT_ETHDEV_WRITER;
1273                                 params->port_id = p_link->pmd_id;
1274                                 params->queue_id = txq_queue_id;
1275                                 params->tx_burst_sz =
1276                                         app->hwq_out_params[in->id].burst;
1277                         } else {
1278                                 struct rte_port_ethdev_writer_nodrop_params
1279                                         *params = &out->params.ethdev_nodrop;
1280
1281                                 out->type =
1282                                         PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP;
1283                                 params->port_id = p_link->pmd_id;
1284                                 params->queue_id = txq_queue_id;
1285                                 params->tx_burst_sz = p_hwq_out->burst;
1286                                 params->n_retries = p_hwq_out->n_retries;
1287                         }
1288                         break;
1289                 }
1290                 case APP_PKTQ_OUT_SWQ:
1291                 {
1292                         struct app_pktq_swq_params *swq_params = &app->swq_params[in->id];
1293
1294                         if ((swq_params->ipv4_ras == 0) && (swq_params->ipv6_ras == 0)) {
1295                                 if (app_swq_get_writers(app, swq_params) == 1) {
1296                                         if (app->swq_params[in->id].dropless == 0) {
1297                                                 struct rte_port_ring_writer_params *params =
1298                                                         &out->params.ring;
1299
1300                                                 out->type = PIPELINE_PORT_OUT_RING_WRITER;
1301                                                 params->ring = app->swq[in->id];
1302                                                 params->tx_burst_sz =
1303                                                         app->swq_params[in->id].burst_write;
1304                                         } else {
1305                                                 struct rte_port_ring_writer_nodrop_params
1306                                                         *params = &out->params.ring_nodrop;
1307
1308                                                 out->type =
1309                                                         PIPELINE_PORT_OUT_RING_WRITER_NODROP;
1310                                                 params->ring = app->swq[in->id];
1311                                                 params->tx_burst_sz =
1312                                                         app->swq_params[in->id].burst_write;
1313                                                 params->n_retries =
1314                                                         app->swq_params[in->id].n_retries;
1315                                         }
1316                                 } else {
1317                                         if (swq_params->dropless == 0) {
1318                                                 struct rte_port_ring_multi_writer_params *params =
1319                                                         &out->params.ring_multi;
1320
1321                                                 out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER;
1322                                                 params->ring = app->swq[in->id];
1323                                                 params->tx_burst_sz = swq_params->burst_write;
1324                                         } else {
1325                                                 struct rte_port_ring_multi_writer_nodrop_params
1326                                                         *params = &out->params.ring_multi_nodrop;
1327
1328                                                 out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP;
1329                                                 params->ring = app->swq[in->id];
1330                                                 params->tx_burst_sz = swq_params->burst_write;
1331                                                 params->n_retries = swq_params->n_retries;
1332                                         }
1333                                 }
1334                         } else {
1335                                 if (swq_params->ipv4_ras == 1) {
1336                                         struct rte_port_ring_writer_ipv4_ras_params *params =
1337                                                 &out->params.ring_ipv4_ras;
1338
1339                                         out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS;
1340                                         params->ring = app->swq[in->id];
1341                                         params->tx_burst_sz = swq_params->burst_write;
1342                                 } else {
1343                                         struct rte_port_ring_writer_ipv6_ras_params *params =
1344                                                 &out->params.ring_ipv6_ras;
1345
1346                                         out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS;
1347                                         params->ring = app->swq[in->id];
1348                                         params->tx_burst_sz = swq_params->burst_write;
1349                                 }
1350                         }
1351                         break;
1352                 }
1353                 case APP_PKTQ_OUT_TM: {
1354                         struct rte_port_sched_writer_params *params =
1355                                 &out->params.sched;
1356
1357                         out->type = PIPELINE_PORT_OUT_SCHED_WRITER;
1358                         params->sched = app->tm[in->id];
1359                         params->tx_burst_sz =
1360                                 app->tm_params[in->id].burst_write;
1361                         break;
1362                 }
1363                 case APP_PKTQ_OUT_SINK:
1364                         out->type = PIPELINE_PORT_OUT_SINK;
1365                         if (app->sink_params[in->id].file_name != NULL) {
1366                                 out->params.sink.file_name = strdup(
1367                                         app->sink_params[in->id].
1368                                         file_name);
1369                                 if (out->params.sink.file_name == NULL) {
1370                                         out->params.sink.max_n_pkts = 0;
1371                                         break;
1372                                 }
1373                                 out->params.sink.max_n_pkts =
1374                                         app->sink_params[in->id].
1375                                         n_pkts_to_dump;
1376                         } else {
1377                                 out->params.sink.file_name = NULL;
1378                                 out->params.sink.max_n_pkts = 0;
1379                         }
1380                         break;
1381                 default:
1382                         break;
1383                 }
1384         }
1385
1386         /* msgq */
1387         p_out->n_msgq = p_in->n_msgq_in;
1388
1389         for (i = 0; i < p_in->n_msgq_in; i++)
1390                 p_out->msgq_in[i] = app->msgq[p_in->msgq_in[i]];
1391
1392         for (i = 0; i < p_in->n_msgq_out; i++)
1393                 p_out->msgq_out[i] = app->msgq[p_in->msgq_out[i]];
1394
1395         /* args */
1396         p_out->n_args = p_in->n_args;
1397         for (i = 0; i < p_in->n_args; i++) {
1398                 p_out->args_name[i] = p_in->args_name[i];
1399                 p_out->args_value[i] = p_in->args_value[i];
1400         }
1401 }
1402
1403 static void
1404 app_init_pipelines(struct app_params *app)
1405 {
1406         uint32_t p_id;
1407
1408         for (p_id = 0; p_id < app->n_pipelines; p_id++) {
1409                 struct app_pipeline_params *params =
1410                         &app->pipeline_params[p_id];
1411                 struct app_pipeline_data *data = &app->pipeline_data[p_id];
1412                 struct pipeline_type *ptype;
1413                 struct pipeline_params pp;
1414
1415                 APP_LOG(app, HIGH, "Initializing %s ...", params->name);
1416
1417                 ptype = app_pipeline_type_find(app, params->type);
1418                 if (ptype == NULL)
1419                         rte_panic("Init error: Unknown pipeline type \"%s\"\n",
1420                                 params->type);
1421
1422                 app_pipeline_params_get(app, params, &pp);
1423
1424                 /* Back-end */
1425                 data->be = NULL;
1426                 if (ptype->be_ops->f_init) {
1427                         data->be = ptype->be_ops->f_init(&pp, (void *) app);
1428
1429                         if (data->be == NULL)
1430                                 rte_panic("Pipeline instance \"%s\" back-end "
1431                                         "init error\n", params->name);
1432                 }
1433
1434                 /* Front-end */
1435                 data->fe = NULL;
1436                 if (ptype->fe_ops->f_init) {
1437                         data->fe = ptype->fe_ops->f_init(&pp, (void *) app);
1438
1439                         if (data->fe == NULL)
1440                                 rte_panic("Pipeline instance \"%s\" front-end "
1441                                 "init error\n", params->name);
1442                 }
1443
1444                 data->ptype = ptype;
1445
1446                 data->timer_period = (rte_get_tsc_hz() *
1447                         params->timer_period) / 100;
1448         }
1449 }
1450
1451 static void
1452 app_init_threads(struct app_params *app)
1453 {
1454         uint64_t time = rte_get_tsc_cycles();
1455         uint32_t p_id;
1456
1457         for (p_id = 0; p_id < app->n_pipelines; p_id++) {
1458                 struct app_pipeline_params *params =
1459                         &app->pipeline_params[p_id];
1460                 struct app_pipeline_data *data = &app->pipeline_data[p_id];
1461                 struct pipeline_type *ptype;
1462                 struct app_thread_data *t;
1463                 struct app_thread_pipeline_data *p;
1464                 int lcore_id;
1465
1466                 lcore_id = cpu_core_map_get_lcore_id(app->core_map,
1467                         params->socket_id,
1468                         params->core_id,
1469                         params->hyper_th_id);
1470
1471                 if (lcore_id < 0)
1472                         rte_panic("Invalid core s%" PRIu32 "c%" PRIu32 "%s\n",
1473                                 params->socket_id,
1474                                 params->core_id,
1475                                 (params->hyper_th_id) ? "h" : "");
1476
1477                 t = &app->thread_data[lcore_id];
1478
1479                 t->timer_period = (rte_get_tsc_hz() * APP_THREAD_TIMER_PERIOD) / 1000;
1480                 t->thread_req_deadline = time + t->timer_period;
1481
1482                 t->headroom_cycles = 0;
1483                 t->headroom_time = rte_get_tsc_cycles();
1484                 t->headroom_ratio = 0.0;
1485
1486                 t->msgq_in = app_thread_msgq_in_get(app,
1487                                 params->socket_id,
1488                                 params->core_id,
1489                                 params->hyper_th_id);
1490                 if (t->msgq_in == NULL)
1491                         rte_panic("Init error: Cannot find MSGQ_IN for thread %" PRId32,
1492                                 lcore_id);
1493
1494                 t->msgq_out = app_thread_msgq_out_get(app,
1495                                 params->socket_id,
1496                                 params->core_id,
1497                                 params->hyper_th_id);
1498                 if (t->msgq_out == NULL)
1499                         rte_panic("Init error: Cannot find MSGQ_OUT for thread %" PRId32,
1500                                 lcore_id);
1501
1502                 ptype = app_pipeline_type_find(app, params->type);
1503                 if (ptype == NULL)
1504                         rte_panic("Init error: Unknown pipeline "
1505                                 "type \"%s\"\n", params->type);
1506
1507                 p = (ptype->be_ops->f_run == NULL) ?
1508                         &t->regular[t->n_regular] :
1509                         &t->custom[t->n_custom];
1510
1511                 p->pipeline_id = p_id;
1512                 p->be = data->be;
1513                 p->f_run = ptype->be_ops->f_run;
1514                 p->f_timer = ptype->be_ops->f_timer;
1515                 p->timer_period = data->timer_period;
1516                 p->deadline = time + data->timer_period;
1517
1518                 data->enabled = 1;
1519
1520                 if (ptype->be_ops->f_run == NULL)
1521                         t->n_regular++;
1522                 else
1523                         t->n_custom++;
1524         }
1525 }
1526
1527 int app_init(struct app_params *app)
1528 {
1529         app_init_core_map(app);
1530         app_init_core_mask(app);
1531
1532         app_init_eal(app);
1533         app_init_mempool(app);
1534         app_init_link(app);
1535         app_init_swq(app);
1536         app_init_tm(app);
1537         app_init_msgq(app);
1538
1539         app_pipeline_common_cmd_push(app);
1540         app_pipeline_thread_cmd_push(app);
1541         app_pipeline_type_register(app, &pipeline_master);
1542         app_pipeline_type_register(app, &pipeline_passthrough);
1543         app_pipeline_type_register(app, &pipeline_flow_classification);
1544         app_pipeline_type_register(app, &pipeline_flow_actions);
1545         app_pipeline_type_register(app, &pipeline_firewall);
1546         app_pipeline_type_register(app, &pipeline_routing);
1547
1548         app_init_pipelines(app);
1549         app_init_threads(app);
1550
1551         return 0;
1552 }
1553
1554 static int
1555 app_pipeline_type_cmd_push(struct app_params *app,
1556         struct pipeline_type *ptype)
1557 {
1558         cmdline_parse_ctx_t *cmds;
1559         uint32_t n_cmds, i;
1560
1561         /* Check input arguments */
1562         if ((app == NULL) ||
1563                 (ptype == NULL))
1564                 return -EINVAL;
1565
1566         n_cmds = pipeline_type_cmds_count(ptype);
1567         if (n_cmds == 0)
1568                 return 0;
1569
1570         cmds = ptype->fe_ops->cmds;
1571
1572         /* Check for available slots in the application commands array */
1573         if (n_cmds > APP_MAX_CMDS - app->n_cmds)
1574                 return -ENOMEM;
1575
1576         /* Push pipeline commands into the application */
1577         memcpy(&app->cmds[app->n_cmds],
1578                 cmds,
1579                 n_cmds * sizeof(cmdline_parse_ctx_t));
1580
1581         for (i = 0; i < n_cmds; i++)
1582                 app->cmds[app->n_cmds + i]->data = app;
1583
1584         app->n_cmds += n_cmds;
1585         app->cmds[app->n_cmds] = NULL;
1586
1587         return 0;
1588 }
1589
1590 int
1591 app_pipeline_type_register(struct app_params *app, struct pipeline_type *ptype)
1592 {
1593         uint32_t n_cmds, i;
1594
1595         /* Check input arguments */
1596         if ((app == NULL) ||
1597                 (ptype == NULL) ||
1598                 (ptype->name == NULL) ||
1599                 (strlen(ptype->name) == 0) ||
1600                 (ptype->be_ops->f_init == NULL) ||
1601                 (ptype->be_ops->f_timer == NULL))
1602                 return -EINVAL;
1603
1604         /* Check for duplicate entry */
1605         for (i = 0; i < app->n_pipeline_types; i++)
1606                 if (strcmp(app->pipeline_type[i].name, ptype->name) == 0)
1607                         return -EEXIST;
1608
1609         /* Check for resource availability */
1610         n_cmds = pipeline_type_cmds_count(ptype);
1611         if ((app->n_pipeline_types == APP_MAX_PIPELINE_TYPES) ||
1612                 (n_cmds > APP_MAX_CMDS - app->n_cmds))
1613                 return -ENOMEM;
1614
1615         /* Copy pipeline type */
1616         memcpy(&app->pipeline_type[app->n_pipeline_types++],
1617                 ptype,
1618                 sizeof(struct pipeline_type));
1619
1620         /* Copy CLI commands */
1621         if (n_cmds)
1622                 app_pipeline_type_cmd_push(app, ptype);
1623
1624         return 0;
1625 }
1626
1627 struct
1628 pipeline_type *app_pipeline_type_find(struct app_params *app, char *name)
1629 {
1630         uint32_t i;
1631
1632         for (i = 0; i < app->n_pipeline_types; i++)
1633                 if (strcmp(app->pipeline_type[i].name, name) == 0)
1634                         return &app->pipeline_type[i];
1635
1636         return NULL;
1637 }