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.
25 #include <rte_ether.h>
26 #include <rte_string_fns.h>
30 #include "parse_utils.h"
31 #include "prox_globals.h"
35 #include "prox_lua_types.h"
36 #include "prox_ipv6.h"
37 #include "prox_compat.h"
39 #define MAX_NB_PORT_NAMES PROX_MAX_PORTS
40 #define MAX_LEN_PORT_NAME 24
41 #define MAX_LEN_VAR_NAME 24
42 #define MAX_LEN_VAL 512
43 #define MAX_NB_VARS 32
45 #if MAX_WT_PER_LB > MAX_INDEX
46 #error MAX_WT_PER_LB > MAX_INDEX
49 /* The CPU topology of the system is used to parse "socket
50 notation". This notation allows to refer to cores on specific
51 sockets and the hyper-thread of those cores. The CPU topology is
52 loaded only if the socket notation is used at least once. */
55 int socket[MAX_SOCKETS][RTE_MAX_LCORE][2];
56 uint32_t n_cores[MAX_SOCKETS];
60 struct cpu_topology cpu_topo;
64 char name[MAX_LEN_PORT_NAME];
67 static struct port_name port_names[MAX_NB_PORT_NAMES];
68 static uint8_t nb_port_names;
72 char name[MAX_LEN_VAR_NAME];
73 char val[MAX_LEN_VAL];
76 static struct var vars[MAX_NB_VARS];
77 static uint8_t nb_vars;
79 static char format_err_str[256];
80 static const char *err_str = "";
82 const char *get_parse_err(void)
87 static int read_cpu_topology(void);
89 static int parse_core(int *socket, int *core, int *ht, const char* str);
91 static void set_errf(const char *format, ...)
95 vsnprintf(format_err_str, sizeof(format_err_str), format, ap);
97 err_str = format_err_str;
100 static struct var *var_lookup(const char *name)
102 for (uint8_t i = 0; i < nb_vars; ++i) {
103 if (!strcmp(name, vars[i].name)) {
110 int parse_single_var(char *val, size_t len, const char *name)
114 match = var_lookup(name);
116 if (strlen(match->val) + 1 > len) {
117 set_errf("Variables '%s' with value '%s' is too long\n",
118 match->name, match->val);
121 prox_strncpy(val, match->val, len);
125 /* name + 1 to skip leading '$' */
126 if (lua_to_string(prox_lua(), GLOBAL, name + 1, val, len) >= 0)
130 set_errf("Variable '%s' not defined!", name);
134 /* Replace $... and each occurrence of ${...} with variable values */
135 int parse_vars(char *val, size_t len, const char *name)
137 static char result[MAX_CFG_STRING_LEN];
138 static char cur_var[MAX_CFG_STRING_LEN];
139 char parsed[MAX_CFG_STRING_LEN];
140 size_t name_len = strlen(name);
141 enum parse_vars_state {NO_VAR, WHOLE_VAR, INLINE_VAR} state = NO_VAR;
142 size_t result_len = 0;
143 size_t start_var = 0;
145 memset(result, 0, sizeof(result));
146 PROX_PANIC(name_len > sizeof(result), "\tUnable to parse var %s: too long\n", name);
148 for (size_t i = 0; i < name_len; ++i) {
151 if (name[i] == '$') {
152 if (i != name_len - 1 && name[i + 1] == '{') {
157 else if (i == 0 && i != name_len - 1) {
161 set_errf("Invalid variable syntax");
166 result[result_len++] = name[i];
170 if (name[i] == '}') {
172 size_t var_len = i - start_var;
174 set_errf("Empty variable are not allowed");
178 strncpy(&cur_var[1], &name[start_var], var_len);
179 cur_var[1 + var_len] = 0;
180 if (parse_single_var(parsed, sizeof(parsed), cur_var)) {
183 strcpy(&result[result_len], parsed);
184 result_len += strlen(parsed);
187 else if (i == name_len - 1) {
188 set_errf("Invalid variable syntax, expected '}'.");
193 if (i == name_len - 1) {
194 return parse_single_var(val, len, name);
199 prox_strncpy(val, result, len);
204 int parse_int_mask(uint32_t *val, uint32_t *mask, const char *str2)
206 char str[MAX_STR_LEN_PROC];
209 if (parse_vars(str, sizeof(str), str2))
212 mask_str = strchr(str, '&');
214 if (mask_str == NULL) {
215 set_errf("Missing '&' when parsing mask");
221 if (parse_int(val, str))
223 if (parse_int(mask, mask_str + 1))
229 int parse_range(uint32_t* lo, uint32_t* hi, const char *str2)
231 char str[MAX_STR_LEN_PROC];
234 if (parse_vars(str, sizeof(str), str2))
237 dash = strstr(str, "-");
240 set_errf("Missing '-' when parsing mask");
246 if (parse_int(lo, str))
248 if (parse_int(hi, dash + 1))
251 int64_t tmp = strtol(str, 0, 0);
252 if (tmp > UINT32_MAX) {
253 set_errf("Integer is bigger than %u", UINT32_MAX);
257 set_errf("Integer is negative");
263 tmp = strtol(dash + 1, 0, 0);
264 if (tmp > UINT32_MAX) {
265 set_errf("Integer is bigger than %u", UINT32_MAX);
269 set_errf("Integer is negative");
276 set_errf("Low boundary is above high boundary in range");
283 int parse_ip(uint32_t *addr, const char *str2)
285 char str[MAX_STR_LEN_PROC];
287 if (parse_vars(str, sizeof(str), str2))
292 if (strlen(str) > MAX_STR_LEN_PROC) {
293 set_errf("String too long (max supported: %d)", MAX_STR_LEN_PROC);
297 if (4 != rte_strsplit(str, strlen(str), ip_parts, 5, '.')) {
298 set_errf("Expecting 4 octets in ip.");
303 for (uint8_t i = 0; i < 4; ++i) {
304 val = atoi(ip_parts[i]);
306 set_errf("Maximum value for octet is 255 but octet %u is %u", i, val);
309 *addr = *addr << 8 | val;
314 int parse_ip4_and_prefix(struct ip4_subnet *val, const char *str2)
316 char str[MAX_STR_LEN_PROC];
320 if (parse_vars(str, sizeof(str), str2))
323 slash = strstr(str, "/");
326 set_errf("Missing '/' when parsing CIDR notation");
331 prefix = atoi(slash + 1);
332 val->prefix = prefix;
335 set_errf("Prefix %d is too big", prefix);
339 set_errf("Prefix %d is too small", prefix);
341 if (parse_ip(&val->ip, str))
347 int parse_ip4_cidr(struct ip4_subnet *val, const char *str2)
349 int rc = parse_ip4_and_prefix(val, str2);
350 /* Apply mask making all bits outside the prefix zero */
351 val->ip &= ((int)(1 << 31)) >> (val->prefix - 1);
356 int parse_ip6_cidr(struct ip6_subnet *val, const char *str2)
358 char str[MAX_STR_LEN_PROC];
362 if (parse_vars(str, sizeof(str), str2))
365 slash = strstr(str, "/");
368 set_errf("Missing '/' when parsing CIDR notation");
373 prefix = atoi(slash + 1);
374 val->prefix = prefix;
376 parse_ip6((struct ipv6_addr *)&val->ip, str);
378 /* Apply mask making all bits outside the prefix zero */
383 while (p >= prefix) {
389 if (prefix % 8 != 0) {
390 val->ip[15-cnt] &= ((int8_t)(1 << 7)) >> ((prefix %8) - 1);
396 int parse_ip6(struct ipv6_addr *addr, const char *str2)
398 char str[MAX_STR_LEN_PROC];
401 if (parse_vars(str, sizeof(str), str2))
404 uint8_t ret = rte_strsplit(str, strlen(str), addr_parts, 9, ':');
407 set_errf("Invalid IPv6 address");
413 for (uint8_t i = 0, j = 0; i < ret; ++i, ++j) {
414 if (*addr_parts[i] == 0) {
416 set_errf("Can only omit zeros once");
420 j += 2 * (8 - ret) + 1;
423 uint16_t w = strtoll(addr_parts[i], NULL, 16);
424 addr->bytes[j++] = (w >> 8) & 0xff;
425 addr->bytes[j] = w & 0xff;
431 int parse_mac(prox_rte_ether_addr *ether_addr, const char *str2)
433 char str[MAX_STR_LEN_PROC];
436 if (parse_vars(str, sizeof(str), str2))
439 uint8_t ret = rte_strsplit(str, strlen(str), addr_parts, 7, ':');
441 ret = rte_strsplit(str, strlen(str), addr_parts, 7, ' ');
444 set_errf("Invalid MAC address format");
448 for (uint8_t i = 0; i < 6; ++i) {
449 if (2 != strlen(addr_parts[i])) {
450 set_errf("Invalid MAC address format");
453 ether_addr->addr_bytes[i] = strtol(addr_parts[i], NULL, 16);
459 char* get_cfg_key(char *str)
461 char *pkey = strchr(str, '=');
468 /* remove leading spaces */
469 while (isspace(*pkey)) {
472 if (*pkey == '\0') { /* an empty key */
479 void strip_spaces(char *strings[], const uint32_t count)
481 for (uint32_t i = 0; i < count; ++i) {
482 while (isspace(strings[i][0])) {
485 size_t len = strlen(strings[i]);
487 while (len && isspace(strings[i][len - 1])) {
488 strings[i][len - 1] = '\0';
494 int is_virtualized(void)
496 char buf[1024]= "/proc/cpuinfo";
498 FILE* fd = fopen(buf, "r");
500 set_errf("Could not open %s", buf);
503 while (fgets(buf, sizeof(buf), fd) != NULL) {
504 if ((strstr(buf, "flags") != NULL) && (strstr(buf, "hypervisor") != NULL))
511 static int get_phys_core(uint32_t *dst, int lcore_id)
515 snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%u/topology/thread_siblings_list", lcore_id);
516 FILE* ht_fd = fopen(buf, "r");
519 set_errf("Could not open cpu topology %s", buf);
523 if (fgets(buf, sizeof(buf), ht_fd) == NULL) {
524 set_errf("Could not read cpu topology");
529 uint32_t list[2] = {-1,-1};
530 parse_list_set(list, buf, 2);
537 static int get_socket(uint32_t core_id, uint32_t *socket)
541 snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%u/topology/physical_package_id", core_id);
542 FILE* fd = fopen(buf, "r");
549 if (fgets(buf, sizeof(buf), fd) != NULL) {
555 *socket = (ret == -1 ? 0 : ret);
560 int lcore_to_socket_core_ht(uint32_t lcore_id, char *dst, size_t len)
562 if (cpu_topo.n_sockets == 0) {
563 if (read_cpu_topology() == -1) {
568 for (uint32_t s = 0; s < cpu_topo.n_sockets; s++) {
569 for (uint32_t i = 0; i < cpu_topo.n_cores[s]; ++i) {
570 if ((uint32_t)cpu_topo.socket[s][i][0] == lcore_id) {
571 snprintf(dst, len, "%us%u", i, s);
573 } else if ((uint32_t)cpu_topo.socket[s][i][1] == lcore_id) {
574 snprintf(dst, len, "%us%uh", i, s);
583 static int get_lcore_id(uint32_t socket_id, uint32_t core_id, int ht)
585 if (cpu_topo.n_sockets == 0) {
586 if (read_cpu_topology() == -1) {
591 if (socket_id == UINT32_MAX)
594 if (socket_id >= MAX_SOCKETS) {
595 set_errf("Socket id %d too high (max allowed is %d)", MAX_SOCKETS);
598 if (core_id >= RTE_MAX_LCORE) {
599 set_errf("Core id %d too high (max allowed is %d)", RTE_MAX_LCORE);
602 if (socket_id >= cpu_topo.n_sockets) {
603 set_errf("Current CPU topology reported that there are %u CPU sockets, CPU topology = %u socket(s), %u physical cores per socket, %u thread(s) per physical core",
604 cpu_topo.n_sockets, cpu_topo.n_sockets, cpu_topo.n_cores[0], cpu_topo.socket[0][0][1] == -1? 1: 2);
607 if (core_id >= cpu_topo.n_cores[socket_id]) {
608 set_errf("Core %u on socket %u does not exist, CPU topology = %u socket(s), %u physical cores per socket, %u thread(s) per physical core",
609 core_id, socket_id, cpu_topo.n_sockets, cpu_topo.n_cores[0], cpu_topo.socket[socket_id][0][1] == -1? 1: 2);
612 if (cpu_topo.socket[socket_id][core_id][!!ht] == -1) {
613 set_errf("Core %u %son socket %u has no hyper-thread, CPU topology = %u socket(s), %u physical cores per socket, %u thread(s) per physical core",
614 core_id, ht ? "(hyper-thread) " : "", socket_id, cpu_topo.n_sockets, cpu_topo.n_cores[0], cpu_topo.socket[socket_id][core_id][1] == -1? 1: 2);
618 return cpu_topo.socket[socket_id][core_id][!!ht];
621 /* Returns 0 on success, negative on error. Parses the syntax XsYh
622 where sYh is optional. If sY is specified, Y is stored in the
623 socket argument. If, in addition, h is specified, *ht is set to
624 1. In case the input is only a number, socket and ht are set to
626 static int parse_core(int *socket, int *core, int *ht, const char* str)
634 *core = strtol(str, &end, 10);
640 if (cpu_topo.n_sockets == 0) {
641 if (read_cpu_topology() == -1) {
647 *socket = strtol(end, &end, 10);
648 if (*socket >= MAX_SOCKETS) {
649 set_errf("Socket id %d too high (max allowed is %d)", *socket, MAX_SOCKETS - 1);
662 set_errf("Can't find hyper-thread since socket has not been specified");
669 static int parse_task(const char *str, uint32_t *socket, uint32_t *core, uint32_t *task, uint32_t *ht, enum ctrl_type *type)
671 const char *str_beg = str;
674 *core = strtol(str, &end, 10);
676 set_errf("Expected number to in core-task definition:\n"
677 "\t(i.e. 5s1t0 for task 0 on core 5 on socket 1)\n"
678 "\tHave: '%s'.", end);
694 *socket = strtol(str, &end, 10);
703 *task = strtol(str, &end, 10);
706 *type = CTRL_TYPE_PKT;
709 else if (*str == 'm') {
710 *type = CTRL_TYPE_MSG;
716 set_errf("Can't find hyper-thread since socket has not been specified");
721 *task = strtol(str, &end, 10);
724 *type = CTRL_TYPE_PKT;
727 else if (*str == 'm') {
728 *type = CTRL_TYPE_MSG;
733 return str - str_beg;
736 static int core_task_set_add(struct core_task_set *val, uint32_t core, uint32_t task, enum ctrl_type type)
738 if (val->n_elems == sizeof(val->core_task)/sizeof(val->core_task[0]))
741 val->core_task[val->n_elems].core = core;
742 val->core_task[val->n_elems].task = task;
743 val->core_task[val->n_elems].type = type;
749 int parse_task_set(struct core_task_set *cts, const char *str2)
751 char str[MAX_STR_LEN_PROC];
753 if (parse_vars(str, sizeof(str), str2))
760 uint32_t socket_beg, core_beg, task_beg, ht_beg,
761 socket_end, core_end, task_end, ht_end;
762 enum ctrl_type type_beg, type_end;
763 uint32_t task_group_start = -1;
765 while (*str3 && *str3 != ' ') {
767 task_group_start = cts->n_elems;
771 if (*str3 == ')' && *(str3 + 1) == 't') {
774 uint32_t t = strtol(str3, &end, 10);
775 enum ctrl_type type = 0;
779 type = CTRL_TYPE_PKT;
782 else if (*str3 == 'm') {
783 type = CTRL_TYPE_MSG;
787 for (uint32_t i = task_group_start; i < cts->n_elems; ++i) {
788 cts->core_task[i].task = t;
789 cts->core_task[i].type = type;
793 ret = parse_task(str3, &socket_beg, &core_beg, &task_beg, &ht_beg, &type_beg);
797 socket_end = socket_beg;
805 ret = parse_task(str3, &socket_end, &core_end, &task_end, &ht_end, &type_end);
814 if (socket_end != socket_beg) {
815 set_errf("Same socket must be used in range syntax.");
817 } else if (ht_beg != ht_end) {
818 set_errf("If 'h' syntax is in range, it must be specified everywhere.\n");
820 } else if (task_end != task_beg && core_end != core_beg) {
821 set_errf("Same task must be used in range syntax when cores are different.\n");
823 } else if (task_end < task_beg) {
824 set_errf("Task for end of range must be higher than task for beginning of range.\n");
826 } else if (type_end != type_beg) {
827 set_errf("Task type for end of range must be the same as task type for beginning.\n");
829 } else if (core_end < core_beg) {
830 set_errf("Core for end of range must be higher than core for beginning of range.\n");
834 for (uint32_t j = core_beg; j <= core_end; ++j) {
835 if (socket_beg != UINT32_MAX && ht_beg != UINT32_MAX)
836 ret = get_lcore_id(socket_beg, j, ht_beg);
841 for (uint32_t k = task_beg; k <= task_end; ++k) {
842 core_task_set_add(cts, ret, k, type_beg);
849 int parse_ip_set(struct ip4_subnet *list, const char *str2, uint32_t max_list)
851 char str[MAX_STR_LEN_PROC];
852 char *parts[MAX_STR_LEN_PROC];
855 if (parse_vars(str, sizeof(str), str2))
857 int n_parts = rte_strsplit(str, strlen(str), parts, MAX_STR_LEN_PROC, ',');
858 for (int i = 0; i < n_parts; i++) {
859 if ((rc = parse_ip4_and_prefix(&list[i], parts[i])) < 0) {
860 set_errf("Unable to parse ip4/prefix");
867 int parse_int_set(uint32_t *list, const char *str2, uint32_t max_list)
869 char str[MAX_STR_LEN_PROC];
870 char *parts[MAX_STR_LEN_PROC];
873 if (parse_vars(str, sizeof(str), str2))
876 int n_parts = rte_strsplit(str, strlen(str), parts, MAX_STR_LEN_PROC, ',');
877 for (int i = 0; i < n_parts; i++) {
878 char *cur_part = parts[i];
880 int n_sub_parts = rte_strsplit(cur_part, strlen(cur_part), sub_parts, 3, '-');
884 if (n_sub_parts == 1) {
885 if (n >= max_list - 1) {
886 set_errf("Too many entries\n");
889 if (parse_int(&list[n], sub_parts[0]))
892 } else if (n_sub_parts == 2) {
893 if (parse_int(&n1, sub_parts[0]))
895 if (parse_int(&n2, sub_parts[1]))
897 if (n + n2 - n1 >= max_list) {
898 set_errf("Too many entries\n");
901 for (uint32_t j = n1; j < n2; j++) {
904 } else if (n_sub_parts >= 3) {
905 set_errf("Multiple '-' characters in range syntax found");
908 set_errf("Invalid list syntax");
915 int parse_list_set(uint32_t *list, const char *str2, uint32_t max_list)
917 char str[MAX_STR_LEN_PROC];
918 char *parts[MAX_STR_LEN_PROC];
920 if (parse_vars(str, sizeof(str), str2))
923 int n_parts = rte_strsplit(str, strlen(str), parts, MAX_STR_LEN_PROC, ',');
924 size_t list_count = 0;
926 for (int i = 0; i < n_parts; ++i) {
927 char *cur_part = parts[i];
929 int n_sub_parts = rte_strsplit(cur_part, strlen(cur_part), sub_parts, 3, '-');
930 int socket1, socket2;
935 if (n_sub_parts == 1) {
936 if (parse_core(&socket1, &core1, &ht1, sub_parts[0]))
942 } else if (n_sub_parts == 2) {
943 if (parse_core(&socket1, &core1, &ht1, sub_parts[0]))
945 if (parse_core(&socket2, &core2, &ht2, sub_parts[1]))
947 } else if (n_sub_parts >= 3) {
948 set_errf("Multiple '-' characters in range syntax found");
951 set_errf("Invalid list syntax");
955 if (socket1 != socket2) {
956 set_errf("Same socket must be used in range syntax");
959 else if (ht1 != ht2) {
960 set_errf("If 'h' syntax is in range, it must be specified everywhere.");
964 for (int cur_core = core1; cur_core <= core2; ++cur_core) {
968 effective_core = get_lcore_id(socket1, cur_core, ht1);
970 effective_core = cur_core;
972 if (list_count >= max_list) {
973 set_errf("Too many elements in list");
976 list[list_count++] = effective_core;
983 int parse_kmg(uint32_t* val, const char *str2)
985 char str[MAX_STR_LEN_PROC];
987 if (parse_vars(str, sizeof(str), str2))
990 char c = str[strlen(str) - 1];
998 // __attribute__ ((fallthrough));
1003 // __attribute__ ((fallthrough));
1010 /* only support optional KMG suffix */
1011 if (c < '0' || c > '9') {
1012 set_errf("Unknown syntax for KMG suffix '%c' (expected K, M or G)", c);
1020 int parse_bool(uint32_t* val, const char *str2)
1022 char str[MAX_STR_LEN_PROC];
1024 if (parse_vars(str, sizeof(str), str2))
1027 if (!strcmp(str, "yes")) {
1031 else if (!strcmp(str, "no")) {
1035 set_errf("Unknown syntax for bool '%s' (expected yes or no)", str);
1039 int parse_flag(uint32_t* val, uint32_t flag, const char *str2)
1041 char str[MAX_STR_LEN_PROC];
1043 if (parse_vars(str, sizeof(str), str2))
1047 if (parse_bool(&tmp, str))
1058 int parse_int(uint32_t* val, const char *str2)
1060 char str[MAX_STR_LEN_PROC];
1062 if (parse_vars(str, sizeof(str), str2))
1065 int64_t tmp = strtol(str, 0, 0);
1066 if (tmp > UINT32_MAX) {
1067 set_errf("Integer is bigger than %u", UINT32_MAX);
1071 set_errf("Integer is negative");
1079 int parse_float(float* val, const char *str2)
1081 char str[MAX_STR_LEN_PROC];
1083 if (parse_vars(str, sizeof(str), str2))
1086 float tmp = strtof(str, 0);
1087 if ((tmp >= HUGE_VALF) || (tmp <= -HUGE_VALF)) {
1088 set_errf("Unable to parse float\n");
1096 int parse_u64(uint64_t* val, const char *str2)
1098 char str[MAX_STR_LEN_PROC];
1100 if (parse_vars(str, sizeof(str), str2))
1104 uint64_t tmp = strtoul(str, NULL, 0);
1106 set_errf("Invalid u64 '%s' (%s)", str, strerror(errno));
1114 int parse_str(char* dst, const char *str2, size_t max_len)
1116 char str[MAX_STR_LEN_PROC];
1118 if (parse_vars(str, sizeof(str), str2))
1121 if (strlen(str) > max_len - 1) {
1122 set_errf("String too long (%u > %u)", strlen(str), max_len - 1);
1126 prox_strncpy(dst, str, max_len);
1130 int parse_path(char *dst, const char *str, size_t max_len)
1132 if (parse_str(dst, str, max_len))
1134 if (access(dst, F_OK)) {
1135 set_errf("Invalid file '%s' (%s)", dst, strerror(errno));
1141 int parse_port_name(uint32_t *val, const char *str2)
1143 char str[MAX_STR_LEN_PROC];
1145 if (parse_vars(str, sizeof(str), str2))
1148 for (uint8_t i = 0; i < nb_port_names; ++i) {
1149 if (!strcmp(str, port_names[i].name)) {
1150 *val = port_names[i].id;
1154 set_errf("Port with name %s not defined", str);
1158 int parse_port_name_list(uint32_t *val, uint32_t* tot, uint8_t max_vals, const char *str2)
1160 char *elements[PROX_MAX_PORTS + 1];
1161 char str[MAX_STR_LEN_PROC];
1165 if (parse_str(str, str2, sizeof(str)))
1168 ret = rte_strsplit(str, strlen(str), elements, PROX_MAX_PORTS + 1, ',');
1170 if (ret == PROX_MAX_PORTS + 1 || ret > max_vals) {
1171 set_errf("Too many ports in port list");
1175 strip_spaces(elements, ret);
1176 for (uint8_t i = 0; i < ret; ++i) {
1177 if (parse_port_name(&cur, elements[i])) {
1188 int parse_remap(uint8_t *mapping, const char *str)
1190 char *elements[PROX_MAX_PORTS + 1];
1191 char *elements2[PROX_MAX_PORTS + 1];
1192 char str_cpy[MAX_STR_LEN_PROC];
1196 if (strlen(str) > MAX_STR_LEN_PROC) {
1197 set_errf("String too long (max supported: %d)", MAX_STR_LEN_PROC);
1200 prox_strncpy(str_cpy, str, MAX_STR_LEN_PROC);
1202 ret = rte_strsplit(str_cpy, strlen(str_cpy), elements, PROX_MAX_PORTS + 1, ',');
1204 set_errf("Invalid remap syntax");
1207 else if (ret > PROX_MAX_PORTS) {
1208 set_errf("Too many remaps");
1212 strip_spaces(elements, ret);
1213 for (uint8_t i = 0; i < ret; ++i) {
1214 ret2 = rte_strsplit(elements[i], strlen(elements[i]), elements2, PROX_MAX_PORTS + 1, '|');
1215 strip_spaces(elements2, ret2);
1216 if (ret2 > PROX_MAX_PORTS) {
1217 set_errf("Too many remaps");
1220 for (uint8_t j = 0; j < ret2; ++j) {
1221 if (parse_port_name(&val, elements2[j])) {
1225 /* This port will be mapped to the i'th
1226 element specified before remap=. */
1234 int add_port_name(uint32_t val, const char *str2)
1236 char str[MAX_STR_LEN_PROC];
1238 if (parse_vars(str, sizeof(str), str2))
1241 struct port_name* pn;
1243 if (nb_port_names == MAX_NB_PORT_NAMES) {
1244 set_errf("Too many ports defined (can define %d)", MAX_NB_PORT_NAMES);
1248 for (uint8_t i = 0; i < nb_port_names; ++i) {
1249 /* each port has to have a unique name*/
1250 if (!strcmp(str, port_names[i].name)) {
1251 set_errf("Port with name %s is already defined", str);
1256 pn = &port_names[nb_port_names];
1257 prox_strncpy(pn->name, str, sizeof(pn->name));
1264 int set_self_var(const char *str)
1266 for (uint8_t i = 0; i < nb_vars; ++i) {
1267 if (!strcmp("$self", vars[i].name)) {
1268 sprintf(vars[i].val, "%s", str);
1273 struct var *v = &vars[nb_vars];
1275 prox_strncpy(v->name, "$self", strlen("$self") + 1);
1276 sprintf(v->val, "%s", str);
1282 int add_var(const char* name, const char *str2, uint8_t cli)
1286 char str[MAX_STR_LEN_PROC];
1288 if (parse_vars(str, sizeof(str), str2))
1291 if (strlen(name) == 0 || strlen(name) == 1) {
1292 set_errf("Can't define variables with empty name");
1296 if (name[0] != '$') {
1297 set_errf("Each variable should start with the $ character");
1301 if (nb_vars == MAX_NB_VARS) {
1302 set_errf("Too many variables defined (can define %d)", MAX_NB_VARS);
1306 for (uint8_t i = 0; i < nb_vars; ++i) {
1307 if (!strcmp(name, vars[i].name)) {
1309 /* Variables defined through program arguments
1311 if (!cli && vars[i].cli) {
1315 set_errf("Variable with name %s is already defined", name);
1321 PROX_PANIC(strlen(name) > sizeof(v->name), "\tUnable to parse var %s: too long\n", name);
1322 PROX_PANIC(strlen(str) > sizeof(v->val), "\tUnable to parse var %s=%s: too long\n", name,str);
1323 prox_strncpy(v->name, name, sizeof(v->name));
1324 prox_strncpy(v->val, str, sizeof(v->val));
1331 static int read_cores_present(uint32_t *cores, int max_cores, int *res)
1333 FILE* fd = fopen("/sys/devices/system/cpu/present", "r");
1337 set_errf("Could not opening file /sys/devices/system/cpu/present");
1341 if (fgets(buf, sizeof(buf), fd) == NULL) {
1342 set_errf("Could not read cores range");
1348 int ret = parse_list_set(cores, buf, max_cores);
1357 static int set_dummy_topology(void)
1361 for (int s = 0; s < MAX_SOCKETS; s++) {
1362 for (int i = 0; i < 32; ++i) {
1363 cpu_topo.socket[s][i][0] = core_count++;
1364 cpu_topo.socket[s][i][1] = core_count++;
1365 cpu_topo.n_cores[s]++;
1368 cpu_topo.n_sockets = MAX_SOCKETS;
1372 static int read_cpu_topology(void)
1374 if (cpu_topo.n_sockets != 0)
1376 if (prox_cfg.flags & DSF_USE_DUMMY_CPU_TOPO)
1377 return set_dummy_topology();
1379 uint32_t cores[RTE_MAX_LCORE];
1382 if (read_cores_present(cores, sizeof(cores)/sizeof(cores[0]), &n_cores) != 0)
1385 for (int s = 0; s < MAX_SOCKETS; s++) {
1386 for (int i = 0; i < RTE_MAX_LCORE; ++i) {
1387 cpu_topo.socket[s][i][0] = -1;
1388 cpu_topo.socket[s][i][1] = -1;
1392 for (int i = 0; i < n_cores; ++i) {
1393 uint32_t socket_id, lcore_id, phys;
1395 lcore_id = cores[i];
1396 if (get_socket(lcore_id, &socket_id) != 0)
1398 if (socket_id >= MAX_SOCKETS) {
1399 set_errf("Can't read CPU topology due too high socket ID (max allowed is %d)",
1403 if (socket_id >= cpu_topo.n_sockets) {
1404 cpu_topo.n_sockets = socket_id + 1;
1406 if (get_phys_core(&phys, lcore_id) != 0)
1408 if (phys >= RTE_MAX_LCORE) {
1409 set_errf("Core ID %u too high", phys);
1413 if (cpu_topo.socket[socket_id][phys][0] == -1) {
1414 cpu_topo.socket[socket_id][phys][0] = lcore_id;
1415 cpu_topo.n_cores[socket_id]++;
1417 else if (cpu_topo.socket[socket_id][phys][1] == -1) {
1418 cpu_topo.socket[socket_id][phys][1] = lcore_id;
1421 set_errf("Too many core siblings");
1426 /* There can be holes in the cpu_topo description at this
1427 point. An example for this is a CPU topology where the
1428 lowest core ID of 2 hyper-threads is always an even
1429 number. Before finished up this phase, compact all the
1430 cores to make the numbers consecutive. */
1432 for (uint32_t i = 0; i < cpu_topo.n_sockets; ++i) {
1433 int spread = 0, compact = 0;
1434 while (cpu_topo.socket[i][spread][0] == -1)
1437 for (uint32_t c = 0; c < cpu_topo.n_cores[i]; ++c) {
1438 cpu_topo.socket[i][compact][0] = cpu_topo.socket[i][spread][0];
1439 cpu_topo.socket[i][compact][1] = cpu_topo.socket[i][spread][1];
1443 while (cpu_topo.socket[i][spread][0] == -1)
1451 static int bit_len_valid(uint32_t len, const char *str)
1454 set_errf("Maximum random length is 32, but length of '%s' is %zu\n", str, len);
1458 plog_err("Random should be multiple of 8 long\n");
1462 plog_err("Random should be at least 1 byte long\n");
1468 int parse_random_str(uint32_t *mask, uint32_t *fixed, uint32_t *len, const char *str)
1470 const size_t len_bits = strlen(str);
1472 if (!bit_len_valid(len_bits, str))
1477 *len = len_bits / 8;
1479 for (uint32_t j = 0; j < len_bits; ++j) {
1480 /* Store in the lower bits the value of the rand string (note
1481 that these are the higher bits in LE). */
1484 *mask |= 1 << (len_bits - 1 - j);
1487 *fixed |= 1 << (len_bits - 1 - j);
1492 set_errf("Unexpected %c\n", str[j]);