4009f0221e1120ba7d836c1dc34213a741a06ab8
[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 <string.h>
36 #include <syslog.h>
37 #include <ctype.h>
38 #include <limits.h>
39 #include <errno.h>
40 #include <getopt.h>
41
42 #include <rte_eal.h>
43 #include <rte_log.h>
44 #include <rte_lcore.h>
45 #include <rte_version.h>
46 #include <rte_devargs.h>
47
48 #include "eal_internal_cfg.h"
49 #include "eal_options.h"
50
51 #define BITS_PER_HEX 4
52
53 const char
54 eal_short_options[] =
55         "b:" /* pci-blacklist */
56         "w:" /* pci-whitelist */
57         "c:"
58         "d:"
59         "m:"
60         "n:"
61         "r:"
62         "v";
63
64 const struct option
65 eal_long_options[] = {
66         {OPT_HUGE_DIR, 1, 0, OPT_HUGE_DIR_NUM},
67         {OPT_PROC_TYPE, 1, 0, OPT_PROC_TYPE_NUM},
68         {OPT_NO_SHCONF, 0, 0, OPT_NO_SHCONF_NUM},
69         {OPT_NO_HPET, 0, 0, OPT_NO_HPET_NUM},
70         {OPT_VMWARE_TSC_MAP, 0, 0, OPT_VMWARE_TSC_MAP_NUM},
71         {OPT_NO_PCI, 0, 0, OPT_NO_PCI_NUM},
72         {OPT_NO_HUGE, 0, 0, OPT_NO_HUGE_NUM},
73         {OPT_FILE_PREFIX, 1, 0, OPT_FILE_PREFIX_NUM},
74         {OPT_SOCKET_MEM, 1, 0, OPT_SOCKET_MEM_NUM},
75         {OPT_PCI_WHITELIST, 1, 0, OPT_PCI_WHITELIST_NUM},
76         {OPT_PCI_BLACKLIST, 1, 0, OPT_PCI_BLACKLIST_NUM},
77         {OPT_VDEV, 1, 0, OPT_VDEV_NUM},
78         {OPT_SYSLOG, 1, NULL, OPT_SYSLOG_NUM},
79         {OPT_LOG_LEVEL, 1, NULL, OPT_LOG_LEVEL_NUM},
80         {OPT_BASE_VIRTADDR, 1, 0, OPT_BASE_VIRTADDR_NUM},
81         {OPT_XEN_DOM0, 0, 0, OPT_XEN_DOM0_NUM},
82         {OPT_CREATE_UIO_DEV, 1, NULL, OPT_CREATE_UIO_DEV_NUM},
83         {OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM},
84         {0, 0, 0, 0}
85 };
86
87 /*
88  * Parse the coremask given as argument (hexadecimal string) and fill
89  * the global configuration (core role and core count) with the parsed
90  * value.
91  */
92 static int xdigit2val(unsigned char c)
93 {
94         int val;
95
96         if (isdigit(c))
97                 val = c - '0';
98         else if (isupper(c))
99                 val = c - 'A' + 10;
100         else
101                 val = c - 'a' + 10;
102         return val;
103 }
104
105 static int
106 eal_parse_coremask(const char *coremask)
107 {
108         struct rte_config *cfg = rte_eal_get_configuration();
109         int i, j, idx = 0;
110         unsigned count = 0;
111         char c;
112         int val;
113
114         if (coremask == NULL)
115                 return -1;
116         /* Remove all blank characters ahead and after .
117          * Remove 0x/0X if exists.
118          */
119         while (isblank(*coremask))
120                 coremask++;
121         if (coremask[0] == '0' && ((coremask[1] == 'x')
122                 || (coremask[1] == 'X')))
123                 coremask += 2;
124         i = strnlen(coremask, PATH_MAX);
125         while ((i > 0) && isblank(coremask[i - 1]))
126                 i--;
127         if (i == 0)
128                 return -1;
129
130         for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
131                 c = coremask[i];
132                 if (isxdigit(c) == 0) {
133                         /* invalid characters */
134                         return -1;
135                 }
136                 val = xdigit2val(c);
137                 for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE; j++, idx++)
138                 {
139                         if ((1 << j) & val) {
140                                 if (!lcore_config[idx].detected) {
141                                         RTE_LOG(ERR, EAL, "lcore %u "
142                                                 "unavailable\n", idx);
143                                         return -1;
144                                 }
145                                 cfg->lcore_role[idx] = ROLE_RTE;
146                                 if (count == 0)
147                                         cfg->master_lcore = idx;
148                                 count++;
149                         } else {
150                                 cfg->lcore_role[idx] = ROLE_OFF;
151                         }
152                 }
153         }
154         for (; i >= 0; i--)
155                 if (coremask[i] != '0')
156                         return -1;
157         for (; idx < RTE_MAX_LCORE; idx++)
158                 cfg->lcore_role[idx] = ROLE_OFF;
159         if (count == 0)
160                 return -1;
161         /* Update the count of enabled logical cores of the EAL configuration */
162         cfg->lcore_count = count;
163         return 0;
164 }
165
166 static int
167 eal_parse_syslog(const char *facility, struct internal_config *conf)
168 {
169         int i;
170         static struct {
171                 const char *name;
172                 int value;
173         } map[] = {
174                 { "auth", LOG_AUTH },
175                 { "cron", LOG_CRON },
176                 { "daemon", LOG_DAEMON },
177                 { "ftp", LOG_FTP },
178                 { "kern", LOG_KERN },
179                 { "lpr", LOG_LPR },
180                 { "mail", LOG_MAIL },
181                 { "news", LOG_NEWS },
182                 { "syslog", LOG_SYSLOG },
183                 { "user", LOG_USER },
184                 { "uucp", LOG_UUCP },
185                 { "local0", LOG_LOCAL0 },
186                 { "local1", LOG_LOCAL1 },
187                 { "local2", LOG_LOCAL2 },
188                 { "local3", LOG_LOCAL3 },
189                 { "local4", LOG_LOCAL4 },
190                 { "local5", LOG_LOCAL5 },
191                 { "local6", LOG_LOCAL6 },
192                 { "local7", LOG_LOCAL7 },
193                 { NULL, 0 }
194         };
195
196         for (i = 0; map[i].name; i++) {
197                 if (!strcmp(facility, map[i].name)) {
198                         conf->syslog_facility = map[i].value;
199                         return 0;
200                 }
201         }
202         return -1;
203 }
204
205 static int
206 eal_parse_log_level(const char *level, uint32_t *log_level)
207 {
208         char *end;
209         unsigned long tmp;
210
211         errno = 0;
212         tmp = strtoul(level, &end, 0);
213
214         /* check for errors */
215         if ((errno != 0) || (level[0] == '\0') ||
216             end == NULL || (*end != '\0'))
217                 return -1;
218
219         /* log_level is a uint32_t */
220         if (tmp >= UINT32_MAX)
221                 return -1;
222
223         *log_level = tmp;
224         return 0;
225 }
226
227 static enum rte_proc_type_t
228 eal_parse_proc_type(const char *arg)
229 {
230         if (strncasecmp(arg, "primary", sizeof("primary")) == 0)
231                 return RTE_PROC_PRIMARY;
232         if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0)
233                 return RTE_PROC_SECONDARY;
234         if (strncasecmp(arg, "auto", sizeof("auto")) == 0)
235                 return RTE_PROC_AUTO;
236
237         return RTE_PROC_INVALID;
238 }
239
240 int
241 eal_parse_common_option(int opt, const char *optarg,
242                         struct internal_config *conf)
243 {
244         switch (opt) {
245         /* blacklist */
246         case 'b':
247                 if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI,
248                                 optarg) < 0) {
249                         return -1;
250                 }
251                 break;
252         /* whitelist */
253         case 'w':
254                 if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI,
255                                 optarg) < 0) {
256                         return -1;
257                 }
258                 break;
259         /* coremask */
260         case 'c':
261                 if (eal_parse_coremask(optarg) < 0) {
262                         RTE_LOG(ERR, EAL, "invalid coremask\n");
263                         return -1;
264                 }
265                 break;
266         /* size of memory */
267         case 'm':
268                 conf->memory = atoi(optarg);
269                 conf->memory *= 1024ULL;
270                 conf->memory *= 1024ULL;
271                 break;
272         /* force number of channels */
273         case 'n':
274                 conf->force_nchannel = atoi(optarg);
275                 if (conf->force_nchannel == 0 ||
276                     conf->force_nchannel > 4) {
277                         RTE_LOG(ERR, EAL, "invalid channel number\n");
278                         return -1;
279                 }
280                 break;
281         /* force number of ranks */
282         case 'r':
283                 conf->force_nrank = atoi(optarg);
284                 if (conf->force_nrank == 0 ||
285                     conf->force_nrank > 16) {
286                         RTE_LOG(ERR, EAL, "invalid rank number\n");
287                         return -1;
288                 }
289                 break;
290         case 'v':
291                 /* since message is explicitly requested by user, we
292                  * write message at highest log level so it can always
293                  * be seen
294                  * even if info or warning messages are disabled */
295                 RTE_LOG(CRIT, EAL, "RTE Version: '%s'\n", rte_version());
296                 break;
297
298         /* long options */
299         case OPT_NO_HUGE_NUM:
300                         conf->no_hugetlbfs = 1;
301                 break;
302
303         case OPT_NO_PCI_NUM:
304                         conf->no_pci = 1;
305                 break;
306
307         case OPT_NO_HPET_NUM:
308                         conf->no_hpet = 1;
309                 break;
310
311         case OPT_VMWARE_TSC_MAP_NUM:
312                         conf->vmware_tsc_map = 1;
313                 break;
314
315         case OPT_NO_SHCONF_NUM:
316                         conf->no_shconf = 1;
317                 break;
318
319         case OPT_PROC_TYPE_NUM:
320                         conf->process_type = eal_parse_proc_type(optarg);
321                 break;
322
323         case OPT_VDEV_NUM:
324                         if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL,
325                                         optarg) < 0) {
326                                 return -1;
327                         }
328                 break;
329
330         case OPT_SYSLOG_NUM:
331                         if (eal_parse_syslog(optarg, conf) < 0) {
332                                 RTE_LOG(ERR, EAL, "invalid parameters for --"
333                                                 OPT_SYSLOG "\n");
334                                 return -1;
335                         }
336                 break;
337
338         case OPT_LOG_LEVEL_NUM: {
339                         uint32_t log;
340
341                         if (eal_parse_log_level(optarg, &log) < 0) {
342                                 RTE_LOG(ERR, EAL,
343                                         "invalid parameters for --"
344                                         OPT_LOG_LEVEL "\n");
345                                 return -1;
346                         }
347                         conf->log_level = log;
348                 break;
349                 }
350
351         /* don't know what to do, leave this to caller */
352         default:
353                 return 1;
354
355         }
356
357         return 0;
358 }
359
360 void
361 eal_common_usage(void)
362 {
363         printf("-c COREMASK -n NUM [-m NB] [-r NUM] [-b <domain:bus:devid.func>]"
364                "[--proc-type primary|secondary|auto]\n\n"
365                "EAL common options:\n"
366                "  -c COREMASK  : A hexadecimal bitmask of cores to run on\n"
367                "  -n NUM       : Number of memory channels\n"
368                "  -v           : Display version information on startup\n"
369                "  -m MB        : memory to allocate (see also --"OPT_SOCKET_MEM")\n"
370                "  -r NUM       : force number of memory ranks (don't detect)\n"
371                "  --"OPT_SYSLOG"     : set syslog facility\n"
372                "  --"OPT_LOG_LEVEL"  : set default log level\n"
373                "  --"OPT_PROC_TYPE"  : type of this process\n"
374                "  --"OPT_PCI_BLACKLIST", -b: add a PCI device in black list.\n"
375                "               Prevent EAL from using this PCI device. The argument\n"
376                "               format is <domain:bus:devid.func>.\n"
377                "  --"OPT_PCI_WHITELIST", -w: add a PCI device in white list.\n"
378                "               Only use the specified PCI devices. The argument format\n"
379                "               is <[domain:]bus:devid.func>. This option can be present\n"
380                "               several times (once per device).\n"
381                "               [NOTE: PCI whitelist cannot be used with -b option]\n"
382                "  --"OPT_VDEV": add a virtual device.\n"
383                "               The argument format is <driver><id>[,key=val,...]\n"
384                "               (ex: --vdev=eth_pcap0,iface=eth2).\n"
385                "  --"OPT_VMWARE_TSC_MAP": use VMware TSC map instead of native RDTSC\n"
386                "\nEAL options for DEBUG use only:\n"
387                "  --"OPT_NO_HUGE"  : use malloc instead of hugetlbfs\n"
388                "  --"OPT_NO_PCI"   : disable pci\n"
389                "  --"OPT_NO_HPET"  : disable hpet\n"
390                "  --"OPT_NO_SHCONF": no shared config (mmap'd files)\n"
391                "\n");
392 }