log: get full path as syslog id
[dpdk.git] / lib / librte_eal / linuxapp / eal / eal.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
5  *   All rights reserved.
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
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include <unistd.h>
41 #include <pthread.h>
42 #include <syslog.h>
43 #include <getopt.h>
44 #include <sys/file.h>
45 #include <stddef.h>
46 #include <errno.h>
47 #include <limits.h>
48 #include <errno.h>
49 #include <sys/mman.h>
50 #include <sys/queue.h>
51
52 #include <rte_common.h>
53 #include <rte_debug.h>
54 #include <rte_memory.h>
55 #include <rte_memzone.h>
56 #include <rte_launch.h>
57 #include <rte_tailq.h>
58 #include <rte_eal.h>
59 #include <rte_eal_memconfig.h>
60 #include <rte_per_lcore.h>
61 #include <rte_lcore.h>
62 #include <rte_log.h>
63 #include <rte_random.h>
64 #include <rte_cycles.h>
65 #include <rte_string_fns.h>
66 #include <rte_cpuflags.h>
67 #include <rte_interrupts.h>
68 #include <rte_pci.h>
69 #include <rte_common.h>
70 #include <rte_version.h>
71 #include <rte_atomic.h>
72 #include <malloc_heap.h>
73
74 #include "eal_private.h"
75 #include "eal_thread.h"
76 #include "eal_internal_cfg.h"
77 #include "eal_filesystem.h"
78 #include "eal_hugepages.h"
79
80 #define OPT_HUGE_DIR    "huge-dir"
81 #define OPT_PROC_TYPE   "proc-type"
82 #define OPT_NO_SHCONF   "no-shconf"
83 #define OPT_NO_HPET     "no-hpet"
84 #define OPT_NO_PCI      "no-pci"
85 #define OPT_NO_HUGE     "no-huge"
86 #define OPT_FILE_PREFIX "file-prefix"
87 #define OPT_SOCKET_MEM  "socket-mem"
88 #define OPT_SYSLOG      "syslog"
89
90 #define RTE_EAL_BLACKLIST_SIZE  0x100
91
92 #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL)
93
94 #define SOCKET_MEM_STRLEN (RTE_MAX_NUMA_NODES * 10)
95
96 #define GET_BLACKLIST_FIELD(in, fd, lim, dlm)                   \
97 {                                                               \
98         unsigned long val;                                      \
99         char *end;                                              \
100         errno = 0;                                              \
101         val = strtoul((in), &end, 16);                          \
102         if (errno != 0 || end[0] != (dlm) || val > (lim))       \
103                 return (-EINVAL);                               \
104         (fd) = (typeof (fd))val;                                \
105         (in) = end + 1;                                         \
106 }
107
108 /* Allow the application to print its usage message too if set */
109 static rte_usage_hook_t rte_application_usage_hook = NULL;
110 /* early configuration structure, when memory config is not mmapped */
111 static struct rte_mem_config early_mem_config;
112
113 /* define fd variable here, because file needs to be kept open for the
114  * duration of the program, as we hold a write lock on it in the primary proc */
115 static int mem_cfg_fd = -1;
116
117 static struct flock wr_lock = {
118                 .l_type = F_WRLCK,
119                 .l_whence = SEEK_SET,
120                 .l_start = offsetof(struct rte_mem_config, memseg),
121                 .l_len = sizeof(early_mem_config.memseg),
122 };
123
124 /* Address of global and public configuration */
125 static struct rte_config rte_config = {
126                 .mem_config = &early_mem_config,
127 };
128
129 static struct rte_pci_addr eal_dev_blacklist[RTE_EAL_BLACKLIST_SIZE];
130
131 /* internal configuration (per-core) */
132 struct lcore_config lcore_config[RTE_MAX_LCORE];
133
134 /* internal configuration */
135 struct internal_config internal_config;
136
137 /* Return a pointer to the configuration structure */
138 struct rte_config *
139 rte_eal_get_configuration(void)
140 {
141         return &rte_config;
142 }
143
144 /* parse a sysfs (or other) file containing one integer value */
145 int
146 eal_parse_sysfs_value(const char *filename, unsigned long *val)
147 {
148         FILE *f;
149         char buf[BUFSIZ];
150         char *end = NULL;
151
152         if ((f = fopen(filename, "r")) == NULL) {
153                 RTE_LOG(ERR, EAL, "%s(): cannot open sysfs value %s\n",
154                         __func__, filename);
155                 return -1;
156         }
157
158         if (fgets(buf, sizeof(buf), f) == NULL) {
159                 RTE_LOG(ERR, EAL, "%s(): cannot read sysfs value %s\n",
160                         __func__, filename);
161                 fclose(f);
162                 return -1;
163         }
164         *val = strtoul(buf, &end, 0);
165         if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
166                 RTE_LOG(ERR, EAL, "%s(): cannot parse sysfs value %s\n",
167                                 __func__, filename);
168                 fclose(f);
169                 return -1;
170         }
171         fclose(f);
172         return 0;
173 }
174
175
176 /* create memory configuration in shared/mmap memory. Take out
177  * a write lock on the memsegs, so we can auto-detect primary/secondary.
178  * This means we never close the file while running (auto-close on exit).
179  * We also don't lock the whole file, so that in future we can use read-locks
180  * on other parts, e.g. memzones, to detect if there are running secondary
181  * processes. */
182 static void
183 rte_eal_config_create(void)
184 {
185         void *rte_mem_cfg_addr;
186         int retval;
187
188         const char *pathname = eal_runtime_config_path();
189
190         if (internal_config.no_shconf)
191                 return;
192
193         if (mem_cfg_fd < 0){
194                 mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660);
195                 if (mem_cfg_fd < 0)
196                         rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
197         }
198
199         retval = ftruncate(mem_cfg_fd, sizeof(*rte_config.mem_config));
200         if (retval < 0){
201                 close(mem_cfg_fd);
202                 rte_panic("Cannot resize '%s' for rte_mem_config\n", pathname);
203         }
204
205         retval = fcntl(mem_cfg_fd, F_SETLK, &wr_lock);
206         if (retval < 0){
207                 close(mem_cfg_fd);
208                 rte_exit(EXIT_FAILURE, "Cannot create lock on '%s'. Is another primary "
209                                 "process running?\n", pathname);
210         }
211
212         rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
213                                 PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
214
215         if (rte_mem_cfg_addr == MAP_FAILED){
216                 rte_panic("Cannot mmap memory for rte_config\n");
217         }
218         memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config));
219         rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
220 }
221
222 /* attach to an existing shared memory config */
223 static void
224 rte_eal_config_attach(void)
225 {
226         void *rte_mem_cfg_addr;
227         const char *pathname = eal_runtime_config_path();
228
229         if (internal_config.no_shconf)
230                 return;
231
232         if (mem_cfg_fd < 0){
233                 mem_cfg_fd = open(pathname, O_RDWR);
234                 if (mem_cfg_fd < 0)
235                         rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
236         }
237
238         rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config), 
239                                 PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
240         close(mem_cfg_fd);
241         if (rte_mem_cfg_addr == MAP_FAILED)
242                 rte_panic("Cannot mmap memory for rte_config\n");
243
244         rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
245 }
246
247 /* Detect if we are a primary or a secondary process */
248 static enum rte_proc_type_t
249 eal_proc_type_detect(void)
250 {
251         enum rte_proc_type_t ptype = RTE_PROC_PRIMARY;
252         const char *pathname = eal_runtime_config_path();
253
254         /* if we can open the file but not get a write-lock we are a secondary
255          * process. NOTE: if we get a file handle back, we keep that open
256          * and don't close it to prevent a race condition between multiple opens */
257         if (((mem_cfg_fd = open(pathname, O_RDWR)) >= 0) &&
258                         (fcntl(mem_cfg_fd, F_SETLK, &wr_lock) < 0))
259                 ptype = RTE_PROC_SECONDARY;
260
261         RTE_LOG(INFO, EAL, "Auto-detected process type: %s\n",
262                         ptype == RTE_PROC_PRIMARY ? "PRIMARY" : "SECONDARY");
263
264         return ptype;
265 }
266
267 /* Sets up rte_config structure with the pointer to shared memory config.*/
268 static void
269 rte_config_init(void)
270 {
271         /* set the magic in configuration structure */
272         rte_config.magic = RTE_MAGIC;
273         rte_config.process_type = (internal_config.process_type == RTE_PROC_AUTO) ?
274                         eal_proc_type_detect() : /* for auto, detect the type */
275                         internal_config.process_type; /* otherwise use what's already set */
276
277         switch (rte_config.process_type){
278         case RTE_PROC_PRIMARY:
279                 rte_eal_config_create();
280                 break;
281         case RTE_PROC_SECONDARY:
282                 rte_eal_config_attach();
283                 rte_eal_mcfg_wait_complete(rte_config.mem_config);
284                 break;
285         case RTE_PROC_AUTO:
286         case RTE_PROC_INVALID:
287                 rte_panic("Invalid process type\n");
288         }
289 }
290
291 /* Unlocks hugepage directories that were locked by eal_hugepage_info_init */
292 static void
293 eal_hugedirs_unlock(void)
294 {
295         int i;
296
297         for (i = 0; i < MAX_HUGEPAGE_SIZES; i++)
298         {
299                 /* skip uninitialized */
300                 if (internal_config.hugepage_info[i].lock_descriptor == 0)
301                         continue;
302                 /* unlock hugepage file */
303                 flock(internal_config.hugepage_info[i].lock_descriptor, LOCK_UN);
304                 close(internal_config.hugepage_info[i].lock_descriptor);
305                 /* reset the field */
306                 internal_config.hugepage_info[i].lock_descriptor = 0;
307         }
308 }
309
310 /* display usage */
311 static void
312 eal_usage(const char *prgname)
313 {
314         printf("\nUsage: %s -c COREMASK -n NUM [-m NB] [-r NUM] [-b <domain:bus:devid.func>]"
315                "[--proc-type primary|secondary|auto] \n\n"
316                "EAL options:\n"
317                "  -c COREMASK  : A hexadecimal bitmask of cores to run on\n"
318                "  -n NUM       : Number of memory channels\n"
319                    "  -v           : Display version information on startup\n"
320                "  -b <domain:bus:devid.func>: to prevent EAL from using specified "
321            "PCI device\n"
322                "                 (multiple -b options are allowed)\n"
323                "  -m MB        : memory to allocate (see also --"OPT_SOCKET_MEM")\n"
324                "  -r NUM       : force number of memory ranks (don't detect)\n"
325                "  --"OPT_SYSLOG"     : set syslog facility\n"
326                "  --"OPT_SOCKET_MEM" : memory to allocate on specific \n"
327                    "                 sockets (use comma separated values)\n"
328                "  --"OPT_HUGE_DIR"   : directory where hugetlbfs is mounted\n"
329                "  --"OPT_PROC_TYPE"  : type of this process\n"
330                "  --"OPT_FILE_PREFIX": prefix for hugepage filenames\n"
331                "\nEAL options for DEBUG use only:\n"
332                "  --"OPT_NO_HUGE"  : use malloc instead of hugetlbfs\n"
333                "  --"OPT_NO_PCI"   : disable pci\n"
334                "  --"OPT_NO_HPET"  : disable hpet\n"
335                "  --"OPT_NO_SHCONF": no shared config (mmap'd files)\n\n",
336                prgname);
337         /* Allow the application to print its usage message too if hook is set */
338         if ( rte_application_usage_hook ) {
339                 printf("===== Application Usage =====\n\n");
340                 rte_application_usage_hook(prgname);
341         }
342 }
343
344 /* Set a per-application usage message */
345 rte_usage_hook_t
346 rte_set_application_usage_hook( rte_usage_hook_t usage_func )
347 {
348         rte_usage_hook_t        old_func;
349
350         /* Will be NULL on the first call to denote the last usage routine. */
351         old_func                                        = rte_application_usage_hook;
352         rte_application_usage_hook      = usage_func;
353
354         return old_func;
355 }
356
357 /*
358  * Parse the coremask given as argument (hexadecimal string) and fill
359  * the global configuration (core role and core count) with the parsed
360  * value.
361  */
362 static int
363 eal_parse_coremask(const char *coremask)
364 {
365         struct rte_config *cfg = rte_eal_get_configuration();
366         unsigned i;
367         char *end = NULL;
368         unsigned long long cm;
369         unsigned count = 0;
370
371         /* parse hexadecimal string */
372         cm = strtoull(coremask, &end, 16);
373         if ((coremask[0] == '\0') || (end == NULL) || (*end != '\0') || (cm == 0))
374                 return -1;
375
376         RTE_LOG(DEBUG, EAL, "coremask set to %llx\n", cm);
377         /* set core role and core count */
378         for (i = 0; i < RTE_MAX_LCORE; i++) {
379                 if ((1ULL << i) & cm) {
380                         if (count == 0)
381                                 cfg->master_lcore = i;
382                         cfg->lcore_role[i] = ROLE_RTE;
383                         count++;
384                 }
385                 else {
386                         cfg->lcore_role[i] = ROLE_OFF;
387                 }
388         }
389         return 0;
390 }
391
392 static int
393 eal_parse_syslog(const char *facility)
394 {
395         int i;
396         static struct {
397                 const char *name;
398                 int value;
399         } map[] = {
400                 { "auth", LOG_AUTH },
401                 { "cron", LOG_CRON },
402                 { "daemon", LOG_DAEMON },
403                 { "ftp", LOG_FTP },
404                 { "kern", LOG_KERN },
405                 { "lpr", LOG_LPR },
406                 { "mail", LOG_MAIL },
407                 { "news", LOG_NEWS },
408                 { "syslog", LOG_SYSLOG },
409                 { "user", LOG_USER },
410                 { "uucp", LOG_UUCP },
411                 { "local0", LOG_LOCAL0 },
412                 { "local1", LOG_LOCAL1 },
413                 { "local2", LOG_LOCAL2 },
414                 { "local3", LOG_LOCAL3 },
415                 { "local4", LOG_LOCAL4 },
416                 { "local5", LOG_LOCAL5 },
417                 { "local6", LOG_LOCAL6 },
418                 { "local7", LOG_LOCAL7 },
419                 { NULL, 0 }
420         };
421
422         for (i = 0; map[i].name; i++) {
423                 if (!strcmp(facility, map[i].name)) {
424                         internal_config.syslog_facility = map[i].value;
425                         return 0;
426                 }
427         }
428         return -1;
429 }
430
431 static int
432 eal_parse_socket_mem(char *socket_mem)
433 {
434         char * arg[RTE_MAX_NUMA_NODES];
435         char *end;
436         int arg_num, i, len;
437         uint64_t total_mem = 0;
438
439         len = strnlen(socket_mem, SOCKET_MEM_STRLEN);
440         if (len == SOCKET_MEM_STRLEN) {
441                 RTE_LOG(ERR, EAL, "--socket-mem is too long\n");
442                 return -1;
443         }
444
445         /* all other error cases will be caught later */
446         if (!isdigit(socket_mem[len-1]))
447                 return -1;
448
449         /* split the optarg into separate socket values */
450         arg_num = rte_strsplit(socket_mem, len,
451                         arg, RTE_MAX_NUMA_NODES, ',');
452
453         /* if split failed, or 0 arguments */
454         if (arg_num <= 0)
455                 return -1;
456
457         internal_config.force_sockets = 1;
458
459         /* parse each defined socket option */
460         errno = 0;
461         for (i = 0; i < arg_num; i++) {
462                 end = NULL;
463                 internal_config.socket_mem[i] = strtoull(arg[i], &end, 10);
464
465                 /* check for invalid input */
466                 if ((errno != 0)  ||
467                                 (arg[i][0] == '\0') || (end == NULL) || (*end != '\0'))
468                         return -1;
469                 internal_config.socket_mem[i] *= 1024ULL;
470                 internal_config.socket_mem[i] *= 1024ULL;
471                 total_mem += internal_config.socket_mem[i];
472         }
473
474         /* check if we have a positive amount of total memory */
475         if (total_mem == 0)
476                 return -1;
477
478         return 0;
479 }
480
481 static inline size_t
482 eal_get_hugepage_mem_size(void)
483 {
484         uint64_t size = 0;
485         unsigned i, j;
486
487         for (i = 0; i < internal_config.num_hugepage_sizes; i++) {
488                 struct hugepage_info *hpi = &internal_config.hugepage_info[i];
489                 if (hpi->hugedir != NULL) {
490                         for (j = 0; j < RTE_MAX_NUMA_NODES; j++) {
491                                 size += hpi->hugepage_sz * hpi->num_pages[j];
492                         }
493                 }
494         }
495
496         return (size < SIZE_MAX) ? (size_t)(size) : SIZE_MAX;
497 }
498
499 static enum rte_proc_type_t
500 eal_parse_proc_type(const char *arg)
501 {
502         if (strncasecmp(arg, "primary", sizeof("primary")) == 0)
503                 return RTE_PROC_PRIMARY;
504         if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0)
505                 return RTE_PROC_SECONDARY;
506         if (strncasecmp(arg, "auto", sizeof("auto")) == 0)
507                 return RTE_PROC_AUTO;
508
509         return RTE_PROC_INVALID;
510 }
511
512 static int
513 eal_parse_blacklist(const char *input,  struct rte_pci_addr *dev2bl)
514 {
515         GET_BLACKLIST_FIELD(input, dev2bl->domain, UINT16_MAX, ':');
516         GET_BLACKLIST_FIELD(input, dev2bl->bus, UINT8_MAX, ':');
517         GET_BLACKLIST_FIELD(input, dev2bl->devid, UINT8_MAX, '.');
518         GET_BLACKLIST_FIELD(input, dev2bl->function, UINT8_MAX, 0);
519         return (0);
520 }
521
522 static ssize_t
523 eal_parse_blacklist_opt(const char *optarg, size_t idx)
524 {
525         if (idx >= sizeof (eal_dev_blacklist) / sizeof (eal_dev_blacklist[0])) {
526                 RTE_LOG(ERR, EAL,
527                     "%s - too many devices to blacklist...\n",
528                     optarg);
529                 return (-EINVAL);
530         } else if (eal_parse_blacklist(optarg, eal_dev_blacklist + idx) != 0) {
531                 RTE_LOG(ERR, EAL,
532                     "%s - invalid device to blacklist...\n",
533                     optarg);
534                 return (-EINVAL);
535         }
536
537         idx += 1;
538         return (idx);
539 }
540
541
542 /* Parse the argument given in the command line of the application */
543 static int
544 eal_parse_args(int argc, char **argv)
545 {
546         int opt, ret, i;
547         char **argvopt;
548         int option_index;
549         int coremask_ok = 0;
550         ssize_t blacklist_index = 0;;
551         char *prgname = argv[0];
552         static struct option lgopts[] = {
553                 {OPT_NO_HUGE, 0, 0, 0},
554                 {OPT_NO_PCI, 0, 0, 0},
555                 {OPT_NO_HPET, 0, 0, 0},
556                 {OPT_HUGE_DIR, 1, 0, 0},
557                 {OPT_NO_SHCONF, 0, 0, 0},
558                 {OPT_PROC_TYPE, 1, 0, 0},
559                 {OPT_FILE_PREFIX, 1, 0, 0},
560                 {OPT_SOCKET_MEM, 1, 0, 0},
561                 {OPT_SYSLOG, 1, NULL, 0},
562                 {0, 0, 0, 0}
563         };
564
565         argvopt = argv;
566
567         internal_config.memory = 0;
568         internal_config.force_nrank = 0;
569         internal_config.force_nchannel = 0;
570         internal_config.hugefile_prefix = HUGEFILE_PREFIX_DEFAULT;
571         internal_config.hugepage_dir = NULL;
572         internal_config.force_sockets = 0;
573         internal_config.syslog_facility = LOG_DAEMON;
574 #ifdef RTE_LIBEAL_USE_HPET
575         internal_config.no_hpet = 0;
576 #else
577         internal_config.no_hpet = 1;
578 #endif
579         /* zero out the NUMA config */
580         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
581                 internal_config.socket_mem[i] = 0;
582
583         /* zero out hugedir descriptors */
584         for (i = 0; i < MAX_HUGEPAGE_SIZES; i++)
585                 internal_config.hugepage_info[i].lock_descriptor = 0;
586
587         while ((opt = getopt_long(argc, argvopt, "b:c:m:n:r:v",
588                                   lgopts, &option_index)) != EOF) {
589
590                 switch (opt) {
591                 /* blacklist */
592                 case 'b':
593                         if ((blacklist_index = eal_parse_blacklist_opt(optarg,
594                             blacklist_index)) < 0) {
595                                 eal_usage(prgname);
596                                 return (-1);
597                         }
598                         break;
599                 /* coremask */
600                 case 'c':
601                         if (eal_parse_coremask(optarg) < 0) {
602                                 RTE_LOG(ERR, EAL, "invalid coremask\n");
603                                 eal_usage(prgname);
604                                 return -1;
605                         }
606                         coremask_ok = 1;
607                         break;
608                 /* size of memory */
609                 case 'm':
610                         internal_config.memory = atoi(optarg);
611                         internal_config.memory *= 1024ULL;
612                         internal_config.memory *= 1024ULL;
613                         break;
614                 /* force number of channels */
615                 case 'n':
616                         internal_config.force_nchannel = atoi(optarg);
617                         if (internal_config.force_nchannel == 0 ||
618                             internal_config.force_nchannel > 4) {
619                                 RTE_LOG(ERR, EAL, "invalid channel number\n");
620                                 eal_usage(prgname);
621                                 return -1;
622                         }
623                         break;
624                 /* force number of ranks */
625                 case 'r':
626                         internal_config.force_nrank = atoi(optarg);
627                         if (internal_config.force_nrank == 0 ||
628                             internal_config.force_nrank > 16) {
629                                 RTE_LOG(ERR, EAL, "invalid rank number\n");
630                                 eal_usage(prgname);
631                                 return -1;
632                         }
633                         break;
634                 case 'v':
635                         /* since message is explicitly requested by user, we
636                          * write message at highest log level so it can always be seen
637                          * even if info or warning messages are disabled */
638                         RTE_LOG(CRIT, EAL, "RTE Version: '%s'\n", rte_version());
639                         break;
640
641                 /* long options */
642                 case 0:
643                         if (!strcmp(lgopts[option_index].name, OPT_NO_HUGE)) {
644                                 internal_config.no_hugetlbfs = 1;
645                         }
646                         else if (!strcmp(lgopts[option_index].name, OPT_NO_PCI)) {
647                                 internal_config.no_pci = 1;
648                         }
649                         else if (!strcmp(lgopts[option_index].name, OPT_NO_HPET)) {
650                                 internal_config.no_hpet = 1;
651                         }
652                         else if (!strcmp(lgopts[option_index].name, OPT_NO_SHCONF)) {
653                                 internal_config.no_shconf = 1;
654                         }
655                         else if (!strcmp(lgopts[option_index].name, OPT_HUGE_DIR)) {
656                                 internal_config.hugepage_dir = optarg;
657                         }
658                         else if (!strcmp(lgopts[option_index].name, OPT_PROC_TYPE)) {
659                                 internal_config.process_type = eal_parse_proc_type(optarg);
660                         }
661                         else if (!strcmp(lgopts[option_index].name, OPT_FILE_PREFIX)) {
662                                 internal_config.hugefile_prefix = optarg;
663                         }
664                         else if (!strcmp(lgopts[option_index].name, OPT_SOCKET_MEM)) {
665                                 if (eal_parse_socket_mem(optarg) < 0) {
666                                         RTE_LOG(ERR, EAL, "invalid parameters for --"
667                                                         OPT_SOCKET_MEM "\n");
668                                         eal_usage(prgname);
669                                         return -1;
670                                 }
671                         }
672                         else if (!strcmp(lgopts[option_index].name, OPT_SYSLOG)) {
673                                 if (eal_parse_syslog(optarg) < 0) {
674                                         RTE_LOG(ERR, EAL, "invalid parameters for --"
675                                                         OPT_SYSLOG "\n");
676                                         eal_usage(prgname);
677                                         return -1;
678                                 }
679                         }
680                         break;
681
682                 default:
683                         eal_usage(prgname);
684                         return -1;
685                 }
686         }
687
688         /* sanity checks */
689         if (!coremask_ok) {
690                 RTE_LOG(ERR, EAL, "coremask not specified\n");
691                 eal_usage(prgname);
692                 return -1;
693         }
694         if (internal_config.process_type == RTE_PROC_AUTO){
695                 internal_config.process_type = eal_proc_type_detect();
696         }
697         if (internal_config.process_type == RTE_PROC_INVALID){
698                 RTE_LOG(ERR, EAL, "Invalid process type specified\n");
699                 eal_usage(prgname);
700                 return -1;
701         }
702         if (internal_config.process_type == RTE_PROC_PRIMARY &&
703                         internal_config.force_nchannel == 0) {
704                 RTE_LOG(ERR, EAL, "Number of memory channels (-n) not specified\n");
705                 eal_usage(prgname);
706                 return -1;
707         }
708         if (index(internal_config.hugefile_prefix,'%') != NULL){
709                 RTE_LOG(ERR, EAL, "Invalid char, '%%', in '"OPT_FILE_PREFIX"' option\n");
710                 eal_usage(prgname);
711                 return -1;
712         }
713         if (internal_config.memory > 0 && internal_config.force_sockets == 1) {
714                 RTE_LOG(ERR, EAL, "Options -m and --socket-mem cannot be specified "
715                                 "at the same time\n");
716                 eal_usage(prgname);
717                 return -1;
718         }
719         /* --no-huge doesn't make sense with either -m or --socket-mem */
720         if (internal_config.no_hugetlbfs &&
721                         (internal_config.memory > 0 ||
722                                         internal_config.force_sockets == 1)) {
723                 RTE_LOG(ERR, EAL, "Options -m or --socket-mem cannot be specified "
724                                 "together with --no-huge!\n");
725                 eal_usage(prgname);
726                 return -1;
727         }
728
729         if (blacklist_index > 0)
730                 rte_eal_pci_set_blacklist(eal_dev_blacklist, blacklist_index);
731
732         if (optind >= 0)
733                 argv[optind-1] = prgname;
734
735         /* if no memory amounts were requested, this will result in 0 and
736          * will be overriden later, right after eal_hugepage_info_init() */
737         for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
738                 internal_config.memory += internal_config.socket_mem[i];
739
740         ret = optind-1;
741         optind = 0; /* reset getopt lib */
742         return ret;
743 }
744
745 static void
746 eal_check_mem_on_local_socket(void)
747 {
748         const struct rte_memseg *ms;
749         int i, socket_id;
750
751         socket_id = rte_lcore_to_socket_id(rte_config.master_lcore);
752
753         ms = rte_eal_get_physmem_layout();
754
755         for (i = 0; i < RTE_MAX_MEMSEG; i++)
756                 if (ms[i].socket_id == socket_id &&
757                                 ms[i].len > 0)
758                         return;
759
760         RTE_LOG(WARNING, EAL, "WARNING: Master core has no "
761                         "memory on local socket!\n");
762 }
763
764 static int
765 sync_func(__attribute__((unused)) void *arg)
766 {
767         return 0;
768 }
769
770 inline static void 
771 rte_eal_mcfg_complete(void)
772 {
773         /* ALL shared mem_config related INIT DONE */
774         if (rte_config.process_type == RTE_PROC_PRIMARY)
775                 rte_config.mem_config->magic = RTE_MAGIC;
776 }
777
778 /* Launch threads, called at application init(). */
779 int
780 rte_eal_init(int argc, char **argv)
781 {
782         int i, fctret, ret;
783         pthread_t thread_id;
784         static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0);
785
786         if (!rte_atomic32_test_and_set(&run_once))
787                 return -1;
788
789         thread_id = pthread_self();
790
791         if (rte_eal_log_early_init() < 0)
792                 rte_panic("Cannot init early logs\n");
793
794         fctret = eal_parse_args(argc, argv);
795         if (fctret < 0)
796                 exit(1);
797
798         if (internal_config.no_hugetlbfs == 0 &&
799                         internal_config.process_type != RTE_PROC_SECONDARY &&
800                         eal_hugepage_info_init() < 0)
801                 rte_panic("Cannot get hugepage information\n");
802
803         if (internal_config.memory == 0 && internal_config.force_sockets == 0) {
804                 if (internal_config.no_hugetlbfs)
805                         internal_config.memory = MEMSIZE_IF_NO_HUGE_PAGE;
806                 else
807                         internal_config.memory = eal_get_hugepage_mem_size();
808         }
809
810         rte_srand(rte_rdtsc());
811
812         rte_config_init();
813         
814         if (rte_eal_cpu_init() < 0)
815                 rte_panic("Cannot detect lcores\n");
816
817         if (rte_eal_memory_init() < 0)
818                 rte_panic("Cannot init memory\n");
819
820         /* the directories are locked during eal_hugepage_info_init */
821         eal_hugedirs_unlock();
822         
823         if (rte_eal_memzone_init() < 0)
824                 rte_panic("Cannot init memzone\n");
825
826         if (rte_eal_tailqs_init() < 0)
827                 rte_panic("Cannot init tail queues for objects\n");
828
829         if (rte_eal_log_init(argv[0], internal_config.syslog_facility) < 0)
830                 rte_panic("Cannot init logs\n");
831
832         if (rte_eal_alarm_init() < 0)
833                 rte_panic("Cannot init interrupt-handling thread\n");
834
835         if (rte_eal_intr_init() < 0)
836                 rte_panic("Cannot init interrupt-handling thread\n");
837
838         if (rte_eal_hpet_init() < 0)
839                 rte_panic("Cannot init HPET\n");
840
841         if (rte_eal_pci_init() < 0)
842                 rte_panic("Cannot init PCI\n");
843
844         RTE_LOG(DEBUG, EAL, "Master core %u is ready (tid=%x)\n",
845                 rte_config.master_lcore, (int)thread_id);
846
847         eal_check_mem_on_local_socket();
848
849         rte_eal_mcfg_complete();
850
851         RTE_LCORE_FOREACH_SLAVE(i) {
852
853                 /*
854                  * create communication pipes between master thread
855                  * and children
856                  */
857                 if (pipe(lcore_config[i].pipe_master2slave) < 0)
858                         rte_panic("Cannot create pipe\n");
859                 if (pipe(lcore_config[i].pipe_slave2master) < 0)
860                         rte_panic("Cannot create pipe\n");
861
862                 lcore_config[i].state = WAIT;
863
864                 /* create a thread for each lcore */
865                 ret = pthread_create(&lcore_config[i].thread_id, NULL,
866                                      eal_thread_loop, NULL);
867                 if (ret != 0)
868                         rte_panic("Cannot create thread\n");
869         }
870
871         eal_thread_init_master(rte_config.master_lcore);
872
873         /*
874          * Launch a dummy function on all slave lcores, so that master lcore
875          * knows they are all ready when this function returns.
876          */
877         rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
878         rte_eal_mp_wait_lcore();
879
880         return fctret;
881 }
882
883 /* get core role */
884 enum rte_lcore_role_t
885 rte_eal_lcore_role(unsigned lcore_id)
886 {
887         return (rte_config.lcore_role[lcore_id]);
888 }
889
890 enum rte_proc_type_t
891 rte_eal_process_type(void)
892 {
893         return (rte_config.process_type);
894 }
895