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