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