VNFs: Fixing klocwork issue in VNFs code
[samplevnf.git] / VNFs / vCGNAPT / 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 #include <rte_version.h>
28
29 #include "app.h"
30 #include "pipeline.h"
31 #include "pipeline_common_fe.h"
32 #include "pipeline_master.h"
33 #include "thread_fe.h"
34 #include "pipeline_cgnapt.h"
35 #include "pipeline_loadb.h"
36 #include "pipeline_timer.h"
37 #include "pipeline_txrx.h"
38 #include "pipeline_arpicmp.h"
39 #include "interface.h"
40 #include "l3fwd_common.h"
41 #include "l3fwd_lpm4.h"
42 #include "l3fwd_lpm6.h"
43 #include "lib_arp.h"
44
45 #define APP_NAME_SIZE   32
46 port_config_t *port_config;
47
48 static void
49 app_init_core_map(struct app_params *app)
50 {
51         APP_LOG(app, HIGH, "Initializing CPU core map ...");
52         app->core_map = cpu_core_map_init(4, 32, 4, 0);
53
54         if (app->core_map == NULL)
55                 rte_panic("Cannot create CPU core map\n");
56
57         if (app->log_level >= APP_LOG_LEVEL_LOW)
58                 cpu_core_map_print(app->core_map);
59 }
60
61 /* Core Mask String in Hex Representation */
62 #define APP_CORE_MASK_STRING_SIZE ((64 * APP_CORE_MASK_SIZE) / 8 * 2 + 1)
63
64 static void
65 app_init_core_mask(struct app_params *app)
66 {
67         char core_mask_str[APP_CORE_MASK_STRING_SIZE];
68         uint32_t i;
69
70         for (i = 0; i < app->n_pipelines; i++) {
71                 struct app_pipeline_params *p = &app->pipeline_params[i];
72                 int lcore_id;
73
74                 lcore_id = cpu_core_map_get_lcore_id(app->core_map,
75                         p->socket_id,
76                         p->core_id,
77                         p->hyper_th_id);
78                 printf("lcore_id:%d\n", lcore_id);
79
80                 if (lcore_id < 0)
81                         rte_panic("Cannot create CPU core mask\n");
82
83                 app_core_enable_in_core_mask(app, lcore_id);
84         }
85
86         app_core_build_core_mask_string(app, core_mask_str);
87         APP_LOG(app, HIGH, "CPU core mask = 0x%s", core_mask_str);
88
89 }
90
91 static void
92 app_init_eal(struct app_params *app)
93 {
94         char buffer[256];
95         char core_mask_str[APP_CORE_MASK_STRING_SIZE];
96         struct app_eal_params *p = &app->eal_params;
97         uint8_t n_args = 0;
98         uint32_t i;
99         int status;
100
101         if (unlikely (n_args >= APP_EAL_ARGC))
102                 goto error_exit;
103         app->eal_argv[n_args++] = strdup(app->app_name);
104
105         app_core_build_core_mask_string(app, core_mask_str);
106         snprintf(buffer, sizeof(buffer), "-c%s", core_mask_str);
107         if (unlikely (n_args >= APP_EAL_ARGC))
108                 goto error_exit;
109         app->eal_argv[n_args++] = strdup(buffer);
110
111         if (p->coremap) {
112                 snprintf(buffer, sizeof(buffer), "--lcores=%s", p->coremap);
113                 if (unlikely (n_args >= APP_EAL_ARGC))
114                         goto error_exit;
115                 app->eal_argv[n_args++] = strdup(buffer);
116         }
117
118         if (p->master_lcore_present) {
119                 snprintf(buffer,
120                         sizeof(buffer),
121                         "--master-lcore=%" PRIu32,
122                         p->master_lcore);
123                 if (unlikely (n_args >= APP_EAL_ARGC))
124                         goto error_exit;
125                 app->eal_argv[n_args++] = strdup(buffer);
126         }
127
128         snprintf(buffer, sizeof(buffer), "-n%" PRIu32, p->channels);
129         if (unlikely (n_args >= APP_EAL_ARGC))
130                 goto error_exit;
131         app->eal_argv[n_args++] = strdup(buffer);
132
133         if (p->memory_present) {
134                 snprintf(buffer, sizeof(buffer), "-m%" PRIu32, p->memory);
135                 if (unlikely (n_args >= APP_EAL_ARGC))
136                         goto error_exit;
137                 app->eal_argv[n_args++] = strdup(buffer);
138         }
139
140         if (p->ranks_present) {
141                 snprintf(buffer, sizeof(buffer), "-r%" PRIu32, p->ranks);
142                 if (unlikely (n_args >= APP_EAL_ARGC))
143                         goto error_exit;
144                 app->eal_argv[n_args++] = strdup(buffer);
145         }
146
147         for (i = 0; i < APP_MAX_LINKS; i++) {
148                 if (p->pci_blacklist[i] == NULL)
149                         break;
150
151                 snprintf(buffer,
152                         sizeof(buffer),
153                         "--pci-blacklist=%s",
154                         p->pci_blacklist[i]);
155                 if (unlikely (n_args >= APP_EAL_ARGC))
156                         goto error_exit;
157                 app->eal_argv[n_args++] = strdup(buffer);
158         }
159
160         if (app->port_mask != 0)
161                 for (i = 0; i < APP_MAX_LINKS; i++) {
162                         if (p->pci_whitelist[i] == NULL)
163                                 break;
164
165                         snprintf(buffer,
166                                 sizeof(buffer),
167                                 "--pci-whitelist=%s",
168                                 p->pci_whitelist[i]);
169                         if (unlikely (n_args >= APP_EAL_ARGC))
170                                 goto error_exit;
171                         if (n_args < 255)
172                                 app->eal_argv[n_args++] = strdup(buffer);
173                 }
174         else
175                 for (i = 0; i < app->n_links; i++) {
176                         char *pci_bdf = app->link_params[i].pci_bdf;
177
178                         snprintf(buffer,
179                                 sizeof(buffer),
180                                 "--pci-whitelist=%s",
181                                 pci_bdf);
182                         if (unlikely (n_args >= APP_EAL_ARGC))
183                                 goto error_exit;
184                         app->eal_argv[n_args++] = strdup(buffer);
185                 }
186
187         for (i = 0; i < APP_MAX_LINKS; i++) {
188                 if (p->vdev[i] == NULL)
189                         break;
190
191                 snprintf(buffer,
192                         sizeof(buffer),
193                         "--vdev=%s",
194                         p->vdev[i]);
195                 if (unlikely (n_args >= APP_EAL_ARGC))
196                         goto error_exit;
197                 app->eal_argv[n_args++] = strdup(buffer);
198         }
199
200         if ((p->vmware_tsc_map_present) && p->vmware_tsc_map) {
201                 snprintf(buffer, sizeof(buffer), "--vmware-tsc-map");
202                 if (unlikely (n_args >= APP_EAL_ARGC))
203                         goto error_exit;
204                 app->eal_argv[n_args++] = strdup(buffer);
205         }
206
207         if (p->proc_type) {
208                 snprintf(buffer,
209                         sizeof(buffer),
210                         "--proc-type=%s",
211                         p->proc_type);
212                 if (unlikely (n_args >= APP_EAL_ARGC))
213                         goto error_exit;
214                 app->eal_argv[n_args++] = strdup(buffer);
215         }
216
217         if (p->syslog) {
218                 snprintf(buffer, sizeof(buffer), "--syslog=%s", p->syslog);
219                 if (unlikely (n_args >= APP_EAL_ARGC))
220                         goto error_exit;
221                 app->eal_argv[n_args++] = strdup(buffer);
222         }
223
224         if (p->log_level_present) {
225                 snprintf(buffer,
226                         sizeof(buffer),
227                         "--log-level=%" PRIu32,
228                         p->log_level);
229                 if (unlikely (n_args >= APP_EAL_ARGC))
230                         goto error_exit;
231                 app->eal_argv[n_args++] = strdup(buffer);
232         }
233
234         if ((p->version_present) && p->version) {
235                 snprintf(buffer, sizeof(buffer), "-v");
236                 if (unlikely (n_args >= APP_EAL_ARGC))
237                         goto error_exit;
238                 app->eal_argv[n_args++] = strdup(buffer);
239         }
240
241         if ((p->help_present) && p->help) {
242                 snprintf(buffer, sizeof(buffer), "--help");
243                 if (unlikely (n_args >= APP_EAL_ARGC))
244                         goto error_exit;
245                 app->eal_argv[n_args++] = strdup(buffer);
246         }
247
248         if ((p->no_huge_present) && p->no_huge) {
249                 snprintf(buffer, sizeof(buffer), "--no-huge");
250                 if (unlikely (n_args >= APP_EAL_ARGC))
251                         goto error_exit;
252                 app->eal_argv[n_args++] = strdup(buffer);
253         }
254
255         if ((p->no_pci_present) && p->no_pci) {
256                 snprintf(buffer, sizeof(buffer), "--no-pci");
257                 if (unlikely (n_args >= APP_EAL_ARGC))
258                         goto error_exit;
259                 app->eal_argv[n_args++] = strdup(buffer);
260         }
261
262         if ((p->no_hpet_present) && p->no_hpet) {
263                 snprintf(buffer, sizeof(buffer), "--no-hpet");
264                 if (unlikely (n_args >= APP_EAL_ARGC))
265                         goto error_exit;
266                 app->eal_argv[n_args++] = strdup(buffer);
267         }
268
269         if ((p->no_shconf_present) && p->no_shconf) {
270                 snprintf(buffer, sizeof(buffer), "--no-shconf");
271                 if (unlikely (n_args >= APP_EAL_ARGC))
272                         goto error_exit;
273                 app->eal_argv[n_args++] = strdup(buffer);
274         }
275
276         if (p->add_driver) {
277                 snprintf(buffer, sizeof(buffer), "-d=%s", p->add_driver);
278                 if (unlikely (n_args >= APP_EAL_ARGC))
279                         goto error_exit;
280                 app->eal_argv[n_args++] = strdup(buffer);
281         }
282
283         if (p->socket_mem) {
284                 snprintf(buffer,
285                         sizeof(buffer),
286                         "--socket-mem=%s",
287                         p->socket_mem);
288                 if (unlikely (n_args >= APP_EAL_ARGC))
289                         goto error_exit;
290                 app->eal_argv[n_args++] = strdup(buffer);
291         }
292
293         if (p->huge_dir) {
294                 snprintf(buffer, sizeof(buffer), "--huge-dir=%s", p->huge_dir);
295                 if (unlikely (n_args >= APP_EAL_ARGC))
296                         goto error_exit;
297                 app->eal_argv[n_args++] = strdup(buffer);
298         }
299
300         if (p->file_prefix) {
301                 snprintf(buffer,
302                         sizeof(buffer),
303                         "--file-prefix=%s",
304                         p->file_prefix);
305                 if (unlikely (n_args >= APP_EAL_ARGC))
306                         goto error_exit;
307                 app->eal_argv[n_args++] = strdup(buffer);
308         }
309
310         if (p->base_virtaddr) {
311                 snprintf(buffer,
312                         sizeof(buffer),
313                         "--base-virtaddr=%s",
314                         p->base_virtaddr);
315                 if (unlikely (n_args >= APP_EAL_ARGC))
316                         goto error_exit;
317                 app->eal_argv[n_args++] = strdup(buffer);
318         }
319
320         if ((p->create_uio_dev_present) && p->create_uio_dev) {
321                 snprintf(buffer, sizeof(buffer), "--create-uio-dev");
322                 if (unlikely (n_args >= APP_EAL_ARGC))
323                         goto error_exit;
324                 app->eal_argv[n_args++] = strdup(buffer);
325         }
326
327         if (p->vfio_intr) {
328                 snprintf(buffer,
329                         sizeof(buffer),
330                         "--vfio-intr=%s",
331                         p->vfio_intr);
332                 if (unlikely (n_args >= APP_EAL_ARGC))
333                         goto error_exit;
334                 app->eal_argv[n_args++] = strdup(buffer);
335         }
336
337         if ((p->xen_dom0_present) && (p->xen_dom0)) {
338                 snprintf(buffer, sizeof(buffer), "--xen-dom0");
339                 if (unlikely (n_args >= APP_EAL_ARGC))
340                         goto error_exit;
341                 app->eal_argv[n_args++] = strdup(buffer);
342         }
343
344         snprintf(buffer, sizeof(buffer), "--");
345         if (unlikely (n_args >= APP_EAL_ARGC))
346                 goto error_exit;
347         app->eal_argv[n_args++] = strdup(buffer);
348
349         app->eal_argc = n_args;
350
351         APP_LOG(app, HIGH, "Initializing EAL ...");
352         if (app->log_level >= APP_LOG_LEVEL_LOW) {
353                 int i;
354
355                 fprintf(stdout, "[APP] EAL arguments: \"");
356                 for (i = 1; i < app->eal_argc; i++)
357                         fprintf(stdout, "%s ", app->eal_argv[i]);
358                 fprintf(stdout, "\"\n");
359         }
360
361         status = rte_eal_init(app->eal_argc, app->eal_argv);
362         if (status < 0) {
363 error_exit:
364                 rte_panic("EAL init error\n");
365         }
366 }
367 #if 0
368 static void
369 app_init_mempool(struct app_params *app)
370 {
371         uint32_t i;
372
373         for (i = 0; i < app->n_mempools; i++) {
374                 struct app_mempool_params *p = &app->mempool_params[i];
375
376                 APP_LOG(app, HIGH, "Initializing %s ...", p->name);
377                 app->mempool[i] = rte_mempool_create(
378                                 p->name,
379                                 p->pool_size,
380                                 p->buffer_size,
381                                 p->cache_size,
382                                 sizeof(struct rte_pktmbuf_pool_private),
383                                 rte_pktmbuf_pool_init, NULL,
384                                 rte_pktmbuf_init, NULL,
385                                 p->cpu_socket_id,
386                                 0);
387
388                 if (app->mempool[i] == NULL)
389                         rte_panic("%s init error\n", p->name);
390         }
391 }
392 #endif
393 static inline int
394 app_link_filter_arp_add(struct app_link_params *link)
395 {
396         struct rte_eth_ethertype_filter filter = {
397                 .ether_type = ETHER_TYPE_ARP,
398                 .flags = 0,
399                 .queue = link->arp_q,
400         };
401
402         return rte_eth_dev_filter_ctrl(link->pmd_id,
403                 RTE_ETH_FILTER_ETHERTYPE,
404                 RTE_ETH_FILTER_ADD,
405                 &filter);
406 }
407
408 static inline int
409 app_link_filter_tcp_syn_add(struct app_link_params *link)
410 {
411         struct rte_eth_syn_filter filter = {
412                 .hig_pri = 1,
413                 .queue = link->tcp_syn_q,
414         };
415
416         return rte_eth_dev_filter_ctrl(link->pmd_id,
417                 RTE_ETH_FILTER_SYN,
418                 RTE_ETH_FILTER_ADD,
419                 &filter);
420 }
421
422 static inline int
423 app_link_filter_ip_add(struct app_link_params *l1, struct app_link_params *l2)
424 {
425         struct rte_eth_ntuple_filter filter = {
426                 .flags = RTE_5TUPLE_FLAGS,
427                 .dst_ip = rte_bswap32(l2->ip),
428                 .dst_ip_mask = UINT32_MAX, /* Enable */
429                 .src_ip = 0,
430                 .src_ip_mask = 0, /* Disable */
431                 .dst_port = 0,
432                 .dst_port_mask = 0, /* Disable */
433                 .src_port = 0,
434                 .src_port_mask = 0, /* Disable */
435                 .proto = 0,
436                 .proto_mask = 0, /* Disable */
437                 .tcp_flags = 0,
438                 .priority = 1, /* Lowest */
439                 .queue = l1->ip_local_q,
440         };
441
442         return rte_eth_dev_filter_ctrl(l1->pmd_id,
443                 RTE_ETH_FILTER_NTUPLE,
444                 RTE_ETH_FILTER_ADD,
445                 &filter);
446 }
447
448 static inline int
449 app_link_filter_ip_del(struct app_link_params *l1, struct app_link_params *l2)
450 {
451         struct rte_eth_ntuple_filter filter = {
452                 .flags = RTE_5TUPLE_FLAGS,
453                 .dst_ip = rte_bswap32(l2->ip),
454                 .dst_ip_mask = UINT32_MAX, /* Enable */
455                 .src_ip = 0,
456                 .src_ip_mask = 0, /* Disable */
457                 .dst_port = 0,
458                 .dst_port_mask = 0, /* Disable */
459                 .src_port = 0,
460                 .src_port_mask = 0, /* Disable */
461                 .proto = 0,
462                 .proto_mask = 0, /* Disable */
463                 .tcp_flags = 0,
464                 .priority = 1, /* Lowest */
465                 .queue = l1->ip_local_q,
466         };
467
468         return rte_eth_dev_filter_ctrl(l1->pmd_id,
469                 RTE_ETH_FILTER_NTUPLE,
470                 RTE_ETH_FILTER_DELETE,
471                 &filter);
472 }
473
474 static inline int
475 app_link_filter_tcp_add(struct app_link_params *l1, struct app_link_params *l2)
476 {
477         struct rte_eth_ntuple_filter filter = {
478                 .flags = RTE_5TUPLE_FLAGS,
479                 .dst_ip = rte_bswap32(l2->ip),
480                 .dst_ip_mask = UINT32_MAX, /* Enable */
481                 .src_ip = 0,
482                 .src_ip_mask = 0, /* Disable */
483                 .dst_port = 0,
484                 .dst_port_mask = 0, /* Disable */
485                 .src_port = 0,
486                 .src_port_mask = 0, /* Disable */
487                 .proto = IPPROTO_TCP,
488                 .proto_mask = UINT8_MAX, /* Enable */
489                 .tcp_flags = 0,
490                 .priority = 2, /* Higher priority than IP */
491                 .queue = l1->tcp_local_q,
492         };
493
494         return rte_eth_dev_filter_ctrl(l1->pmd_id,
495                 RTE_ETH_FILTER_NTUPLE,
496                 RTE_ETH_FILTER_ADD,
497                 &filter);
498 }
499
500 static inline int
501 app_link_filter_tcp_del(struct app_link_params *l1, struct app_link_params *l2)
502 {
503         struct rte_eth_ntuple_filter filter = {
504                 .flags = RTE_5TUPLE_FLAGS,
505                 .dst_ip = rte_bswap32(l2->ip),
506                 .dst_ip_mask = UINT32_MAX, /* Enable */
507                 .src_ip = 0,
508                 .src_ip_mask = 0, /* Disable */
509                 .dst_port = 0,
510                 .dst_port_mask = 0, /* Disable */
511                 .src_port = 0,
512                 .src_port_mask = 0, /* Disable */
513                 .proto = IPPROTO_TCP,
514                 .proto_mask = UINT8_MAX, /* Enable */
515                 .tcp_flags = 0,
516                 .priority = 2, /* Higher priority than IP */
517                 .queue = l1->tcp_local_q,
518         };
519
520         return rte_eth_dev_filter_ctrl(l1->pmd_id,
521                 RTE_ETH_FILTER_NTUPLE,
522                 RTE_ETH_FILTER_DELETE,
523                 &filter);
524 }
525
526 static inline int
527 app_link_filter_udp_add(struct app_link_params *l1, struct app_link_params *l2)
528 {
529         struct rte_eth_ntuple_filter filter = {
530                 .flags = RTE_5TUPLE_FLAGS,
531                 .dst_ip = rte_bswap32(l2->ip),
532                 .dst_ip_mask = UINT32_MAX, /* Enable */
533                 .src_ip = 0,
534                 .src_ip_mask = 0, /* Disable */
535                 .dst_port = 0,
536                 .dst_port_mask = 0, /* Disable */
537                 .src_port = 0,
538                 .src_port_mask = 0, /* Disable */
539                 .proto = IPPROTO_UDP,
540                 .proto_mask = UINT8_MAX, /* Enable */
541                 .tcp_flags = 0,
542                 .priority = 2, /* Higher priority than IP */
543                 .queue = l1->udp_local_q,
544         };
545
546         return rte_eth_dev_filter_ctrl(l1->pmd_id,
547                 RTE_ETH_FILTER_NTUPLE,
548                 RTE_ETH_FILTER_ADD,
549                 &filter);
550 }
551
552 static inline int
553 app_link_filter_udp_del(struct app_link_params *l1, struct app_link_params *l2)
554 {
555         struct rte_eth_ntuple_filter filter = {
556                 .flags = RTE_5TUPLE_FLAGS,
557                 .dst_ip = rte_bswap32(l2->ip),
558                 .dst_ip_mask = UINT32_MAX, /* Enable */
559                 .src_ip = 0,
560                 .src_ip_mask = 0, /* Disable */
561                 .dst_port = 0,
562                 .dst_port_mask = 0, /* Disable */
563                 .src_port = 0,
564                 .src_port_mask = 0, /* Disable */
565                 .proto = IPPROTO_UDP,
566                 .proto_mask = UINT8_MAX, /* Enable */
567                 .tcp_flags = 0,
568                 .priority = 2, /* Higher priority than IP */
569                 .queue = l1->udp_local_q,
570         };
571
572         return rte_eth_dev_filter_ctrl(l1->pmd_id,
573                 RTE_ETH_FILTER_NTUPLE,
574                 RTE_ETH_FILTER_DELETE,
575                 &filter);
576 }
577
578 static inline int
579 app_link_filter_sctp_add(struct app_link_params *l1, struct app_link_params *l2)
580 {
581         struct rte_eth_ntuple_filter filter = {
582                 .flags = RTE_5TUPLE_FLAGS,
583                 .dst_ip = rte_bswap32(l2->ip),
584                 .dst_ip_mask = UINT32_MAX, /* Enable */
585                 .src_ip = 0,
586                 .src_ip_mask = 0, /* Disable */
587                 .dst_port = 0,
588                 .dst_port_mask = 0, /* Disable */
589                 .src_port = 0,
590                 .src_port_mask = 0, /* Disable */
591                 .proto = IPPROTO_SCTP,
592                 .proto_mask = UINT8_MAX, /* Enable */
593                 .tcp_flags = 0,
594                 .priority = 2, /* Higher priority than IP */
595                 .queue = l1->sctp_local_q,
596         };
597
598         return rte_eth_dev_filter_ctrl(l1->pmd_id,
599                 RTE_ETH_FILTER_NTUPLE,
600                 RTE_ETH_FILTER_ADD,
601                 &filter);
602 }
603
604 static inline int
605 app_link_filter_sctp_del(struct app_link_params *l1, struct app_link_params *l2)
606 {
607         struct rte_eth_ntuple_filter filter = {
608                 .flags = RTE_5TUPLE_FLAGS,
609                 .dst_ip = rte_bswap32(l2->ip),
610                 .dst_ip_mask = UINT32_MAX, /* Enable */
611                 .src_ip = 0,
612                 .src_ip_mask = 0, /* Disable */
613                 .dst_port = 0,
614                 .dst_port_mask = 0, /* Disable */
615                 .src_port = 0,
616                 .src_port_mask = 0, /* Disable */
617                 .proto = IPPROTO_SCTP,
618                 .proto_mask = UINT8_MAX, /* Enable */
619                 .tcp_flags = 0,
620                 .priority = 2, /* Higher priority than IP */
621                 .queue = l1->sctp_local_q,
622         };
623
624         return rte_eth_dev_filter_ctrl(l1->pmd_id,
625                 RTE_ETH_FILTER_NTUPLE,
626                 RTE_ETH_FILTER_DELETE,
627                 &filter);
628 }
629 #if 0
630 static void
631 app_link_set_arp_filter(struct app_params *app, struct app_link_params *cp)
632 {
633         if (cp->arp_q != 0) {
634                 int status = app_link_filter_arp_add(cp);
635
636                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
637                         "Adding ARP filter (queue = %" PRIu32 ")",
638                         cp->name, cp->pmd_id, cp->arp_q);
639
640                 if (status)
641                         rte_panic("%s (%" PRIu32 "): "
642                                 "Error adding ARP filter "
643                                 "(queue = %" PRIu32 ") (%" PRId32 ")\n",
644                                 cp->name, cp->pmd_id, cp->arp_q, status);
645         }
646 }
647
648 static void
649 app_link_set_tcp_syn_filter(struct app_params *app, struct app_link_params *cp)
650 {
651         if (cp->tcp_syn_q != 0) {
652                 int status = app_link_filter_tcp_syn_add(cp);
653
654                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
655                         "Adding TCP SYN filter (queue = %" PRIu32 ")",
656                         cp->name, cp->pmd_id, cp->tcp_syn_q);
657
658                 if (status)
659                         rte_panic("%s (%" PRIu32 "): "
660                                 "Error adding TCP SYN filter "
661                                 "(queue = %" PRIu32 ") (%" PRId32 ")\n",
662                                 cp->name, cp->pmd_id, cp->tcp_syn_q,
663                                 status);
664         }
665 }
666
667 /* rte_eth_dev is removed in DPDK version 16.11 and onwards */
668 #if RTE_VERSION < 0x100b0000
669 static int
670 app_link_is_virtual(__rte_unused struct app_link_params *p)
671 {
672         uint32_t pmd_id = p->pmd_id;
673         struct rte_eth_dev *dev = &rte_eth_devices[pmd_id];
674         if (dev->dev_type == RTE_ETH_DEV_VIRTUAL)
675                 return 1;
676         return 0;
677 }
678 #endif
679
680 #endif
681
682 void
683 app_link_up_internal(__rte_unused struct app_params *app, struct app_link_params *cp)
684 {
685 #if 0
686         uint32_t i;
687         int status;
688         struct rte_eth_link link;
689
690 #if RTE_VERSION < 0x100b0000
691         if (app_link_is_virtual(cp)) {
692                 cp->state = 1;
693                 return;
694         }
695 #endif
696
697         /* For each link, add filters for IP of current link */
698         if (cp->ip != 0) {
699                 for (i = 0; i < app->n_links; i++) {
700                         struct app_link_params *p = &app->link_params[i];
701
702                         /* IP */
703                         if (p->ip_local_q != 0) {
704                                 int status = app_link_filter_ip_add(p, cp);
705
706                                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
707                                         "Adding IP filter (queue= %" PRIu32
708                                         ", IP = 0x%08" PRIx32 ")",
709                                         p->name, p->pmd_id, p->ip_local_q,
710                                         cp->ip);
711
712                                 if (status)
713                                         rte_panic("%s (%" PRIu32 "): "
714                                                 "Error adding IP "
715                                                 "filter (queue= %" PRIu32 ", "
716                                                 "IP = 0x%08" PRIx32
717                                                 ") (%" PRId32 ")\n",
718                                                 p->name, p->pmd_id,
719                                                 p->ip_local_q, cp->ip, status);
720                         }
721
722                         /* TCP */
723                         if (p->tcp_local_q != 0) {
724                                 int status = app_link_filter_tcp_add(p, cp);
725
726                                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
727                                         "Adding TCP filter "
728                                         "(queue = %" PRIu32
729                                         ", IP = 0x%08" PRIx32 ")",
730                                         p->name, p->pmd_id, p->tcp_local_q,
731                                         cp->ip);
732
733                                 if (status)
734                                         rte_panic("%s (%" PRIu32 "): "
735                                                 "Error adding TCP "
736                                                 "filter (queue = %" PRIu32 ", "
737                                                 "IP = 0x%08" PRIx32
738                                                 ") (%" PRId32 ")\n",
739                                                 p->name, p->pmd_id,
740                                                 p->tcp_local_q, cp->ip, status);
741                         }
742
743                         /* UDP */
744                         if (p->udp_local_q != 0) {
745                                 int status = app_link_filter_udp_add(p, cp);
746
747                                 APP_LOG(app, LOW, "%s (%" PRIu32 "): "
748                                         "Adding UDP filter "
749                                         "(queue = %" PRIu32
750                                         ", IP = 0x%08" PRIx32 ")",
751                                         p->name, p->pmd_id, p->udp_local_q,
752                                         cp->ip);
753
754                                 if (status)
755                                         rte_panic("%s (%" PRIu32 "): "
756                                                 "Error adding UDP "
757                                                 "filter (queue = %" PRIu32 ", "
758                                                 "IP = 0x%08" PRIx32
759                                                 ") (%" PRId32 ")\n",
760                                                 p->name, p->pmd_id,
761                                                 p->udp_local_q, cp->ip, status);
762                         }
763
764                         /* SCTP */
765                         if (p->sctp_local_q != 0) {
766                                 int status = app_link_filter_sctp_add(p, cp);
767
768                                 APP_LOG(app, LOW, "%s (%" PRIu32
769                                         "): Adding SCTP filter "
770                                         "(queue = %" PRIu32
771                                         ", IP = 0x%08" PRIx32 ")",
772                                         p->name, p->pmd_id, p->sctp_local_q,
773                                         cp->ip);
774
775                                 if (status)
776                                         rte_panic("%s (%" PRIu32 "): "
777                                                 "Error adding SCTP "
778                                                 "filter (queue = %" PRIu32 ", "
779                                                 "IP = 0x%08" PRIx32
780                                                 ") (%" PRId32 ")\n",
781                                                 p->name, p->pmd_id,
782                                                 p->sctp_local_q, cp->ip,
783                                                 status);
784                         }
785                 }
786         }
787
788         rte_eth_link_get(cp->pmd_id, &link);
789         if (!link.link_status) {
790                 /* PMD link up */
791                 status = rte_eth_dev_set_link_up(cp->pmd_id);
792                 if (status < 0)
793                         rte_panic("%s (%" PRIu32 "): PMD set link up error %"
794                                 PRId32 "\n", cp->name, cp->pmd_id, status);
795         }
796 #endif
797         ifm_update_linkstatus(cp->pmd_id, IFM_ETH_LINK_UP);
798
799         /* Mark link as UP */
800         cp->state = 1;
801 }
802
803 void
804 app_link_down_internal(__rte_unused struct app_params *app, struct app_link_params *cp)
805 {
806 #if 0
807         uint32_t i;
808         int status;
809         struct rte_eth_link link;
810
811 #if RTE_VERSION < 0x100b0000
812         if (app_link_is_virtual(cp)) {
813                 cp->state = 0;
814                 return;
815         }
816 #endif
817
818         rte_eth_link_get(cp->pmd_id, &link);
819         if (link.link_status) {
820                 /* PMD link down */
821                 status = rte_eth_dev_set_link_down(cp->pmd_id);
822                 if (status < 0)
823                         rte_panic("%s (%" PRIu32 "): PMD set link down error %"
824                                 PRId32 "\n", cp->name, cp->pmd_id, status);
825         }
826 #endif
827         ifm_update_linkstatus(cp->pmd_id, IFM_ETH_LINK_DOWN);
828         /* Mark link as DOWN */
829         cp->state = 0;
830
831         /* Return if current link IP is not valid */
832         if (cp->ip == 0)
833                 return;
834 #if 0
835         /* For each link, remove filters for IP of current link */
836         for (i = 0; i < app->n_links; i++) {
837                 struct app_link_params *p = &app->link_params[i];
838
839                 /* IP */
840                 if (p->ip_local_q != 0) {
841                         int status = app_link_filter_ip_del(p, cp);
842
843                         APP_LOG(app, LOW, "%s (%" PRIu32
844                                 "): Deleting IP filter "
845                                 "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")",
846                                 p->name, p->pmd_id, p->ip_local_q, cp->ip);
847
848                         if (status)
849                                 rte_panic("%s (%" PRIu32
850                                         "): Error deleting IP filter "
851                                         "(queue = %" PRIu32
852                                         ", IP = 0x%" PRIx32
853                                         ") (%" PRId32 ")\n",
854                                         p->name, p->pmd_id, p->ip_local_q,
855                                         cp->ip, status);
856                 }
857
858                 /* TCP */
859                 if (p->tcp_local_q != 0) {
860                         int status = app_link_filter_tcp_del(p, cp);
861
862                         APP_LOG(app, LOW, "%s (%" PRIu32
863                                 "): Deleting TCP filter "
864                                 "(queue = %" PRIu32
865                                 ", IP = 0x%" PRIx32 ")",
866                                 p->name, p->pmd_id, p->tcp_local_q, cp->ip);
867
868                         if (status)
869                                 rte_panic("%s (%" PRIu32
870                                         "): Error deleting TCP filter "
871                                         "(queue = %" PRIu32
872                                         ", IP = 0x%" PRIx32
873                                         ") (%" PRId32 ")\n",
874                                         p->name, p->pmd_id, p->tcp_local_q,
875                                         cp->ip, status);
876                 }
877
878                 /* UDP */
879                 if (p->udp_local_q != 0) {
880                         int status = app_link_filter_udp_del(p, cp);
881
882                         APP_LOG(app, LOW, "%s (%" PRIu32
883                                 "): Deleting UDP filter "
884                                 "(queue = %" PRIu32 ", IP = 0x%" PRIx32 ")",
885                                 p->name, p->pmd_id, p->udp_local_q, cp->ip);
886
887                         if (status)
888                                 rte_panic("%s (%" PRIu32
889                                         "): Error deleting UDP filter "
890                                         "(queue = %" PRIu32
891                                         ", IP = 0x%" PRIx32
892                                         ") (%" PRId32 ")\n",
893                                         p->name, p->pmd_id, p->udp_local_q,
894                                         cp->ip, status);
895                 }
896
897                 /* SCTP */
898                 if (p->sctp_local_q != 0) {
899                         int status = app_link_filter_sctp_del(p, cp);
900
901                         APP_LOG(app, LOW, "%s (%" PRIu32
902                                 "): Deleting SCTP filter "
903                                 "(queue = %" PRIu32
904                                 ", IP = 0x%" PRIx32 ")",
905                                 p->name, p->pmd_id, p->sctp_local_q, cp->ip);
906
907                         if (status)
908                                 rte_panic("%s (%" PRIu32
909                                         "): Error deleting SCTP filter "
910                                         "(queue = %" PRIu32
911                                         ", IP = 0x%" PRIx32
912                                         ") (%" PRId32 ")\n",
913                                         p->name, p->pmd_id, p->sctp_local_q,
914                                         cp->ip, status);
915                 }
916         }
917 #endif
918 }
919
920 static void
921 app_check_link(struct app_params *app)
922 {
923         uint32_t all_links_up, i;
924
925         all_links_up = 1;
926
927         for (i = 0; i < app->n_links; i++) {
928                 struct app_link_params *p = &app->link_params[i];
929                 struct rte_eth_link link_params;
930
931                 memset(&link_params, 0, sizeof(link_params));
932                 rte_eth_link_get(p->pmd_id, &link_params);
933
934                 APP_LOG(app, HIGH, "%s (%" PRIu32 ") (%" PRIu32 " Gbps) %s",
935                         p->name,
936                         p->pmd_id,
937                         link_params.link_speed / 1000,
938                         link_params.link_status ? "UP" : "DOWN");
939
940                 if (link_params.link_status == ETH_LINK_DOWN)
941                         all_links_up = 0;
942         }
943
944         if (all_links_up == 0)
945                 rte_panic("Some links are DOWN\n");
946 }
947
948 static uint32_t
949 is_any_swq_frag_or_ras(struct app_params *app)
950 {
951         uint32_t i;
952
953         for (i = 0; i < app->n_pktq_swq; i++) {
954                 struct app_pktq_swq_params *p = &app->swq_params[i];
955
956                 if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1) ||
957                         (p->ipv4_ras == 1) || (p->ipv6_ras == 1))
958                         return 1;
959         }
960
961         return 0;
962 }
963
964 static void
965 app_init_link_frag_ras(struct app_params *app)
966 {
967         uint32_t i;
968
969         if (is_any_swq_frag_or_ras(app)) {
970                 for (i = 0; i < app->n_pktq_hwq_out; i++) {
971                         struct app_pktq_hwq_out_params *p_txq =
972                                 &app->hwq_out_params[i];
973
974                         p_txq->conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;
975                 }
976         }
977 }
978
979 static inline int
980 app_get_cpu_socket_id(uint32_t pmd_id)
981 {
982         int status = rte_eth_dev_socket_id(pmd_id);
983
984         return (status != SOCKET_ID_ANY) ? status : 0;
985 }
986
987 struct rte_eth_rxmode rx_mode = {
988         .max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */
989         .split_hdr_size = 0,
990         .header_split   = 0, /**< Header Split disabled. */
991         .hw_ip_checksum = 0, /**< IP checksum offload disabled. */
992         .hw_vlan_filter = 1, /**< VLAN filtering enabled. */
993         .hw_vlan_strip  = 1, /**< VLAN strip enabled. */
994         .hw_vlan_extend = 0, /**< Extended VLAN disabled. */
995         .jumbo_frame    = 0, /**< Jumbo Frame Support disabled. */
996         .hw_strip_crc   = 0, /**< CRC stripping by hardware disabled. */
997 };
998 struct rte_fdir_conf fdir_conf = {
999         .mode = RTE_FDIR_MODE_NONE,
1000         .pballoc = RTE_FDIR_PBALLOC_64K,
1001         .status = RTE_FDIR_REPORT_STATUS,
1002         .mask = {
1003                 .vlan_tci_mask = 0x0,
1004                 .ipv4_mask     = {
1005                 .src_ip = 0xFFFFFFFF,
1006                 .dst_ip = 0xFFFFFFFF,
1007         },
1008         .ipv6_mask     = {
1009                 .src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
1010                 .dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
1011         },
1012         .src_port_mask = 0xFFFF,
1013         .dst_port_mask = 0xFFFF,
1014         .mac_addr_byte_mask = 0xFF,
1015         .tunnel_type_mask = 1,
1016         .tunnel_id_mask = 0xFFFFFFFF,
1017         },
1018         .drop_queue = 127,
1019 };
1020
1021 static void
1022 app_init_link(struct app_params *app)
1023 {
1024         uint32_t i, size;
1025
1026         app_init_link_frag_ras(app);
1027
1028         /*
1029          *Configuring port_config_t structure for interface manager initialization
1030          */
1031         size = RTE_CACHE_LINE_ROUNDUP(sizeof(port_config_t));
1032         port_config = rte_zmalloc(NULL, (app->n_links * size), RTE_CACHE_LINE_SIZE);
1033         if (port_config == NULL)
1034                 rte_panic("port_config is NULL: Memory Allocation failure\n");
1035
1036         for (i = 0; i < app->n_links; i++) {
1037                 struct app_link_params *p_link = &app->link_params[i];
1038                 uint32_t link_id, n_hwq_in, n_hwq_out;
1039                 int status;
1040
1041                 status = sscanf(p_link->name, "LINK%" PRIu32, &link_id);
1042                 if (status < 0)
1043                         rte_panic("%s (%" PRId32 "): "
1044                                 "init error (%" PRId32 ")\n",
1045                                 p_link->name, link_id, status);
1046
1047                 n_hwq_in = app_link_get_n_rxq(app, p_link);
1048                 n_hwq_out = app_link_get_n_txq(app, p_link);
1049
1050                 printf("\n\nn_hwq_in %d\n", n_hwq_in);
1051                 struct rte_eth_conf *My_local_conf = &p_link->conf;
1052                 if(enable_hwlb)
1053                 {
1054                         My_local_conf->rxmode = rx_mode;
1055                         My_local_conf->fdir_conf = fdir_conf;
1056                         My_local_conf->rxmode.mq_mode = ETH_MQ_RX_RSS;
1057                         My_local_conf->rx_adv_conf.rss_conf.rss_key = NULL;
1058                         My_local_conf->rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IP | ETH_RSS_UDP | ETH_RSS_TCP;
1059                         /* pkt-filter-mode is perfect */
1060                         My_local_conf->fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
1061                 } else {
1062                         /* disable-rss */
1063                         My_local_conf->rx_adv_conf.rss_conf.rss_hf = 0;
1064                 }
1065
1066                 /* Set the hardware CRC stripping to avoid double stripping of FCS in VM */
1067                 p_link->conf.rxmode.hw_strip_crc=1;
1068
1069                 APP_LOG(app, HIGH, "Initializing %s (%" PRIu32") "
1070                         "(%" PRIu32 " RXQ, %" PRIu32 " TXQ) ...",
1071                         p_link->name,
1072                         p_link->pmd_id,
1073                         n_hwq_in,
1074                         n_hwq_out);
1075
1076                 port_config[i].port_id = p_link->pmd_id;
1077                 port_config[i].nrx_queue = n_hwq_in;
1078                 port_config[i].ntx_queue = n_hwq_out;
1079                 port_config[i].state = 1;
1080                 port_config[i].promisc = p_link->promisc;
1081                 port_config[i].mempool.pool_size = app->mempool_params[0].pool_size;
1082                 port_config[i].mempool.buffer_size = app->mempool_params[0].buffer_size;
1083                 port_config[i].mempool.cache_size = app->mempool_params[0].cache_size;
1084                 port_config[i].mempool.cpu_socket_id = app->mempool_params[0].cpu_socket_id;
1085                 memcpy (&port_config[i].port_conf, &p_link->conf, sizeof(struct rte_eth_conf));
1086                 memcpy (&port_config[i].rx_conf, &app->hwq_in_params[0].conf, sizeof(struct rte_eth_rxconf));
1087                 memcpy (&port_config[i].tx_conf, &app->hwq_out_params[0].conf, sizeof(struct rte_eth_txconf));
1088
1089                 if(app->header_csum_req) {
1090                         /* Enable TCP and UDP HW Checksum */
1091                         port_config[i].tx_conf.txq_flags &=
1092                                 ~(ETH_TXQ_FLAGS_NOXSUMTCP|ETH_TXQ_FLAGS_NOXSUMUDP);
1093                 }
1094
1095                 if (ifm_port_setup (p_link->pmd_id, &port_config[i])) {
1096                         printf("Failed to configure port %s - %"PRIu32
1097                                ".\n", p_link->name, p_link->pmd_id);
1098                         printf("Try again with offload disabled....\n");
1099                         port_config[i].tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOOFFLOADS;
1100                         if (ifm_port_setup (p_link->pmd_id, &port_config[i]))
1101                              rte_panic ("Port Setup Failed: %s - %"PRIu32"\n", p_link->name, p_link->pmd_id);
1102                 }
1103
1104 #if 0
1105                 /* LINK */
1106                 status = rte_eth_dev_configure(
1107                         p_link->pmd_id,
1108                         n_hwq_in,
1109                         n_hwq_out,
1110                         &p_link->conf);
1111                 if (status < 0)
1112                         rte_panic("%s (%" PRId32 "): "
1113                                 "init error (%" PRId32 ")\n",
1114                                 p_link->name, p_link->pmd_id, status);
1115
1116                 rte_eth_macaddr_get(p_link->pmd_id,
1117                         (struct ether_addr *) &p_link->mac_addr);
1118
1119                 if (p_link->promisc)
1120                         rte_eth_promiscuous_enable(p_link->pmd_id);
1121
1122                 /* RXQ */
1123                 for (j = 0; j < app->n_pktq_hwq_in; j++) {
1124                         struct app_pktq_hwq_in_params *p_rxq =
1125                                 &app->hwq_in_params[j];
1126                         uint32_t rxq_link_id, rxq_queue_id;
1127
1128                         status =
1129                         sscanf(p_rxq->name, "RXQ%" PRIu32 ".%" PRIu32,
1130                                 &rxq_link_id, &rxq_queue_id);
1131                         if (status < 0)
1132                                 rte_panic("%s (%" PRId32 "): "
1133                                 "init error (%" PRId32 ")\n",
1134                                 p_rxq->name, rxq_queue_id, status);
1135
1136                         if (rxq_link_id != link_id)
1137                                 continue;
1138
1139                         status = rte_eth_rx_queue_setup(
1140                                 p_link->pmd_id,
1141                                 rxq_queue_id,
1142                                 p_rxq->size,
1143                                 app_get_cpu_socket_id(p_link->pmd_id),
1144                                 &p_rxq->conf,
1145                                 app->mempool[p_rxq->mempool_id]);
1146                         if (status < 0)
1147                                 rte_panic("%s (%" PRIu32 "): "
1148                                         "%s init error (%" PRId32 ")\n",
1149                                         p_link->name,
1150                                         p_link->pmd_id,
1151                                         p_rxq->name,
1152                                         status);
1153                 }
1154
1155                 /* TXQ */
1156                 for (j = 0; j < app->n_pktq_hwq_out; j++) {
1157                         struct app_pktq_hwq_out_params *p_txq =
1158                                 &app->hwq_out_params[j];
1159                         uint32_t txq_link_id, txq_queue_id;
1160
1161                         status =
1162                         sscanf(p_txq->name, "TXQ%" PRIu32 ".%" PRIu32,
1163                                 &txq_link_id, &txq_queue_id);
1164
1165                         if (status < 0)
1166                                 rte_panic("%s (%" PRId32 "): "
1167                                 "init error (%" PRId32 ")\n",
1168                                 p_txq->name, txq_link_id, status);
1169
1170                         if (txq_link_id != link_id)
1171                                 continue;
1172
1173                         if (app->header_csum_req) {
1174                                 /* Enable TCP and UDP HW Checksum */
1175                                 p_txq->conf.txq_flags &=
1176                                         ~(ETH_TXQ_FLAGS_NOXSUMTCP|
1177                                         ETH_TXQ_FLAGS_NOXSUMUDP);
1178                         }
1179
1180                         status = rte_eth_tx_queue_setup(
1181                                 p_link->pmd_id,
1182                                 txq_queue_id,
1183                                 p_txq->size,
1184                                 app_get_cpu_socket_id(p_link->pmd_id),
1185                                 &p_txq->conf);
1186
1187                         if (status < 0)
1188                                 rte_panic("%s (%" PRIu32 "): "
1189                                         "%s init error (%" PRId32 ")\n",
1190                                         p_link->name,
1191                                         p_link->pmd_id,
1192                                         p_txq->name,
1193                                         status);
1194                 }
1195
1196                 /* LINK START */
1197                 status = rte_eth_dev_start(p_link->pmd_id);
1198                 if (status < 0)
1199                         rte_panic("Cannot start %s (error %" PRId32 ")\n",
1200                                 p_link->name, status);
1201
1202                 /* LINK UP */
1203                 app_link_set_arp_filter(app, p_link);
1204                 app_link_set_tcp_syn_filter(app, p_link);
1205 #endif
1206                 app_link_up_internal(app, p_link);
1207         }
1208
1209         app_check_link(app);
1210 }
1211
1212 static void
1213 app_init_swq(struct app_params *app)
1214 {
1215         uint32_t i;
1216
1217         for (i = 0; i < app->n_pktq_swq; i++) {
1218                 struct app_pktq_swq_params *p = &app->swq_params[i];
1219                 unsigned int flags = 0;
1220
1221                 if (app_swq_get_readers(app, p) == 1)
1222                         flags |= RING_F_SC_DEQ;
1223                 if (app_swq_get_writers(app, p) == 1)
1224                         flags |= RING_F_SP_ENQ;
1225
1226                 APP_LOG(app, HIGH, "Initializing %s...", p->name);
1227                 app->swq[i] = rte_ring_create(
1228                                 p->name,
1229                                 p->size,
1230                                 p->cpu_socket_id,
1231                                 flags);
1232
1233                 if (app->swq[i] == NULL)
1234                         rte_panic("%s init error\n", p->name);
1235         }
1236 }
1237
1238 static void
1239 app_init_tm(struct app_params *app)
1240 {
1241         uint32_t i;
1242
1243         for (i = 0; i < app->n_pktq_tm; i++) {
1244                 struct app_pktq_tm_params *p_tm = &app->tm_params[i];
1245                 struct app_link_params *p_link;
1246                 struct rte_eth_link link_eth_params;
1247                 struct rte_sched_port *sched;
1248                 uint32_t n_subports, subport_id;
1249                 int status;
1250
1251                 p_link = app_get_link_for_tm(app, p_tm);
1252                 /* LINK */
1253                 rte_eth_link_get(p_link->pmd_id, &link_eth_params);
1254
1255                 /* TM */
1256                 p_tm->sched_port_params.name = p_tm->name;
1257                 p_tm->sched_port_params.socket =
1258                         app_get_cpu_socket_id(p_link->pmd_id);
1259                 p_tm->sched_port_params.rate =
1260                         (uint64_t) link_eth_params.link_speed * 1000 * 1000 / 8;
1261
1262                 APP_LOG(app, HIGH, "Initializing %s ...", p_tm->name);
1263                 sched = rte_sched_port_config(&p_tm->sched_port_params);
1264                 if (sched == NULL)
1265                         rte_panic("%s init error\n", p_tm->name);
1266                 app->tm[i] = sched;
1267
1268                 /* Subport */
1269                 n_subports = p_tm->sched_port_params.n_subports_per_port;
1270                 for (subport_id = 0; subport_id < n_subports; subport_id++) {
1271                         uint32_t n_pipes_per_subport, pipe_id;
1272
1273                         status = rte_sched_subport_config(sched,
1274                                 subport_id,
1275                                 &p_tm->sched_subport_params[subport_id]);
1276                         if (status)
1277                                 rte_panic("%s subport %" PRIu32
1278                                         " init error (%" PRId32 ")\n",
1279                                         p_tm->name, subport_id, status);
1280
1281                         /* Pipe */
1282                         n_pipes_per_subport =
1283                                 p_tm->sched_port_params.n_pipes_per_subport;
1284                         for (pipe_id = 0;
1285                                 pipe_id < n_pipes_per_subport;
1286                                 pipe_id++) {
1287                                 int profile_id = p_tm->sched_pipe_to_profile[
1288                                         subport_id * APP_MAX_SCHED_PIPES +
1289                                         pipe_id];
1290
1291                                 if (profile_id == -1)
1292                                         continue;
1293
1294                                 status = rte_sched_pipe_config(sched,
1295                                         subport_id,
1296                                         pipe_id,
1297                                         profile_id);
1298                                 if (status)
1299                                         rte_panic("%s subport %" PRIu32
1300                                                 " pipe %" PRIu32
1301                                                 " (profile %" PRId32 ") "
1302                                                 "init error (% " PRId32 ")\n",
1303                                                 p_tm->name, subport_id, pipe_id,
1304                                                 profile_id, status);
1305                         }
1306                 }
1307         }
1308 }
1309
1310 static void
1311 app_init_msgq(struct app_params *app)
1312 {
1313         uint32_t i;
1314
1315         for (i = 0; i < app->n_msgq; i++) {
1316                 struct app_msgq_params *p = &app->msgq_params[i];
1317
1318                 APP_LOG(app, HIGH, "Initializing %s ...", p->name);
1319                 app->msgq[i] = rte_ring_create(
1320                                 p->name,
1321                                 p->size,
1322                                 p->cpu_socket_id,
1323                                 RING_F_SP_ENQ | RING_F_SC_DEQ);
1324
1325                 if (app->msgq[i] == NULL)
1326                         rte_panic("%s init error\n", p->name);
1327         }
1328 }
1329
1330 static void app_pipeline_params_get(struct app_params *app,
1331         struct app_pipeline_params *p_in,
1332         struct pipeline_params *p_out)
1333 {
1334         uint32_t i;
1335         uint32_t mempool_id;
1336
1337         snprintf(p_out->name, PIPELINE_NAME_SIZE, "%s", p_in->name);
1338
1339         p_out->socket_id = (int) p_in->socket_id;
1340
1341         p_out->log_level = app->log_level;
1342
1343         /* pktq_in */
1344         p_out->n_ports_in = p_in->n_pktq_in;
1345         for (i = 0; i < p_in->n_pktq_in; i++) {
1346                 struct app_pktq_in_params *in = &p_in->pktq_in[i];
1347                 struct pipeline_port_in_params *out = &p_out->port_in[i];
1348
1349                 switch (in->type) {
1350                 case APP_PKTQ_IN_HWQ:
1351                 {
1352                         struct app_pktq_hwq_in_params *p_hwq_in =
1353                                 &app->hwq_in_params[in->id];
1354                         struct app_link_params *p_link =
1355                                 app_get_link_for_rxq(app, p_hwq_in);
1356                         uint32_t rxq_link_id, rxq_queue_id;
1357
1358                         int status =
1359                         sscanf(p_hwq_in->name, "RXQ%" SCNu32 ".%" SCNu32,
1360                                 &rxq_link_id,
1361                                 &rxq_queue_id);
1362                         if(status < 0)
1363                                 rte_panic("%s (%" PRId32 "): "
1364                                 "init error (%" PRId32 ")\n",
1365                                 p_hwq_in->name, rxq_link_id, status);
1366
1367                         out->type = PIPELINE_PORT_IN_ETHDEV_READER;
1368                         out->params.ethdev.port_id = p_link->pmd_id;
1369                         out->params.ethdev.queue_id = rxq_queue_id;
1370                         out->burst_size = p_hwq_in->burst;
1371                         break;
1372                 }
1373                 case APP_PKTQ_IN_SWQ:
1374                 {
1375                         struct app_pktq_swq_params *swq_params =
1376                                 &app->swq_params[in->id];
1377
1378                         if ((swq_params->ipv4_frag == 0) &&
1379                                 (swq_params->ipv6_frag == 0)) {
1380                                 if (app_swq_get_readers(app,
1381                                         swq_params) == 1) {
1382                                         out->type =
1383                                                 PIPELINE_PORT_IN_RING_READER;
1384                                         out->params.ring.ring =
1385                                                 app->swq[in->id];
1386                                         out->burst_size =
1387                                                 app->swq_params[in->id].
1388                                                         burst_read;
1389                                 } else {
1390                                 out->type = PIPELINE_PORT_IN_RING_MULTI_READER;
1391                                 out->params.ring_multi.ring = app->swq[in->id];
1392                                 out->burst_size = swq_params->burst_read;
1393                                 }
1394                         } else {
1395                                 if (swq_params->ipv4_frag == 1) {
1396                                 struct rte_port_ring_reader_ipv4_frag_params
1397                                         *params =
1398                                                 &out->params.ring_ipv4_frag;
1399
1400                                 out->type =
1401                                         PIPELINE_PORT_IN_RING_READER_IPV4_FRAG;
1402                                 params->ring = app->swq[in->id];
1403                                 params->mtu = swq_params->mtu;
1404                                 params->metadata_size =
1405                                         swq_params->metadata_size;
1406                                 params->pool_direct =
1407                                         app->mempool
1408                                         [swq_params->mempool_direct_id];
1409                                 params->pool_indirect =
1410                                         app->mempool
1411                                         [swq_params->mempool_indirect_id];
1412                                 out->burst_size = swq_params->burst_read;
1413                                 } else {
1414                                 struct rte_port_ring_reader_ipv6_frag_params
1415                                         *params =
1416                                                 &out->params.ring_ipv6_frag;
1417
1418                                 out->type =
1419                                         PIPELINE_PORT_IN_RING_READER_IPV6_FRAG;
1420                                 params->ring = app->swq[in->id];
1421                                 params->mtu = swq_params->mtu;
1422                                 params->metadata_size =
1423                                         swq_params->metadata_size;
1424                                 params->pool_direct =
1425                                         app->mempool
1426                                         [swq_params->mempool_direct_id];
1427                                 params->pool_indirect =
1428                                         app->mempool
1429                                         [swq_params->mempool_indirect_id];
1430                                 out->burst_size = swq_params->burst_read;
1431                                 }
1432                         }
1433                         break;
1434                 }
1435                 case APP_PKTQ_IN_TM:
1436                         out->type = PIPELINE_PORT_IN_SCHED_READER;
1437                         out->params.sched.sched = app->tm[in->id];
1438                         out->burst_size = app->tm_params[in->id].burst_read;
1439                         break;
1440                 case APP_PKTQ_IN_SOURCE:
1441                         mempool_id = app->source_params[in->id].mempool_id;
1442                         out->type = PIPELINE_PORT_IN_SOURCE;
1443                         out->params.source.mempool = app->mempool[mempool_id];
1444                         out->burst_size = app->source_params[in->id].burst;
1445
1446 #ifdef RTE_NEXT_ABI
1447                         if (app->source_params[in->id].file_name
1448                                 != NULL) {
1449                                 out->params.source.file_name = strdup(
1450                                         app->source_params[in->id].
1451                                         file_name);
1452                                 if (out->params.source.file_name == NULL) {
1453                                         out->params.source.
1454                                                 n_bytes_per_pkt = 0;
1455                                         break;
1456                                 }
1457                                 out->params.source.n_bytes_per_pkt =
1458                                         app->source_params[in->id].
1459                                         n_bytes_per_pkt;
1460                         }
1461 #endif
1462
1463                         break;
1464                 default:
1465                         break;
1466                 }
1467         }
1468
1469         /* pktq_out */
1470         p_out->n_ports_out = p_in->n_pktq_out;
1471         for (i = 0; i < p_in->n_pktq_out; i++) {
1472                 struct app_pktq_out_params *in = &p_in->pktq_out[i];
1473                 struct pipeline_port_out_params *out = &p_out->port_out[i];
1474
1475                 switch (in->type) {
1476                 case APP_PKTQ_OUT_HWQ:
1477                 {
1478                         struct app_pktq_hwq_out_params *p_hwq_out =
1479                                 &app->hwq_out_params[in->id];
1480                         struct app_link_params *p_link =
1481                                 app_get_link_for_txq(app, p_hwq_out);
1482                         uint32_t txq_link_id, txq_queue_id;
1483
1484                         int status =
1485                         sscanf(p_hwq_out->name,
1486                                 "TXQ%" SCNu32 ".%" SCNu32,
1487                                 &txq_link_id,
1488                                 &txq_queue_id);
1489                         if(status < 0)
1490                                 rte_panic("%s (%" PRId32 "): "
1491                                 "init error (%" PRId32 ")\n",
1492                                 p_hwq_out->name, txq_link_id, status);
1493
1494                         if (p_hwq_out->dropless == 0) {
1495                                 struct rte_port_ethdev_writer_params *params =
1496                                         &out->params.ethdev;
1497
1498                                 out->type = PIPELINE_PORT_OUT_ETHDEV_WRITER;
1499                                 params->port_id = p_link->pmd_id;
1500                                 params->queue_id = txq_queue_id;
1501                                 params->tx_burst_sz =
1502                                         app->hwq_out_params[in->id].burst;
1503                         } else {
1504                                 struct rte_port_ethdev_writer_nodrop_params
1505                                         *params = &out->params.ethdev_nodrop;
1506
1507                                 out->type =
1508                                         PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP;
1509                                 params->port_id = p_link->pmd_id;
1510                                 params->queue_id = txq_queue_id;
1511                                 params->tx_burst_sz = p_hwq_out->burst;
1512                                 params->n_retries = p_hwq_out->n_retries;
1513                         }
1514                         break;
1515                 }
1516                 case APP_PKTQ_OUT_SWQ:
1517                 {
1518                 struct app_pktq_swq_params *swq_params =
1519                         &app->swq_params[in->id];
1520
1521                 if ((swq_params->ipv4_ras == 0) &&
1522                         (swq_params->ipv6_ras == 0)) {
1523                         if (app_swq_get_writers(app, swq_params) == 1) {
1524                                 if (app->swq_params[in->id].dropless == 0) {
1525                                 struct rte_port_ring_writer_params *params =
1526                                         &out->params.ring;
1527
1528                                 out->type = PIPELINE_PORT_OUT_RING_WRITER;
1529                                 params->ring = app->swq[in->id];
1530                                 params->tx_burst_sz =
1531                                         app->swq_params[in->id].burst_write;
1532                                 } else {
1533                                 struct rte_port_ring_writer_nodrop_params
1534                                         *params = &out->params.ring_nodrop;
1535
1536                                 out->type =
1537                                         PIPELINE_PORT_OUT_RING_WRITER_NODROP;
1538                                 params->ring = app->swq[in->id];
1539                                 params->tx_burst_sz =
1540                                         app->swq_params[in->id].burst_write;
1541                                 params->n_retries =
1542                                 app->swq_params[in->id].n_retries;
1543                                 }
1544                         } else {
1545                                 if (swq_params->dropless == 0) {
1546                                 struct rte_port_ring_multi_writer_params
1547                                         *params =
1548                                                 &out->params.ring_multi;
1549
1550                                 out->type =
1551                                         PIPELINE_PORT_OUT_RING_MULTI_WRITER;
1552                                 params->ring = app->swq[in->id];
1553                                 params->tx_burst_sz = swq_params->burst_write;
1554                                 } else {
1555                                 struct rte_port_ring_multi_writer_nodrop_params
1556                                         *params =
1557                                                 &out->params.ring_multi_nodrop;
1558
1559                                 out->type =
1560                                 PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP;
1561
1562                                 params->ring = app->swq[in->id];
1563                                 params->tx_burst_sz = swq_params->burst_write;
1564                                 params->n_retries = swq_params->n_retries;
1565                                 }
1566                                 }
1567                         } else {
1568                         if (swq_params->ipv4_ras == 1) {
1569                                 struct rte_port_ring_writer_ipv4_ras_params
1570                                         *params =
1571                                                 &out->params.ring_ipv4_ras;
1572
1573                                 out->type =
1574                                         PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS;
1575                                 params->ring = app->swq[in->id];
1576                                 params->tx_burst_sz = swq_params->burst_write;
1577                         } else {
1578                                 struct rte_port_ring_writer_ipv6_ras_params
1579                                         *params =
1580                                                 &out->params.ring_ipv6_ras;
1581
1582                                 out->type =
1583                                         PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS;
1584                                 params->ring = app->swq[in->id];
1585                                 params->tx_burst_sz = swq_params->burst_write;
1586                         }
1587                         }
1588                         break;
1589                 }
1590                 case APP_PKTQ_OUT_TM: {
1591                         struct rte_port_sched_writer_params *params =
1592                                 &out->params.sched;
1593
1594                         out->type = PIPELINE_PORT_OUT_SCHED_WRITER;
1595                         params->sched = app->tm[in->id];
1596                         params->tx_burst_sz =
1597                                 app->tm_params[in->id].burst_write;
1598                         break;
1599                 }
1600                 case APP_PKTQ_OUT_SINK:
1601                         out->type = PIPELINE_PORT_OUT_SINK;
1602                         if (app->sink_params[in->id].file_name != NULL) {
1603                                 out->params.sink.file_name = strdup(
1604                                         app->sink_params[in->id].
1605                                         file_name);
1606                                 if (out->params.sink.file_name == NULL) {
1607                                         out->params.sink.max_n_pkts = 0;
1608                                         break;
1609                                 }
1610                                 out->params.sink.max_n_pkts =
1611                                         app->sink_params[in->id].
1612                                         n_pkts_to_dump;
1613                         } else {
1614                                 out->params.sink.file_name = NULL;
1615                                 out->params.sink.max_n_pkts = 0;
1616                         }
1617                         break;
1618                 default:
1619                         break;
1620                 }
1621         }
1622
1623         /* msgq */
1624         p_out->n_msgq = p_in->n_msgq_in;
1625
1626         for (i = 0; i < p_in->n_msgq_in; i++)
1627                 p_out->msgq_in[i] = app->msgq[p_in->msgq_in[i]];
1628
1629         for (i = 0; i < p_in->n_msgq_out; i++)
1630                 p_out->msgq_out[i] = app->msgq[p_in->msgq_out[i]];
1631
1632         /* args */
1633         p_out->n_args = p_in->n_args;
1634         for (i = 0; i < p_in->n_args; i++) {
1635                 p_out->args_name[i] = p_in->args_name[i];
1636                 p_out->args_value[i] = p_in->args_value[i];
1637         }
1638 }
1639
1640 static void
1641 app_init_pipelines(struct app_params *app)
1642 {
1643         uint32_t p_id;
1644
1645         for (p_id = 0; p_id < app->n_pipelines; p_id++) {
1646                 struct app_pipeline_params *params =
1647                         &app->pipeline_params[p_id];
1648                 struct app_pipeline_data *data = &app->pipeline_data[p_id];
1649                 struct pipeline_type *ptype;
1650                 struct pipeline_params pp;
1651
1652                 APP_LOG(app, HIGH, "Initializing %s ...", params->name);
1653
1654                 ptype = app_pipeline_type_find(app, params->type);
1655                 if (ptype == NULL)
1656                         rte_panic("Init error: Unknown pipeline type \"%s\"\n",
1657                                 params->type);
1658
1659                 app_pipeline_params_get(app, params, &pp);
1660
1661                 /* Back-end */
1662                 data->be = NULL;
1663                 if (ptype->be_ops->f_init) {
1664                         data->be = ptype->be_ops->f_init(&pp, (void *) app);
1665
1666                         if (data->be == NULL)
1667                                 rte_panic("Pipeline instance \"%s\" back-end "
1668                                         "init error\n", params->name);
1669                 }
1670
1671                 /* Front-end */
1672                 data->fe = NULL;
1673                 if (ptype->fe_ops->f_init) {
1674                         data->fe = ptype->fe_ops->f_init(&pp, (void *) app);
1675
1676                         if (data->fe == NULL)
1677                                 rte_panic("Pipeline instance \"%s\" front-end "
1678                                 "init error\n", params->name);
1679                 }
1680
1681                 data->ptype = ptype;
1682
1683                 data->timer_period = (rte_get_tsc_hz() *
1684                         params->timer_period) / 100;
1685         }
1686 }
1687
1688 static void
1689 app_init_threads(struct app_params *app)
1690 {
1691         uint64_t time = rte_get_tsc_cycles();
1692         uint32_t p_id;
1693
1694         for (p_id = 0; p_id < app->n_pipelines; p_id++) {
1695                 struct app_pipeline_params *params =
1696                         &app->pipeline_params[p_id];
1697                 struct app_pipeline_data *data = &app->pipeline_data[p_id];
1698                 struct pipeline_type *ptype;
1699                 struct app_thread_data *t;
1700                 struct app_thread_pipeline_data *p;
1701                 int lcore_id;
1702
1703                 lcore_id = cpu_core_map_get_lcore_id(app->core_map,
1704                         params->socket_id,
1705                         params->core_id,
1706                         params->hyper_th_id);
1707
1708                 if (lcore_id < 0)
1709                         rte_panic("Invalid core s%" PRIu32 "c%" PRIu32 "%s\n",
1710                                 params->socket_id,
1711                                 params->core_id,
1712                                 (params->hyper_th_id) ? "h" : "");
1713
1714                 t = &app->thread_data[lcore_id];
1715
1716                 t->timer_period = (rte_get_tsc_hz() *
1717                         APP_THREAD_TIMER_PERIOD) / 1000;
1718                 t->thread_req_deadline = time + t->timer_period;
1719
1720                 t->headroom_cycles = 0;
1721                 t->headroom_time = rte_get_tsc_cycles();
1722                 t->headroom_ratio = 0.0;
1723
1724                 t->msgq_in = app_thread_msgq_in_get(app,
1725                                 params->socket_id,
1726                                 params->core_id,
1727                                 params->hyper_th_id);
1728                 if (t->msgq_in == NULL)
1729                         rte_panic("Init error: Cannot find MSGQ_IN "
1730                                 "for thread %" PRId32, lcore_id);
1731
1732                 t->msgq_out = app_thread_msgq_out_get(app,
1733                                 params->socket_id,
1734                                 params->core_id,
1735                                 params->hyper_th_id);
1736                 if (t->msgq_out == NULL)
1737                         rte_panic("Init error: Cannot find MSGQ_OUT "
1738                                 "for thread %" PRId32, lcore_id);
1739
1740                 ptype = app_pipeline_type_find(app, params->type);
1741                 if (ptype == NULL)
1742                         rte_panic("Init error: Unknown pipeline "
1743                                 "type \"%s\"\n", params->type);
1744
1745                 p = (ptype->be_ops->f_run == NULL) ?
1746                         &t->regular[t->n_regular] :
1747                         &t->custom[t->n_custom];
1748
1749                 p->pipeline_id = p_id;
1750                 p->be = data->be;
1751                 p->f_run = ptype->be_ops->f_run;
1752                 p->f_timer = ptype->be_ops->f_timer;
1753                 p->timer_period = data->timer_period;
1754                 p->deadline = time + data->timer_period;
1755
1756                 data->enabled = 1;
1757
1758                 if (ptype->be_ops->f_run == NULL)
1759                         t->n_regular++;
1760                 else
1761                         t->n_custom++;
1762         }
1763 }
1764
1765 int app_init(struct app_params *app)
1766 {
1767         app_init_core_map(app);
1768         app_init_core_mask(app);
1769
1770         app_init_eal(app);
1771         ifm_init();
1772         //app_init_mempool(app);
1773         app_init_link(app);
1774         app_init_swq(app);
1775         app_init_tm(app);
1776         app_init_msgq(app);
1777
1778         app_pipeline_common_cmd_push(app);
1779         app_pipeline_thread_cmd_push(app);
1780         app_pipeline_type_register(app, &pipeline_master);
1781         app_pipeline_type_register(app, &pipeline_cgnapt);
1782         app_pipeline_type_register(app, &pipeline_loadb);
1783         app_pipeline_type_register(app, &pipeline_timer);
1784         app_pipeline_type_register(app, &pipeline_txrx);
1785         app_pipeline_type_register(app, &pipeline_arpicmp);
1786
1787         app_init_pipelines(app);
1788         app_init_threads(app);
1789
1790         #ifdef L3_STACK_SUPPORT
1791         l3fwd_init();
1792         create_arp_table();
1793         create_nd_table();
1794         populate_lpm_routes();
1795         print_interface_details();
1796         #endif
1797
1798         return 0;
1799 }
1800
1801 static int
1802 app_pipeline_type_cmd_push(struct app_params *app,
1803         struct pipeline_type *ptype)
1804 {
1805         cmdline_parse_ctx_t *cmds;
1806         uint32_t n_cmds, i;
1807
1808         /* Check input arguments */
1809         if ((app == NULL) ||
1810                 (ptype == NULL))
1811                 return -EINVAL;
1812
1813         n_cmds = pipeline_type_cmds_count(ptype);
1814         if (n_cmds == 0)
1815                 return 0;
1816
1817         cmds = ptype->fe_ops->cmds;
1818
1819         /* Check for available slots in the application commands array */
1820         if (n_cmds > APP_MAX_CMDS - app->n_cmds)
1821                 return -ENOMEM;
1822
1823         /* Push pipeline commands into the application */
1824         memcpy(&app->cmds[app->n_cmds],
1825                 cmds,
1826                 n_cmds * sizeof(cmdline_parse_ctx_t));
1827
1828         for (i = 0; i < n_cmds; i++)
1829                 app->cmds[app->n_cmds + i]->data = app;
1830
1831         app->n_cmds += n_cmds;
1832         app->cmds[app->n_cmds] = NULL;
1833
1834         return 0;
1835 }
1836
1837 int
1838 app_pipeline_type_register(struct app_params *app, struct pipeline_type *ptype)
1839 {
1840         uint32_t n_cmds, i;
1841
1842         /* Check input arguments */
1843         if ((app == NULL) ||
1844                 (ptype == NULL) ||
1845                 (ptype->name == NULL) ||
1846                 (strlen(ptype->name) == 0) ||
1847                 (ptype->be_ops->f_init == NULL) ||
1848                 (ptype->be_ops->f_timer == NULL))
1849                 return -EINVAL;
1850
1851         /* Check for duplicate entry */
1852         for (i = 0; i < app->n_pipeline_types; i++)
1853                 if (strcmp(app->pipeline_type[i].name, ptype->name) == 0)
1854                         return -EEXIST;
1855
1856         /* Check for resource availability */
1857         n_cmds = pipeline_type_cmds_count(ptype);
1858         if ((app->n_pipeline_types == APP_MAX_PIPELINE_TYPES) ||
1859                 (n_cmds > APP_MAX_CMDS - app->n_cmds))
1860                 return -ENOMEM;
1861
1862         /* Copy pipeline type */
1863         memcpy(&app->pipeline_type[app->n_pipeline_types++],
1864                 ptype,
1865                 sizeof(struct pipeline_type));
1866
1867         /* Copy CLI commands */
1868         if (n_cmds)
1869                 app_pipeline_type_cmd_push(app, ptype);
1870
1871         return 0;
1872 }
1873
1874 struct
1875 pipeline_type *app_pipeline_type_find(struct app_params *app, char *name)
1876 {
1877         uint32_t i;
1878
1879         for (i = 0; i < app->n_pipeline_types; i++)
1880                 if (strcmp(app->pipeline_type[i].name, name) == 0)
1881                         return &app->pipeline_type[i];
1882
1883         return NULL;
1884 }