2 // Copyright (c) 2010-2017 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <rte_sched.h>
21 #include <rte_string_fns.h>
22 #include <rte_version.h>
24 #include "prox_malloc.h"
27 #include "prox_args.h"
28 #include "prox_assert.h"
33 #include "parse_utils.h"
34 #include "prox_port_cfg.h"
38 #include "prox_compat.h"
40 #define MAX_RTE_ARGV 64
41 #define MAX_ARG_LEN 64
49 #define STR_EQ(s1, s2) (!strcmp((s1), (s2)))
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);
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];
65 static char format_err_str[1024];
66 static const char *err_str = "Unknown error";
68 static struct cfg_section eal_default_cfg = {
69 .name = "eal options",
70 .parser = get_rte_cfg,
77 static struct cfg_section port_cfg = {
79 .parser = get_port_cfg,
80 .data = &prox_port_cfg,
86 static struct cfg_section var_cfg = {
88 .parser = get_var_cfg,
95 static struct cfg_section cache_set_cfg = {
96 .name = "cache set #",
97 .parser = get_cache_set_cfg,
98 .data = &prox_cache_set_cfg,
104 static struct cfg_section defaults_cfg = {
106 .parser = get_defaults_cfg,
113 static struct cfg_section settings_cfg = {
115 .parser = get_global_cfg,
122 static struct cfg_section lua_cfg = {
124 .parser = get_lua_cfg,
131 static struct cfg_section core_cfg = {
133 .parser = get_core_cfg,
134 .data = lcore_cfg_init,
140 static void set_errf(const char *format, ...)
143 va_start(ap, format);
144 vsnprintf(format_err_str, sizeof(format_err_str), format, ap);
146 err_str = format_err_str;
149 /* [eal options] parser */
150 static int get_rte_cfg(__attribute__((unused))unsigned sindex, char *str, void *data)
152 struct rte_cfg *pconfig = (struct rte_cfg *)data;
154 if (str == NULL || pconfig == NULL) {
158 char *pkey = get_cfg_key(str);
160 set_errf("Missing key after option");
164 if (STR_EQ(str, "-m")) {
165 return parse_int(&pconfig->memory, pkey);
167 if (STR_EQ(str, "-n")) {
168 if (parse_int(&pconfig->force_nchannel, pkey)) {
171 if (pconfig->force_nchannel == 0) {
172 set_errf("Invalid number of memory channels");
177 if (STR_EQ(str, "-r")) {
178 if (parse_int(&pconfig->force_nrank, pkey)) {
181 if (pconfig->force_nrank == 0 || pconfig->force_nrank > 16) {
182 set_errf("Invalid number of memory ranks");
188 if (STR_EQ(str, "no-pci")) {
189 return parse_bool(&pconfig->no_pci, pkey);
191 if (STR_EQ(str, "no-hpet")) {
192 return parse_bool(&pconfig->no_hpet, pkey);
194 if (STR_EQ(str, "no-shconf")) {
195 return parse_bool(&pconfig->no_shconf, pkey);
197 if (STR_EQ(str, "no-huge")) {
198 return parse_bool(&pconfig->no_hugetlbfs, pkey);
200 if (STR_EQ(str, "no-output")) {
201 return parse_bool(&pconfig->no_output, pkey);
204 if (STR_EQ(str, "huge-dir")) {
205 if (pconfig->hugedir) {
206 free(pconfig->hugedir);
208 pconfig->hugedir = strdup(pkey);
212 if (STR_EQ(str, "eal")) {
213 char eal[MAX_STR_LEN_PROC];
218 if (parse_str(eal, pkey, sizeof(eal)))
221 strip_spaces(&pkey, 1);
223 pconfig->eal = strdup(pkey);
227 set_errf("Option '%s' is not known", str);
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"},
238 const char *get_cfg_dir(void)
240 static char dir[PATH_MAX];
241 size_t end = strlen(cfg_file) - 1;
242 while (end > 0 && cfg_file[end] != '/')
245 strncpy(dir, cfg_file, end);
249 static int get_lua_cfg(__attribute__((unused)) unsigned sindex, __attribute__((unused)) char *str, __attribute__((unused)) void *data)
253 if (NULL == getcwd(cwd, sizeof(cwd))) {
254 set_errf("Failed to get current directory while loading Lua file\n");
257 status = chdir(get_cfg_dir());
259 set_errf("Failed to change directory to '%s' while loading Lua file\n", get_cfg_dir());
263 struct lua_State *l = prox_lua();
266 strncpy(str_cpy, str, sizeof(str_cpy));
267 uint32_t len = strlen(str_cpy);
268 str_cpy[len++] = '\n';
271 status = luaL_loadstring(l, str_cpy);
273 set_errf("Lua error: '%s'\n", lua_tostring(l, -1));
278 status = lua_pcall(l, 0, LUA_MULTRET, 0);
280 set_errf("Lua error: '%s'\n", lua_tostring(l, -1));
287 set_errf("Failed to restore current directory to '%s' while loading Lua file\n", cwd);
294 /* [global] parser */
295 static int get_global_cfg(__attribute__((unused))unsigned sindex, char *str, void *data)
297 struct prox_cfg *pset = (struct prox_cfg *)data;
299 if (str == NULL || pset == NULL) {
303 char *pkey = get_cfg_key(str);
305 set_errf("Missing key after option");
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);
317 if (STR_EQ(str, "name")) {
318 return parse_str(pset->name, pkey, sizeof(pset->name));
321 if (STR_EQ(str, "start time")) {
322 return parse_int(&pset->start_time, pkey);
325 if (STR_EQ(str, "duration time")) {
326 return parse_int(&pset->duration_time, pkey);
329 if (STR_EQ(str, "shuffle")) {
330 return parse_flag(&pset->flags, DSF_SHUFFLE, pkey);
332 if (STR_EQ(str, "disable cmt")) {
333 return parse_flag(&pset->flags, DSF_DISABLE_CMT, pkey);
335 if (STR_EQ(str, "mp rings")) {
336 return parse_flag(&pset->flags, DSF_MP_RINGS, pkey);
338 if (STR_EQ(str, "enable bypass")) {
339 return parse_flag(&pset->flags, DSF_ENABLE_BYPASS, pkey);
342 if (STR_EQ(str, "cpe table map")) {
343 /* The config defined ports through 0, 1, 2 ... which
344 need to be associated with ports. This is done
345 through defining it using "cpe table map=" */
346 return parse_port_name_list((uint32_t*)pset->cpe_table_ports, NULL, PROX_MAX_PORTS, pkey);
349 if (STR_EQ(str, "pre cmd")) {
353 if (STR_EQ(str, "unique mempool per socket")) {
354 return parse_flag(&pset->flags, UNIQUE_MEMPOOL_PER_SOCKET, pkey);
357 if (STR_EQ(str, "log buffer size")) {
358 if (parse_kmg(&pset->logbuf_size, pkey)) {
361 plog_info("Logging to buffer with size = %d\n", pset->logbuf_size);
365 set_errf("Option '%s' is not known", str);
369 /* [variable] parser */
370 static int get_var_cfg(__attribute__((unused)) unsigned sindex, char *str, __attribute__((unused)) void *data)
372 return add_var(str, get_cfg_key(str), 0);
375 /* [defaults] parser */
376 static int get_defaults_cfg(__attribute__((unused)) unsigned sindex, char *str, __attribute__((unused)) void *data)
381 pkey = get_cfg_key(str);
383 set_errf("Missing key after option");
387 if (STR_EQ(str, "mempool size")) {
389 if (parse_kmg(&val, pkey)) {
393 for (uint8_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
394 struct lcore_cfg *cur_lcore_cfg_init = &lcore_cfg_init[lcore_id];
395 cur_lcore_cfg_init->id = lcore_id;
396 for (uint8_t task_id = 0; task_id < MAX_TASKS_PER_CORE; ++task_id) {
397 struct task_args *targ = &cur_lcore_cfg_init->targs[task_id];
405 if (STR_EQ(str, "qinq tag")) {
406 for (uint8_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
407 struct lcore_cfg *cur_lcore_cfg_init = &lcore_cfg_init[lcore_id];
408 cur_lcore_cfg_init->id = lcore_id;
409 for (uint8_t task_id = 0; task_id < MAX_TASKS_PER_CORE; ++task_id) {
410 struct task_args *targ = &cur_lcore_cfg_init->targs[task_id];
411 parse_int(&targ->qinq_tag, pkey);
416 if (STR_EQ(str, "memcache size")) {
418 if (parse_kmg(&val, pkey)) {
422 for (uint8_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
423 struct lcore_cfg *cur_lcore_cfg_init = &lcore_cfg_init[lcore_id];
424 cur_lcore_cfg_init->id = lcore_id;
425 for (uint8_t task_id = 0; task_id < MAX_TASKS_PER_CORE; ++task_id) {
426 struct task_args *targ = &cur_lcore_cfg_init->targs[task_id];
427 targ->nb_cache_mbuf = val;
433 set_errf("Option '%s' is not known", str);
437 /* [cache set] parser */
438 static int get_cache_set_cfg(unsigned sindex, char *str, void *data)
440 struct prox_cache_set_cfg *cfg = (struct prox_cache_set_cfg *)data;
442 uint8_t cur_if = sindex & ~CFG_INDEXED;
444 if (cur_if >= PROX_MAX_CACHE_SET) {
445 set_errf("Cache set ID is too high (max allowed %d)", PROX_MAX_CACHE_SET - 1 );
449 cfg = &prox_cache_set_cfg[cur_if];
451 if (str == NULL || data == NULL) {
455 char *pkey = get_cfg_key(str);
458 set_errf("Missing key after option");
462 if (STR_EQ(str, "mask")) {
464 int err = parse_int(&val, pkey);
470 plog_info("\tCache set %d has mask %x\n", cur_if, cfg->mask);
477 static int get_port_cfg(unsigned sindex, char *str, void *data)
479 struct prox_port_cfg *cfg = (struct prox_port_cfg *)data;
481 uint8_t cur_if = sindex & ~CFG_INDEXED;
483 if (cur_if >= PROX_MAX_PORTS) {
484 set_errf("Port ID is too high (max allowed %d)", PROX_MAX_PORTS - 1 );
488 cfg = &prox_port_cfg[cur_if];
490 if (str == NULL || data == NULL) {
494 char *pkey = get_cfg_key(str);
497 set_errf("Missing key after option");
501 if (STR_EQ(str, "mac")) {
502 if (STR_EQ(pkey, "hardware")) {
503 cfg->type = PROX_PORT_MAC_HW;
505 else if (STR_EQ(pkey, "random")) {
506 cfg->type = PROX_PORT_MAC_RAND;
509 cfg->type = PROX_PORT_MAC_SET;
510 if (parse_mac(&cfg->eth_addr, pkey)) {
515 else if (STR_EQ(str, "name")) {
517 strncpy(cfg->name, pkey, MAX_NAME_SIZE);
518 PROX_ASSERT(cur_if < PROX_MAX_PORTS);
519 return add_port_name(cur_if, pkey);
521 else if (STR_EQ(str, "rx desc")) {
522 return parse_int(&cfg->n_rxd, pkey);
524 else if (STR_EQ(str, "tx desc")) {
525 return parse_int(&cfg->n_txd, pkey);
527 else if (STR_EQ(str, "promiscuous")) {
529 if (parse_bool(&val, pkey)) {
532 cfg->promiscuous = val;
534 else if (STR_EQ(str, "lsc")) {
535 cfg->lsc_set_explicitely = 1;
537 if (parse_bool(&val, pkey)) {
542 else if (STR_EQ(str, "strip crc")) {
544 if (parse_bool(&val, pkey)) {
547 cfg->port_conf.rxmode.hw_strip_crc = val;
549 else if (STR_EQ(str, "rss")) {
551 if (parse_bool(&val, pkey)) {
555 cfg->port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
556 cfg->port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IPV4;
559 else if (STR_EQ(str, "rx_ring")) {
560 parse_str(cfg->rx_ring, pkey, sizeof(cfg->rx_ring));
562 else if (STR_EQ(str, "tx_ring")) {
563 parse_str(cfg->tx_ring, pkey, sizeof(cfg->tx_ring));
569 static enum police_action str_to_color(const char *str)
571 if (STR_EQ(str, "green"))
573 if (STR_EQ(str, "yellow"))
575 if (STR_EQ(str, "red"))
577 if (STR_EQ(str, "drop"))
582 struct cfg_depr task_cfg_depr[] = {
586 struct cfg_depr core_cfg_depr[] = {
589 {"network side", ""},
593 static int get_core_cfg(unsigned sindex, char *str, void *data)
596 struct lcore_cfg *lconf = (struct lcore_cfg *)data;
598 if (str == NULL || lconf == NULL || !(sindex & CFG_INDEXED)) {
602 pkey = get_cfg_key(str);
604 set_errf("Missing key after option");
608 uint32_t ncore = sindex & ~CFG_INDEXED;
609 if (ncore >= RTE_MAX_LCORE) {
610 set_errf("Core index too high (max allowed %d)", RTE_MAX_LCORE - 1);
614 lconf = &lconf[ncore];
616 for (uint32_t i = 0; i < RTE_DIM(core_cfg_depr); ++i) {
617 if (STR_EQ(str, core_cfg_depr[i].opt)) {
618 set_errf("Option '%s' is deprecated%s%s",
619 core_cfg_depr[i].opt, strlen(core_cfg_depr[i].info)? ": ": "", core_cfg_depr[i].info);
625 lcore_to_socket_core_ht(ncore, buff, sizeof(buff));
627 if (STR_EQ(str, "task")) {
630 if (parse_int(&val, pkey)) {
633 if (val >= MAX_TASKS_PER_CORE) {
634 set_errf("Too many tasks for core (max allowed %d)", MAX_TASKS_PER_CORE - 1);
637 if (val != lconf->n_tasks_all) {
638 set_errf("Task ID skipped or defined twice");
642 lconf->active_task = val;
644 lconf->targs[lconf->active_task].task = lconf->active_task;
646 if (lconf->n_tasks_all < lconf->active_task + 1) {
647 lconf->n_tasks_all = lconf->active_task + 1;
652 struct task_args *targ = &lconf->targs[lconf->active_task];
653 if (STR_EQ(str, "tx ports from routing table")) {
654 uint32_t vals[PROX_MAX_PORTS];
656 if (!(targ->task_init->flag_features & TASK_FEATURE_ROUTING)) {
657 set_errf("tx port form route not supported mode %s", targ->task_init->mode_str);
661 if (parse_port_name_list(vals, &n_if, PROX_MAX_PORTS, pkey)) {
665 for (uint8_t i = 0; i < n_if; ++i) {
666 targ->tx_port_queue[i].port = vals[i];
669 targ->runtime_flags |= TASK_ROUTING;
672 if (STR_EQ(str, "tx ports from cpe table")) {
673 uint32_t vals[PROX_MAX_PORTS];
677 char* mapping_str = strstr(pkey, " remap=");
679 if (mapping_str != NULL) {
681 mapping_str += strlen(" remap=");
682 n_remap = parse_remap(targ->mapping, mapping_str);
685 if (parse_port_name_list(vals, &ret, PROX_MAX_PORTS, pkey)) {
689 if (n_remap != -1 && ret != (uint32_t)n_remap) {
690 set_errf("Expected %d remap elements but had %d", n_remap, ret);
694 for (uint8_t i = 0; i < ret; ++i) {
695 targ->tx_port_queue[i].port = vals[i];
697 /* default mapping this case is port0 -> port0 */
699 targ->mapping[vals[i]] = i;
703 targ->nb_txports = ret;
707 if (STR_EQ(str, "tx cores from routing table")) {
708 if (!(targ->task_init->flag_features & TASK_FEATURE_ROUTING)) {
709 set_errf("tx port form route not supported mode %s", targ->task_init->mode_str);
713 struct core_task_set *cts = &targ->core_task_set[0];
715 if (parse_task_set(cts, pkey))
718 if (cts->n_elems > MAX_WT_PER_LB) {
719 set_errf("Maximum worker threads allowed is %u but have %u", MAX_WT_PER_LB, cts->n_elems);
723 targ->nb_worker_threads = cts->n_elems;
724 targ->nb_txrings = cts->n_elems;
726 if (targ->nb_txrings > MAX_RINGS_PER_TASK) {
727 set_errf("Maximum allowed TX rings is %u but have %u", MAX_RINGS_PER_TASK, targ->nb_txrings);
731 targ->runtime_flags |= TASK_ROUTING;
734 if (STR_EQ(str, "tx cores from cpe table")) {
735 struct core_task_set *core_task_set = &targ->core_task_set[0];
739 mapping_str = strstr(pkey, " remap=");
740 if (mapping_str == NULL) {
741 set_errf("There is no default mapping for tx cores from cpe table. Please specify it through remap=");
745 mapping_str += strlen(" remap=");
746 ret = parse_remap(targ->mapping, mapping_str);
751 struct core_task_set *cts = &targ->core_task_set[0];
753 if (parse_task_set(cts, pkey))
755 if (cts->n_elems > MAX_RINGS_PER_TASK) {
756 set_errf("Maximum cores to route to is %u\n", MAX_RINGS_PER_TASK);
760 targ->nb_txrings = cts->n_elems;
762 if (ret != targ->nb_txrings) {
763 set_errf("Expecting same number of remaps as cores\n", str);
769 if (STR_EQ(str, "delay ms")) {
770 if (targ->delay_us) {
771 set_errf("delay ms and delay us are mutually exclusive\n", str);
775 int rc = parse_int(&delay_ms, pkey);
776 targ->delay_us = delay_ms * 1000;
779 if (STR_EQ(str, "delay us")) {
780 if (targ->delay_us) {
781 set_errf("delay ms and delay us are mutually exclusive\n", str);
784 return parse_int(&targ->delay_us, pkey);
786 if (STR_EQ(str, "random delay us")) {
787 return parse_int(&targ->random_delay_us, pkey);
789 if (STR_EQ(str, "cpe table timeout ms")) {
790 return parse_int(&targ->cpe_table_timeout_ms, pkey);
792 if (STR_EQ(str, "ctrl path polling frequency")) {
793 int rc = parse_int(&targ->ctrl_freq, pkey);
795 if (targ->ctrl_freq == 0) {
796 set_errf("ctrl frequency must be non null.");
803 if (STR_EQ(str, "handle arp")) {
804 return parse_flag(&targ->runtime_flags, TASK_CTRL_HANDLE_ARP, pkey);
806 if (STR_EQ(str, "fast path handle arp")) {
807 return parse_flag(&targ->runtime_flags, TASK_FP_HANDLE_ARP, pkey);
809 if (STR_EQ(str, "multiple arp")) {
810 return parse_flag(&targ->flags, TASK_MULTIPLE_MAC, pkey);
813 /* Using tx port name, only a _single_ port can be assigned to a task. */
814 if (STR_EQ(str, "tx port")) {
815 if (targ->nb_txports > 0) {
816 set_errf("Only one tx port can be defined per task. Use a LB task or routing instead.");
821 uint32_t ports[PROX_MAX_PORTS];
823 if(parse_port_name_list(ports, &n_if, PROX_MAX_PORTS, pkey)) {
827 PROX_ASSERT(n_if-1 < PROX_MAX_PORTS);
829 for (uint8_t i = 0; i < n_if; ++i) {
830 targ->tx_port_queue[i].port = ports[i];
835 targ->nb_worker_threads = targ->nb_txports;
840 if (STR_EQ(str, "rx ring")) {
842 int err = parse_bool(&val, pkey);
843 if (!err && val && targ->rx_port_queue[0].port != OUT_DISCARD) {
844 set_errf("Can't read both from internal ring and external port from the same task. Use multiple tasks instead.");
848 return parse_flag(&targ->flags, TASK_ARG_RX_RING, pkey);
850 if (STR_EQ(str, "private")) {
851 return parse_bool(&targ->use_src, pkey);
853 if (STR_EQ(str, "use src ip")) {
854 return parse_bool(&targ->use_src, pkey);
856 if (STR_EQ(str, "nat table")) {
857 return parse_str(targ->nat_table, pkey, sizeof(targ->nat_table));
859 if (STR_EQ(str, "rules")) {
860 return parse_str(targ->rules, pkey, sizeof(targ->rules));
862 if (STR_EQ(str, "route table")) {
863 return parse_str(targ->route_table, pkey, sizeof(targ->route_table));
865 if (STR_EQ(str, "dscp")) {
866 return parse_str(targ->dscp, pkey, sizeof(targ->dscp));
868 if (STR_EQ(str, "tun_bindings")) {
869 return parse_str(targ->tun_bindings, pkey, sizeof(targ->tun_bindings));
871 if (STR_EQ(str, "cpe table")) {
872 return parse_str(targ->cpe_table_name, pkey, sizeof(targ->cpe_table_name));
874 if (STR_EQ(str, "user table")) {
875 return parse_str(targ->user_table, pkey, sizeof(targ->user_table));
877 if (STR_EQ(str, "streams")) {
878 return parse_str(targ->streams, pkey, sizeof(targ->streams));
880 if (STR_EQ(str, "local lpm")) {
881 return parse_flag(&targ->flags, TASK_ARG_LOCAL_LPM, pkey);
883 if (STR_EQ(str, "drop")) {
884 return parse_flag(&targ->flags, TASK_ARG_DROP, pkey);
886 if (STR_EQ(str, "loop")) {
887 parse_flag(&targ->loop, 1, pkey);
888 return parse_flag(&targ->loop, 1, pkey);
890 if (STR_EQ(str, "qinq")) {
891 return parse_flag(&targ->flags, TASK_ARG_QINQ_ACL, pkey);
893 if (STR_EQ(str, "bps")) {
894 return parse_u64(&targ->rate_bps, pkey);
896 if (STR_EQ(str, "random")) {
897 return parse_str(targ->rand_str[targ->n_rand_str++], pkey, sizeof(targ->rand_str[0]));
899 if (STR_EQ(str, "rand_offset")) {
900 if (targ->n_rand_str == 0) {
901 set_errf("No random defined previously (use random=...)");
905 return parse_int(&targ->rand_offset[targ->n_rand_str - 1], pkey);
907 if (STR_EQ(str, "keep src mac")) {
908 return parse_flag(&targ->flags, DSF_KEEP_SRC_MAC, pkey);
910 if (STR_EQ(str, "pcap file")) {
911 return parse_str(targ->pcap_file, pkey, sizeof(targ->pcap_file));
913 if (STR_EQ(str, "pkt inline")) {
914 char pkey2[MAX_CFG_STRING_LEN];
915 if (parse_str(pkey2, pkey, sizeof(pkey2)) != 0) {
916 set_errf("Error while parsing pkt line, too long\n");
920 const size_t pkey_len = strlen(pkey2);
923 for (size_t i = 0; i < pkey_len; ++i) {
927 if (i + 1 == pkey_len) {
928 set_errf("Incomplete byte at character %z", i);
934 if (pkey2[i] >= '0' && pkey2[i] <= '9') {
935 byte = (pkey2[i] - '0') << 4;
937 else if (pkey2[i] >= 'a' && pkey2[i] <= 'f') {
938 byte = (pkey2[i] - 'a' + 10) << 4;
940 else if (pkey2[i] >= 'A' && pkey2[i] <= 'F') {
941 byte = (pkey2[i] - 'A' + 10) << 4;
944 set_errf("Invalid character in pkt inline at byte %d (%c)", i, pkey2[i]);
948 if (pkey2[i + 1] >= '0' && pkey2[i + 1] <= '9') {
949 byte |= (pkey2[i + 1] - '0');
951 else if (pkey2[i + 1] >= 'a' && pkey2[i + 1] <= 'f') {
952 byte |= (pkey2[i + 1] - 'a' + 10);
954 else if (pkey2[i + 1] >= 'A' && pkey2[i + 1] <= 'F') {
955 byte |= (pkey2[i + 1] - 'A' + 10);
958 set_errf("Invalid character in pkt inline at byte %d (%c)", i, pkey2[i + 1]);
961 if (targ->pkt_size == sizeof(targ->pkt_inline)) {
962 set_errf("Inline packet definition can't be longer than 1518");
965 targ->pkt_inline[targ->pkt_size++] = byte;
971 if (STR_EQ(str, "accuracy limit nsec")) {
972 return parse_int(&targ->accuracy_limit_nsec, pkey);
974 if (STR_EQ(str, "latency bucket size")) {
975 return parse_int(&targ->bucket_size, pkey);
977 if (STR_EQ(str, "latency buffer size")) {
978 return parse_int(&targ->latency_buffer_size, pkey);
980 if (STR_EQ(str, "accuracy pos")) {
981 return parse_int(&targ->accur_pos, pkey);
983 if (STR_EQ(str, "signature")) {
984 return parse_int(&targ->sig, pkey);
986 if (STR_EQ(str, "signature pos")) {
987 return parse_int(&targ->sig_pos, pkey);
989 if (STR_EQ(str, "lat pos")) {
990 targ->lat_enabled = 1;
991 return parse_int(&targ->lat_pos, pkey);
993 if (STR_EQ(str, "packet id pos")) {
994 return parse_int(&targ->packet_id_pos, pkey);
996 if (STR_EQ(str, "probability")) {
998 int rc = parse_float(&probability, pkey);
999 if (probability == 0) {
1000 set_errf("Probability must be != 0\n");
1002 } else if (probability > 100.0) {
1003 set_errf("Probability must be < 100\n");
1006 targ->probability = probability * 10000;
1009 if (STR_EQ(str, "concur conn")) {
1010 return parse_int(&targ->n_concur_conn, pkey);
1012 if (STR_EQ(str, "max setup rate")) {
1013 return parse_int(&targ->max_setup_rate, pkey);
1015 if (STR_EQ(str, "pkt size")) {
1016 return parse_int(&targ->pkt_size, pkey);
1018 if (STR_EQ(str, "min bulk size")) {
1019 return parse_int(&targ->min_bulk_size, pkey);
1021 if (STR_EQ(str, "max bulk size")) {
1022 return parse_int(&targ->max_bulk_size, pkey);
1024 if (STR_EQ(str, "rx port")) {
1025 if (targ->flags & TASK_ARG_RX_RING) {
1026 set_errf("Can't read both from internal ring and external port from the same task. Use multiple tasks instead.");
1029 uint32_t vals[PROX_MAX_PORTS];
1032 if (parse_port_name_list(vals, &n_if, PROX_MAX_PORTS, pkey)) {
1036 for (uint8_t i = 0; i < n_if; ++i) {
1037 PROX_ASSERT(vals[i] < PROX_MAX_PORTS);
1038 targ->rx_port_queue[i].port = vals[i];
1044 if (STR_EQ(str, "mode")) {
1045 /* Check deprecated task modes */
1047 int ret = parse_str(mode, pkey, sizeof(mode));
1051 for (uint32_t i = 0; i < RTE_DIM(task_cfg_depr); ++i) {
1052 if (STR_EQ(mode, task_cfg_depr[i].opt)) {
1053 set_errf("Task mode '%s' is deprecated%s%s",
1054 task_cfg_depr[i].opt, strlen(task_cfg_depr[i].info)? ": ": "", task_cfg_depr[i].info);
1059 /* master is a special mode that is always needed (cannot be turned off) */
1060 if (STR_EQ(mode, "master")) {
1061 prox_cfg.master = ncore;
1062 targ->mode = MASTER;
1063 if (lconf->n_tasks_all > 1 || targ->task != 0) {
1064 set_errf("Master core can only have one task\n");
1067 // Initialize number of tasks to 1 for master, even if no task specified
1068 lconf->n_tasks_all = 1;
1069 lconf->active_task = 0;
1070 lconf->targs[lconf->active_task].task = 0;
1071 struct task_init* task_init = to_task_init(mode, "");
1073 targ->mode = task_init->mode;
1075 targ->task_init = task_init;
1079 struct task_init* task_init = to_task_init(mode, "");
1081 targ->mode = task_init->mode;
1084 set_errf("Task mode '%s' is invalid", mode);
1088 targ->task_init = task_init;
1091 if (STR_EQ(str, "users")) {
1092 return parse_int(&targ->n_flows, pkey);
1095 if (STR_EQ(str, "mark")) {
1096 return parse_flag(&targ->runtime_flags, TASK_MARK, pkey);
1099 if (STR_EQ(str, "mark green")) {
1100 return parse_int(&targ->marking[0], pkey);
1103 if (STR_EQ(str, "mark yellow")) {
1104 return parse_int(&targ->marking[1], pkey);
1107 if (STR_EQ(str, "mark red")) {
1108 return parse_int(&targ->marking[2], pkey);
1111 if (STR_EQ(str, "tx cores")) {
1112 uint8_t dest_task = 0;
1113 /* if user did not specify, dest_port is left at default (first type) */
1114 uint8_t dest_proto = 0;
1115 uint8_t ctrl = CTRL_TYPE_DP;
1116 char *task_str = strstr(pkey, "proto=");
1118 task_str += strlen("proto=");
1120 if (STR_EQ(task_str, "ipv4")) {
1123 else if (STR_EQ(task_str, "arp")) {
1126 else if (STR_EQ(task_str, "ipv6")) {
1130 set_errf("proto needs to be either ipv4, arp or ipv6");
1136 task_str = strstr(pkey, "task=");
1142 task_str += strlen("task=");
1143 char *task_str_end = strstr(task_str, " ");
1147 if (0 == strlen(task_str)) {
1148 set_errf("Invalid task= syntax");
1152 switch (task_str[strlen(task_str) - 1]) {
1154 ctrl = CTRL_TYPE_PKT;
1157 ctrl = CTRL_TYPE_MSG;
1163 if (task_str[strlen(task_str) -1] < '0' ||
1164 task_str[strlen(task_str) -1] > '9') {
1165 set_errf("Unknown ring type %c.\n",
1166 task_str[strlen(task_str) - 1]);
1171 dest_task = atoi(task_str);
1172 if (dest_task >= MAX_TASKS_PER_CORE) {
1173 set_errf("Destination task too high (max allowed %d)", MAX_TASKS_PER_CORE - 1);
1181 struct core_task_set *cts = &targ->core_task_set[dest_proto];
1183 if (parse_task_set(cts, pkey))
1186 if (cts->n_elems > MAX_WT_PER_LB) {
1187 set_errf("Too many worker threads (max allowed %d)", MAX_WT_PER_LB - 1);
1191 targ->nb_worker_threads = cts->n_elems;
1192 targ->nb_txrings += cts->n_elems;
1196 if (STR_EQ(str, "tx crc")) {
1197 return parse_flag(&targ->runtime_flags, TASK_TX_CRC, pkey);
1199 if (STR_EQ(str, "ring size")) {
1200 return parse_int(&targ->ring_size, pkey);
1202 if (STR_EQ(str, "mempool size")) {
1203 return parse_kmg(&targ->nb_mbuf, pkey);
1206 else if (STR_EQ(str, "mbuf size")) {
1207 targ->mbuf_size_set_explicitely = 1;
1208 return parse_int(&targ->mbuf_size, pkey);
1210 if (STR_EQ(str, "memcache size")) {
1211 return parse_kmg(&targ->nb_cache_mbuf, pkey);
1214 if (STR_EQ(str, "byte offset")) {
1215 return parse_int(&targ->byte_offset, pkey);
1218 if (STR_EQ(str, "name")) {
1219 return parse_str(lconf->name, pkey, sizeof(lconf->name));
1221 /* MPLS configuration */
1222 if (STR_EQ(str, "untag mpls")) {
1223 return parse_flag(&targ->runtime_flags, TASK_MPLS_TAGGING, pkey);
1226 if (STR_EQ(str, "add mpls")) {
1227 return parse_flag(&targ->runtime_flags, TASK_MPLS_TAGGING, pkey);
1230 if (STR_EQ(str, "ether type")) {
1231 return parse_int(&targ->etype, pkey);
1234 if (STR_EQ(str, "cache set")) {
1235 return parse_int(&lconf->cache_set, pkey);
1238 if (STR_EQ(str, "sub mode")) {
1239 const char* mode_str = targ->task_init->mode_str;
1240 const char *sub_mode_str = pkey;
1242 targ->task_init = to_task_init(mode_str, sub_mode_str);
1243 if (!targ->task_init) {
1244 if (strcmp(sub_mode_str, "l3") != 0) {
1245 set_errf("sub mode %s not supported for mode %s", sub_mode_str, mode_str);
1248 targ->task_init = to_task_init(mode_str, "");
1249 if (!targ->task_init) {
1250 set_errf("sub mode %s not supported for mode %s", sub_mode_str, mode_str);
1254 if (strcmp(sub_mode_str, "l3") == 0) {
1255 prox_cfg.flags |= DSF_CTRL_PLANE_ENABLED;
1256 targ->flags |= TASK_ARG_L3;
1257 strcpy(targ->sub_mode_str, "l3");
1259 strcpy(targ->sub_mode_str, targ->task_init->sub_mode_str);
1264 if (STR_EQ(str, "mempool name")) {
1265 return parse_str(targ->pool_name, pkey, sizeof(targ->pool_name));
1267 if (STR_EQ(str, "dpi engine")) {
1268 return parse_str(targ->dpi_engine_path, pkey, sizeof(targ->dpi_engine_path));
1270 if (STR_EQ(str, "dpi engine arg")) {
1271 return parse_str(targ->dpi_engine_args[targ->n_dpi_engine_args++], pkey,
1272 sizeof(targ->dpi_engine_args[0]));
1274 if (STR_EQ(str, "dst mac")) { /* destination MAC address to be used for packets */
1275 if (parse_mac(&targ->edaddr, pkey)) {
1276 if (STR_EQ(pkey, "no")) {
1277 targ->flags |= TASK_ARG_DO_NOT_SET_DST_MAC;
1280 if (STR_EQ(pkey, "packet") == 0)
1285 targ->flags |= TASK_ARG_DST_MAC_SET;
1288 if (STR_EQ(str, "src mac")) {
1289 if (parse_mac(&targ->esaddr, pkey)) {
1290 if (STR_EQ(pkey, "no")) {
1291 targ->flags |= TASK_ARG_DO_NOT_SET_SRC_MAC;
1294 else if (STR_EQ(pkey, "packet"))
1296 else if (STR_EQ(pkey, "hw")) {
1297 targ->flags |= TASK_ARG_HW_SRC_MAC;
1303 targ->flags |= TASK_ARG_SRC_MAC_SET;
1306 if (STR_EQ(str, "gateway ipv4")) { /* Gateway IP address used when generating */
1307 return parse_ip(&targ->gateway_ipv4, pkey);
1309 if (STR_EQ(str, "local ipv4")) { /* source IP address to be used for packets */
1310 return parse_ip(&targ->local_ipv4, pkey);
1312 if (STR_EQ(str, "remote ipv4")) { /* source IP address to be used for packets */
1313 return parse_ip(&targ->remote_ipv4, pkey);
1315 if (STR_EQ(str, "local ipv6")) { /* source IPv6 address to be used for packets */
1316 return parse_ip6(&targ->local_ipv6, pkey);
1318 if (STR_EQ(str, "number of packets"))
1319 return parse_int(&targ->n_pkts, pkey);
1320 if (STR_EQ(str, "pipes")) {
1322 int err = parse_int(&val, pkey);
1325 if (!val || !rte_is_power_of_2(val)) {
1326 set_errf("Number of pipes has to be power of 2 and not zero");
1330 targ->qos_conf.port_params.n_pipes_per_subport = val;
1333 if (STR_EQ(str, "queue size")) {
1335 int err = parse_int(&val, pkey);
1340 targ->qos_conf.port_params.qsize[0] = val;
1341 targ->qos_conf.port_params.qsize[1] = val;
1342 targ->qos_conf.port_params.qsize[2] = val;
1343 targ->qos_conf.port_params.qsize[3] = val;
1346 if (STR_EQ(str, "subport tb rate")) {
1347 return parse_int(&targ->qos_conf.subport_params[0].tb_rate, pkey);
1349 if (STR_EQ(str, "subport tb size")) {
1350 return parse_int(&targ->qos_conf.subport_params[0].tb_size, pkey);
1352 if (STR_EQ(str, "subport tc 0 rate")) {
1353 return parse_int(&targ->qos_conf.subport_params[0].tc_rate[0], pkey);
1355 if (STR_EQ(str, "subport tc 1 rate")) {
1356 return parse_int(&targ->qos_conf.subport_params[0].tc_rate[1], pkey);
1358 if (STR_EQ(str, "subport tc 2 rate")) {
1359 return parse_int(&targ->qos_conf.subport_params[0].tc_rate[2], pkey);
1361 if (STR_EQ(str, "subport tc 3 rate")) {
1362 return parse_int(&targ->qos_conf.subport_params[0].tc_rate[3], pkey);
1365 if (STR_EQ(str, "subport tc rate")) {
1367 int err = parse_int(&val, pkey);
1372 targ->qos_conf.subport_params[0].tc_rate[0] = val;
1373 targ->qos_conf.subport_params[0].tc_rate[1] = val;
1374 targ->qos_conf.subport_params[0].tc_rate[2] = val;
1375 targ->qos_conf.subport_params[0].tc_rate[3] = val;
1379 if (STR_EQ(str, "subport tc period")) {
1380 return parse_int(&targ->qos_conf.subport_params[0].tc_period, pkey);
1382 if (STR_EQ(str, "pipe tb rate")) {
1383 return parse_int(&targ->qos_conf.pipe_params[0].tb_rate, pkey);
1385 if (STR_EQ(str, "pipe tb size")) {
1386 return parse_int(&targ->qos_conf.pipe_params[0].tb_size, pkey);
1388 if (STR_EQ(str, "pipe tc rate")) {
1390 int err = parse_int(&val, pkey);
1395 targ->qos_conf.pipe_params[0].tc_rate[0] = val;
1396 targ->qos_conf.pipe_params[0].tc_rate[1] = val;
1397 targ->qos_conf.pipe_params[0].tc_rate[2] = val;
1398 targ->qos_conf.pipe_params[0].tc_rate[3] = val;
1401 if (STR_EQ(str, "pipe tc 0 rate")) {
1402 return parse_int(&targ->qos_conf.pipe_params[0].tc_rate[0], pkey);
1404 if (STR_EQ(str, "pipe tc 1 rate")) {
1405 return parse_int(&targ->qos_conf.pipe_params[0].tc_rate[1], pkey);
1407 if (STR_EQ(str, "pipe tc 2 rate")) {
1408 return parse_int(&targ->qos_conf.pipe_params[0].tc_rate[2], pkey);
1410 if (STR_EQ(str, "pipe tc 3 rate")) {
1411 return parse_int(&targ->qos_conf.pipe_params[0].tc_rate[3], pkey);
1413 if (STR_EQ(str, "pipe tc period")) {
1414 return parse_int(&targ->qos_conf.pipe_params[0].tc_period, pkey);
1416 if (STR_EQ(str, "police action")) {
1417 char *in = strstr(pkey, " io=");
1419 set_errf("Need to specify io colors using io=in_color,out_color\n");
1423 in += strlen(" io=");
1425 char *out = strstr(in, ",");
1427 set_errf("Output color not specified\n");
1432 enum police_action in_color = str_to_color(in);
1433 enum police_action out_color = str_to_color(out);
1435 if (in_color == ACT_INVALID) {
1436 set_errf("Invalid input color %s. Expected green, yellow or red", in);
1439 if (out_color == ACT_INVALID) {
1440 set_errf("Invalid output color %s. Expected green, yellow or red", out);
1443 enum police_action action = str_to_color(pkey);
1444 if (action == ACT_INVALID) {
1445 set_errf("Error action %s. Expected green, yellow, red or drop", pkey);
1448 targ->police_act[in_color][out_color] = action;
1452 if (STR_EQ(str, "qinq tag")) {
1453 return parse_int(&targ->qinq_tag, pkey);
1455 if (STR_EQ(str, "cir")) {
1456 return parse_int(&targ->cir, pkey);
1458 if (STR_EQ(str, "cbs")) {
1459 return parse_int(&targ->cbs, pkey);
1461 if (STR_EQ(str, "pir")) {
1462 return parse_int(&targ->pir, pkey);
1464 if (STR_EQ(str, "pbs")) {
1465 return parse_int(&targ->pbs, pkey);
1467 if (STR_EQ(str, "ebs")) {
1468 return parse_int(&targ->ebs, pkey);
1470 uint32_t queue_id = 0;
1471 if (sscanf(str, "queue %d weight", &queue_id) == 1) {
1473 int err = parse_int(&val, pkey);
1477 targ->qos_conf.pipe_params[0].wrr_weights[queue_id] = val;
1480 if (STR_EQ(str, "classify")) {
1481 if (!(targ->task_init->flag_features & TASK_FEATURE_CLASSIFY)) {
1482 set_errf("Classify is not supported in '%s' mode", targ->task_init->mode_str);
1486 return parse_flag(&targ->runtime_flags, TASK_CLASSIFY, pkey);
1488 if (STR_EQ(str, "flow table size")) {
1489 return parse_int(&targ->flow_table_size, pkey);
1492 if (STR_EQ(str, "tbf rate")) {
1493 return parse_int(&targ->tb_rate, pkey);
1495 if (STR_EQ(str, "tbf size")) {
1496 return parse_int(&targ->tb_size, pkey);
1499 if (STR_EQ(str, "max rules")) {
1500 return parse_int(&targ->n_max_rules, pkey);
1503 if (STR_EQ(str, "tunnel hop limit")) {
1505 int err = parse_int(&val, pkey);
1509 targ->tunnel_hop_limit = val;
1513 if (STR_EQ(str, "lookup port mask")) {
1515 int err = parse_int(&val, pkey);
1519 targ->lookup_port_mask = val;
1523 set_errf("Option '%s' is not known", str);
1524 /* fail on unknown keys */
1528 static int str_is_number(const char *in)
1532 for (size_t i = 0; i < strlen(in); ++i) {
1533 if (!dot_once && in[i] == '.') {
1538 if (in[i] < '0' || in[i] > '9')
1545 /* command line parameters parsing procedure */
1546 int prox_parse_args(int argc, char **argv)
1552 /* Default settings */
1553 prox_cfg.flags |= DSF_AUTOSTART | DSF_WAIT_ON_QUIT;
1554 prox_cfg.ui = PROX_UI_CURSES;
1556 plog_info("\tCommand line:");
1557 for (i = 0; i < argc; ++i) {
1558 plog_info(" %s", argv[i]);
1562 while ((opt = getopt(argc, argv, "f:dnzpo:tkuar:emsiw:l:v:q:")) != EOF) {
1565 /* path to config file */
1568 for (size_t i = 0; i < strlen(cfg_file); ++i) {
1569 if (cfg_file[i] == '/') {
1574 strncpy(prox_cfg.name, cfg_file + offset, MAX_NAME_SIZE);
1577 plog_set_lvl(atoi(optarg));
1580 prox_cfg.log_name_pid = 0;
1581 strncpy(prox_cfg.log_name, optarg, MAX_NAME_SIZE);
1584 prox_cfg.log_name_pid = 1;
1587 prox_cfg.use_stats_logger = 1;
1590 prox_cfg.flags |= DSF_DAEMON;
1591 prox_cfg.ui = PROX_UI_NONE;
1594 prox_cfg.flags |= DSF_USE_DUMMY_CPU_TOPO;
1595 prox_cfg.flags |= DSF_CHECK_INIT;
1598 prox_cfg.flags |= DSF_USE_DUMMY_DEVICES;
1601 if (!str_is_number(optarg) || strlen(optarg) > 11)
1603 strncpy(prox_cfg.update_interval_str, optarg, sizeof(prox_cfg.update_interval_str));
1606 if (prox_cfg.flags & DSF_DAEMON)
1609 if (!strcmp(optarg, "curses")) {
1610 prox_cfg.ui = PROX_UI_CURSES;
1612 else if (!strcmp(optarg, "cli")) {
1613 prox_cfg.ui = PROX_UI_CLI;
1615 else if (!strcmp(optarg, "none")) {
1616 prox_cfg.ui = PROX_UI_NONE;
1619 plog_err("Invalid local UI '%s', local UI can be 'curses', 'cli' or 'none'.", optarg);
1624 if (luaL_loadstring(prox_lua(), optarg)) {
1625 set_errf("Lua error: '%s'\n", lua_tostring(prox_lua(), -1));
1629 if (lua_pcall(prox_lua(), 0, LUA_MULTRET, 0)) {
1630 set_errf("Lua error: '%s'\n", lua_tostring(prox_lua(), -1));
1636 /* autostart all cores */
1637 prox_cfg.flags |= DSF_AUTOSTART;
1640 /* don't autostart */
1641 prox_cfg.flags &= ~DSF_AUTOSTART;
1644 prox_cfg.flags |= DSF_LISTEN_TCP;
1647 prox_cfg.flags |= DSF_LISTEN_UDS;
1650 /* list supported task modes and exit */
1651 prox_cfg.flags |= DSF_LIST_TASK_MODES;
1654 /* check configuration file syntax and exit */
1655 prox_cfg.flags |= DSF_CHECK_SYNTAX;
1658 /* check initialization sequence and exit */
1659 prox_cfg.flags |= DSF_CHECK_INIT;
1664 if (strlen(tmp) >= 3 &&
1665 (tmp2 = strchr(tmp, '='))) {
1668 strncpy(tmp3 + 1, tmp, 63);
1669 plog_info("\tAdding variable: %s = %s\n", tmp3, tmp2 + 1);
1670 ret = add_var(tmp3, tmp2 + 1, 1);
1672 plog_err("\tFailed to add variable, too many variables defines\n");
1675 else if(ret == -3) {
1676 plog_err("\tFailed to add variable, already defined\n");
1683 plog_err("\tUnknown option\n");
1688 /* reset getopt lib for DPDK */
1694 static int check_cfg(void)
1697 #define RETURN_IF(cond, err) \
1703 RETURN_IF(rte_cfg.force_nchannel == 0, "\tError: number of memory channels not specified in [eal options] section\n");
1704 RETURN_IF(prox_cfg.master >= RTE_MAX_LCORE, "\tError: No master core specified (one core needs to have mode=master)\n");
1711 static int calc_tot_rxrings(void)
1713 struct lcore_cfg *slconf, *dlconf;
1714 struct task_args *starg, *dtarg;
1717 struct core_task ct;
1720 while (core_targ_next_early(&dlconf, &dtarg, 1) == 0) {
1721 dtarg->tot_rxrings = 0;
1725 while (core_targ_next_early(&slconf, &starg, 1) == 0) {
1726 for (uint8_t idx = 0; idx < MAX_PROTOCOLS; ++idx) {
1727 for (uint8_t ring_idx = 0; ring_idx < starg->core_task_set[idx].n_elems; ++ring_idx) {
1728 ct = starg->core_task_set[idx].core_task[ring_idx];
1729 if (!prox_core_active(ct.core, 0)) {
1730 set_errf("Core %u is disabled but Core %u task %u is sending to it\n",
1731 ct.core, slconf->id, starg->id);
1735 dlconf = &lcore_cfg_init[ct.core];
1737 if (ct.task >= dlconf->n_tasks_all) {
1738 set_errf("Core %u task %u not enabled\n", ct.core, ct.task);
1742 dtarg = &dlconf->targs[ct.task];
1744 /* Control rings are not relevant at this point. */
1748 if (!(dtarg->flags & TASK_ARG_RX_RING)) {
1749 set_errf("Core %u task %u is not expecting to receive through a ring\n",
1754 dtarg->tot_rxrings++;
1755 if (dtarg->tot_rxrings > MAX_RINGS_PER_TASK) {
1756 set_errf("Core %u task %u is receiving from too many tasks",
1767 static void prox_set_core_mask(void)
1769 struct lcore_cfg *lconf;
1772 for (uint8_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
1773 lconf = &lcore_cfg_init[lcore_id];
1774 if (lconf->n_tasks_all > 0 && lconf->targs[0].mode != MASTER) {
1775 prox_core_set_active(lcore_id);
1780 static int is_using_no_drop(void)
1783 struct lcore_cfg *lconf;
1784 struct task_args *targs;
1787 while(prox_core_next(&lcore_id, 1) == 0) {
1788 lconf = &lcore_cfg_init[lcore_id];
1789 for (uint8_t task_id = 0; task_id < lconf->n_tasks_all; ++task_id) {
1790 targs = &lconf->targs[task_id];
1791 if (!(targs->flags & TASK_ARG_DROP))
1798 int prox_read_config_file(void)
1800 set_global_defaults(&prox_cfg);
1801 set_task_defaults(&prox_cfg, lcore_cfg_init);
1802 set_port_defaults();
1803 plog_info("=== Parsing configuration file '%s' ===\n", cfg_file);
1804 struct cfg_file *pcfg = cfg_open(cfg_file);
1809 struct cfg_section* config_sections[] = {
1821 for (struct cfg_section** section = config_sections; *section != NULL; ++section) {
1822 const char* name = (*section)->name;
1823 size_t len = strlen(name);
1824 plog_info("\t*** Reading [%s] section%s ***\n", name, name[len - 1] == '#'? "s": "");
1825 cfg_parse(pcfg, *section);
1827 if ((*section)->error) {
1828 plog_err("At line %u, section [%s], entry %u: '%s'\n\t%s\n"
1829 , pcfg->err_line, pcfg->err_section, pcfg->err_entry + 1, pcfg->cur_line,
1830 strlen(get_parse_err())? get_parse_err() : err_str);
1831 cfg_close(pcfg); /* cannot close before printing error, print uses internal buffer */
1838 prox_set_core_mask();
1840 if (is_using_no_drop()) {
1841 prox_cfg.flags &= ~DSF_WAIT_ON_QUIT;
1844 if (calc_tot_rxrings()) {
1845 plog_err("Error in configuration: %s\n", err_str);
1852 static void failed_rte_eal_init(__attribute__((unused))const char *prog_name)
1854 plog_err("\tError in rte_eal_init()\n");
1857 int prox_setup_rte(const char *prog_name)
1859 char *rte_argv[MAX_RTE_ARGV];
1860 char rte_arg[MAX_RTE_ARGV][MAX_ARG_LEN];
1861 char tmp[PROX_CM_STR_LEN];
1862 /* create mask of used cores */
1863 plog_info("=== Setting up RTE EAL ===\n");
1865 if (prox_cfg.flags & DSF_USE_DUMMY_CPU_TOPO) {
1866 plog_info("Using dummy cpu topology\n");
1867 snprintf(tmp, sizeof(tmp), "0x1");
1869 prox_core_to_hex(tmp, sizeof(tmp), 0);
1870 plog_info("\tWorker threads core mask is %s\n", tmp);
1871 prox_core_to_hex(tmp, sizeof(tmp), 1);
1872 plog_info("\tWith master core index %u, full core mask is %s\n", prox_cfg.master, tmp);
1875 /* fake command line parameters for rte_eal_init() */
1877 rte_argv[argc] = strdup(prog_name);
1878 sprintf(rte_arg[++argc], "-c%s", tmp);
1879 rte_argv[argc] = rte_arg[argc];
1880 #if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0)
1881 if (prox_cfg.flags & DSF_USE_DUMMY_CPU_TOPO)
1882 sprintf(rte_arg[++argc], "--master-lcore=%u", 0);
1884 sprintf(rte_arg[++argc], "--master-lcore=%u", prox_cfg.master);
1885 rte_argv[argc] = rte_arg[argc];
1887 /* For old DPDK versions, the master core had to be the first
1889 uint32_t first_core = -1;
1891 if (prox_core_next(&first_core, 1) == -1) {
1892 plog_err("Can't core ID of first core in use\n");
1895 if (first_core != prox_cfg.master) {
1896 plog_err("The master core needs to be the first core (master core = %u, first core = %u).\n", first_core, prox_cfg.master);
1901 if (rte_cfg.memory) {
1902 sprintf(rte_arg[++argc], "-m%u", rte_cfg.memory);
1903 rte_argv[argc] = rte_arg[argc];
1906 if (rte_cfg.force_nchannel) {
1907 sprintf(rte_arg[++argc], "-n%u", rte_cfg.force_nchannel);
1908 rte_argv[argc] = rte_arg[argc];
1911 if (rte_cfg.force_nrank) {
1912 sprintf(rte_arg[++argc], "-r%u", rte_cfg.force_nrank);
1913 rte_argv[argc] = rte_arg[argc];
1916 if (rte_cfg.no_hugetlbfs) {
1917 strcpy(rte_arg[++argc], "--no-huge");
1918 rte_argv[argc] = rte_arg[argc];
1921 if (rte_cfg.no_pci) {
1922 strcpy(rte_arg[++argc], "--no-pci");
1923 rte_argv[argc] = rte_arg[argc];
1926 if (rte_cfg.no_hpet) {
1927 strcpy(rte_arg[++argc], "--no-hpet");
1928 rte_argv[argc] = rte_arg[argc];
1931 if (rte_cfg.no_shconf) {
1932 strcpy(rte_arg[++argc], "--no-shconf");
1933 rte_argv[argc] = rte_arg[argc];
1936 if (rte_cfg.eal != NULL) {
1937 char *ptr = rte_cfg.eal;
1939 while (ptr != NULL) {
1940 while (isspace(*ptr))
1943 ptr = strchr(ptr, ' ');
1947 strcpy(rte_arg[++argc], ptr2);
1948 rte_argv[argc] = rte_arg[argc];
1952 if (rte_cfg.hugedir != NULL) {
1953 strcpy(rte_arg[++argc], "--huge-dir");
1954 rte_argv[argc] = rte_arg[argc];
1955 rte_argv[++argc] = rte_cfg.hugedir;
1958 if (rte_cfg.no_output) {
1959 rte_log_set_global_level(0);
1962 plog_info("\tEAL command line:");
1963 if (argc >= MAX_RTE_ARGV) {
1964 plog_err("too many arguments for EAL\n");
1968 for (int h = 0; h <= argc; ++h) {
1969 plog_info(" %s", rte_argv[h]);
1973 rte_set_application_usage_hook(failed_rte_eal_init);
1974 if (rte_eal_init(++argc, rte_argv) < 0) {
1975 plog_err("\tError in rte_eal_init()\n");
1978 plog_info("\tEAL Initialized\n");
1980 if (prox_cfg.flags & DSF_USE_DUMMY_CPU_TOPO)
1983 /* check if all active cores are in enabled in DPDK */
1984 for (uint32_t lcore_id = 0; lcore_id < RTE_MAX_LCORE; ++lcore_id) {
1985 if (lcore_id == prox_cfg.master) {
1986 if (!rte_lcore_is_enabled(lcore_id))
1989 else if (rte_lcore_is_enabled(lcore_id) != prox_core_active(lcore_id, 0)) {
1990 plog_err("\tFailed to enable lcore %u\n", lcore_id);
1993 else if (lcore_cfg_init[lcore_id].n_tasks_all != 0 && !rte_lcore_is_enabled(lcore_id)) {
1994 plog_err("\tFailed to enable lcore %u\n", lcore_id);