Merge "Add support for DPDK 17.11"
[samplevnf.git] / VNFs / DPPD-PROX / prox_args.c
1 /*
2 // Copyright (c) 2010-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 <unistd.h>
18 #include <string.h>
19
20 #include <rte_sched.h>
21 #include <rte_string_fns.h>
22 #include <rte_version.h>
23
24 #include "prox_malloc.h"
25 #include "version.h"
26 #include "defines.h"
27 #include "prox_args.h"
28 #include "prox_assert.h"
29 #include "prox_cfg.h"
30 #include "cfgfile.h"
31 #include "quit.h"
32 #include "log.h"
33 #include "parse_utils.h"
34 #include "prox_port_cfg.h"
35 #include "defaults.h"
36 #include "prox_lua.h"
37 #include "cqm.h"
38 #include "prox_compat.h"
39
40 #define MAX_RTE_ARGV 64
41 #define MAX_ARG_LEN  64
42
43 struct cfg_depr {
44         const char *opt;
45         const char *info;
46 };
47
48 /* Helper macro */
49 #define STR_EQ(s1, s2)  (!strcmp((s1), (s2)))
50
51 /* configuration files support */
52 static int get_rte_cfg(unsigned sindex, char *str, void *data);
53 static int get_global_cfg(unsigned sindex, char *str, void *data);
54 static int get_port_cfg(unsigned sindex, char *str, void *data);
55 static int get_defaults_cfg(unsigned sindex, char *str, void *data);
56 static int get_cache_set_cfg(unsigned sindex, char *str, void *data);
57 static int get_var_cfg(unsigned sindex, char *str, void *data);
58 static int get_lua_cfg(unsigned sindex, char *str, void *data);
59 static int get_core_cfg(unsigned sindex, char *str, void *data);
60
61 static const char *cfg_file = DEFAULT_CONFIG_FILE;
62 static struct rte_cfg    rte_cfg;
63 struct prox_cache_set_cfg  prox_cache_set_cfg[PROX_MAX_CACHE_SET];
64
65 static char format_err_str[1024];
66 static const char *err_str = "Unknown error";
67
68 static struct cfg_section eal_default_cfg = {
69         .name   = "eal options",
70         .parser = get_rte_cfg,
71         .data   = &rte_cfg,
72         .indexp[0]  = 0,
73         .nbindex = 1,
74         .error  = 0
75 };
76
77 static struct cfg_section port_cfg = {
78         .name   = "port #",
79         .parser = get_port_cfg,
80         .data   = &prox_port_cfg,
81         .indexp[0]  = 0,
82         .nbindex = 1,
83         .error  = 0
84 };
85
86 static struct cfg_section var_cfg = {
87         .name   = "variables",
88         .parser = get_var_cfg,
89         .data   = 0,
90         .indexp[0]  = 0,
91         .nbindex = 1,
92         .error  = 0
93 };
94
95 static struct cfg_section cache_set_cfg = {
96         .name   = "cache set #",
97         .parser = get_cache_set_cfg,
98         .data   = &prox_cache_set_cfg,
99         .indexp[0]  = 0,
100         .nbindex = 1,
101         .error  = 0
102 };
103
104 static struct cfg_section defaults_cfg = {
105         .name   = "defaults",
106         .parser = get_defaults_cfg,
107         .data   = 0,
108         .indexp[0]  = 0,
109         .nbindex = 1,
110         .error  = 0
111 };
112
113 static struct cfg_section settings_cfg = {
114         .name   = "global",
115         .parser = get_global_cfg,
116         .data   = &prox_cfg,
117         .indexp[0]  = 0,
118         .nbindex = 1,
119         .error  = 0
120 };
121
122 static struct cfg_section lua_cfg = {
123         .name = "lua",
124         .parser = get_lua_cfg,
125         .raw_lines = 1,
126         .indexp[0] = 0,
127         .nbindex = 1,
128         .error = 0,
129 };
130
131 static struct cfg_section core_cfg = {
132         .name   = "core #",
133         .parser = get_core_cfg,
134         .data   = lcore_cfg_init,
135         .indexp[0]  = 0,
136         .nbindex = 1,
137         .error  = 0
138 };
139
140 static void set_errf(const char *format, ...)
141 {
142         va_list ap;
143         va_start(ap, format);
144         vsnprintf(format_err_str, sizeof(format_err_str), format, ap);
145         va_end(ap);
146         err_str = format_err_str;
147 }
148
149 /* [eal options] parser */
150 static int get_rte_cfg(__attribute__((unused))unsigned sindex, char *str, void *data)
151 {
152         struct rte_cfg *pconfig = (struct rte_cfg *)data;
153
154         if (str == NULL || pconfig == NULL) {
155                 return -1;
156         }
157
158         char *pkey = get_cfg_key(str);
159         if (pkey == NULL) {
160                 set_errf("Missing key after option");
161                 return -1;
162         }
163
164         if (STR_EQ(str, "-m")) {
165                 return parse_int(&pconfig->memory, pkey);
166         }
167         if (STR_EQ(str, "-n")) {
168                 if (parse_int(&pconfig->force_nchannel, pkey)) {
169                         return -1;
170                 }
171                 if (pconfig->force_nchannel == 0) {
172                         set_errf("Invalid number of memory channels");
173                         return -1;
174                 }
175                 return 0;
176         }
177         if (STR_EQ(str, "-r")) {
178                 if (parse_int(&pconfig->force_nrank, pkey)) {
179                         return -1;
180                 }
181                 if (pconfig->force_nrank == 0 || pconfig->force_nrank > 16) {
182                         set_errf("Invalid number of memory ranks");
183                         return -1;
184                 }
185                 return 0;
186         }
187         /* debug options */
188         if (STR_EQ(str, "no-pci")) {
189                 return parse_bool(&pconfig->no_pci, pkey);
190         }
191         if (STR_EQ(str, "no-hpet")) {
192                 return parse_bool(&pconfig->no_hpet, pkey);
193         }
194         if (STR_EQ(str, "no-shconf")) {
195                 return parse_bool(&pconfig->no_shconf, pkey);
196         }
197         if (STR_EQ(str, "no-huge")) {
198                 return parse_bool(&pconfig->no_hugetlbfs, pkey);
199         }
200         if (STR_EQ(str, "no-output")) {
201                 return parse_bool(&pconfig->no_output, pkey);
202         }
203
204         if (STR_EQ(str, "huge-dir")) {
205                 if (pconfig->hugedir) {
206                         free(pconfig->hugedir);
207                 }
208                 pconfig->hugedir = strdup(pkey);
209                 return 0;
210         }
211
212         if (STR_EQ(str, "eal")) {
213                 char eal[MAX_STR_LEN_PROC];
214                 if (pconfig->eal) {
215                         free(pconfig->eal);
216                         pconfig->eal = NULL;
217                 }
218                 if (parse_str(eal, pkey, sizeof(eal)))
219                         return -1;
220                 pkey = eal;
221                 strip_spaces(&pkey, 1);
222                 if (*pkey)
223                         pconfig->eal = strdup(pkey);
224                 return 0;
225         }
226
227         set_errf("Option '%s' is not known", str);
228         return -1;
229 }
230
231 struct cfg_depr global_cfg_depr[] = {
232         {"virtualization", "This is now set automatically if needed"},
233         {"qinq_tag", "This option is deprecated"},
234         {"wait on quit", "This is now set automatically if needed"},
235         {"version", ""}
236 };
237
238 const char *get_cfg_dir(void)
239 {
240         static char dir[PATH_MAX];
241         size_t end = strlen(cfg_file) - 1;
242         while (end > 0 && cfg_file[end] != '/')
243                 end--;
244
245         strncpy(dir, cfg_file, end);
246         return dir;
247 }
248
249 static int get_lua_cfg(__attribute__((unused)) unsigned sindex, __attribute__((unused)) char *str, __attribute__((unused)) void *data)
250 {
251         int status;
252         char cwd[1024];
253         if (NULL == getcwd(cwd, sizeof(cwd))) {
254                 set_errf("Failed to get current directory while loading Lua file\n");
255                 return -1;
256         }
257         status = chdir(get_cfg_dir());
258         if (status) {
259                 set_errf("Failed to change directory to '%s' while loading Lua file\n", get_cfg_dir());
260                 return -1;
261         }
262
263         struct lua_State *l = prox_lua();
264
265         char str_cpy[1024];
266         strncpy(str_cpy, str, sizeof(str_cpy));
267         uint32_t len = strlen(str_cpy);
268         str_cpy[len++] = '\n';
269         str_cpy[len++] = 0;
270
271         status = luaL_loadstring(l, str_cpy);
272         if (status) {
273                 set_errf("Lua error: '%s'\n", lua_tostring(l, -1));
274                 status = chdir(cwd);
275                 return -1;
276         }
277
278         status = lua_pcall(l, 0, LUA_MULTRET, 0);
279         if (status) {
280                 set_errf("Lua error: '%s'\n", lua_tostring(l, -1));
281                 status = chdir(cwd);
282                 return -1;
283         }
284
285         status = chdir(cwd);
286         if (status) {
287                 set_errf("Failed to restore current directory to '%s' while loading Lua file\n", cwd);
288                 return -1;
289         }
290
291         return 0;
292 }
293
294 /* [global] parser */
295 static int get_global_cfg(__attribute__((unused))unsigned sindex, char *str, void *data)
296 {
297         struct prox_cfg *pset = (struct prox_cfg *)data;
298
299         if (str == NULL || pset == NULL) {
300                 return -1;
301         }
302
303         char *pkey = get_cfg_key(str);
304         if (pkey == NULL) {
305                 set_errf("Missing key after option");
306                 return -1;
307         }
308
309         for (uint32_t i = 0; i < RTE_DIM(global_cfg_depr); ++i) {
310                 if (STR_EQ(str, global_cfg_depr[i].opt)) {
311                         set_errf("Option '%s' is deprecated%s%s",
312                                  global_cfg_depr[i].opt, strlen(global_cfg_depr[i].info)? ": ": "", global_cfg_depr[i].info);
313                         return -1;
314                 }
315         }
316
317         if (STR_EQ(str, "name")) {
318                 return parse_str(pset->name, pkey, sizeof(pset->name));
319         }
320
321         if (STR_EQ(str, "start time")) {
322                 return parse_int(&pset->start_time, pkey);
323         }
324
325         if (STR_EQ(str, "duration time")) {
326                 return parse_int(&pset->duration_time, pkey);
327         }
328
329         if (STR_EQ(str, "shuffle")) {
330                 return parse_flag(&pset->flags, DSF_SHUFFLE, pkey);
331         }
332         if (STR_EQ(str, "disable cmt")) {
333                 return parse_flag(&pset->flags, DSF_DISABLE_CMT, pkey);
334         }
335         if (STR_EQ(str, "mp rings")) {
336                 return parse_flag(&pset->flags, DSF_MP_RINGS, pkey);
337         }
338         if (STR_EQ(str, "enable bypass")) {
339                 return parse_flag(&pset->flags, DSF_ENABLE_BYPASS, pkey);
340         }
341
342         if (STR_EQ(str, "cpe table map")) {
343                 /* The config defined ports through 0, 1, 2 ... which
344                    need to be associated with ports. This is done
345                    through defining it using "cpe table map=" */
346                 return parse_port_name_list((uint32_t*)pset->cpe_table_ports, NULL, PROX_MAX_PORTS, pkey);
347         }
348
349         if (STR_EQ(str, "pre cmd")) {
350                 return system(pkey);
351         }
352
353         if (STR_EQ(str, "unique mempool per socket")) {
354                 return parse_flag(&pset->flags, UNIQUE_MEMPOOL_PER_SOCKET, pkey);
355         }
356
357         if (STR_EQ(str, "log buffer size")) {
358                 if (parse_kmg(&pset->logbuf_size, pkey)) {
359                         return -1;
360                 }
361                 plog_info("Logging to buffer with size = %d\n", pset->logbuf_size);
362                 return 0;
363         }
364
365         set_errf("Option '%s' is not known", str);
366         return -1;
367 }
368
369 /* [variable] parser */
370 static int get_var_cfg(__attribute__((unused)) unsigned sindex, char *str, __attribute__((unused)) void *data)
371 {
372         return add_var(str, get_cfg_key(str), 0);
373 }
374
375 /* [defaults] parser */
376 static int get_defaults_cfg(__attribute__((unused)) unsigned sindex, char *str, __attribute__((unused)) void *data)
377 {
378         uint32_t val;
379         char *pkey;
380
381         pkey = get_cfg_key(str);
382         if (pkey == NULL) {
383                 set_errf("Missing key after option");
384                 return -1;
385         }
386
387         if (STR_EQ(str, "mempool size")) {
388
389                 if (parse_kmg(&val, pkey)) {
390                         return -1;
391                 }
392
393                 for (uint8_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
394                         struct lcore_cfg *cur_lcore_cfg_init = &lcore_cfg_init[lcore_id];
395                         cur_lcore_cfg_init->id = lcore_id;
396                         for (uint8_t task_id = 0; task_id < MAX_TASKS_PER_CORE; ++task_id) {
397                                 struct task_args *targ = &cur_lcore_cfg_init->targs[task_id];
398                                 targ->nb_mbuf = val;
399                                 targ->id = task_id;
400                         }
401                 }
402                 return 0;
403         }
404
405         if (STR_EQ(str, "qinq tag")) {
406                 for (uint8_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
407                         struct lcore_cfg *cur_lcore_cfg_init = &lcore_cfg_init[lcore_id];
408                         cur_lcore_cfg_init->id = lcore_id;
409                         for (uint8_t task_id = 0; task_id < MAX_TASKS_PER_CORE; ++task_id) {
410                                 struct task_args *targ = &cur_lcore_cfg_init->targs[task_id];
411                                 parse_int(&targ->qinq_tag, pkey);
412                         }
413                 }
414                 return 0;
415         }
416         if (STR_EQ(str, "memcache size")) {
417
418                 if (parse_kmg(&val, pkey)) {
419                         return -1;
420                 }
421
422                 for (uint8_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
423                         struct lcore_cfg *cur_lcore_cfg_init = &lcore_cfg_init[lcore_id];
424                         cur_lcore_cfg_init->id = lcore_id;
425                         for (uint8_t task_id = 0; task_id < MAX_TASKS_PER_CORE; ++task_id) {
426                                 struct task_args *targ = &cur_lcore_cfg_init->targs[task_id];
427                                 targ->nb_cache_mbuf = val;
428                         }
429                 }
430                 return 0;
431         }
432
433         set_errf("Option '%s' is not known", str);
434         return -1;
435 }
436
437 /* [cache set] parser */
438 static int get_cache_set_cfg(unsigned sindex, char *str, void *data)
439 {
440         struct prox_cache_set_cfg *cfg = (struct prox_cache_set_cfg *)data;
441
442         uint8_t cur_if = sindex & ~CFG_INDEXED;
443
444         if (cur_if >= PROX_MAX_CACHE_SET) {
445                 set_errf("Cache set ID is too high (max allowed %d)", PROX_MAX_CACHE_SET - 1 );
446                 return -1;
447         }
448
449         cfg = &prox_cache_set_cfg[cur_if];
450
451         if (str == NULL || data == NULL) {
452                 return -1;
453         }
454
455         char *pkey = get_cfg_key(str);
456
457         if (pkey == NULL) {
458                 set_errf("Missing key after option");
459                 return -1;
460         }
461
462         if (STR_EQ(str, "mask")) {
463                 uint32_t val;
464                 int err = parse_int(&val, pkey);
465                 if (err) {
466                         return -1;
467                 }
468                 cfg->mask = val;
469                 cfg->socket_id = -1;
470                 plog_info("\tCache set %d has mask %x\n", cur_if, cfg->mask);
471                 return 0;
472         }
473         return 0;
474 }
475
476 /* [port] parser */
477 static int get_port_cfg(unsigned sindex, char *str, void *data)
478 {
479         struct prox_port_cfg *cfg = (struct prox_port_cfg *)data;
480
481         uint8_t cur_if = sindex & ~CFG_INDEXED;
482
483         if (cur_if >= PROX_MAX_PORTS) {
484                 set_errf("Port ID is too high (max allowed %d)", PROX_MAX_PORTS - 1 );
485                 return -1;
486         }
487
488         cfg = &prox_port_cfg[cur_if];
489
490         if (str == NULL || data == NULL) {
491                 return -1;
492         }
493
494         char *pkey = get_cfg_key(str);
495
496         if (pkey == NULL) {
497                 set_errf("Missing key after option");
498                 return -1;
499         }
500
501         if (STR_EQ(str, "mac")) {
502                 if (STR_EQ(pkey, "hardware")) {
503                         cfg->type = PROX_PORT_MAC_HW;
504                 }
505                 else if (STR_EQ(pkey, "random")) {
506                         cfg->type = PROX_PORT_MAC_RAND;
507                 }
508                 else {
509                         cfg->type = PROX_PORT_MAC_SET;
510                         if (parse_mac(&cfg->eth_addr, pkey)) {
511                                 return -1;
512                         }
513                 }
514         }
515         else if (STR_EQ(str, "name")) {
516                 uint32_t val;
517                 strncpy(cfg->name, pkey, MAX_NAME_SIZE);
518                 PROX_ASSERT(cur_if < PROX_MAX_PORTS);
519                 return add_port_name(cur_if, pkey);
520         }
521         else if (STR_EQ(str, "rx desc")) {
522                 return parse_int(&cfg->n_rxd, pkey);
523         }
524         else if (STR_EQ(str, "tx desc")) {
525                 return parse_int(&cfg->n_txd, pkey);
526         }
527         else if (STR_EQ(str, "promiscuous")) {
528                 uint32_t val;
529                 if (parse_bool(&val, pkey)) {
530                         return -1;
531                 }
532                 cfg->promiscuous = val;
533         }
534         else if (STR_EQ(str, "lsc")) {
535                 cfg->lsc_set_explicitely = 1;
536                 uint32_t val;
537                 if (parse_bool(&val, pkey)) {
538                         return -1;
539                 }
540                 cfg->lsc_val = val;
541         }
542         else if (STR_EQ(str, "strip crc")) {
543                 uint32_t val;
544                 if (parse_bool(&val, pkey)) {
545                         return -1;
546                 }
547                 cfg->port_conf.rxmode.hw_strip_crc = val;
548         }
549         else if (STR_EQ(str, "rss")) {
550                 uint32_t val;
551                 if (parse_bool(&val, pkey)) {
552                         return -1;
553                 }
554                 if (val) {
555                         cfg->port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
556                         cfg->port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IPV4;
557                 }
558         }
559         else if (STR_EQ(str, "rx_ring")) {
560                 parse_str(cfg->rx_ring, pkey, sizeof(cfg->rx_ring));
561         }
562         else if (STR_EQ(str, "tx_ring")) {
563                 parse_str(cfg->tx_ring, pkey, sizeof(cfg->tx_ring));
564         }
565
566         return 0;
567 }
568
569 static enum police_action str_to_color(const char *str)
570 {
571         if (STR_EQ(str, "green"))
572                 return ACT_GREEN;
573         if (STR_EQ(str, "yellow"))
574                 return ACT_YELLOW;
575         if (STR_EQ(str, "red"))
576                 return ACT_RED;
577         if (STR_EQ(str, "drop"))
578                 return ACT_DROP;
579         return ACT_INVALID;
580 }
581
582 struct cfg_depr task_cfg_depr[] = {
583         {"sig", ""},
584 };
585
586 struct cfg_depr core_cfg_depr[] = {
587         {"do sig", ""},
588         {"lat", ""},
589         {"network side", ""},
590 };
591
592 /* [core] parser */
593 static int get_core_cfg(unsigned sindex, char *str, void *data)
594 {
595         char *pkey;
596         struct lcore_cfg *lconf = (struct lcore_cfg *)data;
597
598         if (str == NULL || lconf == NULL || !(sindex & CFG_INDEXED)) {
599                 return -1;
600         }
601
602         pkey = get_cfg_key(str);
603         if (pkey == NULL) {
604                 set_errf("Missing key after option");
605                 return -1;
606         }
607
608         uint32_t ncore = sindex & ~CFG_INDEXED;
609         if (ncore >= RTE_MAX_LCORE) {
610                 set_errf("Core index too high (max allowed %d)", RTE_MAX_LCORE - 1);
611                 return -1;
612         }
613
614         lconf = &lconf[ncore];
615
616         for (uint32_t i = 0; i < RTE_DIM(core_cfg_depr); ++i) {
617                 if (STR_EQ(str, core_cfg_depr[i].opt)) {
618                         set_errf("Option '%s' is deprecated%s%s",
619                                  core_cfg_depr[i].opt, strlen(core_cfg_depr[i].info)? ": ": "", core_cfg_depr[i].info);
620                         return -1;
621                 }
622         }
623
624         char buff[128];
625         lcore_to_socket_core_ht(ncore, buff, sizeof(buff));
626         set_self_var(buff);
627         if (STR_EQ(str, "task")) {
628
629                 uint32_t val;
630                 if (parse_int(&val, pkey)) {
631                         return -1;
632                 }
633                 if (val >= MAX_TASKS_PER_CORE) {
634                         set_errf("Too many tasks for core (max allowed %d)", MAX_TASKS_PER_CORE - 1);
635                         return -1;
636                 }
637                 if (val != lconf->n_tasks_all) {
638                         set_errf("Task ID skipped or defined twice");
639                         return -1;
640                 }
641
642                 lconf->active_task = val;
643
644                 lconf->targs[lconf->active_task].task = lconf->active_task;
645
646                 if (lconf->n_tasks_all < lconf->active_task + 1) {
647                         lconf->n_tasks_all = lconf->active_task + 1;
648                 }
649                 return 0;
650         }
651
652         struct task_args *targ = &lconf->targs[lconf->active_task];
653         if (STR_EQ(str, "tx ports from routing table")) {
654                 uint32_t vals[PROX_MAX_PORTS];
655                 uint32_t n_if;
656                 if (!(targ->task_init->flag_features & TASK_FEATURE_ROUTING)) {
657                         set_errf("tx port form route not supported mode %s",  targ->task_init->mode_str);
658                         return -1;
659                 }
660
661                 if (parse_port_name_list(vals, &n_if, PROX_MAX_PORTS, pkey)) {
662                         return -1;
663                 }
664
665                 for (uint8_t i = 0; i < n_if; ++i) {
666                         targ->tx_port_queue[i].port = vals[i];
667                         targ->nb_txports++;
668                 }
669                 targ->runtime_flags |= TASK_ROUTING;
670                 return 0;
671         }
672         if (STR_EQ(str, "tx ports from cpe table")) {
673                 uint32_t vals[PROX_MAX_PORTS];
674                 int n_remap = -1;
675                 uint32_t ret;
676                 uint32_t val;
677                 char* mapping_str = strstr(pkey, " remap=");
678
679                 if (mapping_str != NULL) {
680                         *mapping_str = 0;
681                         mapping_str += strlen(" remap=");
682                         n_remap = parse_remap(targ->mapping, mapping_str);
683                 }
684
685                 if (parse_port_name_list(vals, &ret, PROX_MAX_PORTS, pkey)) {
686                         return -1;
687                 }
688
689                 if (n_remap != -1 && ret != (uint32_t)n_remap) {
690                         set_errf("Expected %d remap elements but had %d", n_remap, ret);
691                         return -1;
692                 }
693
694                 for (uint8_t i = 0; i < ret; ++i) {
695                         targ->tx_port_queue[i].port = vals[i];
696
697                         /* default mapping this case is port0 -> port0 */
698                         if (n_remap == -1) {
699                                 targ->mapping[vals[i]] = i;
700                         }
701                 }
702
703                 targ->nb_txports = ret;
704
705                 return 0;
706         }
707         if (STR_EQ(str, "tx cores from routing table")) {
708                 if (!(targ->task_init->flag_features & TASK_FEATURE_ROUTING)) {
709                         set_errf("tx port form route not supported mode %s",  targ->task_init->mode_str);
710                         return -1;
711                 }
712
713                 struct core_task_set *cts = &targ->core_task_set[0];
714
715                 if (parse_task_set(cts, pkey))
716                         return -1;
717
718                 if (cts->n_elems > MAX_WT_PER_LB) {
719                         set_errf("Maximum worker threads allowed is %u but have %u", MAX_WT_PER_LB, cts->n_elems);
720                         return -1;
721                 }
722
723                 targ->nb_worker_threads = cts->n_elems;
724                 targ->nb_txrings = cts->n_elems;
725
726                 if (targ->nb_txrings > MAX_RINGS_PER_TASK) {
727                         set_errf("Maximum allowed TX rings is %u but have %u", MAX_RINGS_PER_TASK, targ->nb_txrings);
728                         return -1;
729                 }
730
731                 targ->runtime_flags |= TASK_ROUTING;
732                 return 0;
733         }
734         if (STR_EQ(str, "tx cores from cpe table")) {
735                 struct core_task_set *core_task_set =  &targ->core_task_set[0];
736                 int ret, ret2;
737                 char *mapping_str;
738
739                 mapping_str = strstr(pkey, " remap=");
740                 if (mapping_str == NULL) {
741                         set_errf("There is no default mapping for tx cores from cpe table. Please specify it through remap=");
742                         return -1;
743                 }
744                 *mapping_str = 0;
745                 mapping_str += strlen(" remap=");
746                 ret = parse_remap(targ->mapping, mapping_str);
747                 if (ret <= 0) {
748                         return -1;
749                 }
750
751                 struct core_task_set *cts = &targ->core_task_set[0];
752
753                 if (parse_task_set(cts, pkey))
754                         return -1;
755                 if (cts->n_elems > MAX_RINGS_PER_TASK) {
756                         set_errf("Maximum cores to route to is %u\n", MAX_RINGS_PER_TASK);
757                         return -1;
758                 }
759
760                 targ->nb_txrings = cts->n_elems;
761
762                 if (ret != targ->nb_txrings) {
763                         set_errf("Expecting same number of remaps as cores\n", str);
764                         return -1;
765                 }
766                 return 0;
767         }
768
769         if (STR_EQ(str, "delay ms")) {
770                 if (targ->delay_us) {
771                         set_errf("delay ms and delay us are mutually exclusive\n", str);
772                         return -1;
773                 }
774                 uint32_t delay_ms;
775                 int rc = parse_int(&delay_ms, pkey);
776                 targ->delay_us = delay_ms * 1000;
777                 return rc;
778         }
779         if (STR_EQ(str, "delay us")) {
780                 if (targ->delay_us) {
781                         set_errf("delay ms and delay us are mutually exclusive\n", str);
782                         return -1;
783                 }
784                 return parse_int(&targ->delay_us, pkey);
785         }
786         if (STR_EQ(str, "random delay us")) {
787                 return parse_int(&targ->random_delay_us, pkey);
788         }
789         if (STR_EQ(str, "cpe table timeout ms")) {
790                 return parse_int(&targ->cpe_table_timeout_ms, pkey);
791         }
792         if (STR_EQ(str, "ctrl path polling frequency")) {
793                 int rc = parse_int(&targ->ctrl_freq, pkey);
794                 if (rc == 0) {
795                         if (targ->ctrl_freq == 0) {
796                                 set_errf("ctrl frequency must be non null.");
797                                 return -1;
798                         }
799                 }
800                 return rc;
801         }
802
803         if (STR_EQ(str, "handle arp")) {
804                 return parse_flag(&targ->runtime_flags, TASK_CTRL_HANDLE_ARP, pkey);
805         }
806         if (STR_EQ(str, "fast path handle arp")) {
807                 return parse_flag(&targ->runtime_flags, TASK_FP_HANDLE_ARP, pkey);
808         }
809         if (STR_EQ(str, "multiple arp")) {
810                 return parse_flag(&targ->flags, TASK_MULTIPLE_MAC, pkey);
811         }
812
813         /* Using tx port name, only a _single_ port can be assigned to a task. */
814         if (STR_EQ(str, "tx port")) {
815                 if (targ->nb_txports > 0) {
816                         set_errf("Only one tx port can be defined per task. Use a LB task or routing instead.");
817                         return -1;
818                 }
819
820                 uint32_t n_if = 0;
821                 uint32_t ports[PROX_MAX_PORTS];
822
823                 if(parse_port_name_list(ports, &n_if, PROX_MAX_PORTS, pkey)) {
824                         return -1;
825                 }
826
827                 PROX_ASSERT(n_if-1 < PROX_MAX_PORTS);
828
829                 for (uint8_t i = 0; i < n_if; ++i) {
830                         targ->tx_port_queue[i].port = ports[i];
831                         targ->nb_txports++;
832                 }
833
834                 if (n_if > 1) {
835                         targ->nb_worker_threads = targ->nb_txports;
836                 }
837
838                 return 0;
839         }
840         if (STR_EQ(str, "rx ring")) {
841                 uint32_t val;
842                 int err = parse_bool(&val, pkey);
843                 if (!err && val && targ->rx_port_queue[0].port != OUT_DISCARD) {
844                         set_errf("Can't read both from internal ring and external port from the same task. Use multiple tasks instead.");
845                         return -1;
846                 }
847
848                 return parse_flag(&targ->flags, TASK_ARG_RX_RING, pkey);
849         }
850         if (STR_EQ(str, "private")) {
851                 return parse_bool(&targ->use_src, pkey);
852         }
853         if (STR_EQ(str, "use src ip")) {
854                 return parse_bool(&targ->use_src, pkey);
855         }
856         if (STR_EQ(str, "nat table")) {
857                 return parse_str(targ->nat_table, pkey, sizeof(targ->nat_table));
858         }
859         if (STR_EQ(str, "rules")) {
860                 return parse_str(targ->rules, pkey, sizeof(targ->rules));
861         }
862         if (STR_EQ(str, "route table")) {
863                 return parse_str(targ->route_table, pkey, sizeof(targ->route_table));
864         }
865         if (STR_EQ(str, "dscp")) {
866                 return parse_str(targ->dscp, pkey, sizeof(targ->dscp));
867         }
868         if (STR_EQ(str, "tun_bindings")) {
869                 return parse_str(targ->tun_bindings, pkey, sizeof(targ->tun_bindings));
870         }
871         if (STR_EQ(str, "cpe table")) {
872                 return parse_str(targ->cpe_table_name, pkey, sizeof(targ->cpe_table_name));
873         }
874         if (STR_EQ(str, "user table")) {
875                 return parse_str(targ->user_table, pkey, sizeof(targ->user_table));
876         }
877         if (STR_EQ(str, "streams")) {
878                 return parse_str(targ->streams, pkey, sizeof(targ->streams));
879         }
880         if (STR_EQ(str, "local lpm")) {
881                 return parse_flag(&targ->flags, TASK_ARG_LOCAL_LPM, pkey);
882         }
883         if (STR_EQ(str, "drop")) {
884                 return parse_flag(&targ->flags, TASK_ARG_DROP, pkey);
885         }
886         if (STR_EQ(str, "loop")) {
887                 parse_flag(&targ->loop, 1, pkey);
888                 return parse_flag(&targ->loop, 1, pkey);
889         }
890         if (STR_EQ(str, "qinq")) {
891                 return parse_flag(&targ->flags, TASK_ARG_QINQ_ACL, pkey);
892         }
893         if (STR_EQ(str, "bps")) {
894                 return parse_u64(&targ->rate_bps, pkey);
895         }
896         if (STR_EQ(str, "random")) {
897                 return parse_str(targ->rand_str[targ->n_rand_str++], pkey, sizeof(targ->rand_str[0]));
898         }
899         if (STR_EQ(str, "rand_offset")) {
900                 if (targ->n_rand_str == 0) {
901                         set_errf("No random defined previously (use random=...)");
902                         return -1;
903                 }
904
905                 return parse_int(&targ->rand_offset[targ->n_rand_str - 1], pkey);
906         }
907         if (STR_EQ(str, "keep src mac")) {
908                 return parse_flag(&targ->flags, DSF_KEEP_SRC_MAC, pkey);
909         }
910         if (STR_EQ(str, "pcap file")) {
911                 return parse_str(targ->pcap_file, pkey, sizeof(targ->pcap_file));
912         }
913         if (STR_EQ(str, "pkt inline")) {
914                 char pkey2[MAX_CFG_STRING_LEN];
915                 if (parse_str(pkey2, pkey, sizeof(pkey2)) != 0) {
916                         set_errf("Error while parsing pkt line, too long\n");
917                         return -1;
918                 }
919
920                 const size_t pkey_len = strlen(pkey2);
921                 targ->pkt_size = 0;
922
923                 for (size_t i = 0; i < pkey_len; ++i) {
924                         if (pkey2[i] == ' ')
925                                 continue;
926
927                         if (i + 1 == pkey_len) {
928                                 set_errf("Incomplete byte at character %z", i);
929                                 return -1;
930                         }
931
932                         uint8_t byte = 0;
933
934                         if (pkey2[i] >= '0' && pkey2[i] <= '9') {
935                                 byte = (pkey2[i] - '0') << 4;
936                         }
937                         else if (pkey2[i] >= 'a' && pkey2[i] <= 'f') {
938                                 byte = (pkey2[i] - 'a' + 10) << 4;
939                         }
940                         else if (pkey2[i] >= 'A' && pkey2[i] <= 'F') {
941                                 byte = (pkey2[i] - 'A' + 10) << 4;
942                         }
943                         else {
944                                 set_errf("Invalid character in pkt inline at byte %d (%c)", i, pkey2[i]);
945                                 return -1;
946                         }
947
948                         if (pkey2[i + 1] >= '0' && pkey2[i + 1] <= '9') {
949                                 byte |= (pkey2[i + 1] - '0');
950                         }
951                         else if (pkey2[i + 1] >= 'a' && pkey2[i + 1] <= 'f') {
952                                 byte |= (pkey2[i + 1] - 'a' + 10);
953                         }
954                         else if (pkey2[i + 1] >= 'A' && pkey2[i + 1] <= 'F') {
955                                 byte |= (pkey2[i + 1] - 'A' + 10);
956                         }
957                         else {
958                                 set_errf("Invalid character in pkt inline at byte %d (%c)", i, pkey2[i + 1]);
959                                 return -1;
960                         }
961                         if (targ->pkt_size == sizeof(targ->pkt_inline)) {
962                                 set_errf("Inline packet definition can't be longer than 1518");
963                         }
964
965                         targ->pkt_inline[targ->pkt_size++] = byte;
966                         i += 1;
967                 }
968
969                 return 0;
970         }
971         if (STR_EQ(str, "accuracy limit nsec")) {
972                 return parse_int(&targ->accuracy_limit_nsec, pkey);
973         }
974         if (STR_EQ(str, "latency bucket size")) {
975                 return parse_int(&targ->bucket_size, pkey);
976         }
977         if (STR_EQ(str, "latency buffer size")) {
978                 return parse_int(&targ->latency_buffer_size, pkey);
979         }
980         if (STR_EQ(str, "accuracy pos")) {
981                 return parse_int(&targ->accur_pos, pkey);
982         }
983         if (STR_EQ(str, "signature")) {
984                 return parse_int(&targ->sig, pkey);
985         }
986         if (STR_EQ(str, "signature pos")) {
987                 return parse_int(&targ->sig_pos, pkey);
988         }
989         if (STR_EQ(str, "lat pos")) {
990                 targ->lat_enabled = 1;
991                 return parse_int(&targ->lat_pos, pkey);
992         }
993         if (STR_EQ(str, "packet id pos")) {
994                 return parse_int(&targ->packet_id_pos, pkey);
995         }
996         if (STR_EQ(str, "probability")) {
997                 float probability;
998                 int rc = parse_float(&probability, pkey);
999                 if (probability == 0) {
1000                         set_errf("Probability must be != 0\n");
1001                         return -1;
1002                 } else if (probability > 100.0) {
1003                         set_errf("Probability must be < 100\n");
1004                         return -1;
1005                 }
1006                 targ->probability = probability * 10000;
1007                 return rc;
1008         }
1009         if (STR_EQ(str, "concur conn")) {
1010                 return parse_int(&targ->n_concur_conn, pkey);
1011         }
1012         if (STR_EQ(str, "max setup rate")) {
1013                 return parse_int(&targ->max_setup_rate, pkey);
1014         }
1015         if (STR_EQ(str, "pkt size")) {
1016                 return parse_int(&targ->pkt_size, pkey);
1017         }
1018         if (STR_EQ(str, "min bulk size")) {
1019                 return parse_int(&targ->min_bulk_size, pkey);
1020         }
1021         if (STR_EQ(str, "max bulk size")) {
1022                 return parse_int(&targ->max_bulk_size, pkey);
1023         }
1024         if (STR_EQ(str, "rx port")) {
1025                 if (targ->flags & TASK_ARG_RX_RING) {
1026                         set_errf("Can't read both from internal ring and external port from the same task. Use multiple tasks instead.");
1027                         return -1;
1028                 }
1029                 uint32_t vals[PROX_MAX_PORTS];
1030                 uint32_t n_if;
1031
1032                 if (parse_port_name_list(vals, &n_if, PROX_MAX_PORTS, pkey)) {
1033                         return -1;
1034                 }
1035
1036                 for (uint8_t i = 0; i < n_if; ++i) {
1037                         PROX_ASSERT(vals[i] < PROX_MAX_PORTS);
1038                         targ->rx_port_queue[i].port = vals[i];
1039                         targ->nb_rxports++;
1040                 }
1041                 return 0;
1042         }
1043
1044         if (STR_EQ(str, "mode")) {
1045                 /* Check deprecated task modes */
1046                 char mode[255];
1047                 int ret = parse_str(mode, pkey, sizeof(mode));
1048                 if (ret)
1049                         return ret;
1050
1051                 for (uint32_t i = 0; i < RTE_DIM(task_cfg_depr); ++i) {
1052                         if (STR_EQ(mode, task_cfg_depr[i].opt)) {
1053                                 set_errf("Task mode '%s' is deprecated%s%s",
1054                                          task_cfg_depr[i].opt, strlen(task_cfg_depr[i].info)? ": ": "", task_cfg_depr[i].info);
1055                                 return -1;
1056                         }
1057                 }
1058
1059                 /* master is a special mode that is always needed (cannot be turned off) */
1060                 if (STR_EQ(mode, "master")) {
1061                         prox_cfg.master = ncore;
1062                         targ->mode = MASTER;
1063                         if (lconf->n_tasks_all > 1 || targ->task != 0) {
1064                                 set_errf("Master core can only have one task\n");
1065                                 return -1;
1066                         }
1067                         // Initialize number of tasks to 1 for master, even if no task specified
1068                         lconf->n_tasks_all = 1;
1069                         lconf->active_task = 0;
1070                         lconf->targs[lconf->active_task].task = 0;
1071                         struct task_init* task_init = to_task_init(mode, "");
1072                         if (task_init) {
1073                                 targ->mode = task_init->mode;
1074                         }
1075                         targ->task_init = task_init;
1076                         return 0;
1077                 }
1078
1079                 struct task_init* task_init = to_task_init(mode, "");
1080                 if (task_init) {
1081                         targ->mode = task_init->mode;
1082                 }
1083                 else {
1084                         set_errf("Task mode '%s' is invalid", mode);
1085                         tasks_list();
1086                         return -1;
1087                 }
1088                 targ->task_init = task_init;
1089                 return 0;
1090         }
1091         if (STR_EQ(str, "users")) {
1092                 return parse_int(&targ->n_flows, pkey);
1093         }
1094
1095         if (STR_EQ(str, "mark")) {
1096                 return parse_flag(&targ->runtime_flags, TASK_MARK, pkey);
1097         }
1098
1099         if (STR_EQ(str, "mark green")) {
1100                 return parse_int(&targ->marking[0], pkey);
1101         }
1102
1103         if (STR_EQ(str, "mark yellow")) {
1104                 return parse_int(&targ->marking[1], pkey);
1105         }
1106
1107         if (STR_EQ(str, "mark red")) {
1108                 return parse_int(&targ->marking[2], pkey);
1109         }
1110
1111         if (STR_EQ(str, "tx cores")) {
1112                 uint8_t dest_task = 0;
1113                 /* if user did not specify, dest_port is left at default (first type) */
1114                 uint8_t dest_proto = 0;
1115                 uint8_t ctrl = CTRL_TYPE_DP;
1116                 char *task_str = strstr(pkey, "proto=");
1117                 if (task_str) {
1118                         task_str += strlen("proto=");
1119
1120                         if (STR_EQ(task_str, "ipv4")) {
1121                                 dest_proto = IPV4;
1122                         }
1123                         else if (STR_EQ(task_str, "arp")) {
1124                                 dest_proto = ARP;
1125                         }
1126                         else if (STR_EQ(task_str, "ipv6")) {
1127                                 dest_proto = IPV6;
1128                         }
1129                         else {
1130                                 set_errf("proto needs to be either ipv4, arp or ipv6");
1131                                 return -1;
1132                         }
1133
1134                 }
1135
1136                 task_str = strstr(pkey, "task=");
1137
1138                 if (task_str) {
1139                         --task_str;
1140                         *task_str = 0;
1141                         task_str++;
1142                         task_str += strlen("task=");
1143                         char *task_str_end = strstr(task_str, " ");
1144                         if (task_str_end) {
1145                                 *task_str_end = 0;
1146                         }
1147                         if (0 == strlen(task_str)) {
1148                                 set_errf("Invalid task= syntax");
1149                                 return -1;
1150                         }
1151
1152                         switch (task_str[strlen(task_str) - 1]) {
1153                         case 'p':
1154                                 ctrl = CTRL_TYPE_PKT;
1155                                 break;
1156                         case 'm':
1157                                 ctrl = CTRL_TYPE_MSG;
1158                                 break;
1159                         case '\n':
1160                         case 0:
1161                                 break;
1162                         default:
1163                                 if (task_str[strlen(task_str) -1] < '0' ||
1164                                     task_str[strlen(task_str) -1] > '9') {
1165                                         set_errf("Unknown ring type %c.\n",
1166                                                  task_str[strlen(task_str) - 1]);
1167                                         return -1;
1168                                 }
1169                         }
1170
1171                         dest_task = atoi(task_str);
1172                         if (dest_task >= MAX_TASKS_PER_CORE) {
1173                                 set_errf("Destination task too high (max allowed %d)", MAX_TASKS_PER_CORE - 1);
1174                                 return -1;
1175                         }
1176                 }
1177                 else {
1178                         dest_task = 0;
1179                 }
1180
1181                 struct core_task_set *cts = &targ->core_task_set[dest_proto];
1182
1183                 if (parse_task_set(cts, pkey))
1184                         return -1;
1185
1186                 if (cts->n_elems > MAX_WT_PER_LB) {
1187                         set_errf("Too many worker threads (max allowed %d)", MAX_WT_PER_LB - 1);
1188                         return -1;
1189                 }
1190
1191                 targ->nb_worker_threads = cts->n_elems;
1192                 targ->nb_txrings += cts->n_elems;
1193
1194                 return 0;
1195         }
1196         if (STR_EQ(str, "tx crc")) {
1197                 return parse_flag(&targ->runtime_flags, TASK_TX_CRC, pkey);
1198         }
1199         if (STR_EQ(str, "ring size")) {
1200                 return parse_int(&targ->ring_size, pkey);
1201         }
1202         if (STR_EQ(str, "mempool size")) {
1203                 return parse_kmg(&targ->nb_mbuf, pkey);
1204         }
1205
1206         else if (STR_EQ(str, "mbuf size")) {
1207                 targ->mbuf_size_set_explicitely = 1;
1208                 return parse_int(&targ->mbuf_size, pkey);
1209         }
1210         if (STR_EQ(str, "memcache size")) {
1211                 return parse_kmg(&targ->nb_cache_mbuf, pkey);
1212         }
1213
1214         if (STR_EQ(str, "byte offset")) {
1215                 return parse_int(&targ->byte_offset, pkey);
1216         }
1217
1218         if (STR_EQ(str, "name")) {
1219                 return parse_str(lconf->name, pkey, sizeof(lconf->name));
1220         }
1221         /* MPLS configuration */
1222         if (STR_EQ(str, "untag mpls")) {
1223                 return parse_flag(&targ->runtime_flags, TASK_MPLS_TAGGING, pkey);
1224         }
1225
1226         if (STR_EQ(str, "add mpls")) {
1227                 return parse_flag(&targ->runtime_flags, TASK_MPLS_TAGGING, pkey);
1228         }
1229
1230         if (STR_EQ(str, "ether type")) {
1231                 return parse_int(&targ->etype, pkey);
1232         }
1233
1234         if (STR_EQ(str, "cache set")) {
1235                 return parse_int(&lconf->cache_set, pkey);
1236         }
1237
1238         if (STR_EQ(str, "sub mode")) {
1239                 const char* mode_str = targ->task_init->mode_str;
1240                 const char *sub_mode_str = pkey;
1241
1242                 targ->task_init = to_task_init(mode_str, sub_mode_str);
1243                 if (!targ->task_init) {
1244                         if (strcmp(sub_mode_str, "l3") != 0) {
1245                                 set_errf("sub mode %s not supported for mode %s", sub_mode_str, mode_str);
1246                                 return -1;
1247                         }
1248                         targ->task_init = to_task_init(mode_str, "");
1249                         if (!targ->task_init) {
1250                                 set_errf("sub mode %s not supported for mode %s", sub_mode_str, mode_str);
1251                                 return -1;
1252                         }
1253                 }
1254                 if (strcmp(sub_mode_str, "l3") == 0) {
1255                         prox_cfg.flags |= DSF_CTRL_PLANE_ENABLED;
1256                         targ->flags |= TASK_ARG_L3;
1257                         strcpy(targ->sub_mode_str, "l3");
1258                 } else {
1259                         strcpy(targ->sub_mode_str, targ->task_init->sub_mode_str);
1260                 }
1261                 return 0;
1262         }
1263
1264         if (STR_EQ(str, "mempool name")) {
1265                 return parse_str(targ->pool_name, pkey, sizeof(targ->pool_name));
1266         }
1267         if (STR_EQ(str, "dpi engine")) {
1268                 return parse_str(targ->dpi_engine_path, pkey, sizeof(targ->dpi_engine_path));
1269         }
1270         if (STR_EQ(str, "dpi engine arg")) {
1271                 return parse_str(targ->dpi_engine_args[targ->n_dpi_engine_args++], pkey,
1272                                  sizeof(targ->dpi_engine_args[0]));
1273         }
1274         if (STR_EQ(str, "dst mac")) { /* destination MAC address to be used for packets */
1275                 if (parse_mac(&targ->edaddr, pkey)) {
1276                         if (STR_EQ(pkey, "no")) {
1277                                 targ->flags |= TASK_ARG_DO_NOT_SET_DST_MAC;
1278                                 return 0;
1279                         }
1280                         if (STR_EQ(pkey, "packet") == 0)
1281                                 return -1;
1282                         else
1283                                 return 0;
1284                 }
1285                 targ->flags |= TASK_ARG_DST_MAC_SET;
1286                 return 0;
1287         }
1288         if (STR_EQ(str, "src mac")) {
1289                 if (parse_mac(&targ->esaddr, pkey)) {
1290                         if (STR_EQ(pkey, "no")) {
1291                                 targ->flags |= TASK_ARG_DO_NOT_SET_SRC_MAC;
1292                                 return 0;
1293                         }
1294                         else if (STR_EQ(pkey, "packet"))
1295                                 return 0;
1296                         else if (STR_EQ(pkey, "hw")) {
1297                                 targ->flags |= TASK_ARG_HW_SRC_MAC;
1298                                 return 0;
1299                         } else {
1300                                 return -1;
1301                         }
1302                 }
1303                 targ->flags |= TASK_ARG_SRC_MAC_SET;
1304                 return 0;
1305         }
1306         if (STR_EQ(str, "gateway ipv4")) { /* Gateway IP address used when generating */
1307                 return parse_ip(&targ->gateway_ipv4, pkey);
1308         }
1309         if (STR_EQ(str, "local ipv4")) { /* source IP address to be used for packets */
1310                 return parse_ip(&targ->local_ipv4, pkey);
1311         }
1312         if (STR_EQ(str, "remote ipv4")) { /* source IP address to be used for packets */
1313                 return parse_ip(&targ->remote_ipv4, pkey);
1314         }
1315         if (STR_EQ(str, "local ipv6")) { /* source IPv6 address to be used for packets */
1316                 return parse_ip6(&targ->local_ipv6, pkey);
1317         }
1318         if (STR_EQ(str, "number of packets"))
1319                 return parse_int(&targ->n_pkts, pkey);
1320         if (STR_EQ(str, "pipes")) {
1321                 uint32_t val;
1322                 int err = parse_int(&val, pkey);
1323                 if (err)
1324                         return -1;
1325                 if (!val || !rte_is_power_of_2(val)) {
1326                         set_errf("Number of pipes has to be power of 2 and not zero");
1327                         return -1;
1328                 }
1329
1330                 targ->qos_conf.port_params.n_pipes_per_subport = val;
1331                 return 0;
1332         }
1333         if (STR_EQ(str, "queue size")) {
1334                 uint32_t val;
1335                 int err = parse_int(&val, pkey);
1336                 if (err) {
1337                         return -1;
1338                 }
1339
1340                 targ->qos_conf.port_params.qsize[0] = val;
1341                 targ->qos_conf.port_params.qsize[1] = val;
1342                 targ->qos_conf.port_params.qsize[2] = val;
1343                 targ->qos_conf.port_params.qsize[3] = val;
1344                 return 0;
1345         }
1346         if (STR_EQ(str, "subport tb rate")) {
1347                 return parse_int(&targ->qos_conf.subport_params[0].tb_rate, pkey);
1348         }
1349         if (STR_EQ(str, "subport tb size")) {
1350                 return parse_int(&targ->qos_conf.subport_params[0].tb_size, pkey);
1351         }
1352         if (STR_EQ(str, "subport tc 0 rate")) {
1353                 return parse_int(&targ->qos_conf.subport_params[0].tc_rate[0], pkey);
1354         }
1355         if (STR_EQ(str, "subport tc 1 rate")) {
1356                 return parse_int(&targ->qos_conf.subport_params[0].tc_rate[1], pkey);
1357         }
1358         if (STR_EQ(str, "subport tc 2 rate")) {
1359                 return parse_int(&targ->qos_conf.subport_params[0].tc_rate[2], pkey);
1360         }
1361         if (STR_EQ(str, "subport tc 3 rate")) {
1362                 return parse_int(&targ->qos_conf.subport_params[0].tc_rate[3], pkey);
1363         }
1364
1365         if (STR_EQ(str, "subport tc rate")) {
1366                 uint32_t val;
1367                 int err = parse_int(&val, pkey);
1368                 if (err) {
1369                         return -1;
1370                 }
1371
1372                 targ->qos_conf.subport_params[0].tc_rate[0] = val;
1373                 targ->qos_conf.subport_params[0].tc_rate[1] = val;
1374                 targ->qos_conf.subport_params[0].tc_rate[2] = val;
1375                 targ->qos_conf.subport_params[0].tc_rate[3] = val;
1376
1377                 return 0;
1378         }
1379         if (STR_EQ(str, "subport tc period")) {
1380                 return parse_int(&targ->qos_conf.subport_params[0].tc_period, pkey);
1381         }
1382         if (STR_EQ(str, "pipe tb rate")) {
1383                 return parse_int(&targ->qos_conf.pipe_params[0].tb_rate, pkey);
1384         }
1385         if (STR_EQ(str, "pipe tb size")) {
1386                 return parse_int(&targ->qos_conf.pipe_params[0].tb_size, pkey);
1387         }
1388         if (STR_EQ(str, "pipe tc rate")) {
1389                 uint32_t val;
1390                 int err = parse_int(&val, pkey);
1391                 if (err) {
1392                         return -1;
1393                 }
1394
1395                 targ->qos_conf.pipe_params[0].tc_rate[0] = val;
1396                 targ->qos_conf.pipe_params[0].tc_rate[1] = val;
1397                 targ->qos_conf.pipe_params[0].tc_rate[2] = val;
1398                 targ->qos_conf.pipe_params[0].tc_rate[3] = val;
1399                 return 0;
1400         }
1401         if (STR_EQ(str, "pipe tc 0 rate")) {
1402                 return parse_int(&targ->qos_conf.pipe_params[0].tc_rate[0], pkey);
1403         }
1404         if (STR_EQ(str, "pipe tc 1 rate")) {
1405                 return parse_int(&targ->qos_conf.pipe_params[0].tc_rate[1], pkey);
1406         }
1407         if (STR_EQ(str, "pipe tc 2 rate")) {
1408                 return parse_int(&targ->qos_conf.pipe_params[0].tc_rate[2], pkey);
1409         }
1410         if (STR_EQ(str, "pipe tc 3 rate")) {
1411                 return parse_int(&targ->qos_conf.pipe_params[0].tc_rate[3], pkey);
1412         }
1413         if (STR_EQ(str, "pipe tc period")) {
1414                 return parse_int(&targ->qos_conf.pipe_params[0].tc_period, pkey);
1415         }
1416         if (STR_EQ(str, "police action")) {
1417                 char *in = strstr(pkey, " io=");
1418                 if (in == NULL) {
1419                         set_errf("Need to specify io colors using io=in_color,out_color\n");
1420                         return -1;
1421                 }
1422                 *in = 0;
1423                 in += strlen(" io=");
1424
1425                 char *out = strstr(in, ",");
1426                 if (out == NULL) {
1427                         set_errf("Output color not specified\n");
1428                 }
1429                 *out = 0;
1430                 out++;
1431
1432                 enum police_action in_color = str_to_color(in);
1433                 enum police_action out_color = str_to_color(out);
1434
1435                 if (in_color == ACT_INVALID) {
1436                         set_errf("Invalid input color %s. Expected green, yellow or red", in);
1437                         return -1;
1438                 }
1439                 if (out_color == ACT_INVALID) {
1440                         set_errf("Invalid output color %s. Expected green, yellow or red", out);
1441                         return -1;
1442                 }
1443                 enum police_action action = str_to_color(pkey);
1444                 if (action == ACT_INVALID) {
1445                         set_errf("Error action %s. Expected green, yellow, red or drop", pkey);
1446                         return -1;
1447                 }
1448                 targ->police_act[in_color][out_color] = action;
1449
1450                 return 0;
1451         }
1452         if (STR_EQ(str, "qinq tag")) {
1453                 return parse_int(&targ->qinq_tag, pkey);
1454         }
1455         if (STR_EQ(str, "cir")) {
1456                 return parse_int(&targ->cir, pkey);
1457         }
1458         if (STR_EQ(str, "cbs")) {
1459                 return parse_int(&targ->cbs, pkey);
1460         }
1461         if (STR_EQ(str, "pir")) {
1462                 return parse_int(&targ->pir, pkey);
1463         }
1464         if (STR_EQ(str, "pbs")) {
1465                 return parse_int(&targ->pbs, pkey);
1466         }
1467         if (STR_EQ(str, "ebs")) {
1468                 return parse_int(&targ->ebs, pkey);
1469         }
1470         uint32_t queue_id = 0;
1471         if (sscanf(str, "queue %d weight", &queue_id) == 1) {
1472                 uint32_t val;
1473                 int err = parse_int(&val, pkey);
1474                 if (err) {
1475                         return -1;
1476                 }
1477                 targ->qos_conf.pipe_params[0].wrr_weights[queue_id] = val;
1478                 return 0;
1479         }
1480         if (STR_EQ(str, "classify")) {
1481                 if (!(targ->task_init->flag_features & TASK_FEATURE_CLASSIFY)) {
1482                         set_errf("Classify is not supported in '%s' mode", targ->task_init->mode_str);
1483                         return -1;
1484                 }
1485
1486                 return parse_flag(&targ->runtime_flags, TASK_CLASSIFY, pkey);
1487         }
1488         if (STR_EQ(str, "flow table size")) {
1489                 return parse_int(&targ->flow_table_size, pkey);
1490         }
1491 #ifdef GRE_TP
1492         if (STR_EQ(str, "tbf rate")) {
1493                 return parse_int(&targ->tb_rate, pkey);
1494         }
1495         if (STR_EQ(str, "tbf size")) {
1496                 return parse_int(&targ->tb_size, pkey);
1497         }
1498 #endif
1499         if (STR_EQ(str, "max rules")) {
1500                 return parse_int(&targ->n_max_rules, pkey);
1501         }
1502
1503         if (STR_EQ(str, "tunnel hop limit")) {
1504                 uint32_t val;
1505                 int err = parse_int(&val, pkey);
1506                 if (err) {
1507                         return -1;
1508                 }
1509                 targ->tunnel_hop_limit = val;
1510                 return 0;
1511         }
1512
1513         if (STR_EQ(str, "lookup port mask")) {
1514                 uint32_t val;
1515                 int err = parse_int(&val, pkey);
1516                 if (err) {
1517                         return -1;
1518                 }
1519                 targ->lookup_port_mask = val;
1520                 return 0;
1521         }
1522
1523         set_errf("Option '%s' is not known", str);
1524         /* fail on unknown keys */
1525         return -1;
1526 }
1527
1528 static int str_is_number(const char *in)
1529 {
1530         int dot_once = 0;
1531
1532         for (size_t i = 0; i < strlen(in); ++i) {
1533                 if (!dot_once && in[i] == '.') {
1534                         dot_once = 1;
1535                         continue;
1536                 }
1537
1538                 if (in[i] < '0' || in[i] > '9')
1539                         return 0;
1540         }
1541
1542         return 1;
1543 }
1544
1545 /* command line parameters parsing procedure */
1546 int prox_parse_args(int argc, char **argv)
1547 {
1548         int i, opt, ret;
1549         char *tmp, *tmp2;
1550         char tmp3[64];
1551
1552         /* Default settings */
1553         prox_cfg.flags |= DSF_AUTOSTART | DSF_WAIT_ON_QUIT;
1554         prox_cfg.ui = PROX_UI_CURSES;
1555
1556         plog_info("\tCommand line:");
1557         for (i = 0; i < argc; ++i) {
1558                 plog_info(" %s", argv[i]);
1559         }
1560         plog_info("\n");
1561
1562         while ((opt = getopt(argc, argv, "f:dnzpo:tkuar:emsiw:l:v:q:")) != EOF) {
1563                 switch (opt) {
1564                 case 'f':
1565                         /* path to config file */
1566                         cfg_file = optarg;
1567                         size_t offset = 0;
1568                         for (size_t i = 0; i < strlen(cfg_file); ++i) {
1569                                 if (cfg_file[i] == '/') {
1570                                         offset = i + 1;
1571                                 }
1572                         }
1573
1574                         strncpy(prox_cfg.name, cfg_file + offset, MAX_NAME_SIZE);
1575                         break;
1576                 case 'v':
1577                         plog_set_lvl(atoi(optarg));
1578                         break;
1579                 case 'l':
1580                         prox_cfg.log_name_pid = 0;
1581                         strncpy(prox_cfg.log_name, optarg, MAX_NAME_SIZE);
1582                         break;
1583                 case 'p':
1584                         prox_cfg.log_name_pid = 1;
1585                         break;
1586                 case 'k':
1587                         prox_cfg.use_stats_logger = 1;
1588                         break;
1589                 case 'd':
1590                         prox_cfg.flags |= DSF_DAEMON;
1591                         prox_cfg.ui = PROX_UI_NONE;
1592                         break;
1593                 case 'z':
1594                         prox_cfg.flags |= DSF_USE_DUMMY_CPU_TOPO;
1595                         prox_cfg.flags |= DSF_CHECK_INIT;
1596                         break;
1597                 case 'n':
1598                         prox_cfg.flags |= DSF_USE_DUMMY_DEVICES;
1599                         break;
1600                 case 'r':
1601                         if (!str_is_number(optarg) || strlen(optarg) > 11)
1602                                 return -1;
1603                         strncpy(prox_cfg.update_interval_str, optarg, sizeof(prox_cfg.update_interval_str));
1604                         break;
1605                 case 'o':
1606                         if (prox_cfg.flags & DSF_DAEMON)
1607                                 break;
1608
1609                         if (!strcmp(optarg, "curses")) {
1610                                 prox_cfg.ui = PROX_UI_CURSES;
1611                         }
1612                         else if (!strcmp(optarg, "cli")) {
1613                                 prox_cfg.ui = PROX_UI_CLI;
1614                         }
1615                         else if (!strcmp(optarg, "none")) {
1616                                 prox_cfg.ui = PROX_UI_NONE;
1617                         }
1618                         else {
1619                                 plog_err("Invalid local UI '%s', local UI can be 'curses', 'cli' or 'none'.", optarg);
1620                                 return -1;
1621                         }
1622                         break;
1623                 case 'q':
1624                         if (luaL_loadstring(prox_lua(), optarg)) {
1625                                 set_errf("Lua error: '%s'\n", lua_tostring(prox_lua(), -1));
1626                                 return -1;
1627                         }
1628
1629                         if (lua_pcall(prox_lua(), 0, LUA_MULTRET, 0)) {
1630                                 set_errf("Lua error: '%s'\n", lua_tostring(prox_lua(), -1));
1631                                 return -1;
1632                         }
1633
1634                         break;
1635                 case 'a':
1636                         /* autostart all cores */
1637                         prox_cfg.flags |= DSF_AUTOSTART;
1638                         break;
1639                 case 'e':
1640                         /* don't autostart */
1641                         prox_cfg.flags &= ~DSF_AUTOSTART;
1642                         break;
1643                 case 't':
1644                         prox_cfg.flags |= DSF_LISTEN_TCP;
1645                         break;
1646                 case 'u':
1647                         prox_cfg.flags |= DSF_LISTEN_UDS;
1648                         break;
1649                 case 'm':
1650                         /* list supported task modes and exit */
1651                         prox_cfg.flags |= DSF_LIST_TASK_MODES;
1652                         break;
1653                 case 's':
1654                         /* check configuration file syntax and exit */
1655                         prox_cfg.flags |= DSF_CHECK_SYNTAX;
1656                         break;
1657                 case 'i':
1658                         /* check initialization sequence and exit */
1659                         prox_cfg.flags |= DSF_CHECK_INIT;
1660                         break;
1661                 case 'w':
1662                         tmp = optarg;
1663                         tmp2 = 0;
1664                         if (strlen(tmp) >= 3 &&
1665                             (tmp2 = strchr(tmp, '='))) {
1666                                 *tmp2 = 0;
1667                                 tmp3[0] = '$';
1668                                 strncpy(tmp3 + 1, tmp, 63);
1669                                 plog_info("\tAdding variable: %s = %s\n", tmp3, tmp2 + 1);
1670                                 ret = add_var(tmp3, tmp2 + 1, 1);
1671                                 if (ret == -2) {
1672                                         plog_err("\tFailed to add variable, too many variables defines\n");
1673                                         return -1;
1674                                 }
1675                                 else if(ret == -3) {
1676                                         plog_err("\tFailed to add variable, already defined\n");
1677                                         return -1;
1678                                 }
1679                                 break;
1680                         }
1681                         /* fall-through */
1682                 default:
1683                         plog_err("\tUnknown option\n");
1684                         return -1;
1685                 }
1686         }
1687
1688         /* reset getopt lib for DPDK */
1689         optind = 0;
1690
1691         return 0;
1692 }
1693
1694 static int check_cfg(void)
1695 {
1696         /* Sanity check */
1697 #define RETURN_IF(cond, err)                    \
1698         if (cond) {                             \
1699                 plog_err(err);                  \
1700                 return -1;                      \
1701         };
1702
1703         RETURN_IF(rte_cfg.force_nchannel == 0, "\tError: number of memory channels not specified in [eal options] section\n");
1704         RETURN_IF(prox_cfg.master >= RTE_MAX_LCORE, "\tError: No master core specified (one core needs to have mode=master)\n");
1705
1706 #undef RETURN_IF
1707
1708         return 0;
1709 }
1710
1711 static int calc_tot_rxrings(void)
1712 {
1713         struct lcore_cfg *slconf, *dlconf;
1714         struct task_args *starg, *dtarg;
1715         uint32_t dlcore_id;
1716         uint8_t dtask_id;
1717         struct core_task ct;
1718
1719         dlconf = NULL;
1720         while (core_targ_next_early(&dlconf, &dtarg, 1) == 0) {
1721                 dtarg->tot_rxrings = 0;
1722         }
1723
1724         slconf = NULL;
1725         while (core_targ_next_early(&slconf, &starg, 1) == 0) {
1726                 for (uint8_t idx = 0; idx < MAX_PROTOCOLS; ++idx) {
1727                         for (uint8_t ring_idx = 0; ring_idx < starg->core_task_set[idx].n_elems; ++ring_idx) {
1728                                 ct = starg->core_task_set[idx].core_task[ring_idx];
1729                                 if (!prox_core_active(ct.core, 0)) {
1730                                         set_errf("Core %u is disabled but Core %u task %u is sending to it\n",
1731                                                  ct.core, slconf->id, starg->id);
1732                                         return -1;
1733                                 }
1734
1735                                 dlconf = &lcore_cfg_init[ct.core];
1736
1737                                 if (ct.task >= dlconf->n_tasks_all) {
1738                                         set_errf("Core %u task %u not enabled\n", ct.core, ct.task);
1739                                         return -1;
1740                                 }
1741
1742                                 dtarg = &dlconf->targs[ct.task];
1743
1744                                 /* Control rings are not relevant at this point. */
1745                                 if (ct.type)
1746                                         continue;
1747
1748                                 if (!(dtarg->flags & TASK_ARG_RX_RING)) {
1749                                         set_errf("Core %u task %u is not expecting to receive through a ring\n",
1750                                                  ct.core, ct.task);
1751                                         return -1;
1752                                 }
1753
1754                                 dtarg->tot_rxrings++;
1755                                 if (dtarg->tot_rxrings > MAX_RINGS_PER_TASK) {
1756                                         set_errf("Core %u task %u is receiving from too many tasks",
1757                                                  ct.core, ct.task);
1758                                         return -1;
1759                                 }
1760                         }
1761                 }
1762         }
1763
1764         return 0;
1765 }
1766
1767 static void prox_set_core_mask(void)
1768 {
1769         struct lcore_cfg *lconf;
1770
1771         prox_core_clr();
1772         for (uint8_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
1773                 lconf = &lcore_cfg_init[lcore_id];
1774                 if (lconf->n_tasks_all > 0 && lconf->targs[0].mode != MASTER) {
1775                         prox_core_set_active(lcore_id);
1776                 }
1777         }
1778 }
1779
1780 static int is_using_no_drop(void)
1781 {
1782         uint32_t lcore_id;
1783         struct lcore_cfg *lconf;
1784         struct task_args *targs;
1785
1786         lcore_id = -1;
1787         while(prox_core_next(&lcore_id, 1) == 0) {
1788                 lconf = &lcore_cfg_init[lcore_id];
1789                 for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
1790                         targs = &lconf->targs[task_id];
1791                         if (!(targs->flags & TASK_ARG_DROP))
1792                                 return 1;
1793                 }
1794         }
1795         return 0;
1796 }
1797
1798 int prox_read_config_file(void)
1799 {
1800         set_global_defaults(&prox_cfg);
1801         set_task_defaults(&prox_cfg, lcore_cfg_init);
1802         set_port_defaults();
1803         plog_info("=== Parsing configuration file '%s' ===\n", cfg_file);
1804         struct cfg_file *pcfg = cfg_open(cfg_file);
1805         if (pcfg == NULL) {
1806                 return -1;
1807         }
1808
1809         struct cfg_section* config_sections[] = {
1810                 &lua_cfg          ,
1811                 &var_cfg          ,
1812                 &eal_default_cfg  ,
1813                 &cache_set_cfg    ,
1814                 &port_cfg         ,
1815                 &defaults_cfg     ,
1816                 &settings_cfg     ,
1817                 &core_cfg         ,
1818                 NULL
1819         };
1820
1821         for (struct cfg_section** section = config_sections; *section != NULL; ++section) {
1822                 const char* name = (*section)->name;
1823                 size_t len = strlen(name);
1824                 plog_info("\t*** Reading [%s] section%s ***\n", name, name[len - 1] == '#'? "s": "");
1825                 cfg_parse(pcfg, *section);
1826
1827                 if ((*section)->error) {
1828                         plog_err("At line %u, section [%s], entry %u: '%s'\n\t%s\n"
1829                                  , pcfg->err_line, pcfg->err_section, pcfg->err_entry + 1, pcfg->cur_line,
1830                                  strlen(get_parse_err())? get_parse_err() : err_str);
1831                         cfg_close(pcfg); /* cannot close before printing error, print uses internal buffer */
1832                         return -1;
1833                 }
1834         }
1835
1836         cfg_close(pcfg);
1837
1838         prox_set_core_mask();
1839
1840         if (is_using_no_drop()) {
1841                 prox_cfg.flags &= ~DSF_WAIT_ON_QUIT;
1842         }
1843
1844         if (calc_tot_rxrings()) {
1845                 plog_err("Error in configuration: %s\n", err_str);
1846                 return -1;
1847         }
1848
1849         return check_cfg();
1850 }
1851
1852 static void failed_rte_eal_init(__attribute__((unused))const char *prog_name)
1853 {
1854         plog_err("\tError in rte_eal_init()\n");
1855 }
1856
1857 int prox_setup_rte(const char *prog_name)
1858 {
1859         char *rte_argv[MAX_RTE_ARGV];
1860         char  rte_arg[MAX_RTE_ARGV][MAX_ARG_LEN];
1861         char tmp[PROX_CM_STR_LEN];
1862         /* create mask of used cores */
1863         plog_info("=== Setting up RTE EAL ===\n");
1864
1865         if (prox_cfg.flags & DSF_USE_DUMMY_CPU_TOPO) {
1866                 plog_info("Using dummy cpu topology\n");
1867                 snprintf(tmp, sizeof(tmp), "0x1");
1868         } else {
1869                 prox_core_to_hex(tmp, sizeof(tmp), 0);
1870                 plog_info("\tWorker threads core mask is %s\n", tmp);
1871                 prox_core_to_hex(tmp, sizeof(tmp), 1);
1872                 plog_info("\tWith master core index %u, full core mask is %s\n", prox_cfg.master, tmp);
1873         }
1874
1875         /* fake command line parameters for rte_eal_init() */
1876         int argc = 0;
1877         rte_argv[argc] = strdup(prog_name);
1878         sprintf(rte_arg[++argc], "-c%s", tmp);
1879         rte_argv[argc] = rte_arg[argc];
1880 #if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0)
1881         if (prox_cfg.flags & DSF_USE_DUMMY_CPU_TOPO)
1882                 sprintf(rte_arg[++argc], "--master-lcore=%u", 0);
1883         else
1884                 sprintf(rte_arg[++argc], "--master-lcore=%u", prox_cfg.master);
1885         rte_argv[argc] = rte_arg[argc];
1886 #else
1887         /* For old DPDK versions, the master core had to be the first
1888            core. */
1889         uint32_t first_core = -1;
1890
1891         if (prox_core_next(&first_core, 1) == -1) {
1892                 plog_err("Can't core ID of first core in use\n");
1893                 return -1;
1894         }
1895         if (first_core != prox_cfg.master) {
1896                 plog_err("The master core needs to be the first core (master core = %u, first core = %u).\n", first_core, prox_cfg.master);
1897                 return -1;
1898         }
1899 #endif
1900
1901         if (rte_cfg.memory) {
1902                 sprintf(rte_arg[++argc], "-m%u", rte_cfg.memory);
1903                 rte_argv[argc] = rte_arg[argc];
1904         }
1905
1906         if (rte_cfg.force_nchannel) {
1907                 sprintf(rte_arg[++argc], "-n%u", rte_cfg.force_nchannel);
1908                 rte_argv[argc] = rte_arg[argc];
1909         }
1910
1911         if (rte_cfg.force_nrank) {
1912                 sprintf(rte_arg[++argc], "-r%u", rte_cfg.force_nrank);
1913                 rte_argv[argc] = rte_arg[argc];
1914         }
1915
1916         if (rte_cfg.no_hugetlbfs) {
1917                 strcpy(rte_arg[++argc], "--no-huge");
1918                 rte_argv[argc] = rte_arg[argc];
1919         }
1920
1921         if (rte_cfg.no_pci) {
1922                 strcpy(rte_arg[++argc], "--no-pci");
1923                 rte_argv[argc] = rte_arg[argc];
1924         }
1925
1926         if (rte_cfg.no_hpet) {
1927                 strcpy(rte_arg[++argc], "--no-hpet");
1928                 rte_argv[argc] = rte_arg[argc];
1929         }
1930
1931         if (rte_cfg.no_shconf) {
1932                 strcpy(rte_arg[++argc], "--no-shconf");
1933                 rte_argv[argc] = rte_arg[argc];
1934         }
1935
1936         if (rte_cfg.eal != NULL) {
1937                 char *ptr = rte_cfg.eal;
1938                 char *ptr2;
1939                 while (ptr != NULL) {
1940                         while (isspace(*ptr))
1941                                 ptr++;
1942                         ptr2 = ptr;
1943                         ptr = strchr(ptr, ' ');
1944                         if (ptr) {
1945                                 *ptr++ = '\0';
1946                         }
1947                         strcpy(rte_arg[++argc], ptr2);
1948                         rte_argv[argc] = rte_arg[argc];
1949                 }
1950         }
1951
1952         if (rte_cfg.hugedir != NULL) {
1953                 strcpy(rte_arg[++argc], "--huge-dir");
1954                 rte_argv[argc] = rte_arg[argc];
1955                 rte_argv[++argc] = rte_cfg.hugedir;
1956         }
1957
1958         if (rte_cfg.no_output) {
1959                 rte_log_set_global_level(0);
1960         }
1961         /* init EAL */
1962         plog_info("\tEAL command line:");
1963         if (argc >= MAX_RTE_ARGV) {
1964                 plog_err("too many arguments for EAL\n");
1965                 return -1;
1966         }
1967
1968         for (int h = 0; h <= argc; ++h) {
1969                 plog_info(" %s", rte_argv[h]);
1970         }
1971         plog_info("\n");
1972
1973         rte_set_application_usage_hook(failed_rte_eal_init);
1974         if (rte_eal_init(++argc, rte_argv) < 0) {
1975                 plog_err("\tError in rte_eal_init()\n");
1976                 return -1;
1977         }
1978         plog_info("\tEAL Initialized\n");
1979
1980         if (prox_cfg.flags & DSF_USE_DUMMY_CPU_TOPO)
1981                 return 0;
1982
1983         /* check if all active cores are in enabled in DPDK */
1984         for (uint32_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
1985                 if (lcore_id == prox_cfg.master) {
1986                         if (!rte_lcore_is_enabled(lcore_id))
1987                                 return -1;
1988                 }
1989                 else if (rte_lcore_is_enabled(lcore_id) != prox_core_active(lcore_id, 0)) {
1990                         plog_err("\tFailed to enable lcore %u\n", lcore_id);
1991                         return -1;
1992                 }
1993                 else if (lcore_cfg_init[lcore_id].n_tasks_all != 0 && !rte_lcore_is_enabled(lcore_id)) {
1994                         plog_err("\tFailed to enable lcore %u\n", lcore_id);
1995                         return -1;
1996                 }
1997         }
1998         return 0;
1999 }