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