Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation.
3 : : * Copyright(c) 2014 6WIND S.A.
4 : : */
5 : :
6 : : #include <stdlib.h>
7 : : #include <string.h>
8 : : #include <pthread.h>
9 : : #ifndef RTE_EXEC_ENV_WINDOWS
10 : : #include <syslog.h>
11 : : #endif
12 : : #include <ctype.h>
13 : : #include <limits.h>
14 : : #include <errno.h>
15 : : #include <getopt.h>
16 : : #ifndef RTE_EXEC_ENV_WINDOWS
17 : : #include <dlfcn.h>
18 : : #include <libgen.h>
19 : : #endif
20 : : #include <sys/stat.h>
21 : : #ifndef RTE_EXEC_ENV_WINDOWS
22 : : #include <dirent.h>
23 : : #endif
24 : :
25 : : #include <rte_string_fns.h>
26 : : #include <rte_eal.h>
27 : : #include <rte_log.h>
28 : : #include <rte_lcore.h>
29 : : #include <rte_memory.h>
30 : : #include <rte_tailq.h>
31 : : #include <rte_version.h>
32 : : #include <rte_devargs.h>
33 : : #include <rte_memcpy.h>
34 : : #ifndef RTE_EXEC_ENV_WINDOWS
35 : : #include <rte_telemetry.h>
36 : : #endif
37 : : #include <rte_vect.h>
38 : :
39 : : #include "eal_internal_cfg.h"
40 : : #include "eal_options.h"
41 : : #include "eal_filesystem.h"
42 : : #include "eal_private.h"
43 : : #include "log_internal.h"
44 : : #ifndef RTE_EXEC_ENV_WINDOWS
45 : : #include "eal_trace.h"
46 : : #endif
47 : :
48 : : #define BITS_PER_HEX 4
49 : : #define LCORE_OPT_LST 1
50 : : #define LCORE_OPT_MSK 2
51 : : #define LCORE_OPT_MAP 3
52 : :
53 : : const char
54 : : eal_short_options[] =
55 : : "a:" /* allow */
56 : : "b:" /* block */
57 : : "c:" /* coremask */
58 : : "s:" /* service coremask */
59 : : "d:" /* driver */
60 : : "h" /* help */
61 : : "l:" /* corelist */
62 : : "S:" /* service corelist */
63 : : "m:" /* memory size */
64 : : "n:" /* memory channels */
65 : : "r:" /* memory ranks */
66 : : "v" /* version */
67 : : ;
68 : :
69 : : const struct option
70 : : eal_long_options[] = {
71 : : {OPT_BASE_VIRTADDR, 1, NULL, OPT_BASE_VIRTADDR_NUM },
72 : : {OPT_CREATE_UIO_DEV, 0, NULL, OPT_CREATE_UIO_DEV_NUM },
73 : : {OPT_FILE_PREFIX, 1, NULL, OPT_FILE_PREFIX_NUM },
74 : : {OPT_HELP, 0, NULL, OPT_HELP_NUM },
75 : : {OPT_HUGE_DIR, 1, NULL, OPT_HUGE_DIR_NUM },
76 : : {OPT_HUGE_UNLINK, 2, NULL, OPT_HUGE_UNLINK_NUM },
77 : : {OPT_IOVA_MODE, 1, NULL, OPT_IOVA_MODE_NUM },
78 : : {OPT_LCORES, 1, NULL, OPT_LCORES_NUM },
79 : : {OPT_LOG_LEVEL, 1, NULL, OPT_LOG_LEVEL_NUM },
80 : : {OPT_TRACE, 1, NULL, OPT_TRACE_NUM },
81 : : {OPT_TRACE_DIR, 1, NULL, OPT_TRACE_DIR_NUM },
82 : : {OPT_TRACE_BUF_SIZE, 1, NULL, OPT_TRACE_BUF_SIZE_NUM },
83 : : {OPT_TRACE_MODE, 1, NULL, OPT_TRACE_MODE_NUM },
84 : : {OPT_MAIN_LCORE, 1, NULL, OPT_MAIN_LCORE_NUM },
85 : : {OPT_MBUF_POOL_OPS_NAME, 1, NULL, OPT_MBUF_POOL_OPS_NAME_NUM},
86 : : {OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM },
87 : : {OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM },
88 : : {OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM },
89 : : {OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM },
90 : : {OPT_IN_MEMORY, 0, NULL, OPT_IN_MEMORY_NUM },
91 : : {OPT_DEV_BLOCK, 1, NULL, OPT_DEV_BLOCK_NUM },
92 : : {OPT_DEV_ALLOW, 1, NULL, OPT_DEV_ALLOW_NUM },
93 : : {OPT_PROC_TYPE, 1, NULL, OPT_PROC_TYPE_NUM },
94 : : {OPT_SOCKET_MEM, 1, NULL, OPT_SOCKET_MEM_NUM },
95 : : {OPT_SOCKET_LIMIT, 1, NULL, OPT_SOCKET_LIMIT_NUM },
96 : : {OPT_SYSLOG, 1, NULL, OPT_SYSLOG_NUM },
97 : : {OPT_VDEV, 1, NULL, OPT_VDEV_NUM },
98 : : {OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM },
99 : : {OPT_VFIO_VF_TOKEN, 1, NULL, OPT_VFIO_VF_TOKEN_NUM },
100 : : {OPT_VMWARE_TSC_MAP, 0, NULL, OPT_VMWARE_TSC_MAP_NUM },
101 : : {OPT_LEGACY_MEM, 0, NULL, OPT_LEGACY_MEM_NUM },
102 : : {OPT_SINGLE_FILE_SEGMENTS, 0, NULL, OPT_SINGLE_FILE_SEGMENTS_NUM},
103 : : {OPT_MATCH_ALLOCATIONS, 0, NULL, OPT_MATCH_ALLOCATIONS_NUM},
104 : : {OPT_TELEMETRY, 0, NULL, OPT_TELEMETRY_NUM },
105 : : {OPT_NO_TELEMETRY, 0, NULL, OPT_NO_TELEMETRY_NUM },
106 : : {OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM},
107 : : {OPT_HUGE_WORKER_STACK, 2, NULL, OPT_HUGE_WORKER_STACK_NUM },
108 : :
109 : : {0, 0, NULL, 0 }
110 : : };
111 : :
112 : : TAILQ_HEAD(shared_driver_list, shared_driver);
113 : :
114 : : /* Definition for shared object drivers. */
115 : : struct shared_driver {
116 : : TAILQ_ENTRY(shared_driver) next;
117 : :
118 : : char name[PATH_MAX];
119 : : void* lib_handle;
120 : : };
121 : :
122 : : /* List of external loadable drivers */
123 : : static struct shared_driver_list solib_list =
124 : : TAILQ_HEAD_INITIALIZER(solib_list);
125 : :
126 : : #ifndef RTE_EXEC_ENV_WINDOWS
127 : : /* Default path of external loadable drivers */
128 : : static const char *default_solib_dir = RTE_EAL_PMD_PATH;
129 : : #endif
130 : :
131 : : /*
132 : : * Stringified version of solib path used by dpdk-pmdinfo.py
133 : : * Note: PLEASE DO NOT ALTER THIS without making a corresponding
134 : : * change to usertools/dpdk-pmdinfo.py
135 : : */
136 : : static const char dpdk_solib_path[] __rte_used =
137 : : "DPDK_PLUGIN_PATH=" RTE_EAL_PMD_PATH;
138 : :
139 : : TAILQ_HEAD(device_option_list, device_option);
140 : :
141 : : struct device_option {
142 : : TAILQ_ENTRY(device_option) next;
143 : :
144 : : enum rte_devtype type;
145 : : char arg[];
146 : : };
147 : :
148 : : static struct device_option_list devopt_list =
149 : : TAILQ_HEAD_INITIALIZER(devopt_list);
150 : :
151 : : static int main_lcore_parsed;
152 : : static int mem_parsed;
153 : : static int core_parsed;
154 : :
155 : : /* Allow the application to print its usage message too if set */
156 : : static rte_usage_hook_t rte_application_usage_hook;
157 : :
158 : : /* Returns rte_usage_hook_t */
159 : : rte_usage_hook_t
160 : 52 : eal_get_application_usage_hook(void)
161 : : {
162 : 52 : return rte_application_usage_hook;
163 : : }
164 : :
165 : : /* Set a per-application usage message */
166 : : rte_usage_hook_t
167 : 2 : rte_set_application_usage_hook(rte_usage_hook_t usage_func)
168 : : {
169 : : rte_usage_hook_t old_func;
170 : :
171 : : /* Will be NULL on the first call to denote the last usage routine. */
172 : 2 : old_func = rte_application_usage_hook;
173 : 2 : rte_application_usage_hook = usage_func;
174 : :
175 : 2 : return old_func;
176 : : }
177 : :
178 : : #ifndef RTE_EXEC_ENV_WINDOWS
179 : : static char **eal_args;
180 : : static char **eal_app_args;
181 : :
182 : : #define EAL_PARAM_REQ "/eal/params"
183 : : #define EAL_APP_PARAM_REQ "/eal/app_params"
184 : :
185 : : /* callback handler for telemetry library to report out EAL flags */
186 : : int
187 : 0 : handle_eal_info_request(const char *cmd, const char *params __rte_unused,
188 : : struct rte_tel_data *d)
189 : : {
190 : : char **args;
191 : : int used = 0;
192 : : int i = 0;
193 : :
194 [ # # ]: 0 : if (strcmp(cmd, EAL_PARAM_REQ) == 0)
195 : 0 : args = eal_args;
196 : : else
197 : 0 : args = eal_app_args;
198 : :
199 : 0 : rte_tel_data_start_array(d, RTE_TEL_STRING_VAL);
200 [ # # # # ]: 0 : if (args == NULL || args[0] == NULL)
201 : : return 0;
202 : :
203 [ # # ]: 0 : for ( ; args[i] != NULL; i++)
204 : 0 : used = rte_tel_data_add_array_string(d, args[i]);
205 : : return used;
206 : : }
207 : :
208 : : int
209 : 235 : eal_save_args(int argc, char **argv)
210 : : {
211 : : int i, j;
212 : :
213 : 235 : rte_telemetry_register_cmd(EAL_PARAM_REQ, handle_eal_info_request,
214 : : "Returns EAL commandline parameters used. Takes no parameters");
215 : 235 : rte_telemetry_register_cmd(EAL_APP_PARAM_REQ, handle_eal_info_request,
216 : : "Returns app commandline parameters used. Takes no parameters");
217 : :
218 : : /* clone argv to report out later. We overprovision, but
219 : : * this does not waste huge amounts of memory
220 : : */
221 : 235 : eal_args = calloc(argc + 1, sizeof(*eal_args));
222 [ + - ]: 235 : if (eal_args == NULL)
223 : : return -1;
224 : :
225 [ + + ]: 1187 : for (i = 0; i < argc; i++) {
226 [ + - ]: 952 : if (strcmp(argv[i], "--") == 0)
227 : : break;
228 : 952 : eal_args[i] = strdup(argv[i]);
229 : : }
230 : 235 : eal_args[i++] = NULL; /* always finish with NULL */
231 : :
232 : : /* allow reporting of any app args we know about too */
233 [ - + ]: 235 : if (i >= argc)
234 : : return 0;
235 : :
236 : 0 : eal_app_args = calloc(argc - i + 1, sizeof(*eal_args));
237 [ # # ]: 0 : if (eal_app_args == NULL)
238 : : return -1;
239 : :
240 [ # # ]: 0 : for (j = 0; i < argc; j++, i++)
241 : 0 : eal_app_args[j] = strdup(argv[i]);
242 : 0 : eal_app_args[j] = NULL;
243 : :
244 : 0 : return 0;
245 : : }
246 : : #endif
247 : :
248 : : static int
249 : 28 : eal_option_device_add(enum rte_devtype type, const char *optarg)
250 : : {
251 : : struct device_option *devopt;
252 : : size_t optlen;
253 : : int ret;
254 : :
255 : 28 : optlen = strlen(optarg) + 1;
256 : 28 : devopt = calloc(1, sizeof(*devopt) + optlen);
257 [ - + ]: 28 : if (devopt == NULL) {
258 : 0 : EAL_LOG(ERR, "Unable to allocate device option");
259 : 0 : return -ENOMEM;
260 : : }
261 : :
262 : 28 : devopt->type = type;
263 [ - + ]: 28 : ret = strlcpy(devopt->arg, optarg, optlen);
264 [ - + ]: 28 : if (ret < 0) {
265 : 0 : EAL_LOG(ERR, "Unable to copy device option");
266 : 0 : free(devopt);
267 : 0 : return -EINVAL;
268 : : }
269 : 28 : TAILQ_INSERT_TAIL(&devopt_list, devopt, next);
270 : 28 : return 0;
271 : : }
272 : :
273 : : int
274 : 183 : eal_option_device_parse(void)
275 : : {
276 : : struct device_option *devopt;
277 : : void *tmp;
278 : : int ret = 0;
279 : :
280 [ + + ]: 211 : RTE_TAILQ_FOREACH_SAFE(devopt, &devopt_list, next, tmp) {
281 [ + - ]: 28 : if (ret == 0) {
282 : 28 : ret = rte_devargs_add(devopt->type, devopt->arg);
283 [ + + ]: 28 : if (ret)
284 : 13 : EAL_LOG(ERR, "Unable to parse device '%s'",
285 : : devopt->arg);
286 : : }
287 [ + + ]: 28 : TAILQ_REMOVE(&devopt_list, devopt, next);
288 : 28 : free(devopt);
289 : : }
290 : 183 : return ret;
291 : : }
292 : :
293 : : const char *
294 : 8698 : eal_get_hugefile_prefix(void)
295 : : {
296 : : const struct internal_config *internal_conf =
297 : 8698 : eal_get_internal_configuration();
298 : :
299 [ + + ]: 8698 : if (internal_conf->hugefile_prefix != NULL)
300 : 5423 : return internal_conf->hugefile_prefix;
301 : : return HUGEFILE_PREFIX_DEFAULT;
302 : : }
303 : :
304 : : void
305 : 235 : eal_reset_internal_config(struct internal_config *internal_cfg)
306 : : {
307 : : int i;
308 : :
309 : 235 : internal_cfg->memory = 0;
310 : 235 : internal_cfg->force_nrank = 0;
311 : 235 : internal_cfg->force_nchannel = 0;
312 : 235 : internal_cfg->hugefile_prefix = NULL;
313 : 235 : internal_cfg->hugepage_dir = NULL;
314 : 235 : internal_cfg->hugepage_file.unlink_before_mapping = false;
315 : 235 : internal_cfg->hugepage_file.unlink_existing = true;
316 : 235 : internal_cfg->force_sockets = 0;
317 : : /* zero out the NUMA config */
318 [ + + ]: 7755 : for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
319 : 7520 : internal_cfg->socket_mem[i] = 0;
320 : 235 : internal_cfg->force_socket_limits = 0;
321 : : /* zero out the NUMA limits config */
322 [ + + ]: 7755 : for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
323 : 7520 : internal_cfg->socket_limit[i] = 0;
324 : : /* zero out hugedir descriptors */
325 [ + + ]: 940 : for (i = 0; i < MAX_HUGEPAGE_SIZES; i++) {
326 : 705 : memset(&internal_cfg->hugepage_info[i], 0,
327 : : sizeof(internal_cfg->hugepage_info[0]));
328 : 705 : internal_cfg->hugepage_info[i].lock_descriptor = -1;
329 : : }
330 : 235 : internal_cfg->base_virtaddr = 0;
331 : :
332 : : #ifdef LOG_DAEMON
333 : 235 : internal_cfg->syslog_facility = LOG_DAEMON;
334 : : #endif
335 : :
336 : : /* if set to NONE, interrupt mode is determined automatically */
337 : 235 : internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
338 : 235 : memset(internal_cfg->vfio_vf_token, 0,
339 : : sizeof(internal_cfg->vfio_vf_token));
340 : :
341 : : #ifdef RTE_LIBEAL_USE_HPET
342 : : internal_cfg->no_hpet = 0;
343 : : #else
344 : 235 : internal_cfg->no_hpet = 1;
345 : : #endif
346 : 235 : internal_cfg->vmware_tsc_map = 0;
347 : 235 : internal_cfg->create_uio_dev = 0;
348 : 235 : internal_cfg->iova_mode = RTE_IOVA_DC;
349 : 235 : internal_cfg->user_mbuf_pool_ops_name = NULL;
350 : 235 : CPU_ZERO(&internal_cfg->ctrl_cpuset);
351 : 235 : internal_cfg->init_complete = 0;
352 : 235 : internal_cfg->max_simd_bitwidth.bitwidth = RTE_VECT_DEFAULT_SIMD_BITWIDTH;
353 : 235 : internal_cfg->max_simd_bitwidth.forced = 0;
354 : 235 : }
355 : :
356 : : static int
357 : 0 : eal_plugin_add(const char *path)
358 : : {
359 : : struct shared_driver *solib;
360 : :
361 : 0 : solib = malloc(sizeof(*solib));
362 [ # # ]: 0 : if (solib == NULL) {
363 : 0 : EAL_LOG(ERR, "malloc(solib) failed");
364 : 0 : return -1;
365 : : }
366 : : memset(solib, 0, sizeof(*solib));
367 : 0 : strlcpy(solib->name, path, PATH_MAX);
368 : 0 : TAILQ_INSERT_TAIL(&solib_list, solib, next);
369 : :
370 : 0 : return 0;
371 : : }
372 : :
373 : : #ifdef RTE_EXEC_ENV_WINDOWS
374 : : int
375 : : eal_plugins_init(void)
376 : : {
377 : : return 0;
378 : : }
379 : : #else
380 : :
381 : : static int
382 : 0 : eal_plugindir_init(const char *path)
383 : : {
384 : : DIR *d = NULL;
385 : : struct dirent *dent = NULL;
386 : : char sopath[PATH_MAX];
387 : :
388 [ # # # # ]: 0 : if (path == NULL || *path == '\0')
389 : : return 0;
390 : :
391 : 0 : d = opendir(path);
392 [ # # ]: 0 : if (d == NULL) {
393 : 0 : EAL_LOG(ERR, "failed to open directory %s: %s",
394 : : path, strerror(errno));
395 : 0 : return -1;
396 : : }
397 : :
398 [ # # ]: 0 : while ((dent = readdir(d)) != NULL) {
399 : : struct stat sb;
400 : 0 : int nlen = strnlen(dent->d_name, sizeof(dent->d_name));
401 : :
402 : : /* check if name ends in .so or .so.ABI_VERSION */
403 [ # # ]: 0 : if (strcmp(&dent->d_name[nlen - 3], ".so") != 0 &&
404 [ # # ]: 0 : strcmp(&dent->d_name[nlen - 4 - strlen(ABI_VERSION)],
405 : : ".so."ABI_VERSION) != 0)
406 : 0 : continue;
407 : :
408 : : snprintf(sopath, sizeof(sopath), "%s/%s", path, dent->d_name);
409 : :
410 : : /* if a regular file, add to list to load */
411 [ # # # # ]: 0 : if (!(stat(sopath, &sb) == 0 && S_ISREG(sb.st_mode)))
412 : 0 : continue;
413 : :
414 [ # # ]: 0 : if (eal_plugin_add(sopath) == -1)
415 : : break;
416 : : }
417 : :
418 : 0 : closedir(d);
419 : : /* XXX this ignores failures from readdir() itself */
420 [ # # ]: 0 : return (dent == NULL) ? 0 : -1;
421 : : }
422 : :
423 : : static int
424 : 0 : verify_perms(const char *dirpath)
425 : : {
426 : : struct stat st;
427 : :
428 : : /* if not root, check down one level first */
429 [ # # ]: 0 : if (strcmp(dirpath, "/") != 0) {
430 : : static __thread char last_dir_checked[PATH_MAX];
431 : : char copy[PATH_MAX];
432 : : const char *dir;
433 : :
434 : : strlcpy(copy, dirpath, PATH_MAX);
435 : 0 : dir = dirname(copy);
436 [ # # ]: 0 : if (strncmp(dir, last_dir_checked, PATH_MAX) != 0) {
437 [ # # ]: 0 : if (verify_perms(dir) != 0)
438 : 0 : return -1;
439 : : strlcpy(last_dir_checked, dir, PATH_MAX);
440 : : }
441 : : }
442 : :
443 : : /* call stat to check for permissions and ensure not world writable */
444 [ # # ]: 0 : if (stat(dirpath, &st) != 0) {
445 : 0 : EAL_LOG(ERR, "Error with stat on %s, %s",
446 : : dirpath, strerror(errno));
447 : 0 : return -1;
448 : : }
449 [ # # ]: 0 : if (st.st_mode & S_IWOTH) {
450 : 0 : EAL_LOG(ERR,
451 : : "Error, directory path %s is world-writable and insecure",
452 : : dirpath);
453 : 0 : return -1;
454 : : }
455 : :
456 : : return 0;
457 : : }
458 : :
459 : : static void *
460 [ # # ]: 0 : eal_dlopen(const char *pathname)
461 : : {
462 : : void *retval = NULL;
463 : : char *realp = realpath(pathname, NULL);
464 : :
465 [ # # # # ]: 0 : if (realp == NULL && errno == ENOENT) {
466 : : /* not a full or relative path, try a load from system dirs */
467 : 0 : retval = dlopen(pathname, RTLD_NOW);
468 [ # # ]: 0 : if (retval == NULL)
469 : 0 : EAL_LOG(ERR, "%s", dlerror());
470 : 0 : return retval;
471 : : }
472 [ # # ]: 0 : if (realp == NULL) {
473 : 0 : EAL_LOG(ERR, "Error with realpath for %s, %s",
474 : : pathname, strerror(errno));
475 : 0 : goto out;
476 : : }
477 [ # # ]: 0 : if (strnlen(realp, PATH_MAX) == PATH_MAX) {
478 : 0 : EAL_LOG(ERR, "Error, driver path greater than PATH_MAX");
479 : 0 : goto out;
480 : : }
481 : :
482 : : /* do permissions checks */
483 [ # # ]: 0 : if (verify_perms(realp) != 0)
484 : 0 : goto out;
485 : :
486 : 0 : retval = dlopen(realp, RTLD_NOW);
487 [ # # ]: 0 : if (retval == NULL)
488 : 0 : EAL_LOG(ERR, "%s", dlerror());
489 : 0 : out:
490 : 0 : free(realp);
491 : 0 : return retval;
492 : : }
493 : :
494 : : static int
495 [ - + ]: 183 : is_shared_build(void)
496 : : {
497 : : #define EAL_SO "librte_eal.so"
498 : : char soname[32];
499 : : size_t len, minlen = strlen(EAL_SO);
500 : :
501 : : len = strlcpy(soname, EAL_SO"."ABI_VERSION, sizeof(soname));
502 [ - + ]: 183 : if (len > sizeof(soname)) {
503 : 0 : EAL_LOG(ERR, "Shared lib name too long in shared build check");
504 : : len = sizeof(soname) - 1;
505 : : }
506 : :
507 [ + + ]: 732 : while (len >= minlen) {
508 : : void *handle;
509 : :
510 : : /* check if we have this .so loaded, if so - shared build */
511 : 549 : EAL_LOG(DEBUG, "Checking presence of .so '%s'", soname);
512 : 549 : handle = dlopen(soname, RTLD_LAZY | RTLD_NOLOAD);
513 [ - + ]: 549 : if (handle != NULL) {
514 : 0 : EAL_LOG(INFO, "Detected shared linkage of DPDK");
515 : 0 : dlclose(handle);
516 : 0 : return 1;
517 : : }
518 : :
519 : : /* remove any version numbers off the end to retry */
520 [ + - ]: 1464 : while (len-- > 0)
521 [ + + ]: 1464 : if (soname[len] == '.') {
522 : 549 : soname[len] = '\0';
523 : 549 : break;
524 : : }
525 : : }
526 : :
527 : 183 : EAL_LOG(INFO, "Detected static linkage of DPDK");
528 : 183 : return 0;
529 : : }
530 : :
531 : : int
532 : 183 : eal_plugins_init(void)
533 : : {
534 : : struct shared_driver *solib = NULL;
535 : : struct stat sb;
536 : :
537 : : /* If we are not statically linked, add default driver loading
538 : : * path if it exists as a directory.
539 : : * (Using dlopen with NOLOAD flag on EAL, will return NULL if the EAL
540 : : * shared library is not already loaded i.e. it's statically linked.)
541 : : */
542 [ - + ]: 183 : if (is_shared_build() &&
543 [ # # # # ]: 0 : *default_solib_dir != '\0' &&
544 : 0 : stat(default_solib_dir, &sb) == 0 &&
545 [ # # ]: 0 : S_ISDIR(sb.st_mode))
546 : 0 : eal_plugin_add(default_solib_dir);
547 : :
548 [ - + ]: 183 : TAILQ_FOREACH(solib, &solib_list, next) {
549 : :
550 [ # # # # ]: 0 : if (stat(solib->name, &sb) == 0 && S_ISDIR(sb.st_mode)) {
551 [ # # ]: 0 : if (eal_plugindir_init(solib->name) == -1) {
552 : 0 : EAL_LOG(ERR,
553 : : "Cannot init plugin directory %s",
554 : : solib->name);
555 : 0 : return -1;
556 : : }
557 : : } else {
558 : 0 : EAL_LOG(DEBUG, "open shared lib %s",
559 : : solib->name);
560 : 0 : solib->lib_handle = eal_dlopen(solib->name);
561 [ # # ]: 0 : if (solib->lib_handle == NULL)
562 : : return -1;
563 : : }
564 : :
565 : : }
566 : : return 0;
567 : : }
568 : : #endif
569 : :
570 : : /*
571 : : * Parse the coremask given as argument (hexadecimal string) and fill
572 : : * the global configuration (core role and core count) with the parsed
573 : : * value.
574 : : */
575 : 12 : static int xdigit2val(unsigned char c)
576 : : {
577 : : int val;
578 : :
579 [ + - ]: 12 : if (isdigit(c))
580 : 12 : val = c - '0';
581 [ # # ]: 0 : else if (isupper(c))
582 : 0 : val = c - 'A' + 10;
583 : : else
584 : 0 : val = c - 'a' + 10;
585 : 12 : return val;
586 : : }
587 : :
588 : : static int
589 : 0 : eal_parse_service_coremask(const char *coremask)
590 : : {
591 : 0 : struct rte_config *cfg = rte_eal_get_configuration();
592 : : int i, j, idx = 0;
593 : : unsigned int count = 0;
594 : : char c;
595 : : int val;
596 : : uint32_t taken_lcore_count = 0;
597 : :
598 [ # # ]: 0 : if (coremask == NULL)
599 : : return -1;
600 : : /* Remove all blank characters ahead and after .
601 : : * Remove 0x/0X if exists.
602 : : */
603 [ # # ]: 0 : while (isblank(*coremask))
604 : 0 : coremask++;
605 [ # # ]: 0 : if (coremask[0] == '0' && ((coremask[1] == 'x')
606 [ # # ]: 0 : || (coremask[1] == 'X')))
607 : 0 : coremask += 2;
608 : 0 : i = strlen(coremask);
609 [ # # # # ]: 0 : while ((i > 0) && isblank(coremask[i - 1]))
610 : 0 : i--;
611 : :
612 [ # # ]: 0 : if (i == 0)
613 : : return -1;
614 : :
615 [ # # ]: 0 : for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
616 : 0 : c = coremask[i];
617 [ # # ]: 0 : if (isxdigit(c) == 0) {
618 : : /* invalid characters */
619 : : return -1;
620 : : }
621 : 0 : val = xdigit2val(c);
622 [ # # ]: 0 : for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE;
623 : 0 : j++, idx++) {
624 [ # # ]: 0 : if ((1 << j) & val) {
625 : : /* handle main lcore already parsed */
626 : 0 : uint32_t lcore = idx;
627 [ # # ]: 0 : if (main_lcore_parsed &&
628 [ # # ]: 0 : cfg->main_lcore == lcore) {
629 : 0 : EAL_LOG(ERR,
630 : : "lcore %u is main lcore, cannot use as service core",
631 : : idx);
632 : 0 : return -1;
633 : : }
634 : :
635 [ # # ]: 0 : if (eal_cpu_detected(idx) == 0) {
636 : 0 : EAL_LOG(ERR,
637 : : "lcore %u unavailable", idx);
638 : 0 : return -1;
639 : : }
640 : :
641 [ # # ]: 0 : if (cfg->lcore_role[idx] == ROLE_RTE)
642 : 0 : taken_lcore_count++;
643 : :
644 : 0 : lcore_config[idx].core_role = ROLE_SERVICE;
645 : 0 : count++;
646 : : }
647 : : }
648 : : }
649 : :
650 [ # # ]: 0 : for (; i >= 0; i--)
651 [ # # ]: 0 : if (coremask[i] != '0')
652 : : return -1;
653 : :
654 [ # # ]: 0 : for (; idx < RTE_MAX_LCORE; idx++)
655 : 0 : lcore_config[idx].core_index = -1;
656 : :
657 [ # # ]: 0 : if (count == 0)
658 : : return -1;
659 : :
660 [ # # # # ]: 0 : if (core_parsed && taken_lcore_count != count) {
661 : 0 : EAL_LOG(WARNING,
662 : : "Not all service cores are in the coremask. "
663 : : "Please ensure -c or -l includes service cores");
664 : : }
665 : :
666 : 0 : cfg->service_lcore_count = count;
667 : 0 : return 0;
668 : : }
669 : :
670 : : static int
671 : : eal_service_cores_parsed(void)
672 : : {
673 : : int idx;
674 [ + + + + ]: 2838 : for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
675 [ + - + - ]: 2816 : if (lcore_config[idx].core_role == ROLE_SERVICE)
676 : : return 1;
677 : : }
678 : : return 0;
679 : : }
680 : :
681 : : static int
682 : 12 : update_lcore_config(int *cores)
683 : : {
684 : 12 : struct rte_config *cfg = rte_eal_get_configuration();
685 : : unsigned int count = 0;
686 : : unsigned int i;
687 : : int ret = 0;
688 : :
689 [ + + ]: 1548 : for (i = 0; i < RTE_MAX_LCORE; i++) {
690 [ + + ]: 1536 : if (cores[i] != -1) {
691 [ - + ]: 18 : if (eal_cpu_detected(i) == 0) {
692 : 0 : EAL_LOG(ERR, "lcore %u unavailable", i);
693 : : ret = -1;
694 : 0 : continue;
695 : : }
696 : 18 : cfg->lcore_role[i] = ROLE_RTE;
697 : 18 : count++;
698 : : } else {
699 : 1518 : cfg->lcore_role[i] = ROLE_OFF;
700 : : }
701 : 1536 : lcore_config[i].core_index = cores[i];
702 : : }
703 [ + - ]: 12 : if (!ret)
704 : 12 : cfg->lcore_count = count;
705 : 12 : return ret;
706 : : }
707 : :
708 : : static int
709 : 14 : check_core_list(int *lcores, unsigned int count)
710 : : {
711 : : char lcorestr[RTE_MAX_LCORE * 10];
712 : : bool overflow = false;
713 : : int len = 0, ret;
714 : : unsigned int i;
715 : :
716 [ + + ]: 161 : for (i = 0; i < count; i++) {
717 [ + + ]: 147 : if (lcores[i] < RTE_MAX_LCORE)
718 : 145 : continue;
719 : :
720 : 2 : EAL_LOG(ERR, "lcore %d >= RTE_MAX_LCORE (%d)",
721 : : lcores[i], RTE_MAX_LCORE);
722 : : overflow = true;
723 : : }
724 [ + + ]: 14 : if (!overflow)
725 : : return 0;
726 : :
727 : : /*
728 : : * We've encountered a core that's greater than RTE_MAX_LCORE,
729 : : * suggest using --lcores option to map lcores onto physical cores
730 : : * greater than RTE_MAX_LCORE.
731 : : */
732 [ + + ]: 131 : for (i = 0; i < count; i++) {
733 : 129 : ret = snprintf(&lcorestr[len], sizeof(lcorestr) - len,
734 [ + - ]: 129 : "%d@%d,", i, lcores[i]);
735 [ + - ]: 129 : if (ret > 0)
736 : 129 : len = len + ret;
737 : : }
738 [ + - ]: 2 : if (len > 0)
739 : 2 : lcorestr[len - 1] = 0;
740 : 2 : EAL_LOG(ERR, "To use high physical core ids, "
741 : : "please use --lcores to map them to lcore ids below RTE_MAX_LCORE, "
742 : : "e.g. --lcores %s", lcorestr);
743 : 2 : return -1;
744 : : }
745 : :
746 : : int
747 : 13 : rte_eal_parse_coremask(const char *coremask, int *cores)
748 : : {
749 : : const char *coremask_orig = coremask;
750 : : int lcores[RTE_MAX_LCORE];
751 : : unsigned int count = 0;
752 : : int i, j, idx;
753 : : int val;
754 : : char c;
755 : :
756 [ + + ]: 1677 : for (idx = 0; idx < RTE_MAX_LCORE; idx++)
757 : 1664 : cores[idx] = -1;
758 : : idx = 0;
759 : :
760 : : /* Remove all blank characters ahead and after .
761 : : * Remove 0x/0X if exists.
762 : : */
763 [ - + ]: 13 : while (isblank(*coremask))
764 : 0 : coremask++;
765 [ - + ]: 13 : if (coremask[0] == '0' && ((coremask[1] == 'x')
766 [ # # ]: 0 : || (coremask[1] == 'X')))
767 : 0 : coremask += 2;
768 : 13 : i = strlen(coremask);
769 [ + - - + ]: 13 : while ((i > 0) && isblank(coremask[i - 1]))
770 : 0 : i--;
771 [ - + ]: 13 : if (i == 0) {
772 : 0 : EAL_LOG(ERR, "No lcores in coremask: [%s]",
773 : : coremask_orig);
774 : 0 : return -1;
775 : : }
776 : :
777 [ + + ]: 25 : for (i = i - 1; i >= 0; i--) {
778 : 13 : c = coremask[i];
779 [ + + ]: 13 : if (isxdigit(c) == 0) {
780 : : /* invalid characters */
781 : 1 : EAL_LOG(ERR, "invalid characters in coremask: [%s]",
782 : : coremask_orig);
783 : 1 : return -1;
784 : : }
785 : 12 : val = xdigit2val(c);
786 [ + + ]: 60 : for (j = 0; j < BITS_PER_HEX; j++, idx++)
787 : : {
788 [ + + ]: 48 : if ((1 << j) & val) {
789 [ - + ]: 18 : if (count >= RTE_MAX_LCORE) {
790 : 0 : EAL_LOG(ERR, "Too many lcores provided. Cannot exceed RTE_MAX_LCORE (%d)",
791 : : RTE_MAX_LCORE);
792 : 0 : return -1;
793 : : }
794 : 18 : lcores[count++] = idx;
795 : : }
796 : : }
797 : : }
798 [ - + ]: 12 : if (count == 0) {
799 : 0 : EAL_LOG(ERR, "No lcores in coremask: [%s]",
800 : : coremask_orig);
801 : 0 : return -1;
802 : : }
803 : :
804 [ + - ]: 12 : if (check_core_list(lcores, count))
805 : : return -1;
806 : :
807 : : /*
808 : : * Now that we've got a list of cores no longer than RTE_MAX_LCORE,
809 : : * and no lcore in that list is greater than RTE_MAX_LCORE, populate
810 : : * the cores array.
811 : : */
812 : : do {
813 : 18 : count--;
814 : 18 : cores[lcores[count]] = count;
815 [ + + ]: 18 : } while (count != 0);
816 : :
817 : : return 0;
818 : : }
819 : :
820 : : static int
821 : 0 : eal_parse_service_corelist(const char *corelist)
822 : : {
823 : 0 : struct rte_config *cfg = rte_eal_get_configuration();
824 : : int i;
825 : : unsigned count = 0;
826 : 0 : char *end = NULL;
827 : : uint32_t min, max, idx;
828 : : uint32_t taken_lcore_count = 0;
829 : :
830 [ # # ]: 0 : if (corelist == NULL)
831 : : return -1;
832 : :
833 : : /* Remove all blank characters ahead and after */
834 [ # # ]: 0 : while (isblank(*corelist))
835 : 0 : corelist++;
836 : : i = strlen(corelist);
837 : : while ((i > 0) && isblank(corelist[i - 1]))
838 : : i--;
839 : :
840 : : /* Get list of cores */
841 : : min = RTE_MAX_LCORE;
842 : : do {
843 [ # # ]: 0 : while (isblank(*corelist))
844 : 0 : corelist++;
845 [ # # ]: 0 : if (*corelist == '\0')
846 : : return -1;
847 : 0 : errno = 0;
848 : 0 : idx = strtoul(corelist, &end, 10);
849 [ # # # # ]: 0 : if (errno || end == NULL)
850 : : return -1;
851 [ # # ]: 0 : if (idx >= RTE_MAX_LCORE)
852 : : return -1;
853 [ # # ]: 0 : while (isblank(*end))
854 : 0 : end++;
855 [ # # ]: 0 : if (*end == '-') {
856 : : min = idx;
857 [ # # ]: 0 : } else if ((*end == ',') || (*end == '\0')) {
858 : : max = idx;
859 [ # # ]: 0 : if (min == RTE_MAX_LCORE)
860 : : min = idx;
861 [ # # ]: 0 : for (idx = min; idx <= max; idx++) {
862 [ # # ]: 0 : if (cfg->lcore_role[idx] != ROLE_SERVICE) {
863 : : /* handle main lcore already parsed */
864 : : uint32_t lcore = idx;
865 [ # # # # ]: 0 : if (cfg->main_lcore == lcore &&
866 : : main_lcore_parsed) {
867 : 0 : EAL_LOG(ERR,
868 : : "Error: lcore %u is main lcore, cannot use as service core",
869 : : idx);
870 : 0 : return -1;
871 : : }
872 [ # # ]: 0 : if (cfg->lcore_role[idx] == ROLE_RTE)
873 : 0 : taken_lcore_count++;
874 : :
875 : 0 : lcore_config[idx].core_role =
876 : : ROLE_SERVICE;
877 : 0 : count++;
878 : : }
879 : : }
880 : : min = RTE_MAX_LCORE;
881 : : } else
882 : : return -1;
883 : 0 : corelist = end + 1;
884 [ # # ]: 0 : } while (*end != '\0');
885 : :
886 [ # # ]: 0 : if (count == 0)
887 : : return -1;
888 : :
889 [ # # # # ]: 0 : if (core_parsed && taken_lcore_count != count) {
890 : 0 : EAL_LOG(WARNING,
891 : : "Not all service cores were in the coremask. "
892 : : "Please ensure -c or -l includes service cores");
893 : : }
894 : :
895 : : return 0;
896 : : }
897 : :
898 : : static int
899 : 9 : eal_parse_corelist(const char *corelist, int *cores)
900 : : {
901 : : unsigned int count = 0, i;
902 : : int lcores[RTE_MAX_LCORE];
903 : 9 : char *end = NULL;
904 : : int min, max;
905 : : int idx;
906 : :
907 [ + + ]: 1161 : for (idx = 0; idx < RTE_MAX_LCORE; idx++)
908 : 1152 : cores[idx] = -1;
909 : :
910 : : /* Remove all blank characters ahead */
911 [ + + ]: 10 : while (isblank(*corelist))
912 : 1 : corelist++;
913 : :
914 : : /* Get list of cores */
915 : : min = -1;
916 : : do {
917 [ - + ]: 12 : while (isblank(*corelist))
918 : 0 : corelist++;
919 [ + + ]: 12 : if (*corelist == '\0')
920 : : return -1;
921 : 9 : errno = 0;
922 : 9 : idx = strtol(corelist, &end, 10);
923 [ + - + - ]: 9 : if (errno || end == NULL)
924 : : return -1;
925 [ + + ]: 9 : if (idx < 0)
926 : : return -1;
927 [ - + ]: 7 : while (isblank(*end))
928 : 0 : end++;
929 [ + + ]: 7 : if (*end == '-') {
930 : : min = idx;
931 [ + + ]: 5 : } else if ((*end == ',') || (*end == '\0')) {
932 : : max = idx;
933 [ + + ]: 3 : if (min == -1)
934 : : min = idx;
935 [ + + ]: 133 : for (idx = min; idx <= max; idx++) {
936 : : bool dup = false;
937 : :
938 : : /* Check if this idx is already present */
939 [ + + ]: 8258 : for (i = 0; i < count; i++) {
940 [ - + ]: 8128 : if (lcores[i] == idx)
941 : : dup = true;
942 : : }
943 [ - + ]: 130 : if (dup)
944 : 0 : continue;
945 [ - + ]: 130 : if (count >= RTE_MAX_LCORE) {
946 : 0 : EAL_LOG(ERR, "Too many lcores provided. Cannot exceed RTE_MAX_LCORE (%d)",
947 : : RTE_MAX_LCORE);
948 : 0 : return -1;
949 : : }
950 : 130 : lcores[count++] = idx;
951 : : }
952 : : min = -1;
953 : : } else
954 : : return -1;
955 : 5 : corelist = end + 1;
956 [ + + ]: 5 : } while (*end != '\0');
957 : :
958 [ + - ]: 2 : if (count == 0)
959 : : return -1;
960 : :
961 [ - + ]: 2 : if (check_core_list(lcores, count))
962 : : return -1;
963 : :
964 : : /*
965 : : * Now that we've got a list of cores no longer than RTE_MAX_LCORE,
966 : : * and no lcore in that list is greater than RTE_MAX_LCORE, populate
967 : : * the cores array.
968 : : */
969 : : do {
970 : 0 : count--;
971 : 0 : cores[lcores[count]] = count;
972 [ # # ]: 0 : } while (count != 0);
973 : :
974 : : return 0;
975 : : }
976 : :
977 : : /* Changes the lcore id of the main thread */
978 : : static int
979 : 5 : eal_parse_main_lcore(const char *arg)
980 : : {
981 : : char *parsing_end;
982 : 5 : struct rte_config *cfg = rte_eal_get_configuration();
983 : :
984 : 5 : errno = 0;
985 : 5 : cfg->main_lcore = (uint32_t) strtol(arg, &parsing_end, 0);
986 [ + - + + ]: 5 : if (errno || parsing_end[0] != 0)
987 : : return -1;
988 [ + + ]: 4 : if (cfg->main_lcore >= RTE_MAX_LCORE)
989 : : return -1;
990 : 3 : main_lcore_parsed = 1;
991 : :
992 : : /* ensure main core is not used as service core */
993 [ - + ]: 3 : if (lcore_config[cfg->main_lcore].core_role == ROLE_SERVICE) {
994 : 0 : EAL_LOG(ERR,
995 : : "Error: Main lcore is used as a service core");
996 : 0 : return -1;
997 : : }
998 : :
999 : : return 0;
1000 : : }
1001 : :
1002 : : /*
1003 : : * Parse elem, the elem could be single number/range or '(' ')' group
1004 : : * 1) A single number elem, it's just a simple digit. e.g. 9
1005 : : * 2) A single range elem, two digits with a '-' between. e.g. 2-6
1006 : : * 3) A group elem, combines multiple 1) or 2) with '( )'. e.g (0,2-4,6)
1007 : : * Within group elem, '-' used for a range separator;
1008 : : * ',' used for a single number.
1009 : : */
1010 : : static int
1011 : 16 : eal_parse_set(const char *input, rte_cpuset_t *set)
1012 : : {
1013 : : unsigned idx;
1014 : : const char *str = input;
1015 : 16 : char *end = NULL;
1016 : : unsigned min, max;
1017 : :
1018 : 16 : CPU_ZERO(set);
1019 : :
1020 [ - + ]: 16 : while (isblank(*str))
1021 : 0 : str++;
1022 : :
1023 : : /* only digit or left bracket is qualify for start point */
1024 [ + + + + : 16 : if ((!isdigit(*str) && *str != '(') || *str == '\0')
+ - ]
1025 : : return -1;
1026 : :
1027 : : /* process single number or single range of number */
1028 [ + + ]: 14 : if (*str != '(') {
1029 : 6 : errno = 0;
1030 : 6 : idx = strtoul(str, &end, 10);
1031 [ + - + - : 6 : if (errno || end == NULL || idx >= CPU_SETSIZE)
+ + ]
1032 : : return -1;
1033 : : else {
1034 [ - + ]: 5 : while (isblank(*end))
1035 : 0 : end++;
1036 : :
1037 : : min = idx;
1038 : : max = idx;
1039 [ + + ]: 5 : if (*end == '-') {
1040 : : /* process single <number>-<number> */
1041 : 4 : end++;
1042 [ - + ]: 4 : while (isblank(*end))
1043 : 0 : end++;
1044 [ + + ]: 4 : if (!isdigit(*end))
1045 : : return -1;
1046 : :
1047 : 3 : errno = 0;
1048 : 3 : idx = strtoul(end, &end, 10);
1049 [ + - + - : 3 : if (errno || end == NULL || idx >= CPU_SETSIZE)
+ - ]
1050 : : return -1;
1051 : : max = idx;
1052 [ - + ]: 3 : while (isblank(*end))
1053 : 0 : end++;
1054 [ + + ]: 3 : if (*end != ',' && *end != '\0')
1055 : : return -1;
1056 : : }
1057 : :
1058 [ + + - + ]: 2 : if (*end != ',' && *end != '\0' &&
1059 : : *end != '@')
1060 : : return -1;
1061 : :
1062 : 1 : for (idx = RTE_MIN(min, max);
1063 [ + + ]: 3 : idx <= RTE_MAX(min, max); idx++)
1064 [ + - ]: 2 : CPU_SET(idx, set);
1065 : :
1066 : 1 : return end - input;
1067 : : }
1068 : : }
1069 : :
1070 : : /* process set within bracket */
1071 : 8 : str++;
1072 [ - + ]: 8 : while (isblank(*str))
1073 : 0 : str++;
1074 [ + - ]: 8 : if (*str == '\0')
1075 : : return -1;
1076 : :
1077 : : min = RTE_MAX_LCORE;
1078 : : do {
1079 : :
1080 : : /* go ahead to the first digit */
1081 [ - + ]: 13 : while (isblank(*str))
1082 : 0 : str++;
1083 [ + + ]: 13 : if (!isdigit(*str))
1084 : : return -1;
1085 : :
1086 : : /* get the digit value */
1087 : 9 : errno = 0;
1088 : 9 : idx = strtoul(str, &end, 10);
1089 [ + - + - : 9 : if (errno || end == NULL || idx >= CPU_SETSIZE)
+ - ]
1090 : : return -1;
1091 : :
1092 : : /* go ahead to separator '-',',' and ')' */
1093 [ - + ]: 9 : while (isblank(*end))
1094 : 0 : end++;
1095 [ + + ]: 9 : if (*end == '-') {
1096 [ + + ]: 4 : if (min == RTE_MAX_LCORE)
1097 : : min = idx;
1098 : : else /* avoid continuous '-' */
1099 : : return -1;
1100 [ + - ]: 5 : } else if ((*end == ',') || (*end == ')')) {
1101 : : max = idx;
1102 [ + + ]: 5 : if (min == RTE_MAX_LCORE)
1103 : : min = idx;
1104 : 5 : for (idx = RTE_MIN(min, max);
1105 [ + + ]: 13 : idx <= RTE_MAX(min, max); idx++)
1106 [ + - ]: 8 : CPU_SET(idx, set);
1107 : :
1108 : : min = RTE_MAX_LCORE;
1109 : : } else
1110 : : return -1;
1111 : :
1112 : 8 : str = end + 1;
1113 [ + + ]: 8 : } while (*end != '\0' && *end != ')');
1114 : :
1115 : : /*
1116 : : * to avoid failure that tail blank makes end character check fail
1117 : : * in eal_parse_lcores( )
1118 : : */
1119 [ - + ]: 3 : while (isblank(*str))
1120 : 0 : str++;
1121 : :
1122 : 3 : return str - input;
1123 : : }
1124 : :
1125 : : static int
1126 : 6 : check_cpuset(rte_cpuset_t *set)
1127 : : {
1128 : : unsigned int idx;
1129 : :
1130 [ + + ]: 6150 : for (idx = 0; idx < CPU_SETSIZE; idx++) {
1131 [ + + ]: 6144 : if (!CPU_ISSET(idx, set))
1132 : 6126 : continue;
1133 : :
1134 [ - + ]: 18 : if (eal_cpu_detected(idx) == 0) {
1135 : 0 : EAL_LOG(ERR, "core %u "
1136 : : "unavailable", idx);
1137 : 0 : return -1;
1138 : : }
1139 : : }
1140 : : return 0;
1141 : : }
1142 : :
1143 : : /*
1144 : : * The format pattern: --lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
1145 : : * lcores, cpus could be a single digit/range or a group.
1146 : : * '(' and ')' are necessary if it's a group.
1147 : : * If not supply '@cpus', the value of cpus uses the same as lcores.
1148 : : * e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means start 9 EAL thread as below
1149 : : * lcore 0 runs on cpuset 0x41 (cpu 0,6)
1150 : : * lcore 1 runs on cpuset 0x2 (cpu 1)
1151 : : * lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
1152 : : * lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
1153 : : * lcore 6 runs on cpuset 0x41 (cpu 0,6)
1154 : : * lcore 7 runs on cpuset 0x80 (cpu 7)
1155 : : * lcore 8 runs on cpuset 0x100 (cpu 8)
1156 : : */
1157 : : static int
1158 : 13 : eal_parse_lcores(const char *lcores)
1159 : : {
1160 : 13 : struct rte_config *cfg = rte_eal_get_configuration();
1161 : : rte_cpuset_t lcore_set;
1162 : : unsigned int set_count;
1163 : : unsigned idx = 0;
1164 : : unsigned count = 0;
1165 : : const char *lcore_start = NULL;
1166 : : const char *end = NULL;
1167 : : int offset;
1168 : : rte_cpuset_t cpuset;
1169 : : int lflags;
1170 : : int ret = -1;
1171 : :
1172 [ + - ]: 13 : if (lcores == NULL)
1173 : : return -1;
1174 : :
1175 : : /* Remove all blank characters ahead and after */
1176 [ + + ]: 14 : while (isblank(*lcores))
1177 : 1 : lcores++;
1178 : :
1179 : 13 : CPU_ZERO(&cpuset);
1180 : :
1181 : : /* Reset lcore config */
1182 [ + + ]: 1677 : for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
1183 : 1664 : cfg->lcore_role[idx] = ROLE_OFF;
1184 : 1664 : lcore_config[idx].core_index = -1;
1185 : 1664 : CPU_ZERO(&lcore_config[idx].cpuset);
1186 : : }
1187 : :
1188 : : /* Get list of cores */
1189 : : do {
1190 [ - + ]: 15 : while (isblank(*lcores))
1191 : 0 : lcores++;
1192 [ + + ]: 15 : if (*lcores == '\0')
1193 : 1 : goto err;
1194 : :
1195 : : lflags = 0;
1196 : :
1197 : : /* record lcore_set start point */
1198 : : lcore_start = lcores;
1199 : :
1200 : : /* go across a complete bracket */
1201 [ + + ]: 14 : if (*lcore_start == '(') {
1202 : 5 : lcores += strcspn(lcores, ")");
1203 [ - + ]: 5 : if (*lcores++ == '\0')
1204 : 0 : goto err;
1205 : : }
1206 : :
1207 : : /* scan the separator '@', ','(next) or '\0'(finish) */
1208 : 14 : lcores += strcspn(lcores, "@,");
1209 : :
1210 [ + + ]: 14 : if (*lcores == '@') {
1211 : : /* explicit assign cpuset and update the end cursor */
1212 : 5 : offset = eal_parse_set(lcores + 1, &cpuset);
1213 [ + + ]: 5 : if (offset < 0)
1214 : 3 : goto err;
1215 : 2 : end = lcores + 1 + offset;
1216 : : } else { /* ',' or '\0' */
1217 : : /* haven't given cpuset, current loop done */
1218 : : end = lcores;
1219 : :
1220 : : /* go back to check <number>-<number> */
1221 : 9 : offset = strcspn(lcore_start, "(-");
1222 [ + + ]: 9 : if (offset < (end - lcore_start) &&
1223 [ + + ]: 7 : *(lcore_start + offset) != '(')
1224 : : lflags = 1;
1225 : : }
1226 : :
1227 [ - + ]: 11 : if (*end != ',' && *end != '\0')
1228 : 0 : goto err;
1229 : :
1230 : : /* parse lcore_set from start point */
1231 [ + + ]: 11 : if (eal_parse_set(lcore_start, &lcore_set) < 0)
1232 : 9 : goto err;
1233 : :
1234 : : /* without '@', by default using lcore_set as cpuset */
1235 [ + - ]: 2 : if (*lcores != '@')
1236 : : rte_memcpy(&cpuset, &lcore_set, sizeof(cpuset));
1237 : :
1238 : 2 : set_count = CPU_COUNT(&lcore_set);
1239 : : /* start to update lcore_set */
1240 [ + + ]: 258 : for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
1241 [ + + ]: 256 : if (!CPU_ISSET(idx, &lcore_set))
1242 : 250 : continue;
1243 : 6 : set_count--;
1244 : :
1245 [ + - ]: 6 : if (cfg->lcore_role[idx] != ROLE_RTE) {
1246 : 6 : lcore_config[idx].core_index = count;
1247 : 6 : cfg->lcore_role[idx] = ROLE_RTE;
1248 : 6 : count++;
1249 : : }
1250 : :
1251 [ + + ]: 6 : if (lflags) {
1252 : 2 : CPU_ZERO(&cpuset);
1253 : 2 : CPU_SET(idx, &cpuset);
1254 : : }
1255 : :
1256 [ - + ]: 6 : if (check_cpuset(&cpuset) < 0)
1257 : 0 : goto err;
1258 [ - + ]: 6 : rte_memcpy(&lcore_config[idx].cpuset, &cpuset,
1259 : : sizeof(rte_cpuset_t));
1260 : : }
1261 : :
1262 : : /* some cores from the lcore_set can't be handled by EAL */
1263 [ - + ]: 2 : if (set_count != 0)
1264 : 0 : goto err;
1265 : :
1266 : 2 : lcores = end + 1;
1267 [ + - ]: 2 : } while (*end != '\0');
1268 : :
1269 [ # # ]: 0 : if (count == 0)
1270 : 0 : goto err;
1271 : :
1272 : 0 : cfg->lcore_count = count;
1273 : : ret = 0;
1274 : :
1275 : : err:
1276 : :
1277 : : return ret;
1278 : : }
1279 : :
1280 : : #ifndef RTE_EXEC_ENV_WINDOWS
1281 : : static int
1282 : 2 : eal_parse_syslog(const char *facility, struct internal_config *conf)
1283 : : {
1284 : : int i;
1285 : : static const struct {
1286 : : const char *name;
1287 : : int value;
1288 : : } map[] = {
1289 : : { "auth", LOG_AUTH },
1290 : : { "cron", LOG_CRON },
1291 : : { "daemon", LOG_DAEMON },
1292 : : { "ftp", LOG_FTP },
1293 : : { "kern", LOG_KERN },
1294 : : { "lpr", LOG_LPR },
1295 : : { "mail", LOG_MAIL },
1296 : : { "news", LOG_NEWS },
1297 : : { "syslog", LOG_SYSLOG },
1298 : : { "user", LOG_USER },
1299 : : { "uucp", LOG_UUCP },
1300 : : { "local0", LOG_LOCAL0 },
1301 : : { "local1", LOG_LOCAL1 },
1302 : : { "local2", LOG_LOCAL2 },
1303 : : { "local3", LOG_LOCAL3 },
1304 : : { "local4", LOG_LOCAL4 },
1305 : : { "local5", LOG_LOCAL5 },
1306 : : { "local6", LOG_LOCAL6 },
1307 : : { "local7", LOG_LOCAL7 },
1308 : : { NULL, 0 }
1309 : : };
1310 : :
1311 [ + + ]: 29 : for (i = 0; map[i].name; i++) {
1312 [ + + ]: 28 : if (!strcmp(facility, map[i].name)) {
1313 : 1 : conf->syslog_facility = map[i].value;
1314 : 1 : return 0;
1315 : : }
1316 : : }
1317 : : return -1;
1318 : : }
1319 : : #endif
1320 : :
1321 : : static void
1322 : 0 : eal_log_usage(void)
1323 : : {
1324 : : unsigned int level;
1325 : :
1326 : : printf("Log type is a pattern matching items of this list"
1327 : : " (plugins may be missing):\n");
1328 : 0 : rte_log_list_types(stdout, "\t");
1329 : : printf("\n");
1330 : : printf("Syntax using globbing pattern: ");
1331 : : printf("--"OPT_LOG_LEVEL" pattern:level\n");
1332 : : printf("Syntax using regular expression: ");
1333 : : printf("--"OPT_LOG_LEVEL" regexp,level\n");
1334 : : printf("Syntax for the global level: ");
1335 : : printf("--"OPT_LOG_LEVEL" level\n");
1336 : : printf("Logs are emitted if allowed by both global and specific levels.\n");
1337 : : printf("\n");
1338 : : printf("Log level can be a number or the first letters of its name:\n");
1339 [ # # ]: 0 : for (level = 1; level <= RTE_LOG_MAX; level++)
1340 : 0 : printf("\t%d %s\n", level, eal_log_level2str(level));
1341 : 0 : }
1342 : :
1343 : : static int
1344 : 0 : eal_parse_log_priority(const char *level)
1345 : : {
1346 : 0 : size_t len = strlen(level);
1347 : : unsigned long tmp;
1348 : : char *end;
1349 : : unsigned int i;
1350 : :
1351 [ # # ]: 0 : if (len == 0)
1352 : : return -1;
1353 : :
1354 : : /* look for named values, skip 0 which is not a valid level */
1355 [ # # ]: 0 : for (i = 1; i <= RTE_LOG_MAX; i++) {
1356 [ # # ]: 0 : if (strncmp(eal_log_level2str(i), level, len) == 0)
1357 : 0 : return i;
1358 : : }
1359 : :
1360 : : /* not a string, maybe it is numeric */
1361 : 0 : errno = 0;
1362 : 0 : tmp = strtoul(level, &end, 0);
1363 : :
1364 : : /* check for errors */
1365 [ # # # # : 0 : if (errno != 0 || end == NULL || *end != '\0' ||
# # # # ]
1366 : : tmp >= UINT32_MAX)
1367 : : return -1;
1368 : :
1369 : 0 : return tmp;
1370 : : }
1371 : :
1372 : : static int
1373 : 0 : eal_parse_log_level(const char *arg)
1374 : : {
1375 : : const char *pattern = NULL;
1376 : : const char *regex = NULL;
1377 : : char *str, *level;
1378 : : int priority;
1379 : :
1380 [ # # ]: 0 : if (strcmp(arg, "help") == 0) {
1381 : 0 : eal_log_usage();
1382 : 0 : exit(EXIT_SUCCESS);
1383 : : }
1384 : :
1385 : 0 : str = strdup(arg);
1386 [ # # ]: 0 : if (str == NULL)
1387 : : return -1;
1388 : :
1389 [ # # ]: 0 : if ((level = strchr(str, ','))) {
1390 : : regex = str;
1391 : 0 : *level++ = '\0';
1392 [ # # ]: 0 : } else if ((level = strchr(str, ':'))) {
1393 : : pattern = str;
1394 : 0 : *level++ = '\0';
1395 : : } else {
1396 : : level = str;
1397 : : }
1398 : :
1399 : 0 : priority = eal_parse_log_priority(level);
1400 [ # # ]: 0 : if (priority <= 0) {
1401 : 0 : fprintf(stderr, "Invalid log level: %s\n", level);
1402 : 0 : goto fail;
1403 : : }
1404 [ # # ]: 0 : if (priority > (int)RTE_LOG_MAX) {
1405 : 0 : fprintf(stderr, "Log level %d higher than maximum (%d)\n",
1406 : : priority, RTE_LOG_MAX);
1407 : : priority = RTE_LOG_MAX;
1408 : : }
1409 : :
1410 [ # # ]: 0 : if (regex) {
1411 [ # # ]: 0 : if (rte_log_set_level_regexp(regex, priority) < 0) {
1412 : 0 : fprintf(stderr, "cannot set log level %s,%d\n",
1413 : : regex, priority);
1414 : 0 : goto fail;
1415 : : }
1416 [ # # ]: 0 : if (eal_log_save_regexp(regex, priority) < 0)
1417 : 0 : goto fail;
1418 [ # # ]: 0 : } else if (pattern) {
1419 [ # # ]: 0 : if (rte_log_set_level_pattern(pattern, priority) < 0) {
1420 : 0 : fprintf(stderr, "cannot set log level %s:%d\n",
1421 : : pattern, priority);
1422 : 0 : goto fail;
1423 : : }
1424 [ # # ]: 0 : if (eal_log_save_pattern(pattern, priority) < 0)
1425 : 0 : goto fail;
1426 : : } else {
1427 : 0 : rte_log_set_global_level(priority);
1428 : : }
1429 : :
1430 : 0 : free(str);
1431 : 0 : return 0;
1432 : :
1433 : 0 : fail:
1434 : 0 : free(str);
1435 : 0 : return -1;
1436 : : }
1437 : :
1438 : : static enum rte_proc_type_t
1439 : 75 : eal_parse_proc_type(const char *arg)
1440 : : {
1441 [ + - ]: 75 : if (strncasecmp(arg, "primary", sizeof("primary")) == 0)
1442 : : return RTE_PROC_PRIMARY;
1443 [ + + ]: 75 : if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0)
1444 : : return RTE_PROC_SECONDARY;
1445 [ + + ]: 4 : if (strncasecmp(arg, "auto", sizeof("auto")) == 0)
1446 : 3 : return RTE_PROC_AUTO;
1447 : :
1448 : : return RTE_PROC_INVALID;
1449 : : }
1450 : :
1451 : : static int
1452 : 0 : eal_parse_iova_mode(const char *name)
1453 : : {
1454 : : int mode;
1455 : : struct internal_config *internal_conf =
1456 : 0 : eal_get_internal_configuration();
1457 : :
1458 [ # # ]: 0 : if (name == NULL)
1459 : : return -1;
1460 : :
1461 [ # # ]: 0 : if (!strcmp("pa", name))
1462 : : mode = RTE_IOVA_PA;
1463 [ # # ]: 0 : else if (!strcmp("va", name))
1464 : : mode = RTE_IOVA_VA;
1465 : : else
1466 : : return -1;
1467 : :
1468 : 0 : internal_conf->iova_mode = mode;
1469 : 0 : return 0;
1470 : : }
1471 : :
1472 : : static int
1473 : 0 : eal_parse_simd_bitwidth(const char *arg)
1474 : : {
1475 : : char *end;
1476 : : unsigned long bitwidth;
1477 : : int ret;
1478 : : struct internal_config *internal_conf =
1479 : 0 : eal_get_internal_configuration();
1480 : :
1481 [ # # # # ]: 0 : if (arg == NULL || arg[0] == '\0')
1482 : : return -1;
1483 : :
1484 : 0 : errno = 0;
1485 : 0 : bitwidth = strtoul(arg, &end, 0);
1486 : :
1487 : : /* check for errors */
1488 [ # # # # : 0 : if (errno != 0 || end == NULL || *end != '\0' || bitwidth > RTE_VECT_SIMD_MAX)
# # # # ]
1489 : : return -1;
1490 : :
1491 [ # # ]: 0 : if (bitwidth == 0)
1492 : : bitwidth = (unsigned long) RTE_VECT_SIMD_MAX;
1493 : 0 : ret = rte_vect_set_max_simd_bitwidth(bitwidth);
1494 [ # # ]: 0 : if (ret < 0)
1495 : : return -1;
1496 : 0 : internal_conf->max_simd_bitwidth.forced = 1;
1497 : 0 : return 0;
1498 : : }
1499 : :
1500 : : static int
1501 : 1 : eal_parse_base_virtaddr(const char *arg)
1502 : : {
1503 : : char *end;
1504 : : uint64_t addr;
1505 : : struct internal_config *internal_conf =
1506 : 1 : eal_get_internal_configuration();
1507 : :
1508 : 1 : errno = 0;
1509 : 1 : addr = strtoull(arg, &end, 16);
1510 : :
1511 : : /* check for errors */
1512 [ + - + - : 1 : if ((errno != 0) || (arg[0] == '\0') || end == NULL || (*end != '\0'))
+ - + - ]
1513 : : return -1;
1514 : :
1515 : : /* make sure we don't exceed 32-bit boundary on 32-bit target */
1516 : : #ifndef RTE_ARCH_64
1517 : : if (addr >= UINTPTR_MAX)
1518 : : return -1;
1519 : : #endif
1520 : :
1521 : : /* align the addr on 16M boundary, 16MB is the minimum huge page
1522 : : * size on IBM Power architecture. If the addr is aligned to 16MB,
1523 : : * it can align to 2MB for x86. So this alignment can also be used
1524 : : * on x86 and other architectures.
1525 : : */
1526 : 1 : internal_conf->base_virtaddr =
1527 : 1 : RTE_PTR_ALIGN_CEIL((uintptr_t)addr, (size_t)RTE_PGSIZE_16M);
1528 : :
1529 : 1 : return 0;
1530 : : }
1531 : :
1532 : : /* caller is responsible for freeing the returned string */
1533 : : static char *
1534 : 0 : available_cores(void)
1535 : : {
1536 : 0 : char *str = NULL;
1537 : : int previous;
1538 : : int sequence;
1539 : : char *tmp;
1540 : : int idx;
1541 : :
1542 : : /* find the first available cpu */
1543 [ # # ]: 0 : for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
1544 [ # # ]: 0 : if (eal_cpu_detected(idx) == 0)
1545 : : continue;
1546 : : break;
1547 : : }
1548 [ # # ]: 0 : if (idx >= RTE_MAX_LCORE)
1549 : : return NULL;
1550 : :
1551 : : /* first sequence */
1552 [ # # ]: 0 : if (asprintf(&str, "%d", idx) < 0)
1553 : : return NULL;
1554 : : previous = idx;
1555 : : sequence = 0;
1556 : :
1557 [ # # ]: 0 : for (idx++ ; idx < RTE_MAX_LCORE; idx++) {
1558 [ # # ]: 0 : if (eal_cpu_detected(idx) == 0)
1559 : 0 : continue;
1560 : :
1561 [ # # ]: 0 : if (idx == previous + 1) {
1562 : : previous = idx;
1563 : : sequence = 1;
1564 : 0 : continue;
1565 : : }
1566 : :
1567 : : /* finish current sequence */
1568 [ # # ]: 0 : if (sequence) {
1569 [ # # ]: 0 : if (asprintf(&tmp, "%s-%d", str, previous) < 0) {
1570 : 0 : free(str);
1571 : 0 : return NULL;
1572 : : }
1573 : 0 : free(str);
1574 : 0 : str = tmp;
1575 : : }
1576 : :
1577 : : /* new sequence */
1578 [ # # ]: 0 : if (asprintf(&tmp, "%s,%d", str, idx) < 0) {
1579 : 0 : free(str);
1580 : 0 : return NULL;
1581 : : }
1582 : 0 : free(str);
1583 : 0 : str = tmp;
1584 : : previous = idx;
1585 : : sequence = 0;
1586 : : }
1587 : :
1588 : : /* finish last sequence */
1589 [ # # ]: 0 : if (sequence) {
1590 [ # # ]: 0 : if (asprintf(&tmp, "%s-%d", str, previous) < 0) {
1591 : 0 : free(str);
1592 : 0 : return NULL;
1593 : : }
1594 : 0 : free(str);
1595 : 0 : str = tmp;
1596 : : }
1597 : :
1598 : 0 : return str;
1599 : : }
1600 : :
1601 : : #define HUGE_UNLINK_NEVER "never"
1602 : :
1603 : : static int
1604 : 1 : eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out)
1605 : : {
1606 [ + - - + ]: 1 : if (arg == NULL || strcmp(arg, "always") == 0) {
1607 : 0 : out->unlink_before_mapping = true;
1608 : 0 : return 0;
1609 : : }
1610 [ + - ]: 1 : if (strcmp(arg, "existing") == 0) {
1611 : : /* same as not specifying the option */
1612 : : return 0;
1613 : : }
1614 [ + - ]: 1 : if (strcmp(arg, HUGE_UNLINK_NEVER) == 0) {
1615 : 1 : EAL_LOG(WARNING, "Using --"OPT_HUGE_UNLINK"="
1616 : : HUGE_UNLINK_NEVER" may create data leaks.");
1617 : 1 : out->unlink_existing = false;
1618 : 1 : return 0;
1619 : : }
1620 : : return -1;
1621 : : }
1622 : :
1623 : : int
1624 : 516 : eal_parse_common_option(int opt, const char *optarg,
1625 : : struct internal_config *conf)
1626 : : {
1627 : : static int b_used;
1628 : : static int a_used;
1629 : :
1630 [ + + + + : 516 : switch (opt) {
- - + + +
- + + + +
+ - + + +
+ + + - +
+ - - + +
+ - + - -
- + ]
1631 : 7 : case 'b':
1632 [ - + ]: 7 : if (a_used)
1633 : 0 : goto ba_conflict;
1634 [ + - ]: 7 : if (eal_option_device_add(RTE_DEVTYPE_BLOCKED, optarg) < 0)
1635 : : return -1;
1636 : 7 : b_used = 1;
1637 : 7 : break;
1638 : :
1639 : 12 : case 'a':
1640 [ - + ]: 12 : if (b_used)
1641 : 0 : goto ba_conflict;
1642 [ + - ]: 12 : if (eal_option_device_add(RTE_DEVTYPE_ALLOWED, optarg) < 0)
1643 : : return -1;
1644 : 12 : a_used = 1;
1645 : 12 : break;
1646 : : /* coremask */
1647 : : case 'c': {
1648 : : int lcore_indexes[RTE_MAX_LCORE];
1649 : :
1650 [ - + ]: 13 : if (eal_service_cores_parsed())
1651 : 0 : EAL_LOG(WARNING,
1652 : : "Service cores parsed before dataplane cores. Please ensure -c is before -s or -S");
1653 [ + + ]: 13 : if (rte_eal_parse_coremask(optarg, lcore_indexes) < 0) {
1654 : 1 : EAL_LOG(ERR, "invalid coremask syntax");
1655 : 1 : return -1;
1656 : : }
1657 [ - + ]: 12 : if (update_lcore_config(lcore_indexes) < 0) {
1658 : 0 : char *available = available_cores();
1659 : :
1660 : 0 : EAL_LOG(ERR,
1661 : : "invalid coremask, please check specified cores are part of %s",
1662 : : available);
1663 : 0 : free(available);
1664 : 0 : return -1;
1665 : : }
1666 : :
1667 [ - + ]: 12 : if (core_parsed) {
1668 [ # # # # ]: 0 : EAL_LOG(ERR, "Option -c is ignored, because (%s) is set!",
1669 : : (core_parsed == LCORE_OPT_LST) ? "-l" :
1670 : : (core_parsed == LCORE_OPT_MAP) ? "--lcore" :
1671 : : "-c");
1672 : 0 : return -1;
1673 : : }
1674 : :
1675 : 12 : core_parsed = LCORE_OPT_MSK;
1676 : 12 : break;
1677 : : }
1678 : : /* corelist */
1679 : : case 'l': {
1680 : : int lcore_indexes[RTE_MAX_LCORE];
1681 : :
1682 [ - + ]: 9 : if (eal_service_cores_parsed())
1683 : 0 : EAL_LOG(WARNING,
1684 : : "Service cores parsed before dataplane cores. Please ensure -l is before -s or -S");
1685 : :
1686 [ + - ]: 9 : if (eal_parse_corelist(optarg, lcore_indexes) < 0) {
1687 : 9 : EAL_LOG(ERR, "invalid core list syntax");
1688 : 9 : return -1;
1689 : : }
1690 [ # # ]: 0 : if (update_lcore_config(lcore_indexes) < 0) {
1691 : 0 : char *available = available_cores();
1692 : :
1693 : 0 : EAL_LOG(ERR,
1694 : : "invalid core list, please check specified cores are part of %s",
1695 : : available);
1696 : 0 : free(available);
1697 : 0 : return -1;
1698 : : }
1699 : :
1700 [ # # ]: 0 : if (core_parsed) {
1701 [ # # # # ]: 0 : EAL_LOG(ERR, "Option -l is ignored, because (%s) is set!",
1702 : : (core_parsed == LCORE_OPT_MSK) ? "-c" :
1703 : : (core_parsed == LCORE_OPT_MAP) ? "--lcore" :
1704 : : "-l");
1705 : 0 : return -1;
1706 : : }
1707 : :
1708 : 0 : core_parsed = LCORE_OPT_LST;
1709 : 0 : break;
1710 : : }
1711 : : /* service coremask */
1712 : 0 : case 's':
1713 [ # # ]: 0 : if (eal_parse_service_coremask(optarg) < 0) {
1714 : 0 : EAL_LOG(ERR, "invalid service coremask");
1715 : 0 : return -1;
1716 : : }
1717 : : break;
1718 : : /* service corelist */
1719 : 0 : case 'S':
1720 [ # # ]: 0 : if (eal_parse_service_corelist(optarg) < 0) {
1721 : 0 : EAL_LOG(ERR, "invalid service core list");
1722 : 0 : return -1;
1723 : : }
1724 : : break;
1725 : : /* size of memory */
1726 : : case 'm':
1727 : 102 : conf->memory = atoi(optarg);
1728 : 102 : conf->memory *= 1024ULL;
1729 : 102 : conf->memory *= 1024ULL;
1730 : 102 : mem_parsed = 1;
1731 : 102 : break;
1732 : : /* force number of channels */
1733 : : case 'n':
1734 : 3 : conf->force_nchannel = atoi(optarg);
1735 [ + + ]: 3 : if (conf->force_nchannel == 0) {
1736 : 2 : EAL_LOG(ERR, "invalid channel number");
1737 : 2 : return -1;
1738 : : }
1739 : : break;
1740 : : /* force number of ranks */
1741 : : case 'r':
1742 : 5 : conf->force_nrank = atoi(optarg);
1743 [ + + ]: 5 : if (conf->force_nrank == 0 ||
1744 [ + + ]: 3 : conf->force_nrank > 16) {
1745 : 4 : EAL_LOG(ERR, "invalid rank number");
1746 : 4 : return -1;
1747 : : }
1748 : : break;
1749 : : /* force loading of external driver */
1750 : 0 : case 'd':
1751 [ # # ]: 0 : if (eal_plugin_add(optarg) == -1)
1752 : 0 : return -1;
1753 : : break;
1754 : 1 : case 'v':
1755 : : /* since message is explicitly requested by user, we
1756 : : * write message at highest log level so it can always
1757 : : * be seen
1758 : : * even if info or warning messages are disabled */
1759 : 1 : EAL_LOG(CRIT, "RTE Version: '%s'", rte_version());
1760 : 1 : break;
1761 : :
1762 : : /* long options */
1763 : 1 : case OPT_HUGE_UNLINK_NUM:
1764 [ - + ]: 1 : if (eal_parse_huge_unlink(optarg, &conf->hugepage_file) < 0) {
1765 : 0 : EAL_LOG(ERR, "invalid --"OPT_HUGE_UNLINK" option");
1766 : 0 : return -1;
1767 : : }
1768 : : break;
1769 : :
1770 : 98 : case OPT_NO_HUGE_NUM:
1771 : 98 : conf->no_hugetlbfs = 1;
1772 : : /* no-huge is legacy mem */
1773 : 98 : conf->legacy_mem = 1;
1774 : 98 : break;
1775 : :
1776 : 1 : case OPT_NO_PCI_NUM:
1777 : 1 : conf->no_pci = 1;
1778 : 1 : break;
1779 : :
1780 : 1 : case OPT_NO_HPET_NUM:
1781 : 1 : conf->no_hpet = 1;
1782 : 1 : break;
1783 : :
1784 : 0 : case OPT_VMWARE_TSC_MAP_NUM:
1785 : 0 : conf->vmware_tsc_map = 1;
1786 : 0 : break;
1787 : :
1788 : 7 : case OPT_NO_SHCONF_NUM:
1789 : 7 : conf->no_shconf = 1;
1790 : 7 : break;
1791 : :
1792 : 3 : case OPT_IN_MEMORY_NUM:
1793 : 3 : conf->in_memory = 1;
1794 : : /* in-memory is a superset of noshconf and huge-unlink */
1795 : 3 : conf->no_shconf = 1;
1796 : 3 : conf->hugepage_file.unlink_before_mapping = true;
1797 : 3 : break;
1798 : :
1799 : 75 : case OPT_PROC_TYPE_NUM:
1800 : 75 : conf->process_type = eal_parse_proc_type(optarg);
1801 : 75 : break;
1802 : :
1803 : 5 : case OPT_MAIN_LCORE_NUM:
1804 [ + + ]: 5 : if (eal_parse_main_lcore(optarg) < 0) {
1805 : 2 : EAL_LOG(ERR, "invalid parameter for --"
1806 : : OPT_MAIN_LCORE);
1807 : 2 : return -1;
1808 : : }
1809 : : break;
1810 : :
1811 : 9 : case OPT_VDEV_NUM:
1812 [ - + ]: 9 : if (eal_option_device_add(RTE_DEVTYPE_VIRTUAL,
1813 : : optarg) < 0) {
1814 : 0 : return -1;
1815 : : }
1816 : : break;
1817 : :
1818 : : #ifndef RTE_EXEC_ENV_WINDOWS
1819 : 2 : case OPT_SYSLOG_NUM:
1820 [ + + ]: 2 : if (eal_parse_syslog(optarg, conf) < 0) {
1821 : 1 : EAL_LOG(ERR, "invalid parameters for --"
1822 : : OPT_SYSLOG);
1823 : 1 : return -1;
1824 : : }
1825 : : break;
1826 : : #endif
1827 : :
1828 : 0 : case OPT_LOG_LEVEL_NUM: {
1829 [ # # ]: 0 : if (eal_parse_log_level(optarg) < 0) {
1830 : 0 : EAL_LOG(ERR,
1831 : : "invalid parameters for --"
1832 : : OPT_LOG_LEVEL);
1833 : 0 : return -1;
1834 : : }
1835 : : break;
1836 : : }
1837 : :
1838 : : #ifndef RTE_EXEC_ENV_WINDOWS
1839 : 1 : case OPT_TRACE_NUM: {
1840 [ - + ]: 1 : if (eal_trace_args_save(optarg) < 0) {
1841 : 0 : EAL_LOG(ERR, "invalid parameters for --"
1842 : : OPT_TRACE);
1843 : 0 : return -1;
1844 : : }
1845 : : break;
1846 : : }
1847 : :
1848 : 1 : case OPT_TRACE_DIR_NUM: {
1849 [ - + ]: 1 : if (eal_trace_dir_args_save(optarg) < 0) {
1850 : 0 : EAL_LOG(ERR, "invalid parameters for --"
1851 : : OPT_TRACE_DIR);
1852 : 0 : return -1;
1853 : : }
1854 : : break;
1855 : : }
1856 : :
1857 : 0 : case OPT_TRACE_BUF_SIZE_NUM: {
1858 [ # # ]: 0 : if (eal_trace_bufsz_args_save(optarg) < 0) {
1859 : 0 : EAL_LOG(ERR, "invalid parameters for --"
1860 : : OPT_TRACE_BUF_SIZE);
1861 : 0 : return -1;
1862 : : }
1863 : : break;
1864 : : }
1865 : :
1866 : 0 : case OPT_TRACE_MODE_NUM: {
1867 [ # # ]: 0 : if (eal_trace_mode_args_save(optarg) < 0) {
1868 : 0 : EAL_LOG(ERR, "invalid parameters for --"
1869 : : OPT_TRACE_MODE);
1870 : 0 : return -1;
1871 : : }
1872 : : break;
1873 : : }
1874 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
1875 : :
1876 : 13 : case OPT_LCORES_NUM:
1877 [ + - ]: 13 : if (eal_parse_lcores(optarg) < 0) {
1878 : 13 : EAL_LOG(ERR, "invalid parameter for --"
1879 : : OPT_LCORES);
1880 : 13 : return -1;
1881 : : }
1882 : :
1883 [ # # ]: 0 : if (core_parsed) {
1884 [ # # # # ]: 0 : EAL_LOG(ERR, "Option --lcore is ignored, because (%s) is set!",
1885 : : (core_parsed == LCORE_OPT_LST) ? "-l" :
1886 : : (core_parsed == LCORE_OPT_MSK) ? "-c" :
1887 : : "--lcore");
1888 : 0 : return -1;
1889 : : }
1890 : :
1891 : 0 : core_parsed = LCORE_OPT_MAP;
1892 : 0 : break;
1893 : 2 : case OPT_LEGACY_MEM_NUM:
1894 : 2 : conf->legacy_mem = 1;
1895 : 2 : break;
1896 : 1 : case OPT_SINGLE_FILE_SEGMENTS_NUM:
1897 : 1 : conf->single_file_segments = 1;
1898 : 1 : break;
1899 : 0 : case OPT_IOVA_MODE_NUM:
1900 [ # # ]: 0 : if (eal_parse_iova_mode(optarg) < 0) {
1901 : 0 : EAL_LOG(ERR, "invalid parameters for --"
1902 : : OPT_IOVA_MODE);
1903 : 0 : return -1;
1904 : : }
1905 : : break;
1906 : 1 : case OPT_BASE_VIRTADDR_NUM:
1907 [ - + ]: 1 : if (eal_parse_base_virtaddr(optarg) < 0) {
1908 : 0 : EAL_LOG(ERR, "invalid parameter for --"
1909 : : OPT_BASE_VIRTADDR);
1910 : 0 : return -1;
1911 : : }
1912 : : break;
1913 : : case OPT_TELEMETRY_NUM:
1914 : : break;
1915 : 0 : case OPT_NO_TELEMETRY_NUM:
1916 : 0 : conf->no_telemetry = 1;
1917 : 0 : break;
1918 : 0 : case OPT_FORCE_MAX_SIMD_BITWIDTH_NUM:
1919 [ # # ]: 0 : if (eal_parse_simd_bitwidth(optarg) < 0) {
1920 : 0 : EAL_LOG(ERR, "invalid parameter for --"
1921 : : OPT_FORCE_MAX_SIMD_BITWIDTH);
1922 : 0 : return -1;
1923 : : }
1924 : : break;
1925 : :
1926 : : /* don't know what to do, leave this to caller */
1927 : : default:
1928 : : return 1;
1929 : :
1930 : : }
1931 : :
1932 : : return 0;
1933 : :
1934 : 0 : ba_conflict:
1935 : 0 : EAL_LOG(ERR,
1936 : : "Options allow (-a) and block (-b) can't be used at the same time");
1937 : 0 : return -1;
1938 : : }
1939 : :
1940 : : static void
1941 : 181 : eal_auto_detect_cores(struct rte_config *cfg)
1942 : : {
1943 : : unsigned int lcore_id;
1944 : : unsigned int removed = 0;
1945 : : rte_cpuset_t affinity_set;
1946 : :
1947 [ - + ]: 181 : if (rte_thread_get_affinity_by_id(rte_thread_self(), &affinity_set) != 0)
1948 : 0 : CPU_ZERO(&affinity_set);
1949 : :
1950 [ + + ]: 23349 : for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1951 [ + + ]: 23168 : if (cfg->lcore_role[lcore_id] == ROLE_RTE &&
1952 [ + + ]: 2896 : !CPU_ISSET(lcore_id, &affinity_set)) {
1953 : 2600 : cfg->lcore_role[lcore_id] = ROLE_OFF;
1954 : 2600 : removed++;
1955 : : }
1956 : : }
1957 : :
1958 : 181 : cfg->lcore_count -= removed;
1959 : 181 : }
1960 : :
1961 : : static void
1962 : 190 : compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
1963 : : {
1964 : 190 : rte_cpuset_t *cpuset = &internal_cfg->ctrl_cpuset;
1965 : : rte_cpuset_t default_set;
1966 : : unsigned int lcore_id;
1967 : :
1968 [ + + ]: 24510 : for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1969 [ + + ]: 24320 : if (rte_lcore_has_role(lcore_id, ROLE_OFF))
1970 : 24012 : continue;
1971 [ + + ]: 5236 : RTE_CPU_OR(cpuset, cpuset, &lcore_config[lcore_id].cpuset);
1972 : : }
1973 [ + + + + ]: 197790 : RTE_CPU_NOT(cpuset, cpuset);
1974 : :
1975 [ - + ]: 190 : if (rte_thread_get_affinity_by_id(rte_thread_self(), &default_set) != 0)
1976 : 0 : CPU_ZERO(&default_set);
1977 : :
1978 [ + + ]: 3230 : RTE_CPU_AND(cpuset, cpuset, &default_set);
1979 : :
1980 : : /* if no remaining cpu, use main lcore cpu affinity */
1981 [ + - ]: 190 : if (!CPU_COUNT(cpuset)) {
1982 : 190 : memcpy(cpuset, &lcore_config[rte_get_main_lcore()].cpuset,
1983 : : sizeof(*cpuset));
1984 : : }
1985 : 190 : }
1986 : :
1987 : : int
1988 : 235 : eal_cleanup_config(struct internal_config *internal_cfg)
1989 : : {
1990 : 235 : free(internal_cfg->hugefile_prefix);
1991 : 235 : free(internal_cfg->hugepage_dir);
1992 : 235 : free(internal_cfg->user_mbuf_pool_ops_name);
1993 : :
1994 : 235 : return 0;
1995 : : }
1996 : :
1997 : : int
1998 : 190 : eal_adjust_config(struct internal_config *internal_cfg)
1999 : : {
2000 : : int i;
2001 : 190 : struct rte_config *cfg = rte_eal_get_configuration();
2002 : : struct internal_config *internal_conf =
2003 : 190 : eal_get_internal_configuration();
2004 : :
2005 [ + + ]: 190 : if (!core_parsed)
2006 : 181 : eal_auto_detect_cores(cfg);
2007 : :
2008 [ + + ]: 190 : if (internal_conf->process_type == RTE_PROC_AUTO)
2009 : 3 : internal_conf->process_type = eal_proc_type_detect();
2010 : :
2011 : : /* default main lcore is the first one */
2012 [ + + ]: 190 : if (!main_lcore_parsed) {
2013 : 187 : cfg->main_lcore = rte_get_next_lcore(-1, 0, 0);
2014 [ + - ]: 187 : if (cfg->main_lcore >= RTE_MAX_LCORE)
2015 : : return -1;
2016 : 187 : lcore_config[cfg->main_lcore].core_role = ROLE_RTE;
2017 : : }
2018 : :
2019 : 190 : compute_ctrl_threads_cpuset(internal_cfg);
2020 : :
2021 : : /* if no memory amounts were requested, this will result in 0 and
2022 : : * will be overridden later, right after eal_hugepage_info_init() */
2023 [ + + ]: 6270 : for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
2024 : 6080 : internal_cfg->memory += internal_cfg->socket_mem[i];
2025 : :
2026 : : return 0;
2027 : : }
2028 : :
2029 : : int
2030 : 190 : eal_check_common_options(struct internal_config *internal_cfg)
2031 : : {
2032 : 190 : struct rte_config *cfg = rte_eal_get_configuration();
2033 : : const struct internal_config *internal_conf =
2034 : 190 : eal_get_internal_configuration();
2035 : :
2036 [ + + ]: 190 : if (cfg->lcore_role[cfg->main_lcore] != ROLE_RTE) {
2037 : 1 : EAL_LOG(ERR, "Main lcore is not enabled for DPDK");
2038 : 1 : return -1;
2039 : : }
2040 : :
2041 [ + + ]: 189 : if (internal_cfg->process_type == RTE_PROC_INVALID) {
2042 : 1 : EAL_LOG(ERR, "Invalid process type specified");
2043 : 1 : return -1;
2044 : : }
2045 [ + + ]: 188 : if (internal_cfg->hugefile_prefix != NULL &&
2046 [ - + ]: 72 : strlen(internal_cfg->hugefile_prefix) < 1) {
2047 : 0 : EAL_LOG(ERR, "Invalid length of --" OPT_FILE_PREFIX " option");
2048 : 0 : return -1;
2049 : : }
2050 [ + + ]: 188 : if (internal_cfg->hugepage_dir != NULL &&
2051 [ - + ]: 5 : strlen(internal_cfg->hugepage_dir) < 1) {
2052 : 0 : EAL_LOG(ERR, "Invalid length of --" OPT_HUGE_DIR" option");
2053 : 0 : return -1;
2054 : : }
2055 [ - + ]: 188 : if (internal_cfg->user_mbuf_pool_ops_name != NULL &&
2056 [ # # ]: 0 : strlen(internal_cfg->user_mbuf_pool_ops_name) < 1) {
2057 : 0 : EAL_LOG(ERR, "Invalid length of --" OPT_MBUF_POOL_OPS_NAME" option");
2058 : 0 : return -1;
2059 : : }
2060 [ - + ]: 188 : if (strchr(eal_get_hugefile_prefix(), '%') != NULL) {
2061 : 0 : EAL_LOG(ERR, "Invalid char, '%%', in --"OPT_FILE_PREFIX" "
2062 : : "option");
2063 : 0 : return -1;
2064 : : }
2065 [ + + + + ]: 188 : if (mem_parsed && internal_cfg->force_sockets == 1) {
2066 : 2 : EAL_LOG(ERR, "Options -m and --"OPT_SOCKET_MEM" cannot "
2067 : : "be specified at the same time");
2068 : 2 : return -1;
2069 : : }
2070 [ + + + + ]: 186 : if (internal_cfg->no_hugetlbfs && internal_cfg->force_sockets == 1) {
2071 : 1 : EAL_LOG(ERR, "Option --"OPT_SOCKET_MEM" cannot "
2072 : : "be specified together with --"OPT_NO_HUGE);
2073 : 1 : return -1;
2074 : : }
2075 [ + + ]: 185 : if (internal_cfg->no_hugetlbfs &&
2076 [ - + ]: 93 : internal_cfg->hugepage_file.unlink_before_mapping &&
2077 [ # # ]: 0 : !internal_cfg->in_memory) {
2078 : 0 : EAL_LOG(ERR, "Option --"OPT_HUGE_UNLINK" cannot "
2079 : : "be specified together with --"OPT_NO_HUGE);
2080 : 0 : return -1;
2081 : : }
2082 [ + + ]: 185 : if (internal_cfg->no_hugetlbfs &&
2083 [ + + ]: 93 : internal_cfg->huge_worker_stack_size != 0) {
2084 : 2 : EAL_LOG(ERR, "Option --"OPT_HUGE_WORKER_STACK" cannot "
2085 : : "be specified together with --"OPT_NO_HUGE);
2086 : 2 : return -1;
2087 : : }
2088 [ - + - - ]: 183 : if (internal_conf->force_socket_limits && internal_conf->legacy_mem) {
2089 : 0 : EAL_LOG(ERR, "Option --"OPT_SOCKET_LIMIT
2090 : : " is only supported in non-legacy memory mode");
2091 : : }
2092 [ + + ]: 183 : if (internal_cfg->single_file_segments &&
2093 [ - + ]: 1 : internal_cfg->hugepage_file.unlink_before_mapping &&
2094 [ # # ]: 0 : !internal_cfg->in_memory) {
2095 : 0 : EAL_LOG(ERR, "Option --"OPT_SINGLE_FILE_SEGMENTS" is "
2096 : : "not compatible with --"OPT_HUGE_UNLINK);
2097 : 0 : return -1;
2098 : : }
2099 [ + + ]: 183 : if (!internal_cfg->hugepage_file.unlink_existing &&
2100 [ - + ]: 1 : internal_cfg->in_memory) {
2101 : 0 : EAL_LOG(ERR, "Option --"OPT_IN_MEMORY" is not compatible "
2102 : : "with --"OPT_HUGE_UNLINK"="HUGE_UNLINK_NEVER);
2103 : 0 : return -1;
2104 : : }
2105 [ + + ]: 183 : if (internal_cfg->legacy_mem &&
2106 [ - + ]: 93 : internal_cfg->in_memory) {
2107 : 0 : EAL_LOG(ERR, "Option --"OPT_LEGACY_MEM" is not compatible "
2108 : : "with --"OPT_IN_MEMORY);
2109 : 0 : return -1;
2110 : : }
2111 [ + + - + ]: 183 : if (internal_cfg->legacy_mem && internal_cfg->match_allocations) {
2112 : 0 : EAL_LOG(ERR, "Option --"OPT_LEGACY_MEM" is not compatible "
2113 : : "with --"OPT_MATCH_ALLOCATIONS);
2114 : 0 : return -1;
2115 : : }
2116 [ + + - + ]: 183 : if (internal_cfg->no_hugetlbfs && internal_cfg->match_allocations) {
2117 : 0 : EAL_LOG(ERR, "Option --"OPT_NO_HUGE" is not compatible "
2118 : : "with --"OPT_MATCH_ALLOCATIONS);
2119 : 0 : return -1;
2120 : : }
2121 [ + + + + ]: 183 : if (internal_cfg->legacy_mem && internal_cfg->memory == 0) {
2122 : 8 : EAL_LOG(NOTICE, "Static memory layout is selected, "
2123 : : "amount of reserved memory can be adjusted with "
2124 : : "-m or --"OPT_SOCKET_MEM);
2125 : : }
2126 : :
2127 : : return 0;
2128 : : }
2129 : :
2130 : : uint16_t
2131 : 66447 : rte_vect_get_max_simd_bitwidth(void)
2132 : : {
2133 : : const struct internal_config *internal_conf =
2134 : 66447 : eal_get_internal_configuration();
2135 : 66447 : return internal_conf->max_simd_bitwidth.bitwidth;
2136 : : }
2137 : :
2138 : : int
2139 : 0 : rte_vect_set_max_simd_bitwidth(uint16_t bitwidth)
2140 : : {
2141 : : struct internal_config *internal_conf =
2142 : 0 : eal_get_internal_configuration();
2143 [ # # ]: 0 : if (internal_conf->max_simd_bitwidth.forced) {
2144 : 0 : EAL_LOG(NOTICE, "Cannot set max SIMD bitwidth - user runtime override enabled");
2145 : 0 : return -EPERM;
2146 : : }
2147 : :
2148 [ # # # # ]: 0 : if (bitwidth < RTE_VECT_SIMD_DISABLED || !rte_is_power_of_2(bitwidth)) {
2149 : 0 : EAL_LOG(ERR, "Invalid bitwidth value!");
2150 : 0 : return -EINVAL;
2151 : : }
2152 : 0 : internal_conf->max_simd_bitwidth.bitwidth = bitwidth;
2153 : 0 : return 0;
2154 : : }
2155 : :
2156 : : void
2157 : 52 : eal_common_usage(void)
2158 : : {
2159 : : printf("[options]\n\n"
2160 : : "EAL common options:\n"
2161 : : " -c COREMASK Hexadecimal bitmask of cores to run on\n"
2162 : : " -l CORELIST List of cores to run on\n"
2163 : : " The argument format is <c1>[-c2][,c3[-c4],...]\n"
2164 : : " where c1, c2, etc are core indexes between 0 and %d\n"
2165 : : " --"OPT_LCORES" COREMAP Map lcore set to physical cpu set\n"
2166 : : " The argument format is\n"
2167 : : " '<lcores[@cpus]>[<,lcores[@cpus]>...]'\n"
2168 : : " lcores and cpus list are grouped by '(' and ')'\n"
2169 : : " Within the group, '-' is used for range separator,\n"
2170 : : " ',' is used for single number separator.\n"
2171 : : " '( )' can be omitted for single element group,\n"
2172 : : " '@' can be omitted if cpus and lcores have the same value\n"
2173 : : " -s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores\n"
2174 : : " --"OPT_MAIN_LCORE" ID Core ID that is used as main\n"
2175 : : " --"OPT_MBUF_POOL_OPS_NAME" Pool ops name for mbuf to use\n"
2176 : : " -n CHANNELS Number of memory channels\n"
2177 : : " -m MB Memory to allocate (see also --"OPT_SOCKET_MEM")\n"
2178 : : " -r RANKS Force number of memory ranks (don't detect)\n"
2179 : : " -b, --block Add a device to the blocked list.\n"
2180 : : " Prevent EAL from using this device. The argument\n"
2181 : : " format for PCI devices is <domain:bus:devid.func>.\n"
2182 : : " -a, --allow Add a device to the allow list.\n"
2183 : : " Only use the specified devices. The argument format\n"
2184 : : " for PCI devices is <[domain:]bus:devid.func>.\n"
2185 : : " This option can be present several times.\n"
2186 : : " [NOTE: " OPT_DEV_ALLOW " cannot be used with "OPT_DEV_BLOCK" option]\n"
2187 : : " --"OPT_VDEV" Add a virtual device.\n"
2188 : : " The argument format is <driver><id>[,key=val,...]\n"
2189 : : " (ex: --vdev=net_pcap0,iface=eth2).\n"
2190 : : " --"OPT_IOVA_MODE" Set IOVA mode. 'pa' for IOVA_PA\n"
2191 : : " 'va' for IOVA_VA\n"
2192 : : " -d LIB.so|DIR Add a driver or driver directory\n"
2193 : : " (can be used multiple times)\n"
2194 : : " --"OPT_VMWARE_TSC_MAP" Use VMware TSC map instead of native RDTSC\n"
2195 : : " --"OPT_PROC_TYPE" Type of this process (primary|secondary|auto)\n"
2196 : : #ifndef RTE_EXEC_ENV_WINDOWS
2197 : : " --"OPT_SYSLOG" Set syslog facility\n"
2198 : : #endif
2199 : : " --"OPT_LOG_LEVEL"=<level> Set global log level\n"
2200 : : " --"OPT_LOG_LEVEL"=<type-match>:<level>\n"
2201 : : " Set specific log level\n"
2202 : : " --"OPT_LOG_LEVEL"=help Show log types and levels\n"
2203 : : #ifndef RTE_EXEC_ENV_WINDOWS
2204 : : " --"OPT_TRACE"=<regex-match>\n"
2205 : : " Enable trace based on regular expression trace name.\n"
2206 : : " By default, the trace is disabled.\n"
2207 : : " User must specify this option to enable trace.\n"
2208 : : " --"OPT_TRACE_DIR"=<directory path>\n"
2209 : : " Specify trace directory for trace output.\n"
2210 : : " By default, trace output will created at\n"
2211 : : " $HOME directory and parameter must be\n"
2212 : : " specified once only.\n"
2213 : : " --"OPT_TRACE_BUF_SIZE"=<int>\n"
2214 : : " Specify maximum size of allocated memory\n"
2215 : : " for trace output for each thread. Valid\n"
2216 : : " unit can be either 'B|K|M' for 'Bytes',\n"
2217 : : " 'KBytes' and 'MBytes' respectively.\n"
2218 : : " Default is 1MB and parameter must be\n"
2219 : : " specified once only.\n"
2220 : : " --"OPT_TRACE_MODE"=<o[verwrite] | d[iscard]>\n"
2221 : : " Specify the mode of update of trace\n"
2222 : : " output file. Either update on a file can\n"
2223 : : " be wrapped or discarded when file size\n"
2224 : : " reaches its maximum limit.\n"
2225 : : " Default mode is 'overwrite' and parameter\n"
2226 : : " must be specified once only.\n"
2227 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
2228 : : " -v Display version information on startup\n"
2229 : : " -h, --"OPT_HELP" This help\n"
2230 : : " --"OPT_IN_MEMORY" Operate entirely in memory. This will\n"
2231 : : " disable secondary process support\n"
2232 : : " --"OPT_BASE_VIRTADDR" Base virtual address\n"
2233 : : " --"OPT_TELEMETRY" Enable telemetry support (on by default)\n"
2234 : : " --"OPT_NO_TELEMETRY" Disable telemetry support\n"
2235 : : " --"OPT_FORCE_MAX_SIMD_BITWIDTH" Force the max SIMD bitwidth\n"
2236 : : "\nEAL options for DEBUG use only:\n"
2237 : : " --"OPT_HUGE_UNLINK"[=existing|always|never]\n"
2238 : : " When to unlink files in hugetlbfs\n"
2239 : : " ('existing' by default, no value means 'always')\n"
2240 : : " --"OPT_NO_HUGE" Use malloc instead of hugetlbfs\n"
2241 : : " --"OPT_NO_PCI" Disable PCI\n"
2242 : : " --"OPT_NO_HPET" Disable HPET\n"
2243 : : " --"OPT_NO_SHCONF" No shared config (mmap'd files)\n"
2244 : : "\n", RTE_MAX_LCORE);
2245 : 52 : }
|