Support packets in flight
[samplevnf.git] / VNFs / DPPD-PROX / parse_utils.c
1 /*
2 // Copyright (c) 2010-2017 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 <ctype.h>
18 #include <stdio.h>
19 #include <float.h>
20 #include <math.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <stdarg.h>
24
25 #include <rte_ether.h>
26 #include <rte_string_fns.h>
27
28 #include "quit.h"
29 #include "cfgfile.h"
30 #include "parse_utils.h"
31 #include "prox_globals.h"
32 #include "prox_cfg.h"
33 #include "log.h"
34 #include "prox_lua.h"
35 #include "prox_lua_types.h"
36 #include "prox_ipv6.h"
37 #include "prox_compat.h"
38
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
44
45 #if MAX_WT_PER_LB > MAX_INDEX
46 #error MAX_WT_PER_LB > MAX_INDEX
47 #endif
48
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. */
53
54 struct cpu_topology {
55         int socket[MAX_SOCKETS][RTE_MAX_LCORE][2];
56         uint32_t n_cores[MAX_SOCKETS];
57         uint32_t n_sockets;
58 };
59
60 struct cpu_topology cpu_topo;
61
62 struct port_name {
63         uint32_t id;
64         char     name[MAX_LEN_PORT_NAME];
65 };
66
67 static struct port_name port_names[MAX_NB_PORT_NAMES];
68 static uint8_t nb_port_names;
69
70 struct var {
71         uint8_t  cli;
72         char     name[MAX_LEN_VAR_NAME];
73         char     val[MAX_LEN_VAL];
74 };
75
76 static struct var vars[MAX_NB_VARS];
77 static uint8_t nb_vars;
78
79 static char format_err_str[256];
80 static const char *err_str = "";
81
82 const char *get_parse_err(void)
83 {
84         return err_str;
85 }
86
87 static int read_cpu_topology(void);
88
89 static int parse_core(int *socket, int *core, int *ht, const char* str);
90
91 static void set_errf(const char *format, ...)
92 {
93         va_list ap;
94         va_start(ap, format);
95         vsnprintf(format_err_str, sizeof(format_err_str), format, ap);
96         va_end(ap);
97         err_str = format_err_str;
98 }
99
100 static struct var *var_lookup(const char *name)
101 {
102         for (uint8_t i = 0; i < nb_vars; ++i) {
103                 if (!strcmp(name, vars[i].name)) {
104                         return &vars[i];
105                 }
106         }
107         return NULL;
108 }
109
110 int parse_single_var(char *val, size_t len, const char *name)
111 {
112         struct var *match;
113
114         match = var_lookup(name);
115         if (match) {
116                 if (strlen(match->val) + 1 > len) {
117                         set_errf("Variables '%s' with value '%s' is too long\n",
118                                  match->name, match->val);
119                         return -1;
120                 }
121                 prox_strncpy(val, match->val, len);
122                 return 0;
123         }
124         else {
125                 /* name + 1 to skip leading '$' */
126                 if (lua_to_string(prox_lua(), GLOBAL, name + 1, val, len) >= 0)
127                         return 0;
128         }
129
130         set_errf("Variable '%s' not defined!", name);
131         return 1;
132 }
133
134 /* Replace $... and each occurrence of ${...} with variable values */
135 int parse_vars(char *val, size_t len, const char *name)
136 {
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;
144
145         memset(result, 0, sizeof(result));
146         PROX_PANIC(name_len > sizeof(result), "\tUnable to parse var %s: too long\n", name);
147
148         for (size_t i = 0; i < name_len; ++i) {
149                 switch (state) {
150                 case NO_VAR:
151                         if (name[i] == '$') {
152                                 if (i != name_len - 1 && name[i + 1] == '{') {
153                                         start_var = i + 2;
154                                         state = INLINE_VAR;
155                                         i = i + 1;
156                                 }
157                                 else if (i == 0 && i != name_len - 1) {
158                                         state = WHOLE_VAR;
159                                 }
160                                 else {
161                                         set_errf("Invalid variable syntax");
162                                         return -1;
163                                 }
164                         }
165                         else {
166                                 result[result_len++] = name[i];
167                         }
168                         break;
169                 case INLINE_VAR:
170                         if (name[i] == '}') {
171                                 cur_var[0] = '$';
172                                 size_t var_len = i - start_var;
173                                 if (var_len == 0) {
174                                         set_errf("Empty variable are not allowed");
175                                         return -1;
176                                 }
177
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)) {
181                                         return -1;
182                                 }
183                                 strcpy(&result[result_len], parsed);
184                                 result_len += strlen(parsed);
185                                 state = NO_VAR;
186                         }
187                         else if (i == name_len - 1) {
188                                 set_errf("Invalid variable syntax, expected '}'.");
189                                 return -1;
190                         }
191                         break;
192                 case WHOLE_VAR:
193                         if (i == name_len - 1) {
194                                 return parse_single_var(val, len, name);
195                         }
196                         break;
197                 }
198         }
199         prox_strncpy(val, result, len);
200
201         return 0;
202 }
203
204 int parse_int_mask(uint32_t *val, uint32_t *mask, const char *str2)
205 {
206         char str[MAX_STR_LEN_PROC];
207         char *mask_str;
208
209         if (parse_vars(str, sizeof(str), str2))
210                 return -1;
211
212         mask_str = strchr(str, '&');
213
214         if (mask_str == NULL) {
215                 set_errf("Missing '&' when parsing mask");
216                 return -2;
217         }
218
219         *mask_str = 0;
220
221         if (parse_int(val, str))
222                 return -1;
223         if (parse_int(mask, mask_str + 1))
224                 return -1;
225
226         return 0;
227 }
228
229 int parse_range(uint32_t* lo, uint32_t* hi, const char *str2)
230 {
231         char str[MAX_STR_LEN_PROC];
232         char *dash;
233
234         if (parse_vars(str, sizeof(str), str2))
235                 return -1;
236
237         dash = strstr(str, "-");
238
239         if (dash == NULL) {
240                 set_errf("Missing '-' when parsing mask");
241                 return -2;
242         }
243
244         *dash = 0;
245
246         if (parse_int(lo, str))
247                 return -1;
248         if (parse_int(hi, dash + 1))
249                 return -1;
250
251         int64_t tmp = strtol(str, 0, 0);
252         if (tmp > UINT32_MAX) {
253                 set_errf("Integer is bigger than %u", UINT32_MAX);
254                 return -1;
255         }
256         if (tmp < 0) {
257                 set_errf("Integer is negative");
258                 return -2;
259         }
260
261         *lo = tmp;
262
263         tmp = strtol(dash + 1, 0, 0);
264         if (tmp > UINT32_MAX) {
265                 set_errf("Integer is bigger than %u", UINT32_MAX);
266                 return -1;
267         }
268         if (tmp < 0) {
269                 set_errf("Integer is negative");
270                 return -2;
271         }
272
273         *hi = tmp;
274
275         if (*lo > *hi) {
276                 set_errf("Low boundary is above high boundary in range");
277                 return -2;
278         }
279
280         return 0;
281 }
282
283 int parse_ip(uint32_t *addr, const char *str2)
284 {
285         char str[MAX_STR_LEN_PROC];
286
287         if (parse_vars(str, sizeof(str), str2))
288                 return -1;
289
290         char *ip_parts[5];
291
292         if (strlen(str) > MAX_STR_LEN_PROC) {
293                 set_errf("String too long (max supported: %d)", MAX_STR_LEN_PROC);
294                 return -2;
295         }
296
297         if (4 != rte_strsplit(str, strlen(str), ip_parts, 5, '.')) {
298                 set_errf("Expecting 4 octets in ip.");
299                 return -1;
300         }
301
302         uint32_t val;
303         for (uint8_t i = 0; i < 4; ++i) {
304                 val = atoi(ip_parts[i]);
305                 if (val > 255) {
306                         set_errf("Maximum value for octet is 255 but octet %u is %u", i, val);
307                         return -1;
308                 }
309                 *addr = *addr << 8 | val;
310         }
311         return 0;
312 }
313
314 int parse_ip4_and_prefix(struct ip4_subnet *val, const char *str2)
315 {
316         char str[MAX_STR_LEN_PROC];
317         char *slash;
318         int prefix;
319
320         if (parse_vars(str, sizeof(str), str2))
321                 return -1;
322
323         slash = strstr(str, "/");
324
325         if (slash == NULL) {
326                 set_errf("Missing '/' when parsing CIDR notation");
327                 return -2;
328         }
329
330         *slash = 0;
331         prefix = atoi(slash + 1);
332         val->prefix = prefix;
333
334         if (prefix > 32) {
335                 set_errf("Prefix %d is too big", prefix);
336                 return -2;
337         }
338         if (prefix < 1) {
339                 set_errf("Prefix %d is too small", prefix);
340         }
341         if (parse_ip(&val->ip, str))
342                 return -2;
343
344         return 0;
345 }
346
347 int parse_ip4_cidr(struct ip4_subnet *val, const char *str2)
348 {
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);
352
353         return rc;
354 }
355
356 int parse_ip6_cidr(struct ip6_subnet *val, const char *str2)
357 {
358         char str[MAX_STR_LEN_PROC];
359         char *slash;
360         int prefix;
361
362         if (parse_vars(str, sizeof(str), str2))
363                 return -1;
364
365         slash = strstr(str, "/");
366
367         if (slash == NULL) {
368                 set_errf("Missing '/' when parsing CIDR notation");
369                 return -2;
370         }
371
372         *slash = 0;
373         prefix = atoi(slash + 1);
374         val->prefix = prefix;
375
376         parse_ip6((struct ipv6_addr *)&val->ip, str);
377
378         /* Apply mask making all bits outside the prefix zero */
379
380         int p = 120;
381         int cnt = 0;
382
383         while (p >= prefix) {
384                 val->ip[15-cnt] = 0;
385                 p -= 8;
386                 cnt++;
387         }
388
389         if (prefix % 8 != 0) {
390                 val->ip[15-cnt] &= ((int8_t)(1 << 7)) >> ((prefix %8) - 1);
391         }
392
393         return 0;
394 }
395
396 int parse_ip6(struct ipv6_addr *addr, const char *str2)
397 {
398         char str[MAX_STR_LEN_PROC];
399         char *addr_parts[9];
400
401         if (parse_vars(str, sizeof(str), str2))
402                 return -1;
403
404         uint8_t ret = rte_strsplit(str, strlen(str), addr_parts, 9, ':');
405
406         if (ret == 9) {
407                 set_errf("Invalid IPv6 address");
408                 return -1;
409         }
410
411         uint8_t omitted = 0;
412
413         for (uint8_t i = 0, j = 0; i < ret; ++i, ++j) {
414                 if (*addr_parts[i] == 0) {
415                         if (omitted) {
416                                 set_errf("Can only omit zeros once");
417                                 return -1;
418                         }
419                         omitted = 1;
420                         j += 2 * (8 - ret) + 1;
421                 }
422                 else {
423                         uint16_t w = strtoll(addr_parts[i], NULL, 16);
424                         addr->bytes[j++] = (w >> 8) & 0xff;
425                         addr->bytes[j] = w & 0xff;
426                 }
427         }
428         return 0;
429 }
430
431 int parse_mac(prox_rte_ether_addr *ether_addr, const char *str2)
432 {
433         char str[MAX_STR_LEN_PROC];
434         char *addr_parts[7];
435
436         if (parse_vars(str, sizeof(str), str2))
437                 return -1;
438
439         uint8_t ret = rte_strsplit(str, strlen(str), addr_parts, 7, ':');
440         if (ret != 6)
441                 ret = rte_strsplit(str, strlen(str), addr_parts, 7, ' ');
442
443         if (ret != 6) {
444                 set_errf("Invalid MAC address format");
445                 return -1;
446         }
447
448         for (uint8_t i = 0; i < 6; ++i) {
449                 if (2 != strlen(addr_parts[i])) {
450                         set_errf("Invalid MAC address format");
451                         return -1;
452                 }
453                 ether_addr->addr_bytes[i] = strtol(addr_parts[i], NULL, 16);
454         }
455
456         return 0;
457 }
458
459 char* get_cfg_key(char *str)
460 {
461         char *pkey = strchr(str, '=');
462
463         if (pkey == NULL) {
464                 return NULL;
465         }
466         *pkey++ = '\0';
467
468         /* remove leading spaces */
469         while (isspace(*pkey)) {
470                 pkey++;
471         }
472         if (*pkey == '\0') { /* an empty key */
473                 return NULL;
474         }
475
476         return pkey;
477 }
478
479 void strip_spaces(char *strings[], const uint32_t count)
480 {
481         for (uint32_t i = 0; i < count; ++i) {
482                 while (isspace(strings[i][0])) {
483                         ++strings[i];
484                 }
485                 size_t len = strlen(strings[i]);
486
487                 while (len && isspace(strings[i][len - 1])) {
488                         strings[i][len - 1] = '\0';
489                         --len;
490                 }
491         }
492 }
493
494 int is_virtualized(void)
495 {
496         char buf[1024]= "/proc/cpuinfo";
497         int virtualized = 0;
498         FILE* fd = fopen(buf, "r");
499         if (fd == NULL) {
500                 set_errf("Could not open %s", buf);
501                 return -1;
502         }
503         while (fgets(buf, sizeof(buf), fd) != NULL) {
504                 if ((strstr(buf, "flags") != NULL) && (strstr(buf, "hypervisor") != NULL))
505                         virtualized = 1;
506         }
507         fclose(fd);
508         return virtualized;
509 }
510
511 static int get_phys_core(uint32_t *dst, int lcore_id)
512 {
513         uint32_t ret;
514         char buf[1024];
515         snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%u/topology/thread_siblings_list", lcore_id);
516         FILE* ht_fd = fopen(buf, "r");
517
518         if (ht_fd == NULL) {
519                 set_errf("Could not open cpu topology %s", buf);
520                 return -1;
521         }
522
523         if (fgets(buf, sizeof(buf), ht_fd) == NULL) {
524                 set_errf("Could not read cpu topology");
525                 return -1;
526         }
527         fclose(ht_fd);
528
529         uint32_t list[2] = {-1,-1};
530         parse_list_set(list, buf, 2);
531
532         *dst = list[0];
533
534         return 0;
535 }
536
537 static int get_socket(uint32_t core_id, uint32_t *socket)
538 {
539         int ret = -1;
540         char buf[1024];
541         snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%u/topology/physical_package_id", core_id);
542         FILE* fd = fopen(buf, "r");
543
544         if (fd == NULL) {
545                 set_errf("%s", buf);
546                 return -1;
547         }
548
549         if (fgets(buf, sizeof(buf), fd) != NULL) {
550                 ret = atoi(buf);
551         }
552         fclose(fd);
553
554         if (socket)
555                 *socket = (ret == -1 ? 0 : ret);
556
557         return 0;
558 }
559
560 int lcore_to_socket_core_ht(uint32_t lcore_id, char *dst, size_t len)
561 {
562         if (cpu_topo.n_sockets == 0) {
563                 if (read_cpu_topology() == -1) {
564                         return -1;
565                 }
566         }
567
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);
572                                 return 0;
573                         } else if ((uint32_t)cpu_topo.socket[s][i][1] == lcore_id) {
574                                 snprintf(dst, len, "%us%uh", i, s);
575                                 return 0;
576                         }
577                 }
578         }
579
580         return -1;
581 }
582
583 static int get_lcore_id(uint32_t socket_id, uint32_t core_id, int ht)
584 {
585         if (cpu_topo.n_sockets == 0) {
586                 if (read_cpu_topology() == -1) {
587                         return -1;
588                 }
589         }
590
591         if (socket_id == UINT32_MAX)
592                 socket_id = 0;
593
594         if (socket_id >= MAX_SOCKETS) {
595                 set_errf("Socket id %d too high (max allowed is %d)", MAX_SOCKETS);
596                 return -1;
597         }
598         if (core_id >= RTE_MAX_LCORE) {
599                 set_errf("Core id %d too high (max allowed is %d)", RTE_MAX_LCORE);
600                 return -1;
601         }
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);
605                 return -1;
606         }
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);
610                 return -1;
611         }
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);
615
616                 return -1;
617         }
618         return cpu_topo.socket[socket_id][core_id][!!ht];
619 }
620
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
625    -1.*/
626 static int parse_core(int *socket, int *core, int *ht, const char* str)
627 {
628         *socket = -1;
629         *core = -1;
630         *ht = -1;
631
632         char* end;
633
634         *core = strtol(str, &end, 10);
635
636         if (*end == 's') {
637                 *socket = 0;
638                 *ht = 0;
639
640                 if (cpu_topo.n_sockets == 0) {
641                         if (read_cpu_topology() == -1) {
642                                 return -1;
643                         }
644                 }
645
646                 ++end;
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);
650                         return -1;
651                 }
652
653                 if (*end == 'h') {
654                         ++end;
655                         *ht = 1;
656                 }
657
658                 return 0;
659         }
660
661         if (*end == 'h') {
662                 set_errf("Can't find hyper-thread since socket has not been specified");
663                 return -1;
664         }
665
666         return 0;
667 }
668
669 static int parse_task(const char *str, uint32_t *socket, uint32_t *core, uint32_t *task, uint32_t *ht, enum ctrl_type *type)
670 {
671         const char *str_beg = str;
672         char *end;
673
674         *core = strtol(str, &end, 10);
675         if (str == end) {
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);
679                 return -1;
680         }
681
682         *task = 0;
683         *socket = -1;
684         *ht = -1;
685         *type = 0;
686
687         str = end;
688
689         if (*str == 's') {
690                 str++;
691                 *socket = 0;
692                 *ht = 0;
693
694                 *socket = strtol(str, &end, 10);
695                 str = end;
696
697                 if (*str == 'h') {
698                         str++;
699                         *ht = 1;
700                 }
701                 if (*str == 't') {
702                         str++;
703                         *task = strtol(str, &end, 10);
704                         str = end;
705                         if (*str == 'p') {
706                                 *type = CTRL_TYPE_PKT;
707                                 str += 1;
708                         }
709                         else if (*str == 'm') {
710                                 *type = CTRL_TYPE_MSG;
711                                 str += 1;
712                         }
713                 }
714         } else {
715                 if (*str == 'h') {
716                         set_errf("Can't find hyper-thread since socket has not been specified");
717                         return -1;
718                 }
719                 if (*str == 't') {
720                         str++;
721                         *task = strtol(str, &end, 10);
722                         str = end;
723                         if (*str == 'p') {
724                                 *type = CTRL_TYPE_PKT;
725                                 str += 1;
726                         }
727                         else if (*str == 'm') {
728                                 *type = CTRL_TYPE_MSG;
729                                 str += 1;
730                         }
731                 }
732         }
733         return str - str_beg;
734 }
735
736 static int core_task_set_add(struct core_task_set *val, uint32_t core, uint32_t task, enum ctrl_type type)
737 {
738         if (val->n_elems == sizeof(val->core_task)/sizeof(val->core_task[0]))
739                 return -1;
740
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;
744         val->n_elems++;
745
746         return 0;
747 }
748
749 int parse_task_set(struct core_task_set *cts, const char *str2)
750 {
751         char str[MAX_STR_LEN_PROC];
752
753         if (parse_vars(str, sizeof(str), str2))
754                 return -1;
755         cts->n_elems = 0;
756
757         char *str3 = str;
758         int ret;
759
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;
764
765         while (*str3 && *str3 != ' ') {
766                 if (*str3 == '(') {
767                         task_group_start = cts->n_elems;
768                         str3 += 1;
769                         continue;
770                 }
771                 if (*str3 == ')' && *(str3 + 1) == 't') {
772                         str3 += 2;
773                         char *end;
774                         uint32_t t = strtol(str3, &end, 10);
775                         enum ctrl_type type = 0;
776                         str3 = end;
777
778                         if (*str3 == 'p') {
779                                 type = CTRL_TYPE_PKT;
780                                 str3 += 1;
781                         }
782                         else if (*str3 == 'm') {
783                                 type = CTRL_TYPE_MSG;
784                                 str3 += 1;
785                         }
786
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;
790                         }
791                         continue;
792                 }
793                 ret = parse_task(str3, &socket_beg, &core_beg, &task_beg, &ht_beg, &type_beg);
794                 if (ret < 0)
795                         return -1;
796                 str3 += ret;
797                 socket_end = socket_beg;
798                 core_end = core_beg;
799                 task_end = task_beg;
800                 ht_end = ht_beg;
801                 type_end = type_beg;
802
803                 if (*str3 == '-') {
804                         str3 += 1;
805                         ret = parse_task(str3, &socket_end, &core_end, &task_end, &ht_end, &type_end);
806                         if (ret < 0)
807                                 return -1;
808                         str3 += ret;
809                 }
810
811                 if (*str3 == ',')
812                         str3 += 1;
813
814                 if (socket_end != socket_beg) {
815                         set_errf("Same socket must be used in range syntax.");
816                         return -1;
817                 } else if (ht_beg != ht_end) {
818                         set_errf("If 'h' syntax is in range, it must be specified everywhere.\n");
819                         return -1;
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");
822                         return -1;
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");
825                         return -1;
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");
828                         return -1;
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");
831                         return -1;
832                 }
833
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);
837                         else
838                                 ret = j;
839                         if (ret < 0)
840                                 return -1;
841                         for (uint32_t k = task_beg; k <= task_end; ++k) {
842                                 core_task_set_add(cts, ret, k, type_beg);
843                         }
844                 }
845         }
846         return 0;
847 }
848
849 int parse_ip_set(struct ip4_subnet *list, const char *str2, uint32_t max_list)
850 {
851         char str[MAX_STR_LEN_PROC];
852         char *parts[MAX_STR_LEN_PROC];
853         int n = 0, rc;
854
855         if (parse_vars(str, sizeof(str), str2))
856                 return -1;
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");
861                         return -1;
862                 }
863         }
864         return 0;
865 }
866
867 int parse_int_set(uint32_t *list, const char *str2, uint32_t max_list)
868 {
869         char str[MAX_STR_LEN_PROC];
870         char *parts[MAX_STR_LEN_PROC];
871         uint32_t n = 0;
872
873         if (parse_vars(str, sizeof(str), str2))
874                 return -1;
875
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];
879                 char *sub_parts[3];
880                 int n_sub_parts = rte_strsplit(cur_part, strlen(cur_part), sub_parts, 3, '-');
881                 uint32_t n1, n2;
882                 int ret = 0;
883
884                 if (n_sub_parts == 1) {
885                         if (n >= max_list - 1) {
886                                 set_errf("Too many entries\n");
887                                 return -1;
888                         }
889                         if (parse_int(&list[n], sub_parts[0]))
890                                 return -1;
891                         n++;
892                 } else if (n_sub_parts == 2) {
893                         if (parse_int(&n1, sub_parts[0]))
894                                 return -1;
895                         if (parse_int(&n2, sub_parts[1]))
896                                 return -1;
897                         if (n + n2 - n1 >= max_list) {
898                                 set_errf("Too many entries\n");
899                                 return -1;
900                         }
901                         for (uint32_t j = n1; j < n2; j++) {
902                                 list[n++] = j;
903                         }
904                 } else if (n_sub_parts >= 3) {
905                         set_errf("Multiple '-' characters in range syntax found");
906                         return -1;
907                 } else {
908                         set_errf("Invalid list syntax");
909                         return -1;
910                 }
911         }
912         return 0;
913 }
914
915 int parse_list_set(uint32_t *list, const char *str2, uint32_t max_list)
916 {
917         char str[MAX_STR_LEN_PROC];
918         char *parts[MAX_STR_LEN_PROC];
919
920         if (parse_vars(str, sizeof(str), str2))
921                 return -1;
922
923         int n_parts = rte_strsplit(str, strlen(str), parts, MAX_STR_LEN_PROC, ',');
924         size_t list_count = 0;
925
926         for (int i = 0; i < n_parts; ++i) {
927                 char *cur_part = parts[i];
928                 char *sub_parts[3];
929                 int n_sub_parts = rte_strsplit(cur_part, strlen(cur_part), sub_parts, 3, '-');
930                 int socket1, socket2;
931                 int ht1, ht2;
932                 int core1, core2;
933                 int ret = 0;
934
935                 if (n_sub_parts == 1) {
936                         if (parse_core(&socket1, &core1, &ht1, sub_parts[0]))
937                                 return -1;
938
939                         socket2 = socket1;
940                         core2 = core1;
941                         ht2 = ht1;
942                 } else if (n_sub_parts == 2) {
943                         if (parse_core(&socket1, &core1, &ht1, sub_parts[0]))
944                                 return -1;
945                         if (parse_core(&socket2, &core2, &ht2, sub_parts[1]))
946                                 return -1;
947                 } else if (n_sub_parts >= 3) {
948                         set_errf("Multiple '-' characters in range syntax found");
949                         return -1;
950                 } else {
951                         set_errf("Invalid list syntax");
952                         return -1;
953                 }
954
955                 if (socket1 != socket2) {
956                         set_errf("Same socket must be used in range syntax");
957                         return -1;
958                 }
959                 else if (ht1 != ht2) {
960                         set_errf("If 'h' syntax is in range, it must be specified everywhere.");
961                         return -1;
962                 }
963
964                 for (int cur_core = core1; cur_core <= core2; ++cur_core) {
965                         int effective_core;
966
967                         if (socket1 != -1)
968                                 effective_core = get_lcore_id(socket1, cur_core, ht1);
969                         else
970                                 effective_core = cur_core;
971
972                         if (list_count >= max_list) {
973                                 set_errf("Too many elements in list");
974                                 return -1;
975                         }
976                         list[list_count++] = effective_core;
977                 }
978         }
979
980         return list_count;
981 }
982
983 int parse_kmg(uint32_t* val, const char *str2)
984 {
985         char str[MAX_STR_LEN_PROC];
986
987         if (parse_vars(str, sizeof(str), str2))
988                 return -1;
989
990         char c = str[strlen(str) - 1];
991         *val = atoi(str);
992
993         switch (c) {
994         case 'G':
995                 if (*val >> 22)
996                         return -2;
997                 *val <<= 10;
998                 // __attribute__ ((fallthrough));
999         case 'M':
1000                 if (*val >> 22)
1001                         return -2;
1002                 *val <<= 10;
1003                 // __attribute__ ((fallthrough));
1004         case 'K':
1005                 if (*val >> 22)
1006                         return -2;
1007                 *val <<= 10;
1008                 break;
1009         default:
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);
1013                         return -1;
1014                 }
1015         }
1016
1017         return 0;
1018 }
1019
1020 int parse_bool(uint32_t* val, const char *str2)
1021 {
1022         char str[MAX_STR_LEN_PROC];
1023
1024         if (parse_vars(str, sizeof(str), str2))
1025                 return -1;
1026
1027         if (!strcmp(str, "yes")) {
1028                 *val = 1;
1029                 return 0;
1030         }
1031         else if (!strcmp(str, "no")) {
1032                 *val = 0;
1033                 return 0;
1034         }
1035         set_errf("Unknown syntax for bool '%s' (expected yes or no)", str);
1036         return -1;
1037 }
1038
1039 int parse_flag(uint32_t* val, uint32_t flag, const char *str2)
1040 {
1041         char str[MAX_STR_LEN_PROC];
1042
1043         if (parse_vars(str, sizeof(str), str2))
1044                 return -1;
1045
1046         uint32_t tmp;
1047         if (parse_bool(&tmp, str))
1048                 return -1;
1049
1050         if (tmp)
1051                 *val |= flag;
1052         else
1053                 *val &= ~flag;
1054
1055         return 0;
1056 }
1057
1058 int parse_int(uint32_t* val, const char *str2)
1059 {
1060         char str[MAX_STR_LEN_PROC];
1061
1062         if (parse_vars(str, sizeof(str), str2))
1063                 return -1;
1064
1065         int64_t tmp = strtol(str, 0, 0);
1066         if (tmp > UINT32_MAX) {
1067                 set_errf("Integer is bigger than %u", UINT32_MAX);
1068                 return -1;
1069         }
1070         if (tmp < 0) {
1071                 set_errf("Integer is negative");
1072                 return -2;
1073         }
1074         *val = tmp;
1075
1076         return 0;
1077 }
1078
1079 int parse_float(float* val, const char *str2)
1080 {
1081         char str[MAX_STR_LEN_PROC];
1082
1083         if (parse_vars(str, sizeof(str), str2))
1084                 return -1;
1085
1086         float tmp = strtof(str, 0);
1087         if ((tmp >= HUGE_VALF) || (tmp <= -HUGE_VALF)) {
1088                 set_errf("Unable to parse float\n");
1089                 return -1;
1090         }
1091         *val = tmp;
1092
1093         return 0;
1094 }
1095
1096 int parse_u64(uint64_t* val, const char *str2)
1097 {
1098         char str[MAX_STR_LEN_PROC];
1099
1100         if (parse_vars(str, sizeof(str), str2))
1101                 return -1;
1102
1103         errno = 0;
1104         uint64_t tmp = strtoul(str, NULL, 0);
1105         if (errno != 0) {
1106                 set_errf("Invalid u64 '%s' (%s)", str, strerror(errno));
1107                 return -2;
1108         }
1109         *val = tmp;
1110
1111         return 0;
1112 }
1113
1114 int parse_str(char* dst, const char *str2, size_t max_len)
1115 {
1116         char str[MAX_STR_LEN_PROC];
1117
1118         if (parse_vars(str, sizeof(str), str2))
1119                 return -1;
1120
1121         if (strlen(str) > max_len - 1) {
1122                 set_errf("String too long (%u > %u)", strlen(str), max_len - 1);
1123                 return -2;
1124         }
1125
1126         prox_strncpy(dst, str, max_len);
1127         return 0;
1128 }
1129
1130 int parse_path(char *dst, const char *str, size_t max_len)
1131 {
1132         if (parse_str(dst, str, max_len))
1133                 return -1;
1134         if (access(dst, F_OK)) {
1135                 set_errf("Invalid file '%s' (%s)", dst, strerror(errno));
1136                 return -1;
1137         }
1138         return 0;
1139 }
1140
1141 int parse_port_name(uint32_t *val, const char *str2)
1142 {
1143         char str[MAX_STR_LEN_PROC];
1144
1145         if (parse_vars(str, sizeof(str), str2))
1146                 return -1;
1147
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;
1151                         return 0;
1152                 }
1153         }
1154         set_errf("Port with name %s not defined", str);
1155         return 1;
1156 }
1157
1158 int parse_port_name_list(uint32_t *val, uint32_t* tot, uint8_t max_vals, const char *str2)
1159 {
1160         char *elements[PROX_MAX_PORTS + 1];
1161         char str[MAX_STR_LEN_PROC];
1162         uint32_t cur;
1163         int ret;
1164
1165         if (parse_str(str, str2, sizeof(str)))
1166                 return -1;
1167
1168         ret = rte_strsplit(str, strlen(str), elements, PROX_MAX_PORTS + 1, ',');
1169
1170         if (ret == PROX_MAX_PORTS + 1 || ret > max_vals) {
1171                 set_errf("Too many ports in port list");
1172                 return -1;
1173         }
1174
1175         strip_spaces(elements, ret);
1176         for (uint8_t i = 0; i < ret; ++i) {
1177                 if (parse_port_name(&cur, elements[i])) {
1178                         return -1;
1179                 }
1180                 val[i] = cur;
1181         }
1182         if (tot) {
1183                 *tot = ret;
1184         }
1185         return 0;
1186 }
1187
1188 int parse_remap(uint8_t *mapping, const char *str)
1189 {
1190         char *elements[PROX_MAX_PORTS + 1];
1191         char *elements2[PROX_MAX_PORTS + 1];
1192         char str_cpy[MAX_STR_LEN_PROC];
1193         uint32_t val;
1194         int ret, ret2;
1195
1196         if (strlen(str) > MAX_STR_LEN_PROC) {
1197                 set_errf("String too long (max supported: %d)", MAX_STR_LEN_PROC);
1198                 return -2;
1199         }
1200         prox_strncpy(str_cpy, str, MAX_STR_LEN_PROC);
1201
1202         ret = rte_strsplit(str_cpy, strlen(str_cpy), elements, PROX_MAX_PORTS + 1, ',');
1203         if (ret <= 0) {
1204                 set_errf("Invalid remap syntax");
1205                 return -1;
1206         }
1207         else if (ret > PROX_MAX_PORTS) {
1208                 set_errf("Too many remaps");
1209                 return -2;
1210         }
1211
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");
1218                         return -2;
1219                 }
1220                 for (uint8_t j = 0; j < ret2; ++j) {
1221                         if (parse_port_name(&val, elements2[j])) {
1222                                 return -1;
1223                         }
1224
1225                         /* This port will be mapped to the i'th
1226                            element specified before remap=. */
1227                         mapping[val] = i;
1228                 }
1229         }
1230
1231         return ret;
1232 }
1233
1234 int add_port_name(uint32_t val, const char *str2)
1235 {
1236         char str[MAX_STR_LEN_PROC];
1237
1238         if (parse_vars(str, sizeof(str), str2))
1239                 return -1;
1240
1241         struct port_name* pn;
1242
1243         if (nb_port_names == MAX_NB_PORT_NAMES) {
1244                 set_errf("Too many ports defined (can define %d)", MAX_NB_PORT_NAMES);
1245                 return -1;
1246         }
1247
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);
1252                         return -2;
1253                 }
1254         }
1255
1256         pn = &port_names[nb_port_names];
1257         prox_strncpy(pn->name, str, sizeof(pn->name));
1258         pn->id = val;
1259
1260         ++nb_port_names;
1261         return 0;
1262 }
1263
1264 int set_self_var(const char *str)
1265 {
1266         for (uint8_t i = 0; i < nb_vars; ++i) {
1267                 if (!strcmp("$self", vars[i].name)) {
1268                         sprintf(vars[i].val, "%s", str);
1269                         return 0;
1270                 }
1271         }
1272
1273         struct var *v = &vars[nb_vars];
1274
1275         prox_strncpy(v->name, "$self", strlen("$self") + 1);
1276         sprintf(v->val, "%s", str);
1277         nb_vars++;
1278
1279         return 0;
1280 }
1281
1282 int add_var(const char* name, const char *str2, uint8_t cli)
1283 {
1284         struct var* v;
1285
1286         char str[MAX_STR_LEN_PROC];
1287
1288         if (parse_vars(str, sizeof(str), str2))
1289                 return -1;
1290
1291         if (strlen(name) == 0 || strlen(name) == 1) {
1292                 set_errf("Can't define variables with empty name");
1293                 return -1;
1294         }
1295
1296         if (name[0] != '$') {
1297                 set_errf("Each variable should start with the $ character");
1298                 return -1;
1299         }
1300
1301         if (nb_vars == MAX_NB_VARS) {
1302                 set_errf("Too many variables defined (can define %d)", MAX_NB_VARS);
1303                 return -2;
1304         }
1305
1306         for (uint8_t i = 0; i < nb_vars; ++i) {
1307                 if (!strcmp(name, vars[i].name)) {
1308
1309                         /* Variables defined through program arguments
1310                            take precedence. */
1311                         if (!cli && vars[i].cli) {
1312                                 return 0;
1313                         }
1314
1315                         set_errf("Variable with name %s is already defined", name);
1316                         return -3;
1317                 }
1318         }
1319
1320         v = &vars[nb_vars];
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));
1325         v->cli = cli;
1326
1327         ++nb_vars;
1328         return 0;
1329 }
1330
1331 static int read_cores_present(uint32_t *cores, int max_cores, int *res)
1332 {
1333         FILE* fd = fopen("/sys/devices/system/cpu/present", "r");
1334         char buf[1024];
1335
1336         if (fd == NULL) {
1337                 set_errf("Could not opening file /sys/devices/system/cpu/present");
1338                 return -1;
1339         }
1340
1341         if (fgets(buf, sizeof(buf), fd) == NULL) {
1342                 set_errf("Could not read cores range");
1343                 return -1;
1344         }
1345
1346         fclose(fd);
1347
1348         int ret = parse_list_set(cores, buf, max_cores);
1349
1350         if (ret < 0)
1351                 return -1;
1352
1353         *res = ret;
1354         return 0;
1355 }
1356
1357 static int set_dummy_topology(void)
1358 {
1359         int core_count = 0;
1360
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]++;
1366                 }
1367         }
1368         cpu_topo.n_sockets = MAX_SOCKETS;
1369         return 0;
1370 }
1371
1372 static int read_cpu_topology(void)
1373 {
1374         if (cpu_topo.n_sockets != 0)
1375                 return 0;
1376         if (prox_cfg.flags & DSF_USE_DUMMY_CPU_TOPO)
1377                 return set_dummy_topology();
1378
1379         uint32_t cores[RTE_MAX_LCORE];
1380         int n_cores = 0;
1381
1382         if (read_cores_present(cores, sizeof(cores)/sizeof(cores[0]), &n_cores) != 0)
1383                 return -1;
1384
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;
1389                 }
1390         }
1391
1392         for (int i = 0; i < n_cores; ++i) {
1393                 uint32_t socket_id, lcore_id, phys;
1394
1395                 lcore_id = cores[i];
1396                 if (get_socket(lcore_id, &socket_id) != 0)
1397                         return -1;
1398                 if (socket_id >= MAX_SOCKETS) {
1399                         set_errf("Can't read CPU topology due too high socket ID (max allowed is %d)",
1400                                  MAX_SOCKETS);
1401                         return -1;
1402                 }
1403                 if (socket_id >= cpu_topo.n_sockets) {
1404                         cpu_topo.n_sockets = socket_id + 1;
1405                 }
1406                 if (get_phys_core(&phys, lcore_id) != 0)
1407                         return -1;
1408                 if (phys >= RTE_MAX_LCORE) {
1409                         set_errf("Core ID %u too high", phys);
1410                         return -1;
1411                 }
1412
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]++;
1416                 }
1417                 else if (cpu_topo.socket[socket_id][phys][1] == -1) {
1418                         cpu_topo.socket[socket_id][phys][1] = lcore_id;
1419                 }
1420                 else {
1421                         set_errf("Too many core siblings");
1422                         return -1;
1423                 }
1424         }
1425
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. */
1431
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)
1435                         spread++;
1436
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];
1440                         compact++;
1441                         spread++;
1442                         /* Skip gaps */
1443                         while (cpu_topo.socket[i][spread][0] == -1)
1444                                 spread++;
1445                 }
1446         }
1447
1448         return 0;
1449 }
1450
1451 static int bit_len_valid(uint32_t len, const char *str)
1452 {
1453         if (len > 32) {
1454                 set_errf("Maximum random length is 32, but length of '%s' is %zu\n", str, len);
1455                 return 0;
1456         }
1457         if (len % 8) {
1458                 plog_err("Random should be multiple of 8 long\n");
1459                 return 0;
1460         }
1461         if (len == 0) {
1462                 plog_err("Random should be at least 1 byte long\n");
1463                 return 0;
1464         }
1465         return -1;
1466 }
1467
1468 int parse_random_str(uint32_t *mask, uint32_t *fixed, uint32_t *len, const char *str)
1469 {
1470         const size_t len_bits = strlen(str);
1471
1472         if (!bit_len_valid(len_bits, str))
1473                 return -1;
1474
1475         *mask = 0;
1476         *fixed = 0;
1477         *len = len_bits / 8;
1478
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). */
1482                 switch (str[j]) {
1483                 case 'X':
1484                         *mask |= 1 << (len_bits - 1 - j);
1485                         break;
1486                 case '1':
1487                         *fixed |= 1 << (len_bits - 1 - j);
1488                         break;
1489                 case '0':
1490                         break;
1491                 default:
1492                         set_errf("Unexpected %c\n", str[j]);
1493                         return -1;
1494                 }
1495         }
1496         return 0;
1497 }