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