examples/ip_pipeline: fix null packet in source port
[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
1137         snprintf(p_out->name, PIPELINE_NAME_SIZE, "%s", p_in->name);
1138
1139         p_out->socket_id = (int) p_in->socket_id;
1140
1141         p_out->log_level = app->log_level;
1142
1143         /* pktq_in */
1144         p_out->n_ports_in = p_in->n_pktq_in;
1145         for (i = 0; i < p_in->n_pktq_in; i++) {
1146                 struct app_pktq_in_params *in = &p_in->pktq_in[i];
1147                 struct pipeline_port_in_params *out = &p_out->port_in[i];
1148
1149                 switch (in->type) {
1150                 case APP_PKTQ_IN_HWQ:
1151                 {
1152                         struct app_pktq_hwq_in_params *p_hwq_in =
1153                                 &app->hwq_in_params[in->id];
1154                         struct app_link_params *p_link =
1155                                 app_get_link_for_rxq(app, p_hwq_in);
1156                         uint32_t rxq_link_id, rxq_queue_id;
1157
1158                         sscanf(p_hwq_in->name, "RXQ%" SCNu32 ".%" SCNu32,
1159                                 &rxq_link_id,
1160                                 &rxq_queue_id);
1161
1162                         out->type = PIPELINE_PORT_IN_ETHDEV_READER;
1163                         out->params.ethdev.port_id = p_link->pmd_id;
1164                         out->params.ethdev.queue_id = rxq_queue_id;
1165                         out->burst_size = p_hwq_in->burst;
1166                         break;
1167                 }
1168                 case APP_PKTQ_IN_SWQ:
1169                 {
1170                         struct app_pktq_swq_params *swq_params = &app->swq_params[in->id];
1171
1172                         if ((swq_params->ipv4_frag == 0) && (swq_params->ipv6_frag == 0)) {
1173                                 if (app_swq_get_readers(app, swq_params) == 1) {
1174                                         out->type = PIPELINE_PORT_IN_RING_READER;
1175                                         out->params.ring.ring = app->swq[in->id];
1176                                         out->burst_size = app->swq_params[in->id].burst_read;
1177                                 } else {
1178                                         out->type = PIPELINE_PORT_IN_RING_MULTI_READER;
1179                                         out->params.ring_multi.ring = app->swq[in->id];
1180                                         out->burst_size = swq_params->burst_read;
1181                                 }
1182                         } else {
1183                                 if (swq_params->ipv4_frag == 1) {
1184                                         struct rte_port_ring_reader_ipv4_frag_params *params =
1185                                                 &out->params.ring_ipv4_frag;
1186
1187                                         out->type = PIPELINE_PORT_IN_RING_READER_IPV4_FRAG;
1188                                         params->ring = app->swq[in->id];
1189                                         params->mtu = swq_params->mtu;
1190                                         params->metadata_size = swq_params->metadata_size;
1191                                         params->pool_direct =
1192                                                 app->mempool[swq_params->mempool_direct_id];
1193                                         params->pool_indirect =
1194                                                 app->mempool[swq_params->mempool_indirect_id];
1195                                         out->burst_size = swq_params->burst_read;
1196                                 } else {
1197                                         struct rte_port_ring_reader_ipv6_frag_params *params =
1198                                                 &out->params.ring_ipv6_frag;
1199
1200                                         out->type = PIPELINE_PORT_IN_RING_READER_IPV6_FRAG;
1201                                         params->ring = app->swq[in->id];
1202                                         params->mtu = swq_params->mtu;
1203                                         params->metadata_size = swq_params->metadata_size;
1204                                         params->pool_direct =
1205                                                 app->mempool[swq_params->mempool_direct_id];
1206                                         params->pool_indirect =
1207                                                 app->mempool[swq_params->mempool_indirect_id];
1208                                         out->burst_size = swq_params->burst_read;
1209                                 }
1210                         }
1211                         break;
1212                 }
1213                 case APP_PKTQ_IN_TM:
1214                         out->type = PIPELINE_PORT_IN_SCHED_READER;
1215                         out->params.sched.sched = app->tm[in->id];
1216                         out->burst_size = app->tm_params[in->id].burst_read;
1217                         break;
1218                 case APP_PKTQ_IN_SOURCE:
1219                 {
1220                         uint32_t mempool_id =
1221                                 app->source_params[in->id].mempool_id;
1222
1223                         out->type = PIPELINE_PORT_IN_SOURCE;
1224                         out->params.source.mempool = app->mempool[mempool_id];
1225                         out->burst_size = app->source_params[in->id].burst;
1226                         out->params.source.file_name =
1227                                 app->source_params[in->id].file_name;
1228                         out->params.source.n_bytes_per_pkt =
1229                                 app->source_params[in->id].n_bytes_per_pkt;
1230                         break;
1231                 }
1232                 default:
1233                         break;
1234                 }
1235         }
1236
1237         /* pktq_out */
1238         p_out->n_ports_out = p_in->n_pktq_out;
1239         for (i = 0; i < p_in->n_pktq_out; i++) {
1240                 struct app_pktq_out_params *in = &p_in->pktq_out[i];
1241                 struct pipeline_port_out_params *out = &p_out->port_out[i];
1242
1243                 switch (in->type) {
1244                 case APP_PKTQ_OUT_HWQ:
1245                 {
1246                         struct app_pktq_hwq_out_params *p_hwq_out =
1247                                 &app->hwq_out_params[in->id];
1248                         struct app_link_params *p_link =
1249                                 app_get_link_for_txq(app, p_hwq_out);
1250                         uint32_t txq_link_id, txq_queue_id;
1251
1252                         sscanf(p_hwq_out->name,
1253                                 "TXQ%" SCNu32 ".%" SCNu32,
1254                                 &txq_link_id,
1255                                 &txq_queue_id);
1256
1257                         if (p_hwq_out->dropless == 0) {
1258                                 struct rte_port_ethdev_writer_params *params =
1259                                         &out->params.ethdev;
1260
1261                                 out->type = PIPELINE_PORT_OUT_ETHDEV_WRITER;
1262                                 params->port_id = p_link->pmd_id;
1263                                 params->queue_id = txq_queue_id;
1264                                 params->tx_burst_sz =
1265                                         app->hwq_out_params[in->id].burst;
1266                         } else {
1267                                 struct rte_port_ethdev_writer_nodrop_params
1268                                         *params = &out->params.ethdev_nodrop;
1269
1270                                 out->type =
1271                                         PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP;
1272                                 params->port_id = p_link->pmd_id;
1273                                 params->queue_id = txq_queue_id;
1274                                 params->tx_burst_sz = p_hwq_out->burst;
1275                                 params->n_retries = p_hwq_out->n_retries;
1276                         }
1277                         break;
1278                 }
1279                 case APP_PKTQ_OUT_SWQ:
1280                 {
1281                         struct app_pktq_swq_params *swq_params = &app->swq_params[in->id];
1282
1283                         if ((swq_params->ipv4_ras == 0) && (swq_params->ipv6_ras == 0)) {
1284                                 if (app_swq_get_writers(app, swq_params) == 1) {
1285                                         if (app->swq_params[in->id].dropless == 0) {
1286                                                 struct rte_port_ring_writer_params *params =
1287                                                         &out->params.ring;
1288
1289                                                 out->type = PIPELINE_PORT_OUT_RING_WRITER;
1290                                                 params->ring = app->swq[in->id];
1291                                                 params->tx_burst_sz =
1292                                                         app->swq_params[in->id].burst_write;
1293                                         } else {
1294                                                 struct rte_port_ring_writer_nodrop_params
1295                                                         *params = &out->params.ring_nodrop;
1296
1297                                                 out->type =
1298                                                         PIPELINE_PORT_OUT_RING_WRITER_NODROP;
1299                                                 params->ring = app->swq[in->id];
1300                                                 params->tx_burst_sz =
1301                                                         app->swq_params[in->id].burst_write;
1302                                                 params->n_retries =
1303                                                         app->swq_params[in->id].n_retries;
1304                                         }
1305                                 } else {
1306                                         if (swq_params->dropless == 0) {
1307                                                 struct rte_port_ring_multi_writer_params *params =
1308                                                         &out->params.ring_multi;
1309
1310                                                 out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER;
1311                                                 params->ring = app->swq[in->id];
1312                                                 params->tx_burst_sz = swq_params->burst_write;
1313                                         } else {
1314                                                 struct rte_port_ring_multi_writer_nodrop_params
1315                                                         *params = &out->params.ring_multi_nodrop;
1316
1317                                                 out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP;
1318                                                 params->ring = app->swq[in->id];
1319                                                 params->tx_burst_sz = swq_params->burst_write;
1320                                                 params->n_retries = swq_params->n_retries;
1321                                         }
1322                                 }
1323                         } else {
1324                                 if (swq_params->ipv4_ras == 1) {
1325                                         struct rte_port_ring_writer_ipv4_ras_params *params =
1326                                                 &out->params.ring_ipv4_ras;
1327
1328                                         out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS;
1329                                         params->ring = app->swq[in->id];
1330                                         params->tx_burst_sz = swq_params->burst_write;
1331                                 } else {
1332                                         struct rte_port_ring_writer_ipv6_ras_params *params =
1333                                                 &out->params.ring_ipv6_ras;
1334
1335                                         out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS;
1336                                         params->ring = app->swq[in->id];
1337                                         params->tx_burst_sz = swq_params->burst_write;
1338                                 }
1339                         }
1340                         break;
1341                 }
1342                 case APP_PKTQ_OUT_TM: {
1343                         struct rte_port_sched_writer_params *params =
1344                                 &out->params.sched;
1345
1346                         out->type = PIPELINE_PORT_OUT_SCHED_WRITER;
1347                         params->sched = app->tm[in->id];
1348                         params->tx_burst_sz =
1349                                 app->tm_params[in->id].burst_write;
1350                         break;
1351                 }
1352                 case APP_PKTQ_OUT_SINK:
1353                 {
1354                         out->type = PIPELINE_PORT_OUT_SINK;
1355                         out->params.sink.file_name =
1356                                 app->sink_params[in->id].file_name;
1357                         out->params.sink.max_n_pkts =
1358                                 app->sink_params[in->id].
1359                                 n_pkts_to_dump;
1360
1361                         break;
1362                 }
1363                 default:
1364                         break;
1365                 }
1366         }
1367
1368         /* msgq */
1369         p_out->n_msgq = p_in->n_msgq_in;
1370
1371         for (i = 0; i < p_in->n_msgq_in; i++)
1372                 p_out->msgq_in[i] = app->msgq[p_in->msgq_in[i]];
1373
1374         for (i = 0; i < p_in->n_msgq_out; i++)
1375                 p_out->msgq_out[i] = app->msgq[p_in->msgq_out[i]];
1376
1377         /* args */
1378         p_out->n_args = p_in->n_args;
1379         for (i = 0; i < p_in->n_args; i++) {
1380                 p_out->args_name[i] = p_in->args_name[i];
1381                 p_out->args_value[i] = p_in->args_value[i];
1382         }
1383 }
1384
1385 static void
1386 app_init_pipelines(struct app_params *app)
1387 {
1388         uint32_t p_id;
1389
1390         for (p_id = 0; p_id < app->n_pipelines; p_id++) {
1391                 struct app_pipeline_params *params =
1392                         &app->pipeline_params[p_id];
1393                 struct app_pipeline_data *data = &app->pipeline_data[p_id];
1394                 struct pipeline_type *ptype;
1395                 struct pipeline_params pp;
1396
1397                 APP_LOG(app, HIGH, "Initializing %s ...", params->name);
1398
1399                 ptype = app_pipeline_type_find(app, params->type);
1400                 if (ptype == NULL)
1401                         rte_panic("Init error: Unknown pipeline type \"%s\"\n",
1402                                 params->type);
1403
1404                 app_pipeline_params_get(app, params, &pp);
1405
1406                 /* Back-end */
1407                 data->be = NULL;
1408                 if (ptype->be_ops->f_init) {
1409                         data->be = ptype->be_ops->f_init(&pp, (void *) app);
1410
1411                         if (data->be == NULL)
1412                                 rte_panic("Pipeline instance \"%s\" back-end "
1413                                         "init error\n", params->name);
1414                 }
1415
1416                 /* Front-end */
1417                 data->fe = NULL;
1418                 if (ptype->fe_ops->f_init) {
1419                         data->fe = ptype->fe_ops->f_init(&pp, (void *) app);
1420
1421                         if (data->fe == NULL)
1422                                 rte_panic("Pipeline instance \"%s\" front-end "
1423                                 "init error\n", params->name);
1424                 }
1425
1426                 data->ptype = ptype;
1427
1428                 data->timer_period = (rte_get_tsc_hz() *
1429                         params->timer_period) / 100;
1430         }
1431 }
1432
1433 static void
1434 app_init_threads(struct app_params *app)
1435 {
1436         uint64_t time = rte_get_tsc_cycles();
1437         uint32_t p_id;
1438
1439         for (p_id = 0; p_id < app->n_pipelines; p_id++) {
1440                 struct app_pipeline_params *params =
1441                         &app->pipeline_params[p_id];
1442                 struct app_pipeline_data *data = &app->pipeline_data[p_id];
1443                 struct pipeline_type *ptype;
1444                 struct app_thread_data *t;
1445                 struct app_thread_pipeline_data *p;
1446                 int lcore_id;
1447
1448                 lcore_id = cpu_core_map_get_lcore_id(app->core_map,
1449                         params->socket_id,
1450                         params->core_id,
1451                         params->hyper_th_id);
1452
1453                 if (lcore_id < 0)
1454                         rte_panic("Invalid core s%" PRIu32 "c%" PRIu32 "%s\n",
1455                                 params->socket_id,
1456                                 params->core_id,
1457                                 (params->hyper_th_id) ? "h" : "");
1458
1459                 t = &app->thread_data[lcore_id];
1460
1461                 t->timer_period = (rte_get_tsc_hz() * APP_THREAD_TIMER_PERIOD) / 1000;
1462                 t->thread_req_deadline = time + t->timer_period;
1463
1464                 t->headroom_cycles = 0;
1465                 t->headroom_time = rte_get_tsc_cycles();
1466                 t->headroom_ratio = 0.0;
1467
1468                 t->msgq_in = app_thread_msgq_in_get(app,
1469                                 params->socket_id,
1470                                 params->core_id,
1471                                 params->hyper_th_id);
1472                 if (t->msgq_in == NULL)
1473                         rte_panic("Init error: Cannot find MSGQ_IN for thread %" PRId32,
1474                                 lcore_id);
1475
1476                 t->msgq_out = app_thread_msgq_out_get(app,
1477                                 params->socket_id,
1478                                 params->core_id,
1479                                 params->hyper_th_id);
1480                 if (t->msgq_out == NULL)
1481                         rte_panic("Init error: Cannot find MSGQ_OUT for thread %" PRId32,
1482                                 lcore_id);
1483
1484                 ptype = app_pipeline_type_find(app, params->type);
1485                 if (ptype == NULL)
1486                         rte_panic("Init error: Unknown pipeline "
1487                                 "type \"%s\"\n", params->type);
1488
1489                 p = (ptype->be_ops->f_run == NULL) ?
1490                         &t->regular[t->n_regular] :
1491                         &t->custom[t->n_custom];
1492
1493                 p->pipeline_id = p_id;
1494                 p->be = data->be;
1495                 p->f_run = ptype->be_ops->f_run;
1496                 p->f_timer = ptype->be_ops->f_timer;
1497                 p->timer_period = data->timer_period;
1498                 p->deadline = time + data->timer_period;
1499
1500                 data->enabled = 1;
1501
1502                 if (ptype->be_ops->f_run == NULL)
1503                         t->n_regular++;
1504                 else
1505                         t->n_custom++;
1506         }
1507 }
1508
1509 int app_init(struct app_params *app)
1510 {
1511         app_init_core_map(app);
1512         app_init_core_mask(app);
1513
1514         app_init_eal(app);
1515         app_init_mempool(app);
1516         app_init_link(app);
1517         app_init_swq(app);
1518         app_init_tm(app);
1519         app_init_msgq(app);
1520
1521         app_pipeline_common_cmd_push(app);
1522         app_pipeline_thread_cmd_push(app);
1523         app_pipeline_type_register(app, &pipeline_master);
1524         app_pipeline_type_register(app, &pipeline_passthrough);
1525         app_pipeline_type_register(app, &pipeline_flow_classification);
1526         app_pipeline_type_register(app, &pipeline_flow_actions);
1527         app_pipeline_type_register(app, &pipeline_firewall);
1528         app_pipeline_type_register(app, &pipeline_routing);
1529
1530         app_init_pipelines(app);
1531         app_init_threads(app);
1532
1533         return 0;
1534 }
1535
1536 static int
1537 app_pipeline_type_cmd_push(struct app_params *app,
1538         struct pipeline_type *ptype)
1539 {
1540         cmdline_parse_ctx_t *cmds;
1541         uint32_t n_cmds, i;
1542
1543         /* Check input arguments */
1544         if ((app == NULL) ||
1545                 (ptype == NULL))
1546                 return -EINVAL;
1547
1548         n_cmds = pipeline_type_cmds_count(ptype);
1549         if (n_cmds == 0)
1550                 return 0;
1551
1552         cmds = ptype->fe_ops->cmds;
1553
1554         /* Check for available slots in the application commands array */
1555         if (n_cmds > APP_MAX_CMDS - app->n_cmds)
1556                 return -ENOMEM;
1557
1558         /* Push pipeline commands into the application */
1559         memcpy(&app->cmds[app->n_cmds],
1560                 cmds,
1561                 n_cmds * sizeof(cmdline_parse_ctx_t));
1562
1563         for (i = 0; i < n_cmds; i++)
1564                 app->cmds[app->n_cmds + i]->data = app;
1565
1566         app->n_cmds += n_cmds;
1567         app->cmds[app->n_cmds] = NULL;
1568
1569         return 0;
1570 }
1571
1572 int
1573 app_pipeline_type_register(struct app_params *app, struct pipeline_type *ptype)
1574 {
1575         uint32_t n_cmds, i;
1576
1577         /* Check input arguments */
1578         if ((app == NULL) ||
1579                 (ptype == NULL) ||
1580                 (ptype->name == NULL) ||
1581                 (strlen(ptype->name) == 0) ||
1582                 (ptype->be_ops->f_init == NULL) ||
1583                 (ptype->be_ops->f_timer == NULL))
1584                 return -EINVAL;
1585
1586         /* Check for duplicate entry */
1587         for (i = 0; i < app->n_pipeline_types; i++)
1588                 if (strcmp(app->pipeline_type[i].name, ptype->name) == 0)
1589                         return -EEXIST;
1590
1591         /* Check for resource availability */
1592         n_cmds = pipeline_type_cmds_count(ptype);
1593         if ((app->n_pipeline_types == APP_MAX_PIPELINE_TYPES) ||
1594                 (n_cmds > APP_MAX_CMDS - app->n_cmds))
1595                 return -ENOMEM;
1596
1597         /* Copy pipeline type */
1598         memcpy(&app->pipeline_type[app->n_pipeline_types++],
1599                 ptype,
1600                 sizeof(struct pipeline_type));
1601
1602         /* Copy CLI commands */
1603         if (n_cmds)
1604                 app_pipeline_type_cmd_push(app, ptype);
1605
1606         return 0;
1607 }
1608
1609 struct
1610 pipeline_type *app_pipeline_type_find(struct app_params *app, char *name)
1611 {
1612         uint32_t i;
1613
1614         for (i = 0; i < app->n_pipeline_types; i++)
1615                 if (strcmp(app->pipeline_type[i].name, name) == 0)
1616                         return &app->pipeline_type[i];
1617
1618         return NULL;
1619 }