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