eal: fix parsing option --telemetry
[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_string_fns.h>
20 #include <rte_eal.h>
21 #include <rte_log.h>
22 #include <rte_lcore.h>
23 #include <rte_tailq.h>
24 #include <rte_version.h>
25 #include <rte_devargs.h>
26 #include <rte_memcpy.h>
27
28 #include "eal_internal_cfg.h"
29 #include "eal_options.h"
30 #include "eal_filesystem.h"
31 #include "eal_private.h"
32
33 #define BITS_PER_HEX 4
34 #define LCORE_OPT_LST 1
35 #define LCORE_OPT_MSK 2
36 #define LCORE_OPT_MAP 3
37
38 const char
39 eal_short_options[] =
40         "b:" /* pci-blacklist */
41         "c:" /* coremask */
42         "s:" /* service coremask */
43         "d:" /* driver */
44         "h"  /* help */
45         "l:" /* corelist */
46         "S:" /* service corelist */
47         "m:" /* memory size */
48         "n:" /* memory channels */
49         "r:" /* memory ranks */
50         "v"  /* version */
51         "w:" /* pci-whitelist */
52         ;
53
54 const struct option
55 eal_long_options[] = {
56         {OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
57         {OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
58         {OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
59         {OPT_HELP,              0, NULL, OPT_HELP_NUM             },
60         {OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
61         {OPT_HUGE_UNLINK,       0, NULL, OPT_HUGE_UNLINK_NUM      },
62         {OPT_IOVA_MODE,         1, NULL, OPT_IOVA_MODE_NUM        },
63         {OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
64         {OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
65         {OPT_MASTER_LCORE,      1, NULL, OPT_MASTER_LCORE_NUM     },
66         {OPT_MBUF_POOL_OPS_NAME, 1, NULL, OPT_MBUF_POOL_OPS_NAME_NUM},
67         {OPT_NO_HPET,           0, NULL, OPT_NO_HPET_NUM          },
68         {OPT_NO_HUGE,           0, NULL, OPT_NO_HUGE_NUM          },
69         {OPT_NO_PCI,            0, NULL, OPT_NO_PCI_NUM           },
70         {OPT_NO_SHCONF,         0, NULL, OPT_NO_SHCONF_NUM        },
71         {OPT_IN_MEMORY,         0, NULL, OPT_IN_MEMORY_NUM        },
72         {OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
73         {OPT_PCI_WHITELIST,     1, NULL, OPT_PCI_WHITELIST_NUM    },
74         {OPT_PROC_TYPE,         1, NULL, OPT_PROC_TYPE_NUM        },
75         {OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
76         {OPT_SOCKET_LIMIT,      1, NULL, OPT_SOCKET_LIMIT_NUM     },
77         {OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
78         {OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
79         {OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
80         {OPT_VMWARE_TSC_MAP,    0, NULL, OPT_VMWARE_TSC_MAP_NUM   },
81         {OPT_LEGACY_MEM,        0, NULL, OPT_LEGACY_MEM_NUM       },
82         {OPT_SINGLE_FILE_SEGMENTS, 0, NULL, OPT_SINGLE_FILE_SEGMENTS_NUM},
83         {OPT_MATCH_ALLOCATIONS, 0, NULL, OPT_MATCH_ALLOCATIONS_NUM},
84 #ifdef RTE_LIBRTE_TELEMETRY
85         {OPT_TELEMETRY,         0, NULL, OPT_TELEMETRY_NUM        },
86 #endif
87         {0,                     0, NULL, 0                        }
88 };
89
90 TAILQ_HEAD(shared_driver_list, shared_driver);
91
92 /* Definition for shared object drivers. */
93 struct shared_driver {
94         TAILQ_ENTRY(shared_driver) next;
95
96         char    name[PATH_MAX];
97         void*   lib_handle;
98 };
99
100 /* List of external loadable drivers */
101 static struct shared_driver_list solib_list =
102 TAILQ_HEAD_INITIALIZER(solib_list);
103
104 /* Default path of external loadable drivers */
105 static const char *default_solib_dir = RTE_EAL_PMD_PATH;
106
107 /*
108  * Stringified version of solib path used by dpdk-pmdinfo.py
109  * Note: PLEASE DO NOT ALTER THIS without making a corresponding
110  * change to usertools/dpdk-pmdinfo.py
111  */
112 static const char dpdk_solib_path[] __attribute__((used)) =
113 "DPDK_PLUGIN_PATH=" RTE_EAL_PMD_PATH;
114
115 TAILQ_HEAD(device_option_list, device_option);
116
117 struct device_option {
118         TAILQ_ENTRY(device_option) next;
119
120         enum rte_devtype type;
121         char arg[];
122 };
123
124 static struct device_option_list devopt_list =
125 TAILQ_HEAD_INITIALIZER(devopt_list);
126
127 static int master_lcore_parsed;
128 static int mem_parsed;
129 static int core_parsed;
130
131 static int
132 eal_option_device_add(enum rte_devtype type, const char *optarg)
133 {
134         struct device_option *devopt;
135         size_t optlen;
136         int ret;
137
138         optlen = strlen(optarg) + 1;
139         devopt = calloc(1, sizeof(*devopt) + optlen);
140         if (devopt == NULL) {
141                 RTE_LOG(ERR, EAL, "Unable to allocate device option\n");
142                 return -ENOMEM;
143         }
144
145         devopt->type = type;
146         ret = strlcpy(devopt->arg, optarg, optlen);
147         if (ret < 0) {
148                 RTE_LOG(ERR, EAL, "Unable to copy device option\n");
149                 free(devopt);
150                 return -EINVAL;
151         }
152         TAILQ_INSERT_TAIL(&devopt_list, devopt, next);
153         return 0;
154 }
155
156 int
157 eal_option_device_parse(void)
158 {
159         struct device_option *devopt;
160         void *tmp;
161         int ret = 0;
162
163         TAILQ_FOREACH_SAFE(devopt, &devopt_list, next, tmp) {
164                 if (ret == 0) {
165                         ret = rte_devargs_add(devopt->type, devopt->arg);
166                         if (ret)
167                                 RTE_LOG(ERR, EAL, "Unable to parse device '%s'\n",
168                                         devopt->arg);
169                 }
170                 TAILQ_REMOVE(&devopt_list, devopt, next);
171                 free(devopt);
172         }
173         return ret;
174 }
175
176 const char *
177 eal_get_hugefile_prefix(void)
178 {
179         if (internal_config.hugefile_prefix != NULL)
180                 return internal_config.hugefile_prefix;
181         return HUGEFILE_PREFIX_DEFAULT;
182 }
183
184 void
185 eal_reset_internal_config(struct internal_config *internal_cfg)
186 {
187         int i;
188
189         internal_cfg->memory = 0;
190         internal_cfg->force_nrank = 0;
191         internal_cfg->force_nchannel = 0;
192         internal_cfg->hugefile_prefix = NULL;
193         internal_cfg->hugepage_dir = NULL;
194         internal_cfg->force_sockets = 0;
195         /* zero out the NUMA config */
196         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
197                 internal_cfg->socket_mem[i] = 0;
198         internal_cfg->force_socket_limits = 0;
199         /* zero out the NUMA limits config */
200         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
201                 internal_cfg->socket_limit[i] = 0;
202         /* zero out hugedir descriptors */
203         for (i = 0; i < MAX_HUGEPAGE_SIZES; i++) {
204                 memset(&internal_cfg->hugepage_info[i], 0,
205                                 sizeof(internal_cfg->hugepage_info[0]));
206                 internal_cfg->hugepage_info[i].lock_descriptor = -1;
207         }
208         internal_cfg->base_virtaddr = 0;
209
210         internal_cfg->syslog_facility = LOG_DAEMON;
211
212         /* if set to NONE, interrupt mode is determined automatically */
213         internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
214
215 #ifdef RTE_LIBEAL_USE_HPET
216         internal_cfg->no_hpet = 0;
217 #else
218         internal_cfg->no_hpet = 1;
219 #endif
220         internal_cfg->vmware_tsc_map = 0;
221         internal_cfg->create_uio_dev = 0;
222         internal_cfg->iova_mode = RTE_IOVA_DC;
223         internal_cfg->user_mbuf_pool_ops_name = NULL;
224         CPU_ZERO(&internal_cfg->ctrl_cpuset);
225         internal_cfg->init_complete = 0;
226 }
227
228 static int
229 eal_plugin_add(const char *path)
230 {
231         struct shared_driver *solib;
232
233         solib = malloc(sizeof(*solib));
234         if (solib == NULL) {
235                 RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
236                 return -1;
237         }
238         memset(solib, 0, sizeof(*solib));
239         strlcpy(solib->name, path, PATH_MAX-1);
240         solib->name[PATH_MAX-1] = 0;
241         TAILQ_INSERT_TAIL(&solib_list, solib, next);
242
243         return 0;
244 }
245
246 static int
247 eal_plugindir_init(const char *path)
248 {
249         DIR *d = NULL;
250         struct dirent *dent = NULL;
251         char sopath[PATH_MAX];
252
253         if (path == NULL || *path == '\0')
254                 return 0;
255
256         d = opendir(path);
257         if (d == NULL) {
258                 RTE_LOG(ERR, EAL, "failed to open directory %s: %s\n",
259                         path, strerror(errno));
260                 return -1;
261         }
262
263         while ((dent = readdir(d)) != NULL) {
264                 struct stat sb;
265
266                 snprintf(sopath, sizeof(sopath), "%s/%s", path, dent->d_name);
267
268                 if (!(stat(sopath, &sb) == 0 && S_ISREG(sb.st_mode)))
269                         continue;
270
271                 if (eal_plugin_add(sopath) == -1)
272                         break;
273         }
274
275         closedir(d);
276         /* XXX this ignores failures from readdir() itself */
277         return (dent == NULL) ? 0 : -1;
278 }
279
280 int
281 eal_plugins_init(void)
282 {
283         struct shared_driver *solib = NULL;
284         struct stat sb;
285
286         if (*default_solib_dir != '\0' && stat(default_solib_dir, &sb) == 0 &&
287                                 S_ISDIR(sb.st_mode))
288                 eal_plugin_add(default_solib_dir);
289
290         TAILQ_FOREACH(solib, &solib_list, next) {
291
292                 if (stat(solib->name, &sb) == 0 && S_ISDIR(sb.st_mode)) {
293                         if (eal_plugindir_init(solib->name) == -1) {
294                                 RTE_LOG(ERR, EAL,
295                                         "Cannot init plugin directory %s\n",
296                                         solib->name);
297                                 return -1;
298                         }
299                 } else {
300                         RTE_LOG(DEBUG, EAL, "open shared lib %s\n",
301                                 solib->name);
302                         solib->lib_handle = dlopen(solib->name, RTLD_NOW);
303                         if (solib->lib_handle == NULL) {
304                                 RTE_LOG(ERR, EAL, "%s\n", dlerror());
305                                 return -1;
306                         }
307                 }
308
309         }
310         return 0;
311 }
312
313 /*
314  * Parse the coremask given as argument (hexadecimal string) and fill
315  * the global configuration (core role and core count) with the parsed
316  * value.
317  */
318 static int xdigit2val(unsigned char c)
319 {
320         int val;
321
322         if (isdigit(c))
323                 val = c - '0';
324         else if (isupper(c))
325                 val = c - 'A' + 10;
326         else
327                 val = c - 'a' + 10;
328         return val;
329 }
330
331 static int
332 eal_parse_service_coremask(const char *coremask)
333 {
334         struct rte_config *cfg = rte_eal_get_configuration();
335         int i, j, idx = 0;
336         unsigned int count = 0;
337         char c;
338         int val;
339         uint32_t taken_lcore_count = 0;
340
341         if (coremask == NULL)
342                 return -1;
343         /* Remove all blank characters ahead and after .
344          * Remove 0x/0X if exists.
345          */
346         while (isblank(*coremask))
347                 coremask++;
348         if (coremask[0] == '0' && ((coremask[1] == 'x')
349                 || (coremask[1] == 'X')))
350                 coremask += 2;
351         i = strlen(coremask);
352         while ((i > 0) && isblank(coremask[i - 1]))
353                 i--;
354
355         if (i == 0)
356                 return -1;
357
358         for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
359                 c = coremask[i];
360                 if (isxdigit(c) == 0) {
361                         /* invalid characters */
362                         return -1;
363                 }
364                 val = xdigit2val(c);
365                 for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE;
366                                 j++, idx++) {
367                         if ((1 << j) & val) {
368                                 /* handle master lcore already parsed */
369                                 uint32_t lcore = idx;
370                                 if (master_lcore_parsed &&
371                                                 cfg->master_lcore == lcore) {
372                                         RTE_LOG(ERR, EAL,
373                                                 "lcore %u is master lcore, cannot use as service core\n",
374                                                 idx);
375                                         return -1;
376                                 }
377
378                                 if (!lcore_config[idx].detected) {
379                                         RTE_LOG(ERR, EAL,
380                                                 "lcore %u unavailable\n", idx);
381                                         return -1;
382                                 }
383
384                                 if (cfg->lcore_role[idx] == ROLE_RTE)
385                                         taken_lcore_count++;
386
387                                 lcore_config[idx].core_role = ROLE_SERVICE;
388                                 count++;
389                         }
390                 }
391         }
392
393         for (; i >= 0; i--)
394                 if (coremask[i] != '0')
395                         return -1;
396
397         for (; idx < RTE_MAX_LCORE; idx++)
398                 lcore_config[idx].core_index = -1;
399
400         if (count == 0)
401                 return -1;
402
403         if (core_parsed && taken_lcore_count != count) {
404                 RTE_LOG(WARNING, EAL,
405                         "Not all service cores are in the coremask. "
406                         "Please ensure -c or -l includes service cores\n");
407         }
408
409         cfg->service_lcore_count = count;
410         return 0;
411 }
412
413 static int
414 eal_service_cores_parsed(void)
415 {
416         int idx;
417         for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
418                 if (lcore_config[idx].core_role == ROLE_SERVICE)
419                         return 1;
420         }
421         return 0;
422 }
423
424 static int
425 update_lcore_config(int *cores)
426 {
427         struct rte_config *cfg = rte_eal_get_configuration();
428         unsigned int count = 0;
429         unsigned int i;
430         int ret = 0;
431
432         for (i = 0; i < RTE_MAX_LCORE; i++) {
433                 if (cores[i] != -1) {
434                         if (!lcore_config[i].detected) {
435                                 RTE_LOG(ERR, EAL, "lcore %u unavailable\n", i);
436                                 ret = -1;
437                                 continue;
438                         }
439                         cfg->lcore_role[i] = ROLE_RTE;
440                         count++;
441                 } else {
442                         cfg->lcore_role[i] = ROLE_OFF;
443                 }
444                 lcore_config[i].core_index = cores[i];
445         }
446         if (!ret)
447                 cfg->lcore_count = count;
448         return ret;
449 }
450
451 static int
452 eal_parse_coremask(const char *coremask, int *cores)
453 {
454         unsigned count = 0;
455         int i, j, idx;
456         int val;
457         char c;
458
459         for (idx = 0; idx < RTE_MAX_LCORE; idx++)
460                 cores[idx] = -1;
461         idx = 0;
462
463         /* Remove all blank characters ahead and after .
464          * Remove 0x/0X if exists.
465          */
466         while (isblank(*coremask))
467                 coremask++;
468         if (coremask[0] == '0' && ((coremask[1] == 'x')
469                 || (coremask[1] == 'X')))
470                 coremask += 2;
471         i = strlen(coremask);
472         while ((i > 0) && isblank(coremask[i - 1]))
473                 i--;
474         if (i == 0)
475                 return -1;
476
477         for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
478                 c = coremask[i];
479                 if (isxdigit(c) == 0) {
480                         /* invalid characters */
481                         return -1;
482                 }
483                 val = xdigit2val(c);
484                 for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE; j++, idx++)
485                 {
486                         if ((1 << j) & val) {
487                                 cores[idx] = count;
488                                 count++;
489                         }
490                 }
491         }
492         for (; i >= 0; i--)
493                 if (coremask[i] != '0')
494                         return -1;
495         if (count == 0)
496                 return -1;
497         return 0;
498 }
499
500 static int
501 eal_parse_service_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         uint32_t taken_lcore_count = 0;
509
510         if (corelist == NULL)
511                 return -1;
512
513         /* Remove all blank characters ahead and after */
514         while (isblank(*corelist))
515                 corelist++;
516         i = strlen(corelist);
517         while ((i > 0) && isblank(corelist[i - 1]))
518                 i--;
519
520         /* Get list of cores */
521         min = RTE_MAX_LCORE;
522         do {
523                 while (isblank(*corelist))
524                         corelist++;
525                 if (*corelist == '\0')
526                         return -1;
527                 errno = 0;
528                 idx = strtoul(corelist, &end, 10);
529                 if (errno || end == NULL)
530                         return -1;
531                 while (isblank(*end))
532                         end++;
533                 if (*end == '-') {
534                         min = idx;
535                 } else if ((*end == ',') || (*end == '\0')) {
536                         max = idx;
537                         if (min == RTE_MAX_LCORE)
538                                 min = idx;
539                         for (idx = min; idx <= max; idx++) {
540                                 if (cfg->lcore_role[idx] != ROLE_SERVICE) {
541                                         /* handle master lcore already parsed */
542                                         uint32_t lcore = idx;
543                                         if (cfg->master_lcore == lcore &&
544                                                         master_lcore_parsed) {
545                                                 RTE_LOG(ERR, EAL,
546                                                         "Error: lcore %u is master lcore, cannot use as service core\n",
547                                                         idx);
548                                                 return -1;
549                                         }
550                                         if (cfg->lcore_role[idx] == ROLE_RTE)
551                                                 taken_lcore_count++;
552
553                                         lcore_config[idx].core_role =
554                                                         ROLE_SERVICE;
555                                         count++;
556                                 }
557                         }
558                         min = RTE_MAX_LCORE;
559                 } else
560                         return -1;
561                 corelist = end + 1;
562         } while (*end != '\0');
563
564         if (count == 0)
565                 return -1;
566
567         if (core_parsed && taken_lcore_count != count) {
568                 RTE_LOG(WARNING, EAL,
569                         "Not all service cores were in the coremask. "
570                         "Please ensure -c or -l includes service cores\n");
571         }
572
573         return 0;
574 }
575
576 static int
577 eal_parse_corelist(const char *corelist, int *cores)
578 {
579         unsigned count = 0;
580         char *end = NULL;
581         int min, max;
582         int idx;
583
584         for (idx = 0; idx < RTE_MAX_LCORE; idx++)
585                 cores[idx] = -1;
586
587         /* Remove all blank characters ahead */
588         while (isblank(*corelist))
589                 corelist++;
590
591         /* Get list of cores */
592         min = RTE_MAX_LCORE;
593         do {
594                 while (isblank(*corelist))
595                         corelist++;
596                 if (*corelist == '\0')
597                         return -1;
598                 errno = 0;
599                 idx = strtol(corelist, &end, 10);
600                 if (errno || end == NULL)
601                         return -1;
602                 if (idx < 0 || idx >= RTE_MAX_LCORE)
603                         return -1;
604                 while (isblank(*end))
605                         end++;
606                 if (*end == '-') {
607                         min = idx;
608                 } else if ((*end == ',') || (*end == '\0')) {
609                         max = idx;
610                         if (min == RTE_MAX_LCORE)
611                                 min = idx;
612                         for (idx = min; idx <= max; idx++) {
613                                 if (cores[idx] == -1) {
614                                         cores[idx] = count;
615                                         count++;
616                                 }
617                         }
618                         min = RTE_MAX_LCORE;
619                 } else
620                         return -1;
621                 corelist = end + 1;
622         } while (*end != '\0');
623
624         if (count == 0)
625                 return -1;
626         return 0;
627 }
628
629 /* Changes the lcore id of the master thread */
630 static int
631 eal_parse_master_lcore(const char *arg)
632 {
633         char *parsing_end;
634         struct rte_config *cfg = rte_eal_get_configuration();
635
636         errno = 0;
637         cfg->master_lcore = (uint32_t) strtol(arg, &parsing_end, 0);
638         if (errno || parsing_end[0] != 0)
639                 return -1;
640         if (cfg->master_lcore >= RTE_MAX_LCORE)
641                 return -1;
642         master_lcore_parsed = 1;
643
644         /* ensure master core is not used as service core */
645         if (lcore_config[cfg->master_lcore].core_role == ROLE_SERVICE) {
646                 RTE_LOG(ERR, EAL,
647                         "Error: Master lcore is used as a service core\n");
648                 return -1;
649         }
650
651         return 0;
652 }
653
654 /*
655  * Parse elem, the elem could be single number/range or '(' ')' group
656  * 1) A single number elem, it's just a simple digit. e.g. 9
657  * 2) A single range elem, two digits with a '-' between. e.g. 2-6
658  * 3) A group elem, combines multiple 1) or 2) with '( )'. e.g (0,2-4,6)
659  *    Within group elem, '-' used for a range separator;
660  *                       ',' used for a single number.
661  */
662 static int
663 eal_parse_set(const char *input, uint16_t set[], unsigned num)
664 {
665         unsigned idx;
666         const char *str = input;
667         char *end = NULL;
668         unsigned min, max;
669
670         memset(set, 0, num * sizeof(uint16_t));
671
672         while (isblank(*str))
673                 str++;
674
675         /* only digit or left bracket is qualify for start point */
676         if ((!isdigit(*str) && *str != '(') || *str == '\0')
677                 return -1;
678
679         /* process single number or single range of number */
680         if (*str != '(') {
681                 errno = 0;
682                 idx = strtoul(str, &end, 10);
683                 if (errno || end == NULL || idx >= num)
684                         return -1;
685                 else {
686                         while (isblank(*end))
687                                 end++;
688
689                         min = idx;
690                         max = idx;
691                         if (*end == '-') {
692                                 /* process single <number>-<number> */
693                                 end++;
694                                 while (isblank(*end))
695                                         end++;
696                                 if (!isdigit(*end))
697                                         return -1;
698
699                                 errno = 0;
700                                 idx = strtoul(end, &end, 10);
701                                 if (errno || end == NULL || idx >= num)
702                                         return -1;
703                                 max = idx;
704                                 while (isblank(*end))
705                                         end++;
706                                 if (*end != ',' && *end != '\0')
707                                         return -1;
708                         }
709
710                         if (*end != ',' && *end != '\0' &&
711                             *end != '@')
712                                 return -1;
713
714                         for (idx = RTE_MIN(min, max);
715                              idx <= RTE_MAX(min, max); idx++)
716                                 set[idx] = 1;
717
718                         return end - input;
719                 }
720         }
721
722         /* process set within bracket */
723         str++;
724         while (isblank(*str))
725                 str++;
726         if (*str == '\0')
727                 return -1;
728
729         min = RTE_MAX_LCORE;
730         do {
731
732                 /* go ahead to the first digit */
733                 while (isblank(*str))
734                         str++;
735                 if (!isdigit(*str))
736                         return -1;
737
738                 /* get the digit value */
739                 errno = 0;
740                 idx = strtoul(str, &end, 10);
741                 if (errno || end == NULL || idx >= num)
742                         return -1;
743
744                 /* go ahead to separator '-',',' and ')' */
745                 while (isblank(*end))
746                         end++;
747                 if (*end == '-') {
748                         if (min == RTE_MAX_LCORE)
749                                 min = idx;
750                         else /* avoid continuous '-' */
751                                 return -1;
752                 } else if ((*end == ',') || (*end == ')')) {
753                         max = idx;
754                         if (min == RTE_MAX_LCORE)
755                                 min = idx;
756                         for (idx = RTE_MIN(min, max);
757                              idx <= RTE_MAX(min, max); idx++)
758                                 set[idx] = 1;
759
760                         min = RTE_MAX_LCORE;
761                 } else
762                         return -1;
763
764                 str = end + 1;
765         } while (*end != '\0' && *end != ')');
766
767         /*
768          * to avoid failure that tail blank makes end character check fail
769          * in eal_parse_lcores( )
770          */
771         while (isblank(*str))
772                 str++;
773
774         return str - input;
775 }
776
777 /* convert from set array to cpuset bitmap */
778 static int
779 convert_to_cpuset(rte_cpuset_t *cpusetp,
780               uint16_t *set, unsigned num)
781 {
782         unsigned idx;
783
784         CPU_ZERO(cpusetp);
785
786         for (idx = 0; idx < num; idx++) {
787                 if (!set[idx])
788                         continue;
789
790                 if (!lcore_config[idx].detected) {
791                         RTE_LOG(ERR, EAL, "core %u "
792                                 "unavailable\n", idx);
793                         return -1;
794                 }
795
796                 CPU_SET(idx, cpusetp);
797         }
798
799         return 0;
800 }
801
802 /*
803  * The format pattern: --lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
804  * lcores, cpus could be a single digit/range or a group.
805  * '(' and ')' are necessary if it's a group.
806  * If not supply '@cpus', the value of cpus uses the same as lcores.
807  * e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means start 9 EAL thread as below
808  *   lcore 0 runs on cpuset 0x41 (cpu 0,6)
809  *   lcore 1 runs on cpuset 0x2 (cpu 1)
810  *   lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
811  *   lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
812  *   lcore 6 runs on cpuset 0x41 (cpu 0,6)
813  *   lcore 7 runs on cpuset 0x80 (cpu 7)
814  *   lcore 8 runs on cpuset 0x100 (cpu 8)
815  */
816 static int
817 eal_parse_lcores(const char *lcores)
818 {
819         struct rte_config *cfg = rte_eal_get_configuration();
820         static uint16_t set[RTE_MAX_LCORE];
821         unsigned idx = 0;
822         unsigned count = 0;
823         const char *lcore_start = NULL;
824         const char *end = NULL;
825         int offset;
826         rte_cpuset_t cpuset;
827         int lflags;
828         int ret = -1;
829
830         if (lcores == NULL)
831                 return -1;
832
833         /* Remove all blank characters ahead and after */
834         while (isblank(*lcores))
835                 lcores++;
836
837         CPU_ZERO(&cpuset);
838
839         /* Reset lcore config */
840         for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
841                 cfg->lcore_role[idx] = ROLE_OFF;
842                 lcore_config[idx].core_index = -1;
843                 CPU_ZERO(&lcore_config[idx].cpuset);
844         }
845
846         /* Get list of cores */
847         do {
848                 while (isblank(*lcores))
849                         lcores++;
850                 if (*lcores == '\0')
851                         goto err;
852
853                 lflags = 0;
854
855                 /* record lcore_set start point */
856                 lcore_start = lcores;
857
858                 /* go across a complete bracket */
859                 if (*lcore_start == '(') {
860                         lcores += strcspn(lcores, ")");
861                         if (*lcores++ == '\0')
862                                 goto err;
863                 }
864
865                 /* scan the separator '@', ','(next) or '\0'(finish) */
866                 lcores += strcspn(lcores, "@,");
867
868                 if (*lcores == '@') {
869                         /* explicit assign cpu_set */
870                         offset = eal_parse_set(lcores + 1, set, RTE_DIM(set));
871                         if (offset < 0)
872                                 goto err;
873
874                         /* prepare cpu_set and update the end cursor */
875                         if (0 > convert_to_cpuset(&cpuset,
876                                                   set, RTE_DIM(set)))
877                                 goto err;
878                         end = lcores + 1 + offset;
879                 } else { /* ',' or '\0' */
880                         /* haven't given cpu_set, current loop done */
881                         end = lcores;
882
883                         /* go back to check <number>-<number> */
884                         offset = strcspn(lcore_start, "(-");
885                         if (offset < (end - lcore_start) &&
886                             *(lcore_start + offset) != '(')
887                                 lflags = 1;
888                 }
889
890                 if (*end != ',' && *end != '\0')
891                         goto err;
892
893                 /* parse lcore_set from start point */
894                 if (0 > eal_parse_set(lcore_start, set, RTE_DIM(set)))
895                         goto err;
896
897                 /* without '@', by default using lcore_set as cpu_set */
898                 if (*lcores != '@' &&
899                     0 > convert_to_cpuset(&cpuset, set, RTE_DIM(set)))
900                         goto err;
901
902                 /* start to update lcore_set */
903                 for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
904                         if (!set[idx])
905                                 continue;
906
907                         if (cfg->lcore_role[idx] != ROLE_RTE) {
908                                 lcore_config[idx].core_index = count;
909                                 cfg->lcore_role[idx] = ROLE_RTE;
910                                 count++;
911                         }
912
913                         if (lflags) {
914                                 CPU_ZERO(&cpuset);
915                                 CPU_SET(idx, &cpuset);
916                         }
917                         rte_memcpy(&lcore_config[idx].cpuset, &cpuset,
918                                    sizeof(rte_cpuset_t));
919                 }
920
921                 lcores = end + 1;
922         } while (*end != '\0');
923
924         if (count == 0)
925                 goto err;
926
927         cfg->lcore_count = count;
928         ret = 0;
929
930 err:
931
932         return ret;
933 }
934
935 static int
936 eal_parse_syslog(const char *facility, struct internal_config *conf)
937 {
938         int i;
939         static const struct {
940                 const char *name;
941                 int value;
942         } map[] = {
943                 { "auth", LOG_AUTH },
944                 { "cron", LOG_CRON },
945                 { "daemon", LOG_DAEMON },
946                 { "ftp", LOG_FTP },
947                 { "kern", LOG_KERN },
948                 { "lpr", LOG_LPR },
949                 { "mail", LOG_MAIL },
950                 { "news", LOG_NEWS },
951                 { "syslog", LOG_SYSLOG },
952                 { "user", LOG_USER },
953                 { "uucp", LOG_UUCP },
954                 { "local0", LOG_LOCAL0 },
955                 { "local1", LOG_LOCAL1 },
956                 { "local2", LOG_LOCAL2 },
957                 { "local3", LOG_LOCAL3 },
958                 { "local4", LOG_LOCAL4 },
959                 { "local5", LOG_LOCAL5 },
960                 { "local6", LOG_LOCAL6 },
961                 { "local7", LOG_LOCAL7 },
962                 { NULL, 0 }
963         };
964
965         for (i = 0; map[i].name; i++) {
966                 if (!strcmp(facility, map[i].name)) {
967                         conf->syslog_facility = map[i].value;
968                         return 0;
969                 }
970         }
971         return -1;
972 }
973
974 static int
975 eal_parse_log_priority(const char *level)
976 {
977         static const char * const levels[] = {
978                 [RTE_LOG_EMERG]   = "emergency",
979                 [RTE_LOG_ALERT]   = "alert",
980                 [RTE_LOG_CRIT]    = "critical",
981                 [RTE_LOG_ERR]     = "error",
982                 [RTE_LOG_WARNING] = "warning",
983                 [RTE_LOG_NOTICE]  = "notice",
984                 [RTE_LOG_INFO]    = "info",
985                 [RTE_LOG_DEBUG]   = "debug",
986         };
987         size_t len = strlen(level);
988         unsigned long tmp;
989         char *end;
990         unsigned int i;
991
992         if (len == 0)
993                 return -1;
994
995         /* look for named values, skip 0 which is not a valid level */
996         for (i = 1; i < RTE_DIM(levels); i++) {
997                 if (strncmp(levels[i], level, len) == 0)
998                         return i;
999         }
1000
1001         /* not a string, maybe it is numeric */
1002         errno = 0;
1003         tmp = strtoul(level, &end, 0);
1004
1005         /* check for errors */
1006         if (errno != 0 || end == NULL || *end != '\0' ||
1007             tmp >= UINT32_MAX)
1008                 return -1;
1009
1010         return tmp;
1011 }
1012
1013 static int
1014 eal_parse_log_level(const char *arg)
1015 {
1016         const char *pattern = NULL;
1017         const char *regex = NULL;
1018         char *str, *level;
1019         int priority;
1020
1021         str = strdup(arg);
1022         if (str == NULL)
1023                 return -1;
1024
1025         if ((level = strchr(str, ','))) {
1026                 regex = str;
1027                 *level++ = '\0';
1028         } else if ((level = strchr(str, ':'))) {
1029                 pattern = str;
1030                 *level++ = '\0';
1031         } else {
1032                 level = str;
1033         }
1034
1035         priority = eal_parse_log_priority(level);
1036         if (priority < 0) {
1037                 fprintf(stderr, "invalid log priority: %s\n", level);
1038                 goto fail;
1039         }
1040
1041         if (regex) {
1042                 if (rte_log_set_level_regexp(regex, priority) < 0) {
1043                         fprintf(stderr, "cannot set log level %s,%d\n",
1044                                 pattern, priority);
1045                         goto fail;
1046                 }
1047                 if (rte_log_save_regexp(regex, priority) < 0)
1048                         goto fail;
1049         } else if (pattern) {
1050                 if (rte_log_set_level_pattern(pattern, priority) < 0) {
1051                         fprintf(stderr, "cannot set log level %s:%d\n",
1052                                 pattern, priority);
1053                         goto fail;
1054                 }
1055                 if (rte_log_save_pattern(pattern, priority) < 0)
1056                         goto fail;
1057         } else {
1058                 rte_log_set_global_level(priority);
1059         }
1060
1061         free(str);
1062         return 0;
1063
1064 fail:
1065         free(str);
1066         return -1;
1067 }
1068
1069 static enum rte_proc_type_t
1070 eal_parse_proc_type(const char *arg)
1071 {
1072         if (strncasecmp(arg, "primary", sizeof("primary")) == 0)
1073                 return RTE_PROC_PRIMARY;
1074         if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0)
1075                 return RTE_PROC_SECONDARY;
1076         if (strncasecmp(arg, "auto", sizeof("auto")) == 0)
1077                 return RTE_PROC_AUTO;
1078
1079         return RTE_PROC_INVALID;
1080 }
1081
1082 static int
1083 eal_parse_iova_mode(const char *name)
1084 {
1085         int mode;
1086
1087         if (name == NULL)
1088                 return -1;
1089
1090         if (!strcmp("pa", name))
1091                 mode = RTE_IOVA_PA;
1092         else if (!strcmp("va", name))
1093                 mode = RTE_IOVA_VA;
1094         else
1095                 return -1;
1096
1097         internal_config.iova_mode = mode;
1098         return 0;
1099 }
1100
1101 /* caller is responsible for freeing the returned string */
1102 static char *
1103 available_cores(void)
1104 {
1105         char *str = NULL;
1106         int previous;
1107         int sequence;
1108         char *tmp;
1109         int idx;
1110
1111         /* find the first available cpu */
1112         for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
1113                 if (!lcore_config[idx].detected)
1114                         continue;
1115                 break;
1116         }
1117         if (idx >= RTE_MAX_LCORE)
1118                 return NULL;
1119
1120         /* first sequence */
1121         if (asprintf(&str, "%d", idx) < 0)
1122                 return NULL;
1123         previous = idx;
1124         sequence = 0;
1125
1126         for (idx++ ; idx < RTE_MAX_LCORE; idx++) {
1127                 if (!lcore_config[idx].detected)
1128                         continue;
1129
1130                 if (idx == previous + 1) {
1131                         previous = idx;
1132                         sequence = 1;
1133                         continue;
1134                 }
1135
1136                 /* finish current sequence */
1137                 if (sequence) {
1138                         if (asprintf(&tmp, "%s-%d", str, previous) < 0) {
1139                                 free(str);
1140                                 return NULL;
1141                         }
1142                         free(str);
1143                         str = tmp;
1144                 }
1145
1146                 /* new sequence */
1147                 if (asprintf(&tmp, "%s,%d", str, idx) < 0) {
1148                         free(str);
1149                         return NULL;
1150                 }
1151                 free(str);
1152                 str = tmp;
1153                 previous = idx;
1154                 sequence = 0;
1155         }
1156
1157         /* finish last sequence */
1158         if (sequence) {
1159                 if (asprintf(&tmp, "%s-%d", str, previous) < 0) {
1160                         free(str);
1161                         return NULL;
1162                 }
1163                 free(str);
1164                 str = tmp;
1165         }
1166
1167         return str;
1168 }
1169
1170 int
1171 eal_parse_common_option(int opt, const char *optarg,
1172                         struct internal_config *conf)
1173 {
1174         static int b_used;
1175         static int w_used;
1176
1177         switch (opt) {
1178         /* blacklist */
1179         case 'b':
1180                 if (w_used)
1181                         goto bw_used;
1182                 if (eal_option_device_add(RTE_DEVTYPE_BLACKLISTED_PCI,
1183                                 optarg) < 0) {
1184                         return -1;
1185                 }
1186                 b_used = 1;
1187                 break;
1188         /* whitelist */
1189         case 'w':
1190                 if (b_used)
1191                         goto bw_used;
1192                 if (eal_option_device_add(RTE_DEVTYPE_WHITELISTED_PCI,
1193                                 optarg) < 0) {
1194                         return -1;
1195                 }
1196                 w_used = 1;
1197                 break;
1198         /* coremask */
1199         case 'c': {
1200                 int lcore_indexes[RTE_MAX_LCORE];
1201
1202                 if (eal_service_cores_parsed())
1203                         RTE_LOG(WARNING, EAL,
1204                                 "Service cores parsed before dataplane cores. Please ensure -c is before -s or -S\n");
1205                 if (eal_parse_coremask(optarg, lcore_indexes) < 0) {
1206                         RTE_LOG(ERR, EAL, "invalid coremask syntax\n");
1207                         return -1;
1208                 }
1209                 if (update_lcore_config(lcore_indexes) < 0) {
1210                         char *available = available_cores();
1211
1212                         RTE_LOG(ERR, EAL,
1213                                 "invalid coremask, please check specified cores are part of %s\n",
1214                                 available);
1215                         free(available);
1216                         return -1;
1217                 }
1218
1219                 if (core_parsed) {
1220                         RTE_LOG(ERR, EAL, "Option -c is ignored, because (%s) is set!\n",
1221                                 (core_parsed == LCORE_OPT_LST) ? "-l" :
1222                                 (core_parsed == LCORE_OPT_MAP) ? "--lcore" :
1223                                 "-c");
1224                         return -1;
1225                 }
1226
1227                 core_parsed = LCORE_OPT_MSK;
1228                 break;
1229         }
1230         /* corelist */
1231         case 'l': {
1232                 int lcore_indexes[RTE_MAX_LCORE];
1233
1234                 if (eal_service_cores_parsed())
1235                         RTE_LOG(WARNING, EAL,
1236                                 "Service cores parsed before dataplane cores. Please ensure -l is before -s or -S\n");
1237
1238                 if (eal_parse_corelist(optarg, lcore_indexes) < 0) {
1239                         RTE_LOG(ERR, EAL, "invalid core list syntax\n");
1240                         return -1;
1241                 }
1242                 if (update_lcore_config(lcore_indexes) < 0) {
1243                         char *available = available_cores();
1244
1245                         RTE_LOG(ERR, EAL,
1246                                 "invalid core list, please check specified cores are part of %s\n",
1247                                 available);
1248                         free(available);
1249                         return -1;
1250                 }
1251
1252                 if (core_parsed) {
1253                         RTE_LOG(ERR, EAL, "Option -l is ignored, because (%s) is set!\n",
1254                                 (core_parsed == LCORE_OPT_MSK) ? "-c" :
1255                                 (core_parsed == LCORE_OPT_MAP) ? "--lcore" :
1256                                 "-l");
1257                         return -1;
1258                 }
1259
1260                 core_parsed = LCORE_OPT_LST;
1261                 break;
1262         }
1263         /* service coremask */
1264         case 's':
1265                 if (eal_parse_service_coremask(optarg) < 0) {
1266                         RTE_LOG(ERR, EAL, "invalid service coremask\n");
1267                         return -1;
1268                 }
1269                 break;
1270         /* service corelist */
1271         case 'S':
1272                 if (eal_parse_service_corelist(optarg) < 0) {
1273                         RTE_LOG(ERR, EAL, "invalid service core list\n");
1274                         return -1;
1275                 }
1276                 break;
1277         /* size of memory */
1278         case 'm':
1279                 conf->memory = atoi(optarg);
1280                 conf->memory *= 1024ULL;
1281                 conf->memory *= 1024ULL;
1282                 mem_parsed = 1;
1283                 break;
1284         /* force number of channels */
1285         case 'n':
1286                 conf->force_nchannel = atoi(optarg);
1287                 if (conf->force_nchannel == 0) {
1288                         RTE_LOG(ERR, EAL, "invalid channel number\n");
1289                         return -1;
1290                 }
1291                 break;
1292         /* force number of ranks */
1293         case 'r':
1294                 conf->force_nrank = atoi(optarg);
1295                 if (conf->force_nrank == 0 ||
1296                     conf->force_nrank > 16) {
1297                         RTE_LOG(ERR, EAL, "invalid rank number\n");
1298                         return -1;
1299                 }
1300                 break;
1301         /* force loading of external driver */
1302         case 'd':
1303                 if (eal_plugin_add(optarg) == -1)
1304                         return -1;
1305                 break;
1306         case 'v':
1307                 /* since message is explicitly requested by user, we
1308                  * write message at highest log level so it can always
1309                  * be seen
1310                  * even if info or warning messages are disabled */
1311                 RTE_LOG(CRIT, EAL, "RTE Version: '%s'\n", rte_version());
1312                 break;
1313
1314         /* long options */
1315         case OPT_HUGE_UNLINK_NUM:
1316                 conf->hugepage_unlink = 1;
1317                 break;
1318
1319         case OPT_NO_HUGE_NUM:
1320                 conf->no_hugetlbfs = 1;
1321                 /* no-huge is legacy mem */
1322                 conf->legacy_mem = 1;
1323                 break;
1324
1325         case OPT_NO_PCI_NUM:
1326                 conf->no_pci = 1;
1327                 break;
1328
1329         case OPT_NO_HPET_NUM:
1330                 conf->no_hpet = 1;
1331                 break;
1332
1333         case OPT_VMWARE_TSC_MAP_NUM:
1334                 conf->vmware_tsc_map = 1;
1335                 break;
1336
1337         case OPT_NO_SHCONF_NUM:
1338                 conf->no_shconf = 1;
1339                 break;
1340
1341         case OPT_IN_MEMORY_NUM:
1342                 conf->in_memory = 1;
1343                 /* in-memory is a superset of noshconf and huge-unlink */
1344                 conf->no_shconf = 1;
1345                 conf->hugepage_unlink = 1;
1346                 break;
1347
1348         case OPT_PROC_TYPE_NUM:
1349                 conf->process_type = eal_parse_proc_type(optarg);
1350                 break;
1351
1352         case OPT_MASTER_LCORE_NUM:
1353                 if (eal_parse_master_lcore(optarg) < 0) {
1354                         RTE_LOG(ERR, EAL, "invalid parameter for --"
1355                                         OPT_MASTER_LCORE "\n");
1356                         return -1;
1357                 }
1358                 break;
1359
1360         case OPT_VDEV_NUM:
1361                 if (eal_option_device_add(RTE_DEVTYPE_VIRTUAL,
1362                                 optarg) < 0) {
1363                         return -1;
1364                 }
1365                 break;
1366
1367         case OPT_SYSLOG_NUM:
1368                 if (eal_parse_syslog(optarg, conf) < 0) {
1369                         RTE_LOG(ERR, EAL, "invalid parameters for --"
1370                                         OPT_SYSLOG "\n");
1371                         return -1;
1372                 }
1373                 break;
1374
1375         case OPT_LOG_LEVEL_NUM: {
1376                 if (eal_parse_log_level(optarg) < 0) {
1377                         RTE_LOG(ERR, EAL,
1378                                 "invalid parameters for --"
1379                                 OPT_LOG_LEVEL "\n");
1380                         return -1;
1381                 }
1382                 break;
1383         }
1384         case OPT_LCORES_NUM:
1385                 if (eal_parse_lcores(optarg) < 0) {
1386                         RTE_LOG(ERR, EAL, "invalid parameter for --"
1387                                 OPT_LCORES "\n");
1388                         return -1;
1389                 }
1390
1391                 if (core_parsed) {
1392                         RTE_LOG(ERR, EAL, "Option --lcore is ignored, because (%s) is set!\n",
1393                                 (core_parsed == LCORE_OPT_LST) ? "-l" :
1394                                 (core_parsed == LCORE_OPT_MSK) ? "-c" :
1395                                 "--lcore");
1396                         return -1;
1397                 }
1398
1399                 core_parsed = LCORE_OPT_MAP;
1400                 break;
1401         case OPT_LEGACY_MEM_NUM:
1402                 conf->legacy_mem = 1;
1403                 break;
1404         case OPT_SINGLE_FILE_SEGMENTS_NUM:
1405                 conf->single_file_segments = 1;
1406                 break;
1407         case OPT_IOVA_MODE_NUM:
1408                 if (eal_parse_iova_mode(optarg) < 0) {
1409                         RTE_LOG(ERR, EAL, "invalid parameters for --"
1410                                 OPT_IOVA_MODE "\n");
1411                         return -1;
1412                 }
1413                 break;
1414
1415         /* don't know what to do, leave this to caller */
1416         default:
1417                 return 1;
1418
1419         }
1420
1421         return 0;
1422 bw_used:
1423         RTE_LOG(ERR, EAL, "Options blacklist (-b) and whitelist (-w) "
1424                 "cannot be used at the same time\n");
1425         return -1;
1426 }
1427
1428 static void
1429 eal_auto_detect_cores(struct rte_config *cfg)
1430 {
1431         unsigned int lcore_id;
1432         unsigned int removed = 0;
1433         rte_cpuset_t affinity_set;
1434
1435         if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
1436                                 &affinity_set))
1437                 CPU_ZERO(&affinity_set);
1438
1439         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1440                 if (cfg->lcore_role[lcore_id] == ROLE_RTE &&
1441                     !CPU_ISSET(lcore_id, &affinity_set)) {
1442                         cfg->lcore_role[lcore_id] = ROLE_OFF;
1443                         removed++;
1444                 }
1445         }
1446
1447         cfg->lcore_count -= removed;
1448 }
1449
1450 static void
1451 compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
1452 {
1453         rte_cpuset_t *cpuset = &internal_cfg->ctrl_cpuset;
1454         rte_cpuset_t default_set;
1455         unsigned int lcore_id;
1456
1457         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1458                 if (eal_cpu_detected(lcore_id) &&
1459                                 rte_lcore_has_role(lcore_id, ROLE_OFF)) {
1460                         CPU_SET(lcore_id, cpuset);
1461                 }
1462         }
1463
1464         if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
1465                                 &default_set))
1466                 CPU_ZERO(&default_set);
1467
1468         RTE_CPU_AND(cpuset, cpuset, &default_set);
1469
1470         /* if no detected CPU is off, use master core */
1471         if (!CPU_COUNT(cpuset))
1472                 CPU_SET(rte_get_master_lcore(), cpuset);
1473 }
1474
1475 int
1476 eal_cleanup_config(struct internal_config *internal_cfg)
1477 {
1478         if (internal_cfg->hugefile_prefix != NULL)
1479                 free(internal_cfg->hugefile_prefix);
1480         if (internal_cfg->hugepage_dir != NULL)
1481                 free(internal_cfg->hugepage_dir);
1482         if (internal_cfg->user_mbuf_pool_ops_name != NULL)
1483                 free(internal_cfg->user_mbuf_pool_ops_name);
1484
1485         return 0;
1486 }
1487
1488 int
1489 eal_adjust_config(struct internal_config *internal_cfg)
1490 {
1491         int i;
1492         struct rte_config *cfg = rte_eal_get_configuration();
1493
1494         if (!core_parsed)
1495                 eal_auto_detect_cores(cfg);
1496
1497         if (internal_config.process_type == RTE_PROC_AUTO)
1498                 internal_config.process_type = eal_proc_type_detect();
1499
1500         /* default master lcore is the first one */
1501         if (!master_lcore_parsed) {
1502                 cfg->master_lcore = rte_get_next_lcore(-1, 0, 0);
1503                 if (cfg->master_lcore >= RTE_MAX_LCORE)
1504                         return -1;
1505                 lcore_config[cfg->master_lcore].core_role = ROLE_RTE;
1506         }
1507
1508         compute_ctrl_threads_cpuset(internal_cfg);
1509
1510         /* if no memory amounts were requested, this will result in 0 and
1511          * will be overridden later, right after eal_hugepage_info_init() */
1512         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
1513                 internal_cfg->memory += internal_cfg->socket_mem[i];
1514
1515         return 0;
1516 }
1517
1518 int
1519 eal_check_common_options(struct internal_config *internal_cfg)
1520 {
1521         struct rte_config *cfg = rte_eal_get_configuration();
1522
1523         if (cfg->lcore_role[cfg->master_lcore] != ROLE_RTE) {
1524                 RTE_LOG(ERR, EAL, "Master lcore is not enabled for DPDK\n");
1525                 return -1;
1526         }
1527
1528         if (internal_cfg->process_type == RTE_PROC_INVALID) {
1529                 RTE_LOG(ERR, EAL, "Invalid process type specified\n");
1530                 return -1;
1531         }
1532         if (internal_cfg->hugefile_prefix != NULL &&
1533                         strlen(internal_cfg->hugefile_prefix) < 1) {
1534                 RTE_LOG(ERR, EAL, "Invalid length of --" OPT_FILE_PREFIX " option\n");
1535                 return -1;
1536         }
1537         if (internal_cfg->hugepage_dir != NULL &&
1538                         strlen(internal_cfg->hugepage_dir) < 1) {
1539                 RTE_LOG(ERR, EAL, "Invalid length of --" OPT_HUGE_DIR" option\n");
1540                 return -1;
1541         }
1542         if (internal_cfg->user_mbuf_pool_ops_name != NULL &&
1543                         strlen(internal_cfg->user_mbuf_pool_ops_name) < 1) {
1544                 RTE_LOG(ERR, EAL, "Invalid length of --" OPT_MBUF_POOL_OPS_NAME" option\n");
1545                 return -1;
1546         }
1547         if (index(eal_get_hugefile_prefix(), '%') != NULL) {
1548                 RTE_LOG(ERR, EAL, "Invalid char, '%%', in --"OPT_FILE_PREFIX" "
1549                         "option\n");
1550                 return -1;
1551         }
1552         if (mem_parsed && internal_cfg->force_sockets == 1) {
1553                 RTE_LOG(ERR, EAL, "Options -m and --"OPT_SOCKET_MEM" cannot "
1554                         "be specified at the same time\n");
1555                 return -1;
1556         }
1557         if (internal_cfg->no_hugetlbfs && internal_cfg->force_sockets == 1) {
1558                 RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_MEM" cannot "
1559                         "be specified together with --"OPT_NO_HUGE"\n");
1560                 return -1;
1561         }
1562         if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink &&
1563                         !internal_cfg->in_memory) {
1564                 RTE_LOG(ERR, EAL, "Option --"OPT_HUGE_UNLINK" cannot "
1565                         "be specified together with --"OPT_NO_HUGE"\n");
1566                 return -1;
1567         }
1568         if (internal_config.force_socket_limits && internal_config.legacy_mem) {
1569                 RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_LIMIT
1570                         " is only supported in non-legacy memory mode\n");
1571         }
1572         if (internal_cfg->single_file_segments &&
1573                         internal_cfg->hugepage_unlink &&
1574                         !internal_cfg->in_memory) {
1575                 RTE_LOG(ERR, EAL, "Option --"OPT_SINGLE_FILE_SEGMENTS" is "
1576                         "not compatible with --"OPT_HUGE_UNLINK"\n");
1577                 return -1;
1578         }
1579         if (internal_cfg->legacy_mem &&
1580                         internal_cfg->in_memory) {
1581                 RTE_LOG(ERR, EAL, "Option --"OPT_LEGACY_MEM" is not compatible "
1582                                 "with --"OPT_IN_MEMORY"\n");
1583                 return -1;
1584         }
1585         if (internal_cfg->legacy_mem && internal_cfg->match_allocations) {
1586                 RTE_LOG(ERR, EAL, "Option --"OPT_LEGACY_MEM" is not compatible "
1587                                 "with --"OPT_MATCH_ALLOCATIONS"\n");
1588                 return -1;
1589         }
1590         if (internal_cfg->no_hugetlbfs && internal_cfg->match_allocations) {
1591                 RTE_LOG(ERR, EAL, "Option --"OPT_NO_HUGE" is not compatible "
1592                                 "with --"OPT_MATCH_ALLOCATIONS"\n");
1593                 return -1;
1594         }
1595
1596         return 0;
1597 }
1598
1599 void
1600 eal_common_usage(void)
1601 {
1602         printf("[options]\n\n"
1603                "EAL common options:\n"
1604                "  -c COREMASK         Hexadecimal bitmask of cores to run on\n"
1605                "  -l CORELIST         List of cores to run on\n"
1606                "                      The argument format is <c1>[-c2][,c3[-c4],...]\n"
1607                "                      where c1, c2, etc are core indexes between 0 and %d\n"
1608                "  --"OPT_LCORES" COREMAP    Map lcore set to physical cpu set\n"
1609                "                      The argument format is\n"
1610                "                            '<lcores[@cpus]>[<,lcores[@cpus]>...]'\n"
1611                "                      lcores and cpus list are grouped by '(' and ')'\n"
1612                "                      Within the group, '-' is used for range separator,\n"
1613                "                      ',' is used for single number separator.\n"
1614                "                      '( )' can be omitted for single element group,\n"
1615                "                      '@' can be omitted if cpus and lcores have the same value\n"
1616                "  -s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores\n"
1617                "  --"OPT_MASTER_LCORE" ID   Core ID that is used as master\n"
1618                "  --"OPT_MBUF_POOL_OPS_NAME" Pool ops name for mbuf to use\n"
1619                "  -n CHANNELS         Number of memory channels\n"
1620                "  -m MB               Memory to allocate (see also --"OPT_SOCKET_MEM")\n"
1621                "  -r RANKS            Force number of memory ranks (don't detect)\n"
1622                "  -b, --"OPT_PCI_BLACKLIST" Add a PCI device in black list.\n"
1623                "                      Prevent EAL from using this PCI device. The argument\n"
1624                "                      format is <domain:bus:devid.func>.\n"
1625                "  -w, --"OPT_PCI_WHITELIST" Add a PCI device in white list.\n"
1626                "                      Only use the specified PCI devices. The argument format\n"
1627                "                      is <[domain:]bus:devid.func>. This option can be present\n"
1628                "                      several times (once per device).\n"
1629                "                      [NOTE: PCI whitelist cannot be used with -b option]\n"
1630                "  --"OPT_VDEV"              Add a virtual device.\n"
1631                "                      The argument format is <driver><id>[,key=val,...]\n"
1632                "                      (ex: --vdev=net_pcap0,iface=eth2).\n"
1633                "  --"OPT_IOVA_MODE"   Set IOVA mode. 'pa' for IOVA_PA\n"
1634                "                      'va' for IOVA_VA\n"
1635                "  -d LIB.so|DIR       Add a driver or driver directory\n"
1636                "                      (can be used multiple times)\n"
1637                "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
1638                "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
1639                "  --"OPT_SYSLOG"            Set syslog facility\n"
1640                "  --"OPT_LOG_LEVEL"=<int>   Set global log level\n"
1641                "  --"OPT_LOG_LEVEL"=<type-match>:<int>\n"
1642                "                      Set specific log level\n"
1643                "  -v                  Display version information on startup\n"
1644                "  -h, --help          This help\n"
1645                "  --"OPT_IN_MEMORY"   Operate entirely in memory. This will\n"
1646                "                      disable secondary process support\n"
1647                "\nEAL options for DEBUG use only:\n"
1648                "  --"OPT_HUGE_UNLINK"       Unlink hugepage files after init\n"
1649                "  --"OPT_NO_HUGE"           Use malloc instead of hugetlbfs\n"
1650                "  --"OPT_NO_PCI"            Disable PCI\n"
1651                "  --"OPT_NO_HPET"           Disable HPET\n"
1652                "  --"OPT_NO_SHCONF"         No shared config (mmap'd files)\n"
1653                "\n", RTE_MAX_LCORE);
1654         rte_option_usage();
1655 }