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