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