eal: use SPDX tags in 6WIND copyrighted files
[dpdk.git] / lib / librte_eal / common / eal_common_options.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation.
3  * Copyright(c) 2014 6WIND S.A.
4  */
5
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <syslog.h>
10 #include <ctype.h>
11 #include <limits.h>
12 #include <errno.h>
13 #include <getopt.h>
14 #include <dlfcn.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <dirent.h>
18
19 #include <rte_eal.h>
20 #include <rte_log.h>
21 #include <rte_lcore.h>
22 #include <rte_tailq.h>
23 #include <rte_version.h>
24 #include <rte_devargs.h>
25 #include <rte_memcpy.h>
26
27 #include "eal_internal_cfg.h"
28 #include "eal_options.h"
29 #include "eal_filesystem.h"
30
31 #define BITS_PER_HEX 4
32
33 const char
34 eal_short_options[] =
35         "b:" /* pci-blacklist */
36         "c:" /* coremask */
37         "s:" /* service coremask */
38         "d:" /* driver */
39         "h"  /* help */
40         "l:" /* corelist */
41         "S:" /* service corelist */
42         "m:" /* memory size */
43         "n:" /* memory channels */
44         "r:" /* memory ranks */
45         "v"  /* version */
46         "w:" /* pci-whitelist */
47         ;
48
49 const struct option
50 eal_long_options[] = {
51         {OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
52         {OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
53         {OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
54         {OPT_HELP,              0, NULL, OPT_HELP_NUM             },
55         {OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
56         {OPT_HUGE_UNLINK,       0, NULL, OPT_HUGE_UNLINK_NUM      },
57         {OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
58         {OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
59         {OPT_MASTER_LCORE,      1, NULL, OPT_MASTER_LCORE_NUM     },
60         {OPT_MBUF_POOL_OPS_NAME, 1, NULL, OPT_MBUF_POOL_OPS_NAME_NUM},
61         {OPT_NO_HPET,           0, NULL, OPT_NO_HPET_NUM          },
62         {OPT_NO_HUGE,           0, NULL, OPT_NO_HUGE_NUM          },
63         {OPT_NO_PCI,            0, NULL, OPT_NO_PCI_NUM           },
64         {OPT_NO_SHCONF,         0, NULL, OPT_NO_SHCONF_NUM        },
65         {OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
66         {OPT_PCI_WHITELIST,     1, NULL, OPT_PCI_WHITELIST_NUM    },
67         {OPT_PROC_TYPE,         1, NULL, OPT_PROC_TYPE_NUM        },
68         {OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
69         {OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
70         {OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
71         {OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
72         {OPT_VMWARE_TSC_MAP,    0, NULL, OPT_VMWARE_TSC_MAP_NUM   },
73         {0,                     0, NULL, 0                        }
74 };
75
76 TAILQ_HEAD(shared_driver_list, shared_driver);
77
78 /* Definition for shared object drivers. */
79 struct shared_driver {
80         TAILQ_ENTRY(shared_driver) next;
81
82         char    name[PATH_MAX];
83         void*   lib_handle;
84 };
85
86 /* List of external loadable drivers */
87 static struct shared_driver_list solib_list =
88 TAILQ_HEAD_INITIALIZER(solib_list);
89
90 /* Default path of external loadable drivers */
91 static const char *default_solib_dir = RTE_EAL_PMD_PATH;
92
93 /*
94  * Stringified version of solib path used by dpdk-pmdinfo.py
95  * Note: PLEASE DO NOT ALTER THIS without making a corresponding
96  * change to usertools/dpdk-pmdinfo.py
97  */
98 static const char dpdk_solib_path[] __attribute__((used)) =
99 "DPDK_PLUGIN_PATH=" RTE_EAL_PMD_PATH;
100
101 TAILQ_HEAD(device_option_list, device_option);
102
103 struct device_option {
104         TAILQ_ENTRY(device_option) next;
105
106         enum rte_devtype type;
107         char arg[];
108 };
109
110 static struct device_option_list devopt_list =
111 TAILQ_HEAD_INITIALIZER(devopt_list);
112
113 static int master_lcore_parsed;
114 static int mem_parsed;
115 static int core_parsed;
116
117 static int
118 eal_option_device_add(enum rte_devtype type, const char *optarg)
119 {
120         struct device_option *devopt;
121         size_t optlen;
122         int ret;
123
124         optlen = strlen(optarg) + 1;
125         devopt = calloc(1, sizeof(*devopt) + optlen);
126         if (devopt == NULL) {
127                 RTE_LOG(ERR, EAL, "Unable to allocate device option\n");
128                 return -ENOMEM;
129         }
130
131         devopt->type = type;
132         ret = snprintf(devopt->arg, optlen, "%s", optarg);
133         if (ret < 0) {
134                 RTE_LOG(ERR, EAL, "Unable to copy device option\n");
135                 free(devopt);
136                 return -EINVAL;
137         }
138         TAILQ_INSERT_TAIL(&devopt_list, devopt, next);
139         return 0;
140 }
141
142 int
143 eal_option_device_parse(void)
144 {
145         struct device_option *devopt;
146         void *tmp;
147         int ret = 0;
148
149         TAILQ_FOREACH_SAFE(devopt, &devopt_list, next, tmp) {
150                 if (ret == 0) {
151                         ret = rte_eal_devargs_add(devopt->type, devopt->arg);
152                         if (ret)
153                                 RTE_LOG(ERR, EAL, "Unable to parse device '%s'\n",
154                                         devopt->arg);
155                 }
156                 TAILQ_REMOVE(&devopt_list, devopt, next);
157                 free(devopt);
158         }
159         return ret;
160 }
161
162 void
163 eal_reset_internal_config(struct internal_config *internal_cfg)
164 {
165         int i;
166
167         internal_cfg->memory = 0;
168         internal_cfg->force_nrank = 0;
169         internal_cfg->force_nchannel = 0;
170         internal_cfg->hugefile_prefix = HUGEFILE_PREFIX_DEFAULT;
171         internal_cfg->hugepage_dir = NULL;
172         internal_cfg->force_sockets = 0;
173         /* zero out the NUMA config */
174         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
175                 internal_cfg->socket_mem[i] = 0;
176         /* zero out hugedir descriptors */
177         for (i = 0; i < MAX_HUGEPAGE_SIZES; i++)
178                 internal_cfg->hugepage_info[i].lock_descriptor = -1;
179         internal_cfg->base_virtaddr = 0;
180
181         internal_cfg->syslog_facility = LOG_DAEMON;
182
183         /* if set to NONE, interrupt mode is determined automatically */
184         internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
185
186 #ifdef RTE_LIBEAL_USE_HPET
187         internal_cfg->no_hpet = 0;
188 #else
189         internal_cfg->no_hpet = 1;
190 #endif
191         internal_cfg->vmware_tsc_map = 0;
192         internal_cfg->create_uio_dev = 0;
193         internal_cfg->user_mbuf_pool_ops_name = NULL;
194 }
195
196 static int
197 eal_plugin_add(const char *path)
198 {
199         struct shared_driver *solib;
200
201         solib = malloc(sizeof(*solib));
202         if (solib == NULL) {
203                 RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
204                 return -1;
205         }
206         memset(solib, 0, sizeof(*solib));
207         strncpy(solib->name, path, PATH_MAX-1);
208         solib->name[PATH_MAX-1] = 0;
209         TAILQ_INSERT_TAIL(&solib_list, solib, next);
210
211         return 0;
212 }
213
214 static int
215 eal_plugindir_init(const char *path)
216 {
217         DIR *d = NULL;
218         struct dirent *dent = NULL;
219         char sopath[PATH_MAX];
220
221         if (path == NULL || *path == '\0')
222                 return 0;
223
224         d = opendir(path);
225         if (d == NULL) {
226                 RTE_LOG(ERR, EAL, "failed to open directory %s: %s\n",
227                         path, strerror(errno));
228                 return -1;
229         }
230
231         while ((dent = readdir(d)) != NULL) {
232                 struct stat sb;
233
234                 snprintf(sopath, PATH_MAX-1, "%s/%s", path, dent->d_name);
235                 sopath[PATH_MAX-1] = 0;
236
237                 if (!(stat(sopath, &sb) == 0 && S_ISREG(sb.st_mode)))
238                         continue;
239
240                 if (eal_plugin_add(sopath) == -1)
241                         break;
242         }
243
244         closedir(d);
245         /* XXX this ignores failures from readdir() itself */
246         return (dent == NULL) ? 0 : -1;
247 }
248
249 int
250 eal_plugins_init(void)
251 {
252         struct shared_driver *solib = NULL;
253         struct stat sb;
254
255         if (*default_solib_dir != '\0' && stat(default_solib_dir, &sb) == 0 &&
256                                 S_ISDIR(sb.st_mode))
257                 eal_plugin_add(default_solib_dir);
258
259         TAILQ_FOREACH(solib, &solib_list, next) {
260
261                 if (stat(solib->name, &sb) == 0 && S_ISDIR(sb.st_mode)) {
262                         if (eal_plugindir_init(solib->name) == -1) {
263                                 RTE_LOG(ERR, EAL,
264                                         "Cannot init plugin directory %s\n",
265                                         solib->name);
266                                 return -1;
267                         }
268                 } else {
269                         RTE_LOG(DEBUG, EAL, "open shared lib %s\n",
270                                 solib->name);
271                         solib->lib_handle = dlopen(solib->name, RTLD_NOW);
272                         if (solib->lib_handle == NULL) {
273                                 RTE_LOG(ERR, EAL, "%s\n", dlerror());
274                                 return -1;
275                         }
276                 }
277
278         }
279         return 0;
280 }
281
282 /*
283  * Parse the coremask given as argument (hexadecimal string) and fill
284  * the global configuration (core role and core count) with the parsed
285  * value.
286  */
287 static int xdigit2val(unsigned char c)
288 {
289         int val;
290
291         if (isdigit(c))
292                 val = c - '0';
293         else if (isupper(c))
294                 val = c - 'A' + 10;
295         else
296                 val = c - 'a' + 10;
297         return val;
298 }
299
300 static int
301 eal_parse_service_coremask(const char *coremask)
302 {
303         struct rte_config *cfg = rte_eal_get_configuration();
304         int i, j, idx = 0;
305         unsigned int count = 0;
306         char c;
307         int val;
308
309         if (coremask == NULL)
310                 return -1;
311         /* Remove all blank characters ahead and after .
312          * Remove 0x/0X if exists.
313          */
314         while (isblank(*coremask))
315                 coremask++;
316         if (coremask[0] == '0' && ((coremask[1] == 'x')
317                 || (coremask[1] == 'X')))
318                 coremask += 2;
319         i = strlen(coremask);
320         while ((i > 0) && isblank(coremask[i - 1]))
321                 i--;
322
323         if (i == 0)
324                 return -1;
325
326         for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
327                 c = coremask[i];
328                 if (isxdigit(c) == 0) {
329                         /* invalid characters */
330                         return -1;
331                 }
332                 val = xdigit2val(c);
333                 for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE;
334                                 j++, idx++) {
335                         if ((1 << j) & val) {
336                                 /* handle master lcore already parsed */
337                                 uint32_t lcore = idx;
338                                 if (master_lcore_parsed &&
339                                                 cfg->master_lcore == lcore) {
340                                         RTE_LOG(ERR, EAL,
341                                                 "Error: lcore %u is master lcore, cannot use as service core\n",
342                                                 idx);
343                                         return -1;
344                                 }
345
346                                 if (!lcore_config[idx].detected) {
347                                         RTE_LOG(ERR, EAL,
348                                                 "lcore %u unavailable\n", idx);
349                                         return -1;
350                                 }
351                                 lcore_config[idx].core_role = ROLE_SERVICE;
352                                 count++;
353                         }
354                 }
355         }
356
357         for (; i >= 0; i--)
358                 if (coremask[i] != '0')
359                         return -1;
360
361         for (; idx < RTE_MAX_LCORE; idx++)
362                 lcore_config[idx].core_index = -1;
363
364         if (count == 0)
365                 return -1;
366
367         cfg->service_lcore_count = count;
368         return 0;
369 }
370
371 static int
372 eal_parse_coremask(const char *coremask)
373 {
374         struct rte_config *cfg = rte_eal_get_configuration();
375         int i, j, idx = 0;
376         unsigned count = 0;
377         char c;
378         int val;
379
380         if (coremask == NULL)
381                 return -1;
382         /* Remove all blank characters ahead and after .
383          * Remove 0x/0X if exists.
384          */
385         while (isblank(*coremask))
386                 coremask++;
387         if (coremask[0] == '0' && ((coremask[1] == 'x')
388                 || (coremask[1] == 'X')))
389                 coremask += 2;
390         i = strlen(coremask);
391         while ((i > 0) && isblank(coremask[i - 1]))
392                 i--;
393         if (i == 0)
394                 return -1;
395
396         for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
397                 c = coremask[i];
398                 if (isxdigit(c) == 0) {
399                         /* invalid characters */
400                         return -1;
401                 }
402                 val = xdigit2val(c);
403                 for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE; j++, idx++)
404                 {
405                         if ((1 << j) & val) {
406                                 if (!lcore_config[idx].detected) {
407                                         RTE_LOG(ERR, EAL, "lcore %u "
408                                                 "unavailable\n", idx);
409                                         return -1;
410                                 }
411                                 cfg->lcore_role[idx] = ROLE_RTE;
412                                 lcore_config[idx].core_index = count;
413                                 count++;
414                         } else {
415                                 cfg->lcore_role[idx] = ROLE_OFF;
416                                 lcore_config[idx].core_index = -1;
417                         }
418                 }
419         }
420         for (; i >= 0; i--)
421                 if (coremask[i] != '0')
422                         return -1;
423         for (; idx < RTE_MAX_LCORE; idx++) {
424                 cfg->lcore_role[idx] = ROLE_OFF;
425                 lcore_config[idx].core_index = -1;
426         }
427         if (count == 0)
428                 return -1;
429         /* Update the count of enabled logical cores of the EAL configuration */
430         cfg->lcore_count = count;
431         return 0;
432 }
433
434 static int
435 eal_parse_service_corelist(const char *corelist)
436 {
437         struct rte_config *cfg = rte_eal_get_configuration();
438         int i, idx = 0;
439         unsigned count = 0;
440         char *end = NULL;
441         int min, max;
442
443         if (corelist == NULL)
444                 return -1;
445
446         /* Remove all blank characters ahead and after */
447         while (isblank(*corelist))
448                 corelist++;
449         i = strlen(corelist);
450         while ((i > 0) && isblank(corelist[i - 1]))
451                 i--;
452
453         /* Get list of cores */
454         min = RTE_MAX_LCORE;
455         do {
456                 while (isblank(*corelist))
457                         corelist++;
458                 if (*corelist == '\0')
459                         return -1;
460                 errno = 0;
461                 idx = strtoul(corelist, &end, 10);
462                 if (errno || end == NULL)
463                         return -1;
464                 while (isblank(*end))
465                         end++;
466                 if (*end == '-') {
467                         min = idx;
468                 } else if ((*end == ',') || (*end == '\0')) {
469                         max = idx;
470                         if (min == RTE_MAX_LCORE)
471                                 min = idx;
472                         for (idx = min; idx <= max; idx++) {
473                                 if (cfg->lcore_role[idx] != ROLE_SERVICE) {
474                                         /* handle master lcore already parsed */
475                                         uint32_t lcore = idx;
476                                         if (cfg->master_lcore == lcore &&
477                                                         master_lcore_parsed) {
478                                                 RTE_LOG(ERR, EAL,
479                                                         "Error: lcore %u is master lcore, cannot use as service core\n",
480                                                         idx);
481                                                 return -1;
482                                         }
483                                         lcore_config[idx].core_role =
484                                                         ROLE_SERVICE;
485                                         count++;
486                                 }
487                         }
488                         min = RTE_MAX_LCORE;
489                 } else
490                         return -1;
491                 corelist = end + 1;
492         } while (*end != '\0');
493
494         if (count == 0)
495                 return -1;
496
497         return 0;
498 }
499
500 static int
501 eal_parse_corelist(const char *corelist)
502 {
503         struct rte_config *cfg = rte_eal_get_configuration();
504         int i, idx = 0;
505         unsigned count = 0;
506         char *end = NULL;
507         int min, max;
508
509         if (corelist == NULL)
510                 return -1;
511
512         /* Remove all blank characters ahead and after */
513         while (isblank(*corelist))
514                 corelist++;
515         i = strlen(corelist);
516         while ((i > 0) && isblank(corelist[i - 1]))
517                 i--;
518
519         /* Reset config */
520         for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
521                 cfg->lcore_role[idx] = ROLE_OFF;
522                 lcore_config[idx].core_index = -1;
523         }
524
525         /* Get list of cores */
526         min = RTE_MAX_LCORE;
527         do {
528                 while (isblank(*corelist))
529                         corelist++;
530                 if (*corelist == '\0')
531                         return -1;
532                 errno = 0;
533                 idx = strtoul(corelist, &end, 10);
534                 if (errno || end == NULL)
535                         return -1;
536                 while (isblank(*end))
537                         end++;
538                 if (*end == '-') {
539                         min = idx;
540                 } else if ((*end == ',') || (*end == '\0')) {
541                         max = idx;
542                         if (min == RTE_MAX_LCORE)
543                                 min = idx;
544                         for (idx = min; idx <= max; idx++) {
545                                 if (cfg->lcore_role[idx] != ROLE_RTE) {
546                                         cfg->lcore_role[idx] = ROLE_RTE;
547                                         lcore_config[idx].core_index = count;
548                                         count++;
549                                 }
550                         }
551                         min = RTE_MAX_LCORE;
552                 } else
553                         return -1;
554                 corelist = end + 1;
555         } while (*end != '\0');
556
557         if (count == 0)
558                 return -1;
559
560         /* Update the count of enabled logical cores of the EAL configuration */
561         cfg->lcore_count = count;
562
563         return 0;
564 }
565
566 /* Changes the lcore id of the master thread */
567 static int
568 eal_parse_master_lcore(const char *arg)
569 {
570         char *parsing_end;
571         struct rte_config *cfg = rte_eal_get_configuration();
572
573         errno = 0;
574         cfg->master_lcore = (uint32_t) strtol(arg, &parsing_end, 0);
575         if (errno || parsing_end[0] != 0)
576                 return -1;
577         if (cfg->master_lcore >= RTE_MAX_LCORE)
578                 return -1;
579         master_lcore_parsed = 1;
580
581         /* ensure master core is not used as service core */
582         if (lcore_config[cfg->master_lcore].core_role == ROLE_SERVICE) {
583                 RTE_LOG(ERR, EAL, "Error: Master lcore is used as a service core.\n");
584                 return -1;
585         }
586
587         return 0;
588 }
589
590 /*
591  * Parse elem, the elem could be single number/range or '(' ')' group
592  * 1) A single number elem, it's just a simple digit. e.g. 9
593  * 2) A single range elem, two digits with a '-' between. e.g. 2-6
594  * 3) A group elem, combines multiple 1) or 2) with '( )'. e.g (0,2-4,6)
595  *    Within group elem, '-' used for a range separator;
596  *                       ',' used for a single number.
597  */
598 static int
599 eal_parse_set(const char *input, uint16_t set[], unsigned num)
600 {
601         unsigned idx;
602         const char *str = input;
603         char *end = NULL;
604         unsigned min, max;
605
606         memset(set, 0, num * sizeof(uint16_t));
607
608         while (isblank(*str))
609                 str++;
610
611         /* only digit or left bracket is qualify for start point */
612         if ((!isdigit(*str) && *str != '(') || *str == '\0')
613                 return -1;
614
615         /* process single number or single range of number */
616         if (*str != '(') {
617                 errno = 0;
618                 idx = strtoul(str, &end, 10);
619                 if (errno || end == NULL || idx >= num)
620                         return -1;
621                 else {
622                         while (isblank(*end))
623                                 end++;
624
625                         min = idx;
626                         max = idx;
627                         if (*end == '-') {
628                                 /* process single <number>-<number> */
629                                 end++;
630                                 while (isblank(*end))
631                                         end++;
632                                 if (!isdigit(*end))
633                                         return -1;
634
635                                 errno = 0;
636                                 idx = strtoul(end, &end, 10);
637                                 if (errno || end == NULL || idx >= num)
638                                         return -1;
639                                 max = idx;
640                                 while (isblank(*end))
641                                         end++;
642                                 if (*end != ',' && *end != '\0')
643                                         return -1;
644                         }
645
646                         if (*end != ',' && *end != '\0' &&
647                             *end != '@')
648                                 return -1;
649
650                         for (idx = RTE_MIN(min, max);
651                              idx <= RTE_MAX(min, max); idx++)
652                                 set[idx] = 1;
653
654                         return end - input;
655                 }
656         }
657
658         /* process set within bracket */
659         str++;
660         while (isblank(*str))
661                 str++;
662         if (*str == '\0')
663                 return -1;
664
665         min = RTE_MAX_LCORE;
666         do {
667
668                 /* go ahead to the first digit */
669                 while (isblank(*str))
670                         str++;
671                 if (!isdigit(*str))
672                         return -1;
673
674                 /* get the digit value */
675                 errno = 0;
676                 idx = strtoul(str, &end, 10);
677                 if (errno || end == NULL || idx >= num)
678                         return -1;
679
680                 /* go ahead to separator '-',',' and ')' */
681                 while (isblank(*end))
682                         end++;
683                 if (*end == '-') {
684                         if (min == RTE_MAX_LCORE)
685                                 min = idx;
686                         else /* avoid continuous '-' */
687                                 return -1;
688                 } else if ((*end == ',') || (*end == ')')) {
689                         max = idx;
690                         if (min == RTE_MAX_LCORE)
691                                 min = idx;
692                         for (idx = RTE_MIN(min, max);
693                              idx <= RTE_MAX(min, max); idx++)
694                                 set[idx] = 1;
695
696                         min = RTE_MAX_LCORE;
697                 } else
698                         return -1;
699
700                 str = end + 1;
701         } while (*end != '\0' && *end != ')');
702
703         /*
704          * to avoid failure that tail blank makes end character check fail
705          * in eal_parse_lcores( )
706          */
707         while (isblank(*str))
708                 str++;
709
710         return str - input;
711 }
712
713 /* convert from set array to cpuset bitmap */
714 static int
715 convert_to_cpuset(rte_cpuset_t *cpusetp,
716               uint16_t *set, unsigned num)
717 {
718         unsigned idx;
719
720         CPU_ZERO(cpusetp);
721
722         for (idx = 0; idx < num; idx++) {
723                 if (!set[idx])
724                         continue;
725
726                 if (!lcore_config[idx].detected) {
727                         RTE_LOG(ERR, EAL, "core %u "
728                                 "unavailable\n", idx);
729                         return -1;
730                 }
731
732                 CPU_SET(idx, cpusetp);
733         }
734
735         return 0;
736 }
737
738 /*
739  * The format pattern: --lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
740  * lcores, cpus could be a single digit/range or a group.
741  * '(' and ')' are necessary if it's a group.
742  * If not supply '@cpus', the value of cpus uses the same as lcores.
743  * e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means start 9 EAL thread as below
744  *   lcore 0 runs on cpuset 0x41 (cpu 0,6)
745  *   lcore 1 runs on cpuset 0x2 (cpu 1)
746  *   lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
747  *   lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
748  *   lcore 6 runs on cpuset 0x41 (cpu 0,6)
749  *   lcore 7 runs on cpuset 0x80 (cpu 7)
750  *   lcore 8 runs on cpuset 0x100 (cpu 8)
751  */
752 static int
753 eal_parse_lcores(const char *lcores)
754 {
755         struct rte_config *cfg = rte_eal_get_configuration();
756         static uint16_t set[RTE_MAX_LCORE];
757         unsigned idx = 0;
758         unsigned count = 0;
759         const char *lcore_start = NULL;
760         const char *end = NULL;
761         int offset;
762         rte_cpuset_t cpuset;
763         int lflags;
764         int ret = -1;
765
766         if (lcores == NULL)
767                 return -1;
768
769         /* Remove all blank characters ahead and after */
770         while (isblank(*lcores))
771                 lcores++;
772
773         CPU_ZERO(&cpuset);
774
775         /* Reset lcore config */
776         for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
777                 cfg->lcore_role[idx] = ROLE_OFF;
778                 lcore_config[idx].core_index = -1;
779                 CPU_ZERO(&lcore_config[idx].cpuset);
780         }
781
782         /* Get list of cores */
783         do {
784                 while (isblank(*lcores))
785                         lcores++;
786                 if (*lcores == '\0')
787                         goto err;
788
789                 lflags = 0;
790
791                 /* record lcore_set start point */
792                 lcore_start = lcores;
793
794                 /* go across a complete bracket */
795                 if (*lcore_start == '(') {
796                         lcores += strcspn(lcores, ")");
797                         if (*lcores++ == '\0')
798                                 goto err;
799                 }
800
801                 /* scan the separator '@', ','(next) or '\0'(finish) */
802                 lcores += strcspn(lcores, "@,");
803
804                 if (*lcores == '@') {
805                         /* explicit assign cpu_set */
806                         offset = eal_parse_set(lcores + 1, set, RTE_DIM(set));
807                         if (offset < 0)
808                                 goto err;
809
810                         /* prepare cpu_set and update the end cursor */
811                         if (0 > convert_to_cpuset(&cpuset,
812                                                   set, RTE_DIM(set)))
813                                 goto err;
814                         end = lcores + 1 + offset;
815                 } else { /* ',' or '\0' */
816                         /* haven't given cpu_set, current loop done */
817                         end = lcores;
818
819                         /* go back to check <number>-<number> */
820                         offset = strcspn(lcore_start, "(-");
821                         if (offset < (end - lcore_start) &&
822                             *(lcore_start + offset) != '(')
823                                 lflags = 1;
824                 }
825
826                 if (*end != ',' && *end != '\0')
827                         goto err;
828
829                 /* parse lcore_set from start point */
830                 if (0 > eal_parse_set(lcore_start, set, RTE_DIM(set)))
831                         goto err;
832
833                 /* without '@', by default using lcore_set as cpu_set */
834                 if (*lcores != '@' &&
835                     0 > convert_to_cpuset(&cpuset, set, RTE_DIM(set)))
836                         goto err;
837
838                 /* start to update lcore_set */
839                 for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
840                         if (!set[idx])
841                                 continue;
842
843                         if (cfg->lcore_role[idx] != ROLE_RTE) {
844                                 lcore_config[idx].core_index = count;
845                                 cfg->lcore_role[idx] = ROLE_RTE;
846                                 count++;
847                         }
848
849                         if (lflags) {
850                                 CPU_ZERO(&cpuset);
851                                 CPU_SET(idx, &cpuset);
852                         }
853                         rte_memcpy(&lcore_config[idx].cpuset, &cpuset,
854                                    sizeof(rte_cpuset_t));
855                 }
856
857                 lcores = end + 1;
858         } while (*end != '\0');
859
860         if (count == 0)
861                 goto err;
862
863         cfg->lcore_count = count;
864         ret = 0;
865
866 err:
867
868         return ret;
869 }
870
871 static int
872 eal_parse_syslog(const char *facility, struct internal_config *conf)
873 {
874         int i;
875         static struct {
876                 const char *name;
877                 int value;
878         } map[] = {
879                 { "auth", LOG_AUTH },
880                 { "cron", LOG_CRON },
881                 { "daemon", LOG_DAEMON },
882                 { "ftp", LOG_FTP },
883                 { "kern", LOG_KERN },
884                 { "lpr", LOG_LPR },
885                 { "mail", LOG_MAIL },
886                 { "news", LOG_NEWS },
887                 { "syslog", LOG_SYSLOG },
888                 { "user", LOG_USER },
889                 { "uucp", LOG_UUCP },
890                 { "local0", LOG_LOCAL0 },
891                 { "local1", LOG_LOCAL1 },
892                 { "local2", LOG_LOCAL2 },
893                 { "local3", LOG_LOCAL3 },
894                 { "local4", LOG_LOCAL4 },
895                 { "local5", LOG_LOCAL5 },
896                 { "local6", LOG_LOCAL6 },
897                 { "local7", LOG_LOCAL7 },
898                 { NULL, 0 }
899         };
900
901         for (i = 0; map[i].name; i++) {
902                 if (!strcmp(facility, map[i].name)) {
903                         conf->syslog_facility = map[i].value;
904                         return 0;
905                 }
906         }
907         return -1;
908 }
909
910 static int
911 eal_parse_log_level(const char *arg)
912 {
913         char *end, *str, *type, *level;
914         unsigned long tmp;
915
916         str = strdup(arg);
917         if (str == NULL)
918                 return -1;
919
920         if (strchr(str, ',') == NULL) {
921                 type = NULL;
922                 level = str;
923         } else {
924                 type = strsep(&str, ",");
925                 level = strsep(&str, ",");
926         }
927
928         errno = 0;
929         tmp = strtoul(level, &end, 0);
930
931         /* check for errors */
932         if ((errno != 0) || (level[0] == '\0') ||
933                     end == NULL || (*end != '\0'))
934                 goto fail;
935
936         /* log_level is a uint32_t */
937         if (tmp >= UINT32_MAX)
938                 goto fail;
939
940         if (type == NULL) {
941                 rte_log_set_global_level(tmp);
942         } else if (rte_log_set_level_regexp(type, tmp) < 0) {
943                 printf("cannot set log level %s,%lu\n",
944                         type, tmp);
945                 goto fail;
946         }
947
948         free(str);
949         return 0;
950
951 fail:
952         free(str);
953         return -1;
954 }
955
956 static enum rte_proc_type_t
957 eal_parse_proc_type(const char *arg)
958 {
959         if (strncasecmp(arg, "primary", sizeof("primary")) == 0)
960                 return RTE_PROC_PRIMARY;
961         if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0)
962                 return RTE_PROC_SECONDARY;
963         if (strncasecmp(arg, "auto", sizeof("auto")) == 0)
964                 return RTE_PROC_AUTO;
965
966         return RTE_PROC_INVALID;
967 }
968
969 int
970 eal_parse_common_option(int opt, const char *optarg,
971                         struct internal_config *conf)
972 {
973         static int b_used;
974         static int w_used;
975
976         switch (opt) {
977         /* blacklist */
978         case 'b':
979                 if (w_used)
980                         goto bw_used;
981                 if (eal_option_device_add(RTE_DEVTYPE_BLACKLISTED_PCI,
982                                 optarg) < 0) {
983                         return -1;
984                 }
985                 b_used = 1;
986                 break;
987         /* whitelist */
988         case 'w':
989                 if (b_used)
990                         goto bw_used;
991                 if (eal_option_device_add(RTE_DEVTYPE_WHITELISTED_PCI,
992                                 optarg) < 0) {
993                         return -1;
994                 }
995                 w_used = 1;
996                 break;
997         /* coremask */
998         case 'c':
999                 if (eal_parse_coremask(optarg) < 0) {
1000                         RTE_LOG(ERR, EAL, "invalid coremask\n");
1001                         return -1;
1002                 }
1003                 core_parsed = 1;
1004                 break;
1005         /* corelist */
1006         case 'l':
1007                 if (eal_parse_corelist(optarg) < 0) {
1008                         RTE_LOG(ERR, EAL, "invalid core list\n");
1009                         return -1;
1010                 }
1011                 core_parsed = 1;
1012                 break;
1013         /* service coremask */
1014         case 's':
1015                 if (eal_parse_service_coremask(optarg) < 0) {
1016                         RTE_LOG(ERR, EAL, "invalid service coremask\n");
1017                         return -1;
1018                 }
1019                 break;
1020         /* service corelist */
1021         case 'S':
1022                 if (eal_parse_service_corelist(optarg) < 0) {
1023                         RTE_LOG(ERR, EAL, "invalid service core list\n");
1024                         return -1;
1025                 }
1026                 break;
1027         /* size of memory */
1028         case 'm':
1029                 conf->memory = atoi(optarg);
1030                 conf->memory *= 1024ULL;
1031                 conf->memory *= 1024ULL;
1032                 mem_parsed = 1;
1033                 break;
1034         /* force number of channels */
1035         case 'n':
1036                 conf->force_nchannel = atoi(optarg);
1037                 if (conf->force_nchannel == 0) {
1038                         RTE_LOG(ERR, EAL, "invalid channel number\n");
1039                         return -1;
1040                 }
1041                 break;
1042         /* force number of ranks */
1043         case 'r':
1044                 conf->force_nrank = atoi(optarg);
1045                 if (conf->force_nrank == 0 ||
1046                     conf->force_nrank > 16) {
1047                         RTE_LOG(ERR, EAL, "invalid rank number\n");
1048                         return -1;
1049                 }
1050                 break;
1051         /* force loading of external driver */
1052         case 'd':
1053                 if (eal_plugin_add(optarg) == -1)
1054                         return -1;
1055                 break;
1056         case 'v':
1057                 /* since message is explicitly requested by user, we
1058                  * write message at highest log level so it can always
1059                  * be seen
1060                  * even if info or warning messages are disabled */
1061                 RTE_LOG(CRIT, EAL, "RTE Version: '%s'\n", rte_version());
1062                 break;
1063
1064         /* long options */
1065         case OPT_HUGE_UNLINK_NUM:
1066                 conf->hugepage_unlink = 1;
1067                 break;
1068
1069         case OPT_NO_HUGE_NUM:
1070                 conf->no_hugetlbfs = 1;
1071                 break;
1072
1073         case OPT_NO_PCI_NUM:
1074                 conf->no_pci = 1;
1075                 break;
1076
1077         case OPT_NO_HPET_NUM:
1078                 conf->no_hpet = 1;
1079                 break;
1080
1081         case OPT_VMWARE_TSC_MAP_NUM:
1082                 conf->vmware_tsc_map = 1;
1083                 break;
1084
1085         case OPT_NO_SHCONF_NUM:
1086                 conf->no_shconf = 1;
1087                 break;
1088
1089         case OPT_PROC_TYPE_NUM:
1090                 conf->process_type = eal_parse_proc_type(optarg);
1091                 break;
1092
1093         case OPT_MASTER_LCORE_NUM:
1094                 if (eal_parse_master_lcore(optarg) < 0) {
1095                         RTE_LOG(ERR, EAL, "invalid parameter for --"
1096                                         OPT_MASTER_LCORE "\n");
1097                         return -1;
1098                 }
1099                 break;
1100
1101         case OPT_VDEV_NUM:
1102                 if (eal_option_device_add(RTE_DEVTYPE_VIRTUAL,
1103                                 optarg) < 0) {
1104                         return -1;
1105                 }
1106                 break;
1107
1108         case OPT_SYSLOG_NUM:
1109                 if (eal_parse_syslog(optarg, conf) < 0) {
1110                         RTE_LOG(ERR, EAL, "invalid parameters for --"
1111                                         OPT_SYSLOG "\n");
1112                         return -1;
1113                 }
1114                 break;
1115
1116         case OPT_LOG_LEVEL_NUM: {
1117                 if (eal_parse_log_level(optarg) < 0) {
1118                         RTE_LOG(ERR, EAL,
1119                                 "invalid parameters for --"
1120                                 OPT_LOG_LEVEL "\n");
1121                         return -1;
1122                 }
1123                 break;
1124         }
1125         case OPT_LCORES_NUM:
1126                 if (eal_parse_lcores(optarg) < 0) {
1127                         RTE_LOG(ERR, EAL, "invalid parameter for --"
1128                                 OPT_LCORES "\n");
1129                         return -1;
1130                 }
1131                 core_parsed = 1;
1132                 break;
1133
1134         /* don't know what to do, leave this to caller */
1135         default:
1136                 return 1;
1137
1138         }
1139
1140         return 0;
1141 bw_used:
1142         RTE_LOG(ERR, EAL, "Options blacklist (-b) and whitelist (-w) "
1143                 "cannot be used at the same time\n");
1144         return -1;
1145 }
1146
1147 static void
1148 eal_auto_detect_cores(struct rte_config *cfg)
1149 {
1150         unsigned int lcore_id;
1151         unsigned int removed = 0;
1152         rte_cpuset_t affinity_set;
1153         pthread_t tid = pthread_self();
1154
1155         if (pthread_getaffinity_np(tid, sizeof(rte_cpuset_t),
1156                                 &affinity_set) < 0)
1157                 CPU_ZERO(&affinity_set);
1158
1159         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1160                 if (cfg->lcore_role[lcore_id] == ROLE_RTE &&
1161                     !CPU_ISSET(lcore_id, &affinity_set)) {
1162                         cfg->lcore_role[lcore_id] = ROLE_OFF;
1163                         removed++;
1164                 }
1165         }
1166
1167         cfg->lcore_count -= removed;
1168 }
1169
1170 int
1171 eal_adjust_config(struct internal_config *internal_cfg)
1172 {
1173         int i;
1174         struct rte_config *cfg = rte_eal_get_configuration();
1175
1176         if (!core_parsed)
1177                 eal_auto_detect_cores(cfg);
1178
1179         if (internal_config.process_type == RTE_PROC_AUTO)
1180                 internal_config.process_type = eal_proc_type_detect();
1181
1182         /* default master lcore is the first one */
1183         if (!master_lcore_parsed) {
1184                 cfg->master_lcore = rte_get_next_lcore(-1, 0, 0);
1185                 lcore_config[cfg->master_lcore].core_role = ROLE_RTE;
1186         }
1187
1188         /* if no memory amounts were requested, this will result in 0 and
1189          * will be overridden later, right after eal_hugepage_info_init() */
1190         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
1191                 internal_cfg->memory += internal_cfg->socket_mem[i];
1192
1193         return 0;
1194 }
1195
1196 int
1197 eal_check_common_options(struct internal_config *internal_cfg)
1198 {
1199         struct rte_config *cfg = rte_eal_get_configuration();
1200
1201         if (cfg->lcore_role[cfg->master_lcore] != ROLE_RTE) {
1202                 RTE_LOG(ERR, EAL, "Master lcore is not enabled for DPDK\n");
1203                 return -1;
1204         }
1205
1206         if (internal_cfg->process_type == RTE_PROC_INVALID) {
1207                 RTE_LOG(ERR, EAL, "Invalid process type specified\n");
1208                 return -1;
1209         }
1210         if (index(internal_cfg->hugefile_prefix, '%') != NULL) {
1211                 RTE_LOG(ERR, EAL, "Invalid char, '%%', in --"OPT_FILE_PREFIX" "
1212                         "option\n");
1213                 return -1;
1214         }
1215         if (mem_parsed && internal_cfg->force_sockets == 1) {
1216                 RTE_LOG(ERR, EAL, "Options -m and --"OPT_SOCKET_MEM" cannot "
1217                         "be specified at the same time\n");
1218                 return -1;
1219         }
1220         if (internal_cfg->no_hugetlbfs && internal_cfg->force_sockets == 1) {
1221                 RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_MEM" cannot "
1222                         "be specified together with --"OPT_NO_HUGE"\n");
1223                 return -1;
1224         }
1225
1226         if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink) {
1227                 RTE_LOG(ERR, EAL, "Option --"OPT_HUGE_UNLINK" cannot "
1228                         "be specified together with --"OPT_NO_HUGE"\n");
1229                 return -1;
1230         }
1231
1232         return 0;
1233 }
1234
1235 void
1236 eal_common_usage(void)
1237 {
1238         printf("[options]\n\n"
1239                "EAL common options:\n"
1240                "  -c COREMASK         Hexadecimal bitmask of cores to run on\n"
1241                "  -l CORELIST         List of cores to run on\n"
1242                "                      The argument format is <c1>[-c2][,c3[-c4],...]\n"
1243                "                      where c1, c2, etc are core indexes between 0 and %d\n"
1244                "  --"OPT_LCORES" COREMAP    Map lcore set to physical cpu set\n"
1245                "                      The argument format is\n"
1246                "                            '<lcores[@cpus]>[<,lcores[@cpus]>...]'\n"
1247                "                      lcores and cpus list are grouped by '(' and ')'\n"
1248                "                      Within the group, '-' is used for range separator,\n"
1249                "                      ',' is used for single number separator.\n"
1250                "                      '( )' can be omitted for single element group,\n"
1251                "                      '@' can be omitted if cpus and lcores have the same value\n"
1252                "  -s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores\n"
1253                "  --"OPT_MASTER_LCORE" ID   Core ID that is used as master\n"
1254                "  --"OPT_MBUF_POOL_OPS_NAME" Pool ops name for mbuf to use\n"
1255                "  -n CHANNELS         Number of memory channels\n"
1256                "  -m MB               Memory to allocate (see also --"OPT_SOCKET_MEM")\n"
1257                "  -r RANKS            Force number of memory ranks (don't detect)\n"
1258                "  -b, --"OPT_PCI_BLACKLIST" Add a PCI device in black list.\n"
1259                "                      Prevent EAL from using this PCI device. The argument\n"
1260                "                      format is <domain:bus:devid.func>.\n"
1261                "  -w, --"OPT_PCI_WHITELIST" Add a PCI device in white list.\n"
1262                "                      Only use the specified PCI devices. The argument format\n"
1263                "                      is <[domain:]bus:devid.func>. This option can be present\n"
1264                "                      several times (once per device).\n"
1265                "                      [NOTE: PCI whitelist cannot be used with -b option]\n"
1266                "  --"OPT_VDEV"              Add a virtual device.\n"
1267                "                      The argument format is <driver><id>[,key=val,...]\n"
1268                "                      (ex: --vdev=net_pcap0,iface=eth2).\n"
1269                "  -d LIB.so|DIR       Add a driver or driver directory\n"
1270                "                      (can be used multiple times)\n"
1271                "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
1272                "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
1273                "  --"OPT_SYSLOG"            Set syslog facility\n"
1274                "  --"OPT_LOG_LEVEL"=<int>   Set global log level\n"
1275                "  --"OPT_LOG_LEVEL"=<type-regexp>,<int>\n"
1276                "                      Set specific log level\n"
1277                "  -v                  Display version information on startup\n"
1278                "  -h, --help          This help\n"
1279                "\nEAL options for DEBUG use only:\n"
1280                "  --"OPT_HUGE_UNLINK"       Unlink hugepage files after init\n"
1281                "  --"OPT_NO_HUGE"           Use malloc instead of hugetlbfs\n"
1282                "  --"OPT_NO_PCI"            Disable PCI\n"
1283                "  --"OPT_NO_HPET"           Disable HPET\n"
1284                "  --"OPT_NO_SHCONF"         No shared config (mmap'd files)\n"
1285                "\n", RTE_MAX_LCORE);
1286 }