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