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